import React, { useMemo } from 'react'; import { View, Text, StyleSheet, ScrollView, ActivityIndicator } from 'react-native'; import { COLORS, FONTS } from '@/constants/theme'; import { Header } from '@/components/Header'; import { useTransactions } from '@/hooks/useTransactions'; import { calculateBalance, formatRupiah } from '@/utils/helpers'; export default function ExploreScreen() { const { transactions, loading } = useTransactions(); const monthlyData = useMemo(() => { const grouped: Record = {}; transactions.forEach((t) => { const monthKey = t.date.substring(0, 7); if (!grouped[monthKey]) { grouped[monthKey] = { income: 0, expense: 0 }; } if (t.type === 'income') { grouped[monthKey].income += t.amount; } else { grouped[monthKey].expense += t.amount; } }); return Object.entries(grouped) .map(([month, data]) => ({ month, income: data.income, expense: data.expense, balance: data.income - data.expense, })) .sort((a, b) => b.month.localeCompare(a.month)) .slice(0, 6); }, [transactions]); const categoryData = useMemo(() => { const grouped: Record = {}; transactions .filter((t) => t.type === 'expense') .forEach((t) => { if (!grouped[t.category]) grouped[t.category] = 0; grouped[t.category] += t.amount; }); return Object.entries(grouped) .map(([category, amount]) => ({ category, amount })) .sort((a, b) => b.amount - a.amount) .slice(0, 5); }, [transactions]); const balance = calculateBalance(transactions); if (loading) { return ( ); } const formatMonth = (monthStr: string) => { const [year, month] = monthStr.split('-'); const date = new Date(parseInt(year), parseInt(month) - 1); return new Intl.DateTimeFormat('id-ID', { month: 'long', year: 'numeric' }).format(date); }; return (
Ringkasan Keseluruhan Total Pemasukan {formatRupiah(balance.income)} Total Pengeluaran {formatRupiah(balance.expense)} Saldo Akhir {formatRupiah(balance.total)} Ringkasan Bulanan {monthlyData.length === 0 ? ( Belum ada data ) : ( monthlyData.map((item) => ( {formatMonth(item.month)} +{formatRupiah(item.income)} -{formatRupiah(item.expense)} )) )} Kategori Pengeluaran {categoryData.length === 0 ? ( Belum ada data ) : ( categoryData.map((item) => ( {item.category} {formatRupiah(item.amount)} )) )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: COLORS.background }, content: { flex: 1, padding: 16 }, loading: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: COLORS.background }, card: { backgroundColor: COLORS.card, borderRadius: 12, padding: 16, marginBottom: 16, elevation: 3 }, sectionTitle: { fontSize: FONTS.regular, fontWeight: 'bold', color: COLORS.text, marginBottom: 16 }, summaryRow: { flexDirection: 'row', justifyContent: 'space-between' }, summaryItem: { flex: 1, alignItems: 'center' }, summaryLabel: { fontSize: FONTS.small, color: COLORS.textSecondary, marginBottom: 4 }, summaryAmount: { fontSize: FONTS.regular, fontWeight: '600' }, income: { color: COLORS.income }, expense: { color: COLORS.expense }, divider: { height: 1, backgroundColor: COLORS.border, marginVertical: 16 }, totalRow: { alignItems: 'center' }, totalLabel: { fontSize: FONTS.small, color: COLORS.textSecondary, marginBottom: 4 }, totalAmount: { fontSize: FONTS.large, fontWeight: 'bold', color: COLORS.text }, monthItem: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: COLORS.border }, monthLabel: { fontSize: FONTS.small, color: COLORS.text }, monthAmounts: { flexDirection: 'row', gap: 12 }, incomeSmall: { fontSize: FONTS.small, color: COLORS.income }, expenseSmall: { fontSize: FONTS.small, color: COLORS.expense }, categoryItem: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: COLORS.border }, categoryLabel: { fontSize: FONTS.small, color: COLORS.text }, categoryAmount: { fontSize: FONTS.small, fontWeight: '600', color: COLORS.expense }, emptyText: { fontSize: FONTS.small, color: COLORS.textSecondary, textAlign: 'center', paddingVertical: 16 }, });