Vou criar um sistema de aplicativo de bônus completo para você. Aqui está uma solução abrangente:

## 📱 **Sistema de Aplicativo de Bônus**

### **1. Estrutura Principal**

“`javascript
// App.js – Componente Principal
import React, { useState, useEffect } from ‘react’;
import { NavigationContainer } from ‘@react-navigation/native’;
import { createBottomTabNavigator } from ‘@react-navigation/bottom-tabs’;
import { Ionicons } from ‘@expo/vector-icons’;

// Telas do App
import HomeScreen from ‘./screens/HomeScreen’;
import BonusScreen from ‘./screens/BonusScreen’;
import TasksScreen from ‘./screens/TasksScreen’;
import RewardsScreen from ‘./screens/RewardsScreen’;
import ProfileScreen from ‘./screens/ProfileScreen’;

const Tab = createBottomTabNavigator();

export default function App() {
return (

({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === ‘Home’) iconName = focused ? ‘home’ : ‘home-outline’;
else if (route.name === ‘Bônus’) iconName = focused ? ‘gift’ : ‘gift-outline’;
else if (route.name === ‘Tarefas’) iconName = focused ? ‘checkbox’ : ‘checkbox-outline’;
else if (route.name === ‘Prêmios’) iconName = focused ? ‘trophy’ : ‘trophy-outline’;
else if (route.name === ‘Perfil’) iconName = focused ? ‘person’ : ‘person-outline’;
return ;
},
})}
>







);
}
“`

### **2. Sistema de Pontuação e Bônus**

“`javascript
// services/BonusService.js
class BonusService {
constructor() {
this.userPoints = 0;
this.bonusHistory = [];
this.dailyTasks = [];
this.rewards = [];
}

// Tipos de bônus disponíveis
bonusTypes = {
DAILY_LOGIN: { points: 10, name: ‘Login Diário’ },
COMPLETE_PROFILE: { points: 50, name: ‘Perfil Completo’ },
FIRST_PURCHASE: { points: 100, name: ‘Primeira Compra’ },
REFERRAL: { points: 200, name: ‘Indicação’ },
SOCIAL_SHARE: { points: 20, name: ‘Compartilhamento’ },
REVIEW: { points: 30, name: ‘Avaliação’ },
WEEKLY_STREAK: { points: 150, name: ‘Sequência Semanal’ },
};

// Adicionar pontos
addPoints(type, description = ”) {
const bonus = this.bonusTypes[type];
if (!bonus) return false;

this.userPoints += bonus.points;

const transaction = {
id: Date.now(),
type: bonus.name,
points: bonus.points,
description,
date: new Date().toISOString(),
status: ‘completed’
};

this.bonusHistory.unshift(transaction);
this.saveToStorage();

return transaction;
}

// Resgatar prêmio
redeemReward(rewardId) {
const reward = this.rewards.find(r => r.id === rewardId);
if (!reward || this.userPoints < reward.cost) { return { success: false, message: 'Pontos insuficientes' }; } this.userPoints -= reward.cost; const transaction = { id: Date.now(), type: 'RESGATE', points: -reward.cost, description: `Resgate: ${reward.name}`, date: new Date().toISOString(), status: 'pending' }; this.bonusHistory.unshift(transaction); this.saveToStorage(); return { success: true, message: 'Resgate solicitado com sucesso!', transaction }; } // Verificar tarefas diárias checkDailyTasks() { const today = new Date().toDateString(); this.dailyTasks = [ { id: 1, title: 'Fazer login no app', description: 'Ganhe pontos por acessar diariamente', points: 10, completed: false, type: 'daily', icon: 'log-in' }, { id: 2, title: 'Completar perfil', description: 'Adicione suas informações pessoais', points: 50, completed: false, type: 'one-time', icon: 'person' }, { id: 3, title: 'Indicar um amigo', description: 'Compartilhe seu código de indicação', points: 100, completed: false, type: 'referral', icon: 'people' }, { id: 4, title: 'Avaliar o app', description: 'Deixe sua avaliação na loja', points: 30, completed: false, type: 'one-time', icon: 'star' } ]; } // Carregar prêmios disponíveis loadRewards() { this.rewards = [ { id: 1, name: 'Cupom R$10', description: 'Desconto de R$10 na próxima compra', cost: 1000, category: 'voucher', stock: 50 }, { id: 2, name: 'Frete Grátis', description: 'Frete grátis em qualquer compra', cost: 500, category: 'shipping', stock: 100 }, { id: 3, name: 'Produto Exclusivo', description: 'Acesso antecipado a lançamentos', cost: 2000, category: 'product', stock: 10 }, { id: 4, name: 'Assinatura Premium', description: '1 mês de assinatura premium', cost: 5000, category: 'subscription', stock: 20 } ]; } // Salvar no armazenamento local saveToStorage() { // Implementar AsyncStorage ou similar const data = { userPoints: this.userPoints, bonusHistory: this.bonusHistory, lastLogin: new Date().toISOString() }; // AsyncStorage.setItem('bonusData', JSON.stringify(data)); } // Carregar do armazenamento async loadFromStorage() { // const data = await AsyncStorage.getItem('bonusData'); // if (data) { // const parsed = JSON.parse(data); // this.userPoints = parsed.userPoints; // this.bonusHistory = parsed.bonusHistory; // } } } export default new BonusService(); ``` ### **3. Tela de Bônus (Principal)** ```javascript // screens/BonusScreen.js import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, ScrollView, TouchableOpacity, Alert, Image } from 'react-native'; import BonusService from '../services/BonusService'; const BonusScreen = () => {
const [points, setPoints] = useState(0);
const [history, setHistory] = useState([]);
const [dailyBonus, setDailyBonus] = useState(null);

