import React, { useCallback, useState } from "react"; import { View, ScrollView, Pressable, TextInput, ActivityIndicator, RefreshControl, } from "react-native"; import { useFocusEffect } from "expo-router"; import { useSirouRouter } from "@sirou/react-native"; import { AppRoutes } from "@/lib/routes"; import { api } from "@/lib/api"; import { Text } from "@/components/ui/text"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Plus, Search, FileText, Calendar, ChevronRight } from "@/lib/icons"; import { ScreenWrapper } from "@/components/ScreenWrapper"; import { StandardHeader } from "@/components/StandardHeader"; import { EmptyState } from "@/components/EmptyState"; import { useColorScheme } from "nativewind"; import { getPlaceholderColor } from "@/lib/colors"; const TYPE_OPTIONS = ["All", "VAT", "WITHHOLDING_TAX"]; const STATUS_OPTIONS = ["All", "DRAFT", "SUBMITTED", "PAID", "CANCELLED"]; const TYPE_STYLES: Record = { VAT: { bg: "bg-blue-500/10", text: "text-blue-600" }, WITHHOLDING_TAX: { bg: "bg-purple-500/10", text: "text-purple-600" }, }; const STATUS_STYLES: Record< string, { bg: string; text: string; border: string } > = { DRAFT: { bg: "bg-slate-500/15", text: "text-slate-700", border: "border-slate-200", }, SUBMITTED: { bg: "bg-amber-500/15", text: "text-amber-700", border: "border-amber-200", }, PAID: { bg: "bg-emerald-500/15", text: "text-emerald-700", border: "border-emerald-200", }, CANCELLED: { bg: "bg-red-500/15", text: "text-red-700", border: "border-red-200", }, }; export default function DeclarationsScreen() { const nav = useSirouRouter(); const { colorScheme } = useColorScheme(); const isDark = colorScheme === "dark"; const [declarations, setDeclarations] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [loadingMore, setLoadingMore] = useState(false); const [search, setSearch] = useState(""); const [typeFilter, setTypeFilter] = useState("All"); const [statusFilter, setStatusFilter] = useState("All"); const fetchPage = useCallback( async (pageNum: number, replace = false) => { try { pageNum === 1 && !replace ? setLoading(true) : setLoadingMore(true); const query: any = { page: pageNum, limit: 10 }; if (typeFilter !== "All") query.type = typeFilter; if (statusFilter !== "All") query.status = statusFilter; const response = await api.declarations.getAll({ query }); const data = response.data || response; setDeclarations((prev) => replace || pageNum === 1 ? data : [...prev, ...data], ); setHasMore(response.meta?.hasNextPage ?? false); setPage(pageNum); } catch (err) { console.error("[Declarations] Fetch error:", err); } finally { setLoading(false); setRefreshing(false); setLoadingMore(false); } }, [typeFilter, statusFilter], ); useFocusEffect( useCallback(() => { fetchPage(1, true); }, [fetchPage]), ); const onRefresh = () => { setRefreshing(true); fetchPage(1, true); }; const loadMore = () => { if (hasMore && !loadingMore && !loading) { fetchPage(page + 1); } }; const filtered = useCallback(() => { if (!search.trim()) return declarations; const q = search.toLowerCase(); return declarations.filter( (d) => d.title?.toLowerCase().includes(q) || d.declarationNumber?.toLowerCase().includes(q) || d.tin?.toLowerCase().includes(q), ); }, [declarations, search]); const typeStyle = (t: string) => TYPE_STYLES[t] || TYPE_STYLES.VAT; const statusStyle = (s: string) => STATUS_STYLES[s] || STATUS_STYLES.DRAFT; if (loading && declarations.length === 0) { return ( ); } return ( } contentContainerStyle={{ paddingBottom: 150 }} onScroll={({ nativeEvent }) => { const close = nativeEvent.layoutMeasurement.height + nativeEvent.contentOffset.y >= nativeEvent.contentSize.height - 20; if (close) loadMore(); }} scrollEventThrottle={400} > {TYPE_OPTIONS.map((t) => ( { setTypeFilter(t); setPage(1); }} className={`rounded-[4px] px-4 py-1.5 ${ typeFilter === t ? "bg-primary" : "bg-card border border-border" }`} > {t === "All" ? "All" : t.replace("_", " ")} ))} {filtered().length > 0 ? ( {filtered().map((d: any) => ( nav.go("declarations/[id]", { id: d.id })} > {d.type?.replace("_", " ") || "VAT"} {d.title || `Declaration #${d.declarationNumber}`} {d.declarationNumber ? `#${d.declarationNumber}` : ""} {d.period ? ` · ${d.period}` : ""} {d.daysUntilDue != null ? ` · ${d.isOverdue ? `${Math.abs(d.daysUntilDue)}d overdue` : `${d.daysUntilDue}d left`}` : ""} {d.status || "DRAFT"} ))} {hasMore && ( {loadingMore ? ( ) : ( Load More )} )} ) : ( )} ); }