This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-B2B/src/app/[locale]/(portal)/me/orders/page.tsx
kirukib 1f30f00da6 Finalize portal polish: profile, avatars, ID cards, and list UX.
Ship leftover Yimaru login/personas, sidebar sections, filter modal, chart/stat clip fixes, and matching feature docs so the polish work is fully committed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 21:57:07 +03:00

136 lines
4.8 KiB
TypeScript

"use client";
import { useMemo, useState } from "react";
import { useTranslations } from "next-intl";
import { useQuery } from "@tanstack/react-query";
import { PageShell } from "@/components/layout/page-shell";
import { StatusBadge } from "@/components/shared/status-badge";
import { TableToolbar, matchesSearch } from "@/components/table/table-toolbar";
import { TablePanel } from "@/components/table/table-panel";
import { useAuth } from "@/providers/auth-provider";
import { mockApi } from "@/lib/api/mock-client";
import { formatDate, formatEtb } from "@/lib/format";
import { Link } from "@/i18n/routing";
import { Button } from "@/components/ui/button";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { ArrowLeft } from "lucide-react";
export default function MemberOrdersPage() {
const t = useTranslations();
const { user } = useAuth();
const memberId = user?.memberId ?? "mem_001";
const [search, setSearch] = useState("");
const [statusFilter, setStatusFilter] = useState("all");
const { data: orders, isLoading } = useQuery({
queryKey: ["member-orders", memberId],
queryFn: () => mockApi.getMemberOrders(memberId),
enabled: !!user,
});
const filtered = useMemo(() => {
return (orders ?? []).filter((order) => {
if (statusFilter !== "all" && order.status !== statusFilter) return false;
return matchesSearch([order.id, order.status], search);
});
}, [orders, search, statusFilter]);
if (!user) return null;
return (
<PageShell
title={t("member.ordersTitle")}
description={t("member.ordersSubtitle")}
breadcrumb
extra={
<Button variant="outline" className="gap-2" render={<Link href="/me" />}>
<ArrowLeft className="size-4" />
{t("common.back")}
</Button>
}
>
<TablePanel
loading={isLoading}
toolbar={
<TableToolbar
search={search}
onSearchChange={setSearch}
searchPlaceholder={t("common.searchPlaceholder")}
filters={[
{
id: "status",
label: t("common.status"),
value: statusFilter,
onChange: setStatusFilter,
allLabel: t("common.all"),
options: [
{ value: "placed", label: "Placed" },
{ value: "processing", label: "Processing" },
{ value: "delivered", label: "Delivered" },
{ value: "cancelled", label: "Cancelled" },
],
},
]}
resultCount={filtered.length}
resultLabel={t("common.results")}
/>
}
>
<Table>
<TableHeader>
<TableRow>
<TableHead>{t("member.order")}</TableHead>
<TableHead className="text-right">{t("statements.total")}</TableHead>
<TableHead className="text-right">{t("statements.covered")}</TableHead>
<TableHead className="text-right">{t("member.memberPaid")}</TableHead>
<TableHead>{t("member.items")}</TableHead>
<TableHead>{t("common.status")}</TableHead>
<TableHead>{t("member.placed")}</TableHead>
<TableHead>{t("common.actions")}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filtered.length ? (
filtered.map((order) => (
<TableRow key={order.id}>
<TableCell className="font-mono text-xs">{order.id}</TableCell>
<TableCell className="text-right">{formatEtb(order.totalEtb)}</TableCell>
<TableCell className="text-right">{formatEtb(order.coveredEtb)}</TableCell>
<TableCell className="text-right">{formatEtb(order.memberPaidEtb)}</TableCell>
<TableCell>{order.itemCount}</TableCell>
<TableCell>
<StatusBadge status={order.status} />
</TableCell>
<TableCell>{formatDate(order.placedAt)}</TableCell>
<TableCell>
<Button
variant="ghost"
size="sm"
render={<Link href={`/me/orders/${order.id}`} />}
>
{t("common.view")}
</Button>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={8} className="h-28 text-center text-sm text-muted-foreground">
{t("common.empty")}
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TablePanel>
</PageShell>
);
}