import { Select } from "@/components/Select"; import { BORDER_RADIUS, COLORS, SPACING } from "@/constants/theme"; import { useAuth } from "@/contexts/AuthContext"; import { RideDB, obterCorridas } from "@/services/db"; import { Asset } from "expo-asset"; import { File } from "expo-file-system"; import * as Print from "expo-print"; import { router, useFocusEffect } from "expo-router"; import * as Sharing from "expo-sharing"; import React, { useCallback, useState } from "react"; import { ActivityIndicator, Alert, ScrollView, StyleSheet, Text, TouchableOpacity, View, } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; // ── Month helpers ───────────────────────────────────────────────────────────── function currentYearMonth() { const now = new Date(); return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`; } function getMonthOptions() { const now = new Date(); return Array.from({ length: 12 }, (_, i) => { const d = new Date(now.getFullYear(), now.getMonth() - i, 1); const value = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; const label = d.toLocaleDateString("pt-BR", { month: "long", year: "numeric" }); return { value, label: label.charAt(0).toUpperCase() + label.slice(1) }; }); } function parseRideDate(dateStr: string): Date | null { if (!dateStr) return null; const br = dateStr.match(/^(\d{2})\/(\d{2})\/(\d{4})/); if (br) return new Date(`${br[3]}-${br[2]}-${br[1]}T00:00:00`); const iso = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})/); if (iso) return new Date(`${iso[1]}-${iso[2]}-${iso[3]}T00:00:00`); return null; } function filterByMonth(rides: RideDB[], yearMonth: string): RideDB[] { const [year, month] = yearMonth.split("-").map(Number); return rides.filter((r) => { const d = parseRideDate(r.ride_date) ?? parseRideDate(r.createdAt); return d ? d.getFullYear() === year && d.getMonth() + 1 === month : false; }); } // ── Report calculation ──────────────────────────────────────────────────────── type CompanyReport = { name: string; rides: number; km: number; total: number }; function buildCompanyReports(rides: RideDB[]): CompanyReport[] { const map = new Map(); for (const r of rides) { const prev = map.get(r.company) ?? { name: r.company, rides: 0, km: 0, total: 0 }; map.set(r.company, { ...prev, rides: prev.rides + 1, km: prev.km + r.km, total: prev.total + r.total, }); } return Array.from(map.values()).sort((a, b) => b.total - a.total); } // ── PDF generation ──────────────────────────────────────────────────────────── async function getLogoBase64(): Promise { try { const asset = Asset.fromModule(require("@/assets/toptran.png")); await asset.downloadAsync(); if (asset.localUri) { const file = new File(asset.localUri); const base64 = await file.base64(); return `data:image/png;base64,${base64}`; } } catch { // logo optional — PDF will show text fallback } return ""; } function buildPdfHtml( monthLabel: string, userName: string, companies: CompanyReport[], totalRides: number, totalKm: number, totalEarnings: number, logoSrc: string, ): string { const rows = companies .map( (c) => ` ${c.name} ${c.rides} ${c.km.toFixed(1)} km R$ ${c.total.toFixed(2)} `, ) .join(""); const generated = new Date().toLocaleDateString("pt-BR") + " às " + new Date().toLocaleTimeString("pt-BR"); return `
${logoSrc ? `` : `TopTran`}

Relatório de Corridas

${monthLabel}

Motorista: ${userName}

${totalRides}
Corridas
${totalKm.toFixed(1)}
Km Rodados
R$ ${totalEarnings.toFixed(2)}
Total Ganho

Detalhamento por Empresa

${rows}
Empresa Corridas Km Total
TOTAL DO PERÍODO ${totalRides} ${totalKm.toFixed(1)} km R$ ${totalEarnings.toFixed(2)}
`; } // ── Screen ──────────────────────────────────────────────────────────────────── const MONTH_OPTIONS = getMonthOptions(); export default function RelatorioPage() { const { user } = useAuth(); const [selectedMonth, setSelectedMonth] = useState(currentYearMonth()); const [allRides, setAllRides] = useState([]); const [exporting, setExporting] = useState(false); useFocusEffect( useCallback(() => { if (!user?.id) return; obterCorridas(user.id).then(setAllRides).catch(console.error); }, [user?.id]), ); const rides = filterByMonth(allRides, selectedMonth); const companies = buildCompanyReports(rides); const totalKm = rides.reduce((s, r) => s + r.km, 0); const totalEarnings = rides.reduce((s, r) => s + r.total, 0); const monthLabel = MONTH_OPTIONS.find((o) => o.value === selectedMonth)?.label ?? selectedMonth; const handleExport = async () => { if (rides.length === 0) { Alert.alert("Sem dados", "Não há corridas registradas em " + monthLabel + "."); return; } try { setExporting(true); const logoSrc = await getLogoBase64(); const html = buildPdfHtml( monthLabel, user?.name ?? "Motorista", companies, rides.length, totalKm, totalEarnings, logoSrc, ); const { uri } = await Print.printToFileAsync({ html }); await Sharing.shareAsync(uri, { mimeType: "application/pdf", dialogTitle: `Relatório ${monthLabel}`, }); } catch (e: any) { Alert.alert("Erro", e?.message ?? "Não foi possível gerar o PDF."); } finally { setExporting(false); } }; return ( router.back()} style={styles.backButton} activeOpacity={0.7}> Voltar Relatório Análise de ganhos por período {/* Filtro de mês */} Período