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 */}
{/* Bônus Diário */}
{dailyBonus && (
)}
{/* Bônus Rápidos */}
>
>
>
{/* Histórico */}
{history.length > 0 ? (
history.map((item) => (
{new Date(item.date).toLocaleDateString()}
]}>
{item.points > 0 ? ‘+’ : ”}{item.points}
))
) : (
)}
);
};
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' });


