import { useState } from 'react' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { usePOSStore } from '@/stores/pos.store' import { api } from '@/lib/api-client' import { posMutations, posKeys, type Transaction } from '@/api/pos' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Separator } from '@/components/ui/separator' import { CheckCircle, Printer, Mail } from 'lucide-react' import { toast } from 'sonner' import { POSReceipt, downloadReceiptPDF, printReceipt } from './pos-receipt' interface POSPaymentDialogProps { open: boolean onOpenChange: (open: boolean) => void paymentMethod: string transaction: Transaction onComplete: () => void } export function POSPaymentDialog({ open, onOpenChange, paymentMethod, transaction, onComplete }: POSPaymentDialogProps) { const queryClient = useQueryClient() const { currentTransactionId } = usePOSStore() const total = parseFloat(transaction.total) const [amountTendered, setAmountTendered] = useState('') const [checkNumber, setCheckNumber] = useState('') const [completed, setCompleted] = useState(false) const [result, setResult] = useState(null) const completeMutation = useMutation({ mutationFn: () => { const data: { paymentMethod: string; amountTendered?: number; checkNumber?: string } = { paymentMethod, } if (paymentMethod === 'cash') { data.amountTendered = parseFloat(amountTendered) || 0 } if (paymentMethod === 'check') { data.checkNumber = checkNumber || undefined } return posMutations.complete(currentTransactionId!, data) }, onSuccess: (txn) => { queryClient.invalidateQueries({ queryKey: posKeys.transaction(currentTransactionId!) }) queryClient.invalidateQueries({ queryKey: ['pos', 'products'] }) setResult(txn) setCompleted(true) }, onError: (err) => toast.error(err.message), }) const tenderedAmount = parseFloat(amountTendered) || 0 const changeDue = paymentMethod === 'cash' ? Math.max(0, tenderedAmount - total) : 0 const canComplete = paymentMethod === 'cash' ? tenderedAmount >= total : true function handleDone() { onComplete() onOpenChange(false) } const QUICK_AMOUNTS = [1, 5, 10, 20, 50, 100] // Fetch receipt config interface AppConfigEntry { key: string; value: string | null } const { data: configData } = useQuery({ queryKey: ['config'], queryFn: () => api.get<{ data: AppConfigEntry[] }>('/v1/config'), enabled: !!result?.id, }) const receiptConfig = { header: configData?.data?.find((c) => c.key === 'receipt_header')?.value || undefined, footer: configData?.data?.find((c) => c.key === 'receipt_footer')?.value || undefined, returnPolicy: configData?.data?.find((c) => c.key === 'receipt_return_policy')?.value || undefined, social: configData?.data?.find((c) => c.key === 'receipt_social')?.value || undefined, } // Fetch full receipt data after completion const { data: receiptData } = useQuery({ queryKey: ['pos', 'receipt', result?.id], queryFn: () => api.get<{ transaction: Transaction & { lineItems: { description: string; qty: number; unitPrice: string; taxAmount: string; lineTotal: string; discountAmount: string }[] } company: { name: string; phone: string | null; email: string | null; address: { street?: string; city?: string; state?: string; zip?: string } | null } location: { name: string; phone: string | null; email: string | null; address: { street?: string; city?: string; state?: string; zip?: string } | null } }>(`/v1/transactions/${result!.id}/receipt`), enabled: !!result?.id, }) const [showReceipt, setShowReceipt] = useState(false) if (completed && result) { const changeGiven = parseFloat(result.changeGiven ?? '0') // Receipt print view if (showReceipt && receiptData) { return ( { setShowReceipt(false); handleDone() }}>
) } return ( handleDone()}>

Sale Complete

{result.transactionNumber}

Total ${parseFloat(result.total).toFixed(2)}
{paymentMethod === 'cash' && changeGiven > 0 && (
Change Due ${changeGiven.toFixed(2)}
)}
) } return ( {paymentMethod === 'cash' ? 'Cash Payment' : paymentMethod === 'check' ? 'Check Payment' : 'Card Payment'}
Total Due ${total.toFixed(2)}
{paymentMethod === 'cash' && ( <>
setAmountTendered(e.target.value)} placeholder="0.00" className="h-12 text-xl text-right font-mono" autoFocus />
{QUICK_AMOUNTS.map((amt) => ( ))}
{tenderedAmount >= total && (
Change ${changeDue.toFixed(2)}
)} )} {paymentMethod === 'check' && (
setCheckNumber(e.target.value)} placeholder="Check #" className="h-11" autoFocus />
)} {paymentMethod === 'card_present' && (

Process card payment on terminal, then confirm below.

)}
) }