"use client"; import { useState, useEffect } from "react"; import TableWrapper from "@/components/table-wrapper"; import Header from "@/components/header"; import TotalDisplay from "@/components/total-display"; import { toast } from "sonner"; import { type Budgetable, areRowsEqual } from "@/lib/utils"; export default function App() { const [data, setData] = useState(() => []); const [isEditing, setIsEditing] = useState(false); const [loading, setLoading] = useState(false); const [newRow, setNewRow] = useState({ id: "", title: "", price: 0, link: "", note: "", status: "Unpaid", }); const [recentlyUpdatedRowId, setRecentlyUpdatedRowId] = useState< string | null >(null); useEffect(() => { async function fetchData() { setLoading(true); try { const res = await fetch("/pocketbase"); if (!res.ok) throw new Error("Failed to fetch data"); const records: Budgetable[] = await res.json(); setData(records); } catch (err) { toast.error("Error fetching data. Please try again later."); console.error("Error fetching data:", err); } finally { setLoading(false); } } fetchData(); }, []); const handleSave = async ( updatedRow: Budgetable, originalRow: Budgetable, ) => { if (areRowsEqual(updatedRow, originalRow)) { return; } try { const res = await fetch(`/pocketbase/${updatedRow.id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(updatedRow), }); if (!res.ok) throw new Error("Failed to update row"); const updatedData = await res.json(); setData((prev) => prev.map((row) => (row.id === updatedRow.id ? updatedData : row)), ); setRecentlyUpdatedRowId(updatedRow.id); setTimeout(() => setRecentlyUpdatedRowId(null), 500); toast.success("Row updated successfully!"); } catch (err) { toast.error("Error updating row. Please try again."); console.error("Error updating row:", err); } }; const handleAddRow = async () => { if (!newRow.title || newRow.price <= 0) { toast("Title and price are required."); return; } try { const res = await fetch("/pocketbase", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newRow), }); if (!res.ok) throw new Error("Failed to add row"); const record: Budgetable = await res.json(); setData((prev) => [...prev, record]); setNewRow({ id: "", title: "", price: 0, link: "", note: "", status: "Unpaid", }); toast.success("Row added successfully!"); } catch (err) { toast.error("Error adding row. Please try again."); console.error("Error adding row:", err); } }; const handleDeleteRow = async (id: string) => { try { const res = await fetch(`/pocketbase/${id}`, { method: "DELETE" }); if (!res.ok) throw new Error("Failed to delete row"); setData((prev) => prev.filter((row) => row.id !== id)); toast.success("Row deleted successfully!"); } catch (err) { toast.error("Error deleting row. Please try again."); console.error("Error deleting row:", err); } }; const toggleStatus = async (row: Budgetable) => { const updatedStatus: "Paid" | "Unpaid" = row.status === "Paid" ? "Unpaid" : "Paid"; const updatedRow: Budgetable = { ...row, status: updatedStatus }; await handleSave(updatedRow, row); setData((prev) => prev.map((item) => (item.id === row.id ? updatedRow : item)), ); }; const total = data.reduce( (sum, item) => sum + (item.status === "Unpaid" ? item.price : 0), 0, ); return (
{loading}
); }