unzip frontend

This commit is contained in:
2025-08-16 14:41:12 +02:00
parent b60af66732
commit 598774bca6
87 changed files with 9676 additions and 0 deletions
@@ -0,0 +1,144 @@
"use client"
import type React from "react"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
interface PaymentFormProps {
clientName: string
outstandingAmount: number
open: boolean
onOpenChange: (open: boolean) => void
onSubmit: (payment: { amount: number; notes: string; date: string }) => void
}
export function PaymentForm({ clientName, outstandingAmount, open, onOpenChange, onSubmit }: PaymentFormProps) {
const [formData, setFormData] = useState({
amount: 0,
notes: "",
date: new Date().toISOString().split("T")[0],
})
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
onSubmit(formData)
onOpenChange(false)
setFormData({
amount: 0,
notes: "",
date: new Date().toISOString().split("T")[0],
})
}
const maxPayment = outstandingAmount
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle>Record Payment</DialogTitle>
<DialogDescription>Record a payment from {clientName}</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="p-4 bg-muted rounded-lg">
<p className="text-sm text-muted-foreground mb-1">Outstanding Amount</p>
<p className="text-2xl font-bold">${outstandingAmount.toFixed(2)}</p>
</div>
<div className="space-y-2">
<Label htmlFor="amount">Payment Amount ($) *</Label>
<Input
id="amount"
type="number"
step="0.01"
min="0.01"
max={maxPayment}
value={formData.amount}
onChange={(e) => setFormData({ ...formData, amount: Number.parseFloat(e.target.value) || 0 })}
placeholder="0.00"
required
/>
<div className="flex gap-2">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setFormData({ ...formData, amount: maxPayment / 4 })}
>
25%
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setFormData({ ...formData, amount: maxPayment / 2 })}
>
50%
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setFormData({ ...formData, amount: maxPayment })}
>
Full Amount
</Button>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="date">Payment Date *</Label>
<Input
id="date"
type="date"
value={formData.date}
onChange={(e) => setFormData({ ...formData, date: e.target.value })}
required
/>
</div>
<div className="space-y-2">
<Label htmlFor="notes">Notes</Label>
<Textarea
id="notes"
value={formData.notes}
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
placeholder="Payment method, reference number, etc."
rows={3}
/>
</div>
{formData.amount > 0 && (
<div className="p-3 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg">
<p className="text-sm text-green-800 dark:text-green-200">
New outstanding amount: <strong>${(outstandingAmount - formData.amount).toFixed(2)}</strong>
</p>
</div>
)}
<DialogFooter>
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
Cancel
</Button>
<Button type="submit" disabled={formData.amount <= 0 || formData.amount > maxPayment}>
Record Payment
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
)
}