import React, { useState, useEffect } from "react"; import { View, ScrollView, Pressable, TextInput, StyleSheet, ActivityIndicator, } from "react-native"; import { Text } from "@/components/ui/text"; import { Button } from "@/components/ui/button"; import { ArrowLeft, ArrowRight, Trash2, Send, Plus, Calendar, ChevronDown, CalendarSearch, } from "@/lib/icons"; import { ScreenWrapper } from "@/components/ScreenWrapper"; import { useSirouRouter } from "@sirou/react-native"; import { AppRoutes } from "@/lib/routes"; import { Stack, useLocalSearchParams } from "expo-router"; import { useRouter } from "expo-router"; import { ShadowWrapper } from "@/components/ShadowWrapper"; import { api } from "@/lib/api"; import { toast } from "@/lib/toast-store"; import { PickerModal, SelectOption } from "@/components/PickerModal"; import { CalendarGrid } from "@/components/CalendarGrid"; import { StandardHeader } from "@/components/StandardHeader"; import { getPlaceholderColor } from "@/lib/colors"; type Item = { id: number; description: string; qty: string; price: string }; const S = StyleSheet.create({ input: { height: 44, paddingHorizontal: 12, fontSize: 12, fontWeight: "500", borderRadius: 6, borderWidth: 1, }, inputCenter: { height: 44, paddingHorizontal: 12, fontSize: 14, fontWeight: "500", borderRadius: 6, borderWidth: 1, textAlign: "center", }, }); function useInputColors() { const { colorScheme } = useColorScheme(); // Fix usage const dark = colorScheme === "dark"; return { bg: dark ? "rgba(30,30,30,0.8)" : "rgba(241,245,249,0.2)", border: dark ? "rgba(255,255,255,0.08)" : "rgba(203,213,225,0.6)", text: dark ? "#f1f5f9" : "#0f172a", placeholder: "rgba(100,116,139,0.45)", }; } function Field({ label, value, onChangeText, placeholder, numeric = false, center = false, flex, }: { label: string; value: string; onChangeText: (v: string) => void; placeholder: string; numeric?: boolean; center?: boolean; flex?: number; }) { const c = useInputColors(); const isDark = colorScheme.get() === "dark"; return ( {label} ); } export default function EditProformaScreen() { const nav = useSirouRouter(); const router = useRouter(); const { id } = useLocalSearchParams(); const isEdit = !!id; const [loading, setLoading] = useState(isEdit); const [submitting, setSubmitting] = useState(false); // Form fields const [proformaNumber, setProformaNumber] = useState(""); const [customerName, setCustomerName] = useState(""); const [customerEmail, setCustomerEmail] = useState(""); const [customerPhone, setCustomerPhone] = useState(""); const [currency, setCurrency] = useState("USD"); const [description, setDescription] = useState(""); const [notes, setNotes] = useState(""); const [taxAmount, setTaxAmount] = useState(""); const [discountAmount, setDiscountAmount] = useState(""); // Dates const [issueDate, setIssueDate] = useState(new Date()); const [dueDate, setDueDate] = useState(new Date()); // Items const [items, setItems] = useState([ { id: 1, description: "", qty: "", price: "" }, ]); // Modals const [currencyModal, setCurrencyModal] = useState(false); const [issueModal, setIssueModal] = useState(false); const [dueModal, setDueModal] = useState(false); // Fetch existing data for edit useEffect(() => { if (isEdit) { fetchProforma(); } }, [id]); const fetchProforma = async () => { try { setLoading(true); const data = await api.proforma.getById({ params: { id: id as string } }); // Prefill form setProformaNumber(data.proformaNumber || ""); setCustomerName(data.customerName || ""); setCustomerEmail(data.customerEmail || ""); setCustomerPhone(data.customerPhone || ""); setCurrency(data.currency || "USD"); setDescription(data.description || ""); setNotes(data.notes || ""); setTaxAmount(String(data.taxAmount?.value || data.taxAmount || "")); setDiscountAmount(String(data.discountAmount?.value || data.discountAmount || "")); setIssueDate(new Date(data.issueDate)); setDueDate(new Date(data.dueDate)); setItems( data.items?.map((item: any, idx: number) => ({ id: idx + 1, description: item.description || "", qty: String(item.quantity || ""), price: String(item.unitPrice?.value || item.unitPrice || ""), })) || [{ id: 1, description: "", qty: "", price: "" }] ); } catch (error) { toast.error("Error", "Failed to load proforma, using test data"); // For testing, set dummy data setProformaNumber(dummyData.proformaNumber); setCustomerName(dummyData.customerName); setCustomerEmail(dummyData.customerEmail); setCustomerPhone(dummyData.customerPhone); setCurrency(dummyData.currency); setDescription(dummyData.description); setNotes(dummyData.notes); setTaxAmount(String(dummyData.taxAmount?.value || dummyData.taxAmount || "")); setDiscountAmount(String(dummyData.discountAmount?.value || dummyData.discountAmount || "")); setIssueDate(new Date(dummyData.issueDate)); setDueDate(new Date(dummyData.dueDate)); setItems( dummyData.items?.map((item: any, idx: number) => ({ id: idx + 1, description: item.description || "", qty: String(item.quantity || ""), price: String(item.unitPrice?.value || item.unitPrice || ""), })) || [{ id: 1, description: "", qty: "", price: "" }] ); } finally { setLoading(false); } }; const addItem = () => { const newId = Math.max(...items.map((i) => i.id)) + 1; setItems([...items, { id: newId, description: "", qty: "", price: "" }]); }; const removeItem = (id: number) => { if (items.length > 1) { setItems(items.filter((i) => i.id !== id)); } }; const updateItem = (id: number, field: keyof Item, value: string) => { setItems( items.map((i) => (i.id === id ? { ...i, [field]: value } : i)) ); }; const calculateSubtotal = () => { return items.reduce((acc, item) => { const qty = parseFloat(item.qty) || 0; const price = parseFloat(item.price) || 0; return acc + qty * price; }, 0); }; const calculateTotal = () => { const subtotal = calculateSubtotal(); const tax = parseFloat(taxAmount) || 0; const discount = parseFloat(discountAmount) || 0; return subtotal + tax - discount; }; const handleSubmit = async () => { // Validation if (!proformaNumber || !customerName) { toast.error("Error", "Please fill required fields"); return; } setSubmitting(true); try { const payload = { proformaNumber, customerName, customerEmail, customerPhone, amount: calculateTotal(), currency, issueDate: issueDate.toISOString(), dueDate: dueDate.toISOString(), description, notes, taxAmount: parseFloat(taxAmount) || 0, discountAmount: parseFloat(discountAmount) || 0, items: items.map((item) => ({ description: item.description, quantity: parseFloat(item.qty) || 0, unitPrice: parseFloat(item.price) || 0, total: (parseFloat(item.qty) || 0) * (parseFloat(item.price) || 0), })), }; if (isEdit) { await api.proforma.update({ params: { id: id as string }, body: payload, }); toast.success("Success", "Proforma updated successfully"); } else { await api.proforma.create({ body: payload }); toast.success("Success", "Proforma created successfully"); } nav.back(); } catch (error: any) { toast.error("Error", error.message || "Failed to save proforma"); } finally { setSubmitting(false); } }; if (loading) { return ( ); } const currencies = ["USD", "EUR", "GBP", "CAD"]; return ( {/* Proforma Details */} Proforma Details {/* Customer Details */} Customer Details {/* Dates */} Dates setIssueModal(true)} > Issue Date: {issueDate.toLocaleDateString()} setDueModal(true)} > Due Date: {dueDate.toLocaleDateString()} {/* Items */} Items {items.map((item) => ( updateItem(item.id, "description", v)} placeholder="Item description" /> updateItem(item.id, "qty", v)} placeholder="0" numeric center /> updateItem(item.id, "price", v)} placeholder="0.00" numeric center /> removeItem(item.id)} > ))} {/* Totals */} Totals Subtotal {currency} {calculateSubtotal().toFixed(2)} Total {currency} {calculateTotal().toFixed(2)} {/* Currency */} Currency setCurrencyModal(true)} > {currency} {/* Bottom Action */} {/* Modals */} setCurrencyModal(false)} > {currencies.map((curr) => ( { setCurrency(v); setCurrencyModal(false); }} /> ))} // @ts-ignore { setIssueDate(new Date(dateStr)); setIssueModal(false); }} onClose={() => setIssueModal(false)} /> // @ts-ignore { setDueDate(new Date(dateStr)); setDueModal(false); }} onClose={() => setDueModal(false)} /> ); }