From 2c2dfba45357bbd205a59145ae55a2779c911ae0 Mon Sep 17 00:00:00 2001 From: Lucas Faria Mendes Date: Fri, 14 Aug 2026 15:06:35 -0300 Subject: remake Signed-off-by: Lucas Faria Mendes --- src/components/expense-row.tsx | 213 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 src/components/expense-row.tsx (limited to 'src/components/expense-row.tsx') diff --git a/src/components/expense-row.tsx b/src/components/expense-row.tsx new file mode 100644 index 0000000..0f58c78 --- /dev/null +++ b/src/components/expense-row.tsx @@ -0,0 +1,213 @@ +import React from 'react'; +import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import Animated, { FadeInDown, LinearTransition } from 'react-native-reanimated'; +import { Colors, Radius, Spacing, Typography } from '@/constants/theme'; +import type { OneTimeExpense, RecurringExpense } from '@/types'; + +const CATEGORY_EMOJI: Record = { + moradia: '🏠', + alimentação: '🍽️', + transporte: '🚗', + saúde: '💊', + educação: '📚', + lazer: '🎬', + serviços: '⚙️', + outros: '📦', +}; + +interface ExpenseRowProps { + name: string; + amount: number; + category: string; + subtitle?: string; + index?: number; + onPress?: () => void; + rightElement?: React.ReactNode; + type?: 'expense' | 'income'; +} + +export function ExpenseRow({ + name, + amount, + category, + subtitle, + index = 0, + onPress, + rightElement, + type = 'expense', +}: ExpenseRowProps) { + const emoji = CATEGORY_EMOJI[category] ?? '📦'; + const prefix = type === 'income' ? '+ ' : '- '; + const amountColor = type === 'income' ? Colors.positive : Colors.negative; + + const formattedAmount = amount.toLocaleString('pt-BR', { + style: 'currency', + currency: 'BRL', + minimumFractionDigits: 2, + }); + + return ( + + + + {emoji} + + + + + {name} + + {subtitle ? ( + + {subtitle} + + ) : null} + + + + + {prefix}{formattedAmount} + + {rightElement} + + + + ); +} + +interface RecurringExpenseRowProps { + expense: RecurringExpense; + index?: number; + onToggle: () => void; + onPress: () => void; +} + +export function RecurringExpenseRow({ + expense, + index = 0, + onToggle, + onPress, +}: RecurringExpenseRowProps) { + return ( + + + {expense.is_active ? 'Ativo' : 'Pausado'} + + + } + /> + ); +} + +interface OneTimeExpenseRowProps { + expense: OneTimeExpense; + index?: number; + onPress: () => void; +} + +export function OneTimeExpenseRow({ + expense, + index = 0, + onPress, +}: OneTimeExpenseRowProps) { + const date = new Date(expense.expense_date + 'T12:00:00'); + const formattedDate = date.toLocaleDateString('pt-BR', { + day: '2-digit', + month: 'short', + }); + + return ( + + ); +} + +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: Spacing.md, + gap: Spacing.md, + }, + iconBox: { + width: 44, + height: 44, + borderRadius: Radius.md, + backgroundColor: Colors.surfaceElevated, + alignItems: 'center', + justifyContent: 'center', + }, + emoji: { + fontSize: 22, + }, + info: { + flex: 1, + gap: 2, + }, + name: { + ...Typography.bodyLarge, + color: Colors.textPrimary, + }, + subtitle: { + ...Typography.caption, + color: Colors.textSecondary, + }, + right: { + alignItems: 'flex-end', + gap: Spacing.xs, + }, + amount: { + ...Typography.bodyLarge, + fontFamily: 'DMSans_600SemiBold', + }, + toggleBadge: { + paddingHorizontal: Spacing.sm, + paddingVertical: 2, + borderRadius: Radius.full, + }, + toggleActive: { + backgroundColor: `${Colors.positive}22`, + }, + toggleInactive: { + backgroundColor: `${Colors.textMuted}22`, + }, + toggleText: { + ...Typography.caption, + color: Colors.textSecondary, + }, +}); -- cgit v1.2.3