feat: add template checkpoint edit dialog and vendor management components
- Implemented TemplateCheckpointEditDialog for creating and editing inspection checkpoints. - Added VendorActions component for managing vendor actions including edit, activate/deactivate, and delete. - Created VendorContext for managing vendor state across components. - Developed VendorGeneralInfo component to display detailed vendor information. - Introduced AedSymbol and Money components for consistent currency representation. - Added PromptDialog for user input prompts throughout the application. - Implemented RelationLink component for unified related-data display in CRUD tables. - Created InspectionTemplatesClient for API interactions related to inspection templates.
This commit is contained in:
@@ -20,8 +20,9 @@ import {
|
||||
} from "@/shared/components/ui/card"
|
||||
import { Badge } from "@/shared/components/ui/badge"
|
||||
import { cn } from "@/shared/lib/utils"
|
||||
import { formatDate, formatCurrency, formatEnum, formatTaxLabel } from "@/shared/utils/formatters"
|
||||
import { formatDate, formatEnum, formatTaxLabel } from "@/shared/utils/formatters"
|
||||
import { useExpense } from "./expense-context"
|
||||
import { Money } from "@/shared/components/money"
|
||||
|
||||
function InfoItem({
|
||||
icon: Icon,
|
||||
@@ -30,7 +31,7 @@ function InfoItem({
|
||||
}: {
|
||||
icon: React.ComponentType<{ className?: string }>
|
||||
label: string
|
||||
value?: string | null
|
||||
value?: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-start gap-3">
|
||||
@@ -92,10 +93,10 @@ export function ExpenseGeneralInfo() {
|
||||
<Card className="flex flex-col gap-1 p-4">
|
||||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Total</span>
|
||||
<span className="mt-1 text-lg font-semibold">
|
||||
{formatCurrency(expense.total ?? 0)}
|
||||
{<Money value={expense.total ?? 0} />}
|
||||
</span>
|
||||
{expense.sub_total != null && expense.sub_total !== expense.total && (
|
||||
<span className="text-xs text-muted-foreground">Subtotal: {formatCurrency(expense.sub_total)}</span>
|
||||
<span className="text-xs text-muted-foreground">Subtotal: {<Money value={expense.sub_total} />}</span>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
@@ -103,7 +104,7 @@ export function ExpenseGeneralInfo() {
|
||||
<Card className="flex flex-col gap-1 p-4">
|
||||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Paid</span>
|
||||
<span className="mt-1 text-lg font-semibold text-green-600 dark:text-green-400">
|
||||
{formatCurrency(paymentsM ?? 0)}
|
||||
{<Money value={paymentsM ?? 0} />}
|
||||
</span>
|
||||
</Card>
|
||||
|
||||
@@ -111,7 +112,7 @@ export function ExpenseGeneralInfo() {
|
||||
<Card className={cn("flex flex-col gap-1 p-4", (balanceDue ?? 0) > 0 && "border-destructive/50 bg-destructive/5")}>
|
||||
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Balance Due</span>
|
||||
<span className={cn("mt-1 text-lg font-semibold", (balanceDue ?? 0) > 0 ? "text-destructive" : "text-green-600 dark:text-green-400")}>
|
||||
{formatCurrency(balanceDue ?? 0)}
|
||||
{<Money value={balanceDue ?? 0} />}
|
||||
</span>
|
||||
</Card>
|
||||
</div>
|
||||
@@ -139,10 +140,10 @@ export function ExpenseGeneralInfo() {
|
||||
<InfoItem icon={Percent} label="Discount Type" value={formatEnum(expense.discount)} />
|
||||
)}
|
||||
{expense.discount_amount_major != null && expense.discount_amount_major > 0 && (
|
||||
<InfoItem icon={Percent} label="Discount" value={formatCurrency(expense.discount_amount_major)} />
|
||||
<InfoItem icon={Percent} label="Discount" value={<Money value={expense.discount_amount_major} />} />
|
||||
)}
|
||||
{expense.tax_amount != null && expense.tax_amount > 0 && (
|
||||
<InfoItem icon={Percent} label={taxLabel} value={formatCurrency(expense.tax_amount)} />
|
||||
<InfoItem icon={Percent} label={taxLabel} value={<Money value={expense.tax_amount} />} />
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/shared/components/ui/table"
|
||||
import { formatCurrency } from "@/shared/utils/formatters"
|
||||
import { Money } from "@/shared/components/money"
|
||||
|
||||
type ExpenseItem = {
|
||||
id?: number
|
||||
@@ -89,8 +89,8 @@ export function ExpenseItemsSection({
|
||||
{item.description || "—"}
|
||||
</TableCell>
|
||||
<TableCell className="text-right text-sm">{qty.toLocaleString()}</TableCell>
|
||||
<TableCell className="text-right text-sm">{formatCurrency(rate)}</TableCell>
|
||||
<TableCell className="text-right font-semibold">{formatCurrency(amount)}</TableCell>
|
||||
<TableCell className="text-right text-sm">{<Money value={rate} />}</TableCell>
|
||||
<TableCell className="text-right font-semibold">{<Money value={amount} />}</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
})}
|
||||
@@ -104,25 +104,25 @@ export function ExpenseItemsSection({
|
||||
{subTotal != null && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-muted-foreground">Subtotal</span>
|
||||
<span className="font-medium">{formatCurrency(subTotal)}</span>
|
||||
<span className="font-medium">{<Money value={subTotal} />}</span>
|
||||
</div>
|
||||
)}
|
||||
{discountAmount != null && discountAmount > 0 && discountType !== "no" && (
|
||||
<div className="flex justify-between text-destructive">
|
||||
<span>Discount</span>
|
||||
<span>− {formatCurrency(discountAmount)}</span>
|
||||
<span>− {<Money value={discountAmount} />}</span>
|
||||
</div>
|
||||
)}
|
||||
{taxAmount != null && taxAmount > 0 && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-muted-foreground">{taxLabel || "Tax"}</span>
|
||||
<span className="font-medium">{formatCurrency(taxAmount)}</span>
|
||||
<span className="font-medium">{<Money value={taxAmount} />}</span>
|
||||
</div>
|
||||
)}
|
||||
{total != null && (
|
||||
<div className="flex justify-between border-t pt-2 text-base font-semibold">
|
||||
<span>Total</span>
|
||||
<span>{formatCurrency(total)}</span>
|
||||
<span>{<Money value={total} />}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user