import { destroy, index, store, } from '@/actions/App/Http/Controllers/AccountBalanceController'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { AmountInput } from '@/components/ui/amount-input'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import type { Account, AccountBalance } from '@/types/account'; import { Pencil, Trash2 } from 'lucide-react'; import { useCallback, useEffect, useState } from 'react'; interface BalancesModalProps { account: Account; open: boolean; onOpenChange: (open: boolean) => void; onBalanceChange?: () => void; } interface PaginatedResponse { data: AccountBalance[]; current_page: number; last_page: number; per_page: number; total: number; } export function BalancesModal({ account, open, onOpenChange, onBalanceChange, }: BalancesModalProps) { const [balances, setBalances] = useState([]); const [isLoading, setIsLoading] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [lastPage, setLastPage] = useState(1); const [total, setTotal] = useState(0); const [editingBalance, setEditingBalance] = useState( null, ); const [editDate, setEditDate] = useState(''); const [editAmount, setEditAmount] = useState(0); const [isEditSubmitting, setIsEditSubmitting] = useState(false); const [deletingBalance, setDeletingBalance] = useState(null); const [isDeleting, setIsDeleting] = useState(false); const formatter = new Intl.NumberFormat(undefined, { style: 'currency', currency: account.currency_code, }); const fetchBalances = useCallback( async (page: number) => { setIsLoading(true); try { const response = await fetch( index.url(account.id, { query: { page: String(page) } }), { headers: { Accept: 'application/json', }, }, ); if (!response.ok) { throw new Error('Failed to fetch balances'); } const data: PaginatedResponse = await response.json(); setBalances(data.data); setCurrentPage(data.current_page); setLastPage(data.last_page); setTotal(data.total); } catch (err) { console.error('Failed to fetch balances:', err); } finally { setIsLoading(false); } }, [account.id], ); useEffect(() => { if (open) { fetchBalances(1); } else { setBalances([]); setCurrentPage(1); setLastPage(1); setTotal(0); } }, [open, fetchBalances]); function handleEditClick(balance: AccountBalance) { setEditingBalance(balance); setEditDate(balance.balance_date.split('T')[0]); setEditAmount(balance.balance); } async function handleEditSubmit(e: React.FormEvent) { e.preventDefault(); if (!editingBalance) return; setIsEditSubmitting(true); try { const response = await fetch(store.url(account.id), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-XSRF-TOKEN': decodeURIComponent( document.cookie .split('; ') .find((row) => row.startsWith('XSRF-TOKEN=')) ?.split('=')[1] || '', ), Accept: 'application/json', }, body: JSON.stringify({ balance_date: editDate, balance: editAmount, }), }); if (!response.ok) { throw new Error('Failed to update balance'); } setEditingBalance(null); fetchBalances(currentPage); onBalanceChange?.(); } catch (err) { console.error('Failed to update balance:', err); } finally { setIsEditSubmitting(false); } } async function handleDelete() { if (!deletingBalance) return; setIsDeleting(true); try { const response = await fetch( destroy.url({ account: account.id, accountBalance: deletingBalance.id, }), { method: 'DELETE', headers: { 'X-XSRF-TOKEN': decodeURIComponent( document.cookie .split('; ') .find((row) => row.startsWith('XSRF-TOKEN=')) ?.split('=')[1] || '', ), Accept: 'application/json', }, }, ); if (!response.ok) { throw new Error('Failed to delete balance'); } setDeletingBalance(null); fetchBalances(currentPage); onBalanceChange?.(); } catch (err) { console.error('Failed to delete balance:', err); } finally { setIsDeleting(false); } } function formatDate(dateString: string): string { const date = new Date(dateString); return date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', }); } return ( <> Balance History View and manage balance records for this account.
Date Balance Actions {isLoading ? ( Loading... ) : balances.length === 0 ? ( No balance records found. ) : ( balances.map((balance) => ( {formatDate( balance.balance_date, )} {formatter.format( balance.balance / 100, )}
)) )}
{lastPage > 1 && (
{total} balance record{total !== 1 ? 's' : ''}
Page {currentPage} of {lastPage}
)}
!open && setEditingBalance(null)} > Edit Balance Update the balance record.
setEditDate(e.target.value)} required />
!open && setDeletingBalance(null)} > Delete balance Are you sure you want to delete this balance record? This action cannot be undone. Cancel {isDeleting ? 'Deleting...' : 'Delete'} ); }