import { ActionIcon, Box, Button, Card, Center, Container, Group, Loader, SimpleGrid, Stack, Tabs, Text, } from "@mantine/core"; import { ArrowLeft, ArrowRight, Banknote, Download, FileText, IdCard, LayoutGrid, Package, } from "lucide-react"; import { useMutation, useQuery } from "@tanstack/react-query"; import { useMemo } from "react"; import { useNavigate, useParams } from "react-router-dom"; import { BookingStatusBadge, CompanyStatusBadge, CompanyTypeBadge, PaymentStatusBadge, ProfileApprovalActions, ProfileChips, ProfileStatusBadge, ProfileTypeBadge, TableCard, formatBytes, formatDate, formatMoney, humanize, } from "@/components/customers"; import { KpiStrip, PageContainer, PageHeader } from "@/components/page"; import { api } from "@/services/api"; import type { CompanyProfile, CustomerBooking, CustomerDocument, CustomerPayment, } from "@/types/customer"; import { DataTable, type ColumnDef } from "@edr/ui-common"; function InfoField({ label, value }: { label: string; value?: string | null }) { return ( {label} {value && value.trim() ? value : "—"} ); } function tableStatus(query: { isLoading: boolean; isError: boolean }) { return query.isLoading ? "loading" : query.isError ? "error" : "success"; } export default function CustomerDetailPage() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { data: company, isLoading } = useQuery( api.customers.getById.queryOptions({ input: { id: id ?? "" }, enabled: Boolean(id), }), ); const approveMutation = useMutation( api.customers.setCompanyStatus.mutationOptions(), ); const bookingsQuery = useQuery( api.customers.bookings.queryOptions({ input: { id: id ?? "" }, enabled: Boolean(id), }), ); const documentsQuery = useQuery( api.customers.documents.queryOptions({ input: { id: id ?? "" }, enabled: Boolean(id), }), ); const paymentsQuery = useQuery( api.customers.payments.queryOptions({ input: { id: id ?? "" }, enabled: Boolean(id), }), ); const bookings = bookingsQuery.data ?? []; const documents = documentsQuery.data ?? []; const payments = paymentsQuery.data ?? []; const totalPaid = useMemo( () => payments .filter((p) => p.status === "success") .reduce((sum, p) => sum + p.amount, 0), [payments], ); const paidCurrency = payments[0]?.currency ?? "ETB"; const profileColumns: ColumnDef[] = useMemo( () => [ { id: "type", header: "Role", cell: ({ row }) => , }, { id: "reference", header: "Reference", cell: ({ row }) => ( {row.original.reference} ), }, { id: "businessLicense", header: "Business license", cell: ({ row }) => ( {row.original.businessLicense || "—"} ), }, { id: "status", header: "Status", cell: ({ row }) => , }, { id: "createdAt", header: "Registered", cell: ({ row }) => ( {formatDate(row.original.createdAt)} ), }, { id: "actions", header: "", meta: { headerClassName: "text-right", cellClassName: "text-right" }, cell: ({ row }) => ( ), }, ], [], ); const bookingColumns: ColumnDef[] = useMemo( () => [ { id: "reference", header: "Booking", cell: ({ row }) => ( {row.original.reference} ), }, { id: "route", header: "Route", cell: ({ row }) => { const b = row.original; return ( {b.originLabel} {b.destinationLabel} ); }, }, { id: "type", header: "Type", cell: ({ row }) => ( {humanize(row.original.tradeDirection)} ·{" "} {humanize(row.original.freightType)} ), }, { id: "status", header: "Status", cell: ({ row }) => , }, { id: "amount", header: "Amount", meta: { headerClassName: "text-right", cellClassName: "text-right" }, cell: ({ row }) => ( {formatMoney(row.original.totalAmount, row.original.currency)} ), }, { id: "createdAt", header: "Created", meta: { headerClassName: "text-right", cellClassName: "text-right" }, cell: ({ row }) => ( {formatDate(row.original.createdAt)} ), }, ], [], ); const documentColumns: ColumnDef[] = useMemo( () => [ { id: "name", header: "Document", cell: ({ row }) => ( {row.original.name} ), }, { id: "code", header: "Type", cell: ({ row }) => ( {humanize(row.original.code)} ), }, { id: "size", header: "Size", cell: ({ row }) => ( {formatBytes(row.original.size)} ), }, { id: "uploadedAt", header: "Uploaded", cell: ({ row }) => ( {formatDate(row.original.uploadedAt)} ), }, { id: "actions", header: "", meta: { headerClassName: "text-right", cellClassName: "text-right" }, cell: ({ row }) => ( ), }, ], [], ); const paymentColumns: ColumnDef[] = useMemo( () => [ { id: "reference", header: "Payment", cell: ({ row }) => ( {row.original.reference} ), }, { id: "booking", header: "Booking", cell: ({ row }) => ( {row.original.bookingReference} ), }, { id: "method", header: "Method", cell: ({ row }) => ( {humanize(row.original.method)} ), }, { id: "status", header: "Status", cell: ({ row }) => , }, { id: "paidAt", header: "Paid", cell: ({ row }) => ( {formatDate(row.original.paidAt)} ), }, { id: "amount", header: "Amount", meta: { headerClassName: "text-right", cellClassName: "text-right" }, cell: ({ row }) => ( {formatMoney(row.original.amount, row.original.currency)} ), }, ], [], ); if (isLoading) { return (
); } if (!company) { return ( Customer not found ); } return ( {company.status === "pending" && ( )} } /> }> Overview }> Bookings }> Documents }> Payments {/* OVERVIEW */} p.status === "pending", ).length, icon: IdCard, color: "yellow", }, { label: "Bookings", value: bookings.length, icon: Package, color: "blue", }, { label: "Total paid", value: formatMoney(totalPaid, paidCurrency), icon: Banknote, color: "edr-green", }, ]} /> Company information Role profiles {/* BOOKINGS */} void bookingsQuery.refetch(), } : undefined } /> {/* DOCUMENTS */} void documentsQuery.refetch(), } : undefined } /> {/* PAYMENTS */} void paymentsQuery.refetch(), } : undefined } /> ); }