154 lines
7.9 KiB
TypeScript
154 lines
7.9 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { View, Text, ScrollView, TouchableOpacity, Linking } from 'react-native';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { useRouter, useLocalSearchParams } from 'expo-router';
|
|
import { StatusBar } from 'expo-status-bar';
|
|
import { ChevronLeft, Download, CheckCircle2, XCircle, Calendar, CreditCard } from 'lucide-react-native';
|
|
import api from '@/utils/api';
|
|
import { useAlert } from '@/components/AlertComponent';
|
|
import LoadingScreen from '@/components/LoadingScreen';
|
|
import { InvoiceInfo, InvoiceAccounting } from '@/types/types';
|
|
|
|
export default function InvoiceDetailScreen() {
|
|
const router = useRouter();
|
|
const { id } = useLocalSearchParams();
|
|
const alert = useAlert();
|
|
|
|
const [invoiceInfo, setInvoiceInfo] = useState<InvoiceInfo | null>(null);
|
|
const [partite, setPartite] = useState<InvoiceAccounting[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
const fetchInvoiceInfo = async () => {
|
|
try {
|
|
const response = await api.get(`/invoice-supplier/get-info?id=${id}`);
|
|
if (response.data?.success) {
|
|
setInvoiceInfo(response.data.result.info);
|
|
|
|
// Map backend keys to our frontend types
|
|
const mappedPartite: InvoiceAccounting[] = response.data.result.partite.map((p: any) => ({
|
|
expiry: p.scadenza,
|
|
tpa_description: p.tpa_descrizione,
|
|
amount: p.importo_dovuto,
|
|
isPaid: p.pagata
|
|
}));
|
|
setPartite(mappedPartite);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching invoice info:', error);
|
|
alert.showAlert('error', 'Errore', 'Impossibile recuperare il dettaglio della fattura.');
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (id) {
|
|
fetchInvoiceInfo();
|
|
}
|
|
}, [id]);
|
|
|
|
const handleDownload = () => {
|
|
if (invoiceInfo?.link) {
|
|
Linking.openURL(invoiceInfo.link);
|
|
} else {
|
|
alert.showAlert('error', 'Nessun Documento', 'Non è presente un documento allegato per questa fattura.');
|
|
}
|
|
};
|
|
|
|
if (isLoading || !invoiceInfo) {
|
|
return <LoadingScreen />;
|
|
}
|
|
|
|
return (
|
|
<View className="flex-1 bg-gray-50">
|
|
<StatusBar style="dark" />
|
|
{/* Header */}
|
|
<View className="bg-white px-6 pb-6 shadow-sm border-b border-gray-100">
|
|
<SafeAreaView edges={['top']} className="pt-5 flex-row items-center justify-between">
|
|
<TouchableOpacity onPress={() => router.back()} className="p-2 bg-gray-50 rounded-full active:bg-gray-100">
|
|
<ChevronLeft size={24} color="#082963" />
|
|
</TouchableOpacity>
|
|
<Text className="text-xl font-bold text-gray-800 text-center flex-1">Dettaglio Fattura</Text>
|
|
<TouchableOpacity onPress={handleDownload} className="p-2.5 bg-blue-50 rounded-full active:bg-blue-100 shadow-sm">
|
|
<Download size={22} color="#1071C2" />
|
|
</TouchableOpacity>
|
|
</SafeAreaView>
|
|
</View>
|
|
|
|
<ScrollView contentContainerStyle={{ padding: 20, paddingBottom: 100, gap: 16 }} showsVerticalScrollIndicator={false}>
|
|
{/* General Info Card */}
|
|
<View className="bg-white p-6 rounded-3xl shadow-sm border border-gray-100">
|
|
<Text className="text-sm font-bold text-gray-400 uppercase tracking-wider mb-4">Informazioni</Text>
|
|
|
|
<View className="mb-4">
|
|
<Text className="text-xs font-bold text-gray-400 uppercase mb-1">Numero Documento</Text>
|
|
<Text className="text-base font-bold text-gray-800">{invoiceInfo.documentNumber}</Text>
|
|
</View>
|
|
|
|
<View className="mb-4">
|
|
<Text className="text-xs font-bold text-gray-400 uppercase mb-1">Fornitore</Text>
|
|
<Text className="text-xl font-bold text-[#082963]">{invoiceInfo.supplier}</Text>
|
|
</View>
|
|
|
|
<View className="mb-4">
|
|
<Text className="text-xs font-bold text-gray-400 uppercase mb-1">Cantiere</Text>
|
|
<Text className="text-base font-bold text-gray-800">{invoiceInfo.placeName}</Text>
|
|
</View>
|
|
|
|
<View className="flex-row justify-between bg-gray-50 p-4 rounded-2xl mb-2">
|
|
<View>
|
|
<Text className="text-xs font-bold text-gray-400 uppercase mb-1">Data Documento</Text>
|
|
<Text className="font-bold text-gray-800">{invoiceInfo.date}</Text>
|
|
</View>
|
|
<View className="items-end">
|
|
<Text className="text-xs font-bold text-gray-400 uppercase mb-1">Importo</Text>
|
|
<Text className="font-bold text-[#1071C2]">{invoiceInfo.totalAmount}</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Expiries */}
|
|
{partite && partite.length > 0 && (
|
|
<View className="bg-white p-6 rounded-3xl shadow-sm border border-gray-100">
|
|
<Text className="text-sm font-bold text-gray-400 uppercase tracking-wider mb-4">Scadenze</Text>
|
|
|
|
<View className="gap-4">
|
|
{partite.map((item, idx) => (
|
|
<View key={idx} className={`border border-gray-100 rounded-2xl p-4 ${item.isPaid ? 'bg-green-50/30' : 'bg-red-50/30'}`}>
|
|
<View className="flex-row justify-between items-center mb-3">
|
|
<View className="flex-row items-center gap-2">
|
|
<Calendar size={16} color="#082963" />
|
|
<Text className="font-bold text-[#082963]">{item.expiry}</Text>
|
|
</View>
|
|
<View className={`px-2 py-1 rounded-md flex-row items-center gap-1 ${item.isPaid ? 'bg-green-100' : 'bg-red-100'}`}>
|
|
{item.isPaid ? <CheckCircle2 size={12} color="#109D59" /> : <XCircle size={12} color="#DC4437" />}
|
|
<Text className={`text-[10px] font-bold uppercase ${item.isPaid ? 'text-green-700' : 'text-red-700'}`}>
|
|
{item.isPaid ? 'Pagata' : 'Da Pagare'}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
|
|
<View className="flex-row justify-between items-center pt-3 border-t border-gray-100 gap-2">
|
|
<View className="flex-row items-center gap-2 flex-1 mr-2">
|
|
<View className="mt-0.5">
|
|
<CreditCard size={14} color="#8F9BB3" />
|
|
</View>
|
|
<Text className="text-xs uppercase text-gray-500 font-medium shrink flex-wrap">{item.tpa_description}</Text>
|
|
</View>
|
|
<Text className={`font-bold text-base whitespace-nowrap ${item.isPaid ? 'text-[#109D59]' : 'text-[#DC4437]'}`}>
|
|
{item.amount}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
))}
|
|
</View>
|
|
</View>
|
|
)}
|
|
|
|
|
|
|
|
</ScrollView>
|
|
</View>
|
|
);
|
|
}
|