useEffect(() => {
loadData();
checkDailyBonus();
}, []);

const loadData = () => {
setPoints(BonusService.userPoints);
setHistory(BonusService.bonusHistory.slice(0, 10));
};

const checkDailyBonus = () => {
const lastClaim = localStorage.getItem(‘lastDailyBonus’);
const today = new Date().toDateString();

if (lastClaim !== today) {
setDailyBonus({
available: true,
points: 50,
message: ‘Bônus diário disponível!’
});
}
};

const claimDailyBonus = () => {
BonusService.addPoints(‘DAILY_LOGIN’, ‘Bônus diário’);
setDailyBonus(null);
localStorage.setItem(‘lastDailyBonus’, new Date().toDateString());
loadData();
Alert.alert(‘Sucesso!’, ‘Bônus diário resgatado!’);
};

const claimBonus = (type) => {
BonusService.addPoints(type);
loadData();
Alert.alert(‘Parabéns!’, ‘Bônus adicionado à sua conta!’);
};

return (

{/* Cabeçalho com Pontos */}

SEUS PONTOS
{points.toLocaleString()}
Continue acumulando para resgatar prêmios!

{/* Bônus Diário */}
{dailyBonus && (


🎁 BÔNUS DIÁRIO
+{dailyBonus.points} pontos
Toque para resgatar


)}

{/* Bônus Rápidos */}

Bônus Rápidos

claimBonus(‘SOCIAL_SHARE’)}
>
📱
Compartilhar
+20 pontos

claimBonus(‘REVIEW’)}
>

Avaliar
+30 pontos

Alert.alert(‘Indicação’, ‘Seu código: BONUS2024’)}
>
👥
Indicar
+200 pontos


{/* Histórico */}

Histórico Recente
{history.length > 0 ? (
history.map((item) => (


{item.type}
{item.description}

{new Date(item.date).toLocaleDateString()}


0 ? styles.positive : styles.negative
]}>
{item.points > 0 ? ‘+’ : ”}{item.points}


))
) : (
Nenhuma transação ainda
)}


);
};

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: ‘#f5f5f5’,
},
header: {
backgroundColor: ‘#4CAF50’,
padding: 20,
alignItems: ‘center’,
},
pointsLabel: {
color: ‘white’,
fontSize: 14,
opacity: 0.9,
},
pointsValue: {
color: ‘white’,
fontSize: 48,
fontWeight: ‘bold’,
marginVertical: 5,
},
pointsSubtitle: {
color: ‘white’,
fontSize: 12,
opacity: 0.8,
},
dailyBonusCard: {
backgroundColor: ‘#FF9800’,
margin: 15,
borderRadius: 15,
padding: 20,
},
dailyBonusContent: {
alignItems: ‘center’,
},
dailyBonusTitle: {
color: ‘white’,
fontSize: 18,
fontWeight: ‘bold’,
},
dailyBonusPoints: {
color: ‘white’,
fontSize: 32,
fontWeight: ‘bold’,
marginVertical: 5,
},
dailyBonusMessage: {
color: ‘white’,
fontSize: 14,
opacity: 0.9,
},
section: {
backgroundColor: ‘white’,
margin: 15,
borderRadius: 10,
padding: 15,
},
sectionTitle: {
fontSize: 18,
fontWeight: ‘bold’,
marginBottom: 15,
color: ‘#333’,
},
quickBonusGrid: {
flexDirection: ‘row’,
justifyContent: ‘space-between’,
},
bonusCard: {
backgroundColor: ‘#E8F5E9’,
borderRadius: 10,
padding: 15,
alignItems: ‘center’,
flex: 1,
marginHorizontal: 5,
},
bonusIcon: {
fontSize: 24,
marginBottom: 5,
},
bonusCardTitle: {
fontSize: 12,
fontWeight: ‘600’,
color: ‘#333’,
marginBottom: 2,
},
bonusCardPoints: {
fontSize: 11,
color: ‘#4CAF50’,
fontWeight: ‘bold’,
},
historyItem: {
flexDirection: ‘row’,
justifyContent: ‘space-between’,
alignItems: ‘center’,
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: ‘#eee’,
},
historyType: {
fontSize: 14,
fontWeight: ‘600’,
color: ‘#333’,
},
historyDesc: {
fontSize: 12,
color: ‘#666’,
marginTop: 2,
},
historyDate: {
fontSize: 10,
color: ‘#999’,
marginTop: 2,
},
historyPoints: {
fontSize: 16,
fontWeight: ‘bold’,
},
positive: {
color: ‘#4CAF50’,
},
negative: {
color: ‘#F44336’,
},
emptyText: {
textAlign: ‘center’,
color: ‘#999’,
padding: 20,
},
});

export default BonusScreen;
“`

### **4. Backend Simples (Node.js)**

“`javascript
// server.js – Backend para gerenciar bônus
const express = require(‘express’);
const mongoose = require(‘mongoose’);
const cors = require(‘cors’);

const app = express();
app.use(cors());
app.use(express.json());

// Modelos
const UserSchema = new mongoose.Schema({
userId: String,
points: { type: Number, default: 0 },
bonusHistory: [{
type: String,
points: Number,
description: String,
date: Date,
status: String
}],
referralCode: String,
dailyStreak: { type: Number, default: 0 },
lastLogin: Date
});

const RewardSchema = new mongoose.Schema({
name: String,
description: String,
cost: Number,
category: String,
stock: Number,
image: String,
active: { type: Boolean, default: true }
});

const User = mongoose.model(‘User’, UserSchema);
const Reward = mongoose.model(‘Reward’, RewardSchema);

// Rotas
app.post(‘/api/bonus/add’, async (req, res) => {
const { userId, type, points, description } = req.body;

try {
const user = await User.findOne({ userId });
if (!user) return res.status(404).json({ error: ‘Usuário não encontrado’ });

user.points += points;
user.bonusHistory.push({
type,
points,
description,
date: new Date(),
status: ‘completed’
});

await user.save();
res.json({ success: true, points: user.points });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

app.post(‘/api/bonus/redeem’, async (req, res) => {
const { userId, rewardId } = req.body;

try {
const user = await User.findOne({ userId });
const reward = await Reward.findById(rewardId);

if (!user || !reward) {
return res.status(404).json({ error: ‘Não encontrado’ });
}

if (user.points < reward.cost) { return res.status(400).json({ error: 'Pontos insuficientes' }); } if (reward.stock <= 0) { return res.status(400).json({ error: 'Prêmio esgotado' });

Share this post