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)}
/>
);
}