Files
reui-blocks/blocks/data-table16.tsx
T

973 lines
31 KiB
TypeScript

"use client";
import type {
Column,
ColumnDef,
Row,
RowSelectionState,
SortingState,
} from "@tanstack/react-table";
import {
flexRender,
getCoreRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import {
ArrowDown,
ArrowUp,
Calendar,
CheckCheckIcon,
CheckCircle,
ChevronLeft,
ChevronsUpDown,
Clock,
LoaderIcon,
MapPin,
MoreHorizontal,
Package,
PieChart,
RefreshCcw,
User,
} from "lucide-react";
import * as React from "react";
import { z } from "zod";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
const formatNumber = (value: number) => value.toLocaleString("fa-IR");
const formatPrice = (value: number) =>
new Intl.NumberFormat("fa-IR", {
style: "currency",
currency: "IRR",
}).format(value);
type UseDataTableOptions<TData> = {
data: Array<TData>;
columns: Array<ColumnDef<TData, unknown>>;
getRowId?: (row: TData) => string;
initialSorting?: SortingState;
initialGlobalFilter?: string;
initialSelection?: RowSelectionState;
enableRowSelection?: boolean;
};
export function useDataTable<TData>(options: UseDataTableOptions<TData>) {
const {
data,
columns,
getRowId,
initialSorting = [],
initialGlobalFilter = "",
initialSelection = {},
enableRowSelection = true,
} = options;
const [sorting, setSorting] = React.useState<SortingState>(initialSorting);
const [globalFilter, setGlobalFilter] =
React.useState<string>(initialGlobalFilter);
const [rowSelection, setRowSelection] =
React.useState<RowSelectionState>(initialSelection);
const table = useReactTable({
data,
columns,
getRowId,
state: {
sorting,
globalFilter,
rowSelection,
},
onSortingChange: setSorting,
onRowSelectionChange: setRowSelection,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
enableRowSelection,
});
return {
table,
sorting,
setSorting,
globalFilter,
setGlobalFilter,
rowSelection,
setRowSelection,
};
}
type DataTableColumnHeaderProps<TData, TValue> = {
column: Column<TData, TValue>;
title: string;
};
export const DataTableColumnHeader = <TData, TValue>({
column,
title,
}: DataTableColumnHeaderProps<TData, TValue>) => {
const canSort = column.getCanSort();
const sorted = column.getIsSorted();
if (!canSort) {
return (
<span className="flex h-8 items-center text-sm font-medium text-foreground">
{title}
</span>
);
}
return (
<Button
variant="ghost"
size="sm"
className="flex h-8 items-center gap-2 px-0 text-sm font-medium text-foreground"
onClick={() => column.toggleSorting(sorted === "asc")}
>
<span>{title}</span>
{sorted === "desc" ? (
<ArrowDown className="h-4 w-4" />
) : sorted === "asc" ? (
<ArrowUp className="h-4 w-4" />
) : (
<ChevronsUpDown className="h-4 w-4 opacity-50" />
)}
</Button>
);
};
interface DataTableRowActionsProps<TData> {
row: Row<TData>;
schema: z.ZodSchema;
itemName: string;
idField?: string;
}
export function DataTableRowActions<TData>({
row,
schema,
itemName,
idField = "id",
}: DataTableRowActionsProps<TData>) {
const item = schema.parse(row.original) as TData;
const itemRecord = item as Record<string, unknown>;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="size-8 data-[state=open]:bg-muted"
>
<MoreHorizontal />
<span className="sr-only">باز کردن منو</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-[160px]">
<DropdownMenuLabel>عملیات</DropdownMenuLabel>
<DropdownMenuItem
onClick={() =>
navigator.clipboard.writeText(
String(itemRecord[idField] || itemRecord.id),
)
}
>
کپی شناسه {itemName}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>ویرایش {itemName}</DropdownMenuItem>
<DropdownMenuItem>مشاهده جزئیات</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
// Customer details schema
const CustomerSchema = z.object({
name: z.string(),
email: z.string(),
segment: z.string(),
});
// Shipping details schema
const ShippingSchema = z.object({
service: z.string(),
fulfillment_channel: z.string(),
warehouse: z.string(),
delivery_eta: z.string(),
tracking_number: z.string(),
assigned_to: z.string(),
});
// Order details schema
const OrderDetailsSchema = z.object({
payment_method: z.string(),
items: z.number(),
coupon_code: z.string().nullable(),
gift: z.boolean(),
return_status: z.string(),
notes: z.string(),
});
export const Orderschema = z.object({
id: z.string(),
purchased: z.string(),
order_status: z.string(),
payment_status: z.string(),
order_total: z.number(),
currency: z.string(),
priority: z.string(),
order_date: z.string(),
last_updated: z.string(),
risk_level: z.string(),
customer: CustomerSchema,
shipping: ShippingSchema,
orderDetails: OrderDetailsSchema,
});
type Order = z.infer<typeof Orderschema>;
export const data = [
{
id: "#301456",
purchased: "کاپشن چرمی",
order_status: "آماده تحویل",
customer: "سارا احمدی",
payment_method: "****7321",
payment_status: "پرداخت‌شده",
items: 3,
order_date: "2025-10-24T08:28:33.060Z",
delivery_eta: "2025-10-31T08:28:33.060Z",
fulfillment_channel: "FBA",
shipping_service: "هوایی سریع",
warehouse: "ORD-4",
order_total: 243.4,
currency: "IRR",
customer_email: "sarah.johnson@example.com",
customer_segment: "عمده‌فروشی",
priority: "کم",
coupon_code: "WELCOME10",
gift: false,
return_status: "تأیید‌شده",
assigned_to: "مژگان بیت",
risk_level: "کم",
tracking_number: "TRK5817960062",
last_updated: "2025-10-24T10:28:33.060Z",
notes: "سارا احمدی ارسال هوایی سریع را ترجیح می‌دهد.",
},
{
id: "#789123",
purchased: "کفش اسپرت آبی",
order_status: "تحویل‌شده",
customer: "رضا محمدی",
payment_method: "****4509",
payment_status: "پرداخت‌شده",
items: 2,
order_date: "2025-10-22T20:28:33.060Z",
delivery_eta: "2025-10-25T20:28:33.060Z",
fulfillment_channel: "شخص ثالث",
shipping_service: "تحویل یک‌روزه",
warehouse: "DFW-2",
order_total: 119.96,
currency: "IRR",
customer_email: "michael.brown@example.com",
customer_segment: "بازارچه",
priority: "عادی",
coupon_code: "VIPONLY",
gift: false,
return_status: "تأیید‌شده",
assigned_to: "هستی سینگ",
risk_level: "کم",
tracking_number: "TRK3189925655",
last_updated: "2025-10-22T22:28:33.060Z",
notes: "رضا محمدی ارسال تحویل یک‌روزه را ترجیح می‌دهد.",
},
{
id: "#654321",
purchased: "هودی قرمز",
order_status: "تحویل‌شده",
customer: "نیلوفر حسینی",
payment_method: "****9812",
payment_status: "در انتظار پیگیری",
items: 4,
order_date: "2025-10-21T08:28:33.060Z",
delivery_eta: "2025-10-28T08:28:33.060Z",
fulfillment_channel: "FBA",
shipping_service: "هوایی سریع",
warehouse: "ATL-1",
order_total: 354.63,
currency: "IRR",
customer_email: "emily.davis@example.com",
customer_segment: "ویژه",
priority: "فوری",
coupon_code: "VIPONLY",
gift: false,
return_status: "درخواست‌شده",
assigned_to: "هستی سینگ",
risk_level: "متوسط",
tracking_number: "TRK2861732425",
last_updated: "2025-10-21T10:28:33.060Z",
notes: "نیلوفر حسینی ارسال هوایی سریع را ترجیح می‌دهد.",
},
{
id: "#987654",
purchased: "عینک آفتابی مشکی",
order_status: "تحویل‌نشده",
customer: "داوود کریمی",
payment_method: "****6734",
payment_status: "در انتظار پیگیری",
items: 1,
order_date: "2025-10-19T20:28:33.060Z",
delivery_eta: "2025-10-22T20:28:33.060Z",
fulfillment_channel: "شخص ثالث",
shipping_service: "تحویل یک‌روزه",
warehouse: "LAX-5",
order_total: 119.73,
currency: "IRR",
customer_email: "david.lee@example.com",
customer_segment: "بازارچه",
priority: "کم",
coupon_code: "WELCOME10",
gift: false,
return_status: "دریافت‌شده",
assigned_to: "رایلی نگوین",
risk_level: "کم",
tracking_number: "TRK5254503688",
last_updated: "2025-10-19T22:28:33.060Z",
notes: "داوود کریمی ارسال تحویل یک‌روزه را ترجیح می‌دهد.",
},
{
id: "#432187",
purchased: "کوله‌پشتی سبز",
order_status: "تحویل‌شده",
customer: "لیلا رحیمی",
payment_method: "****2901",
payment_status: "پرداخت‌شده",
items: 2,
order_date: "2025-10-18T08:28:33.060Z",
delivery_eta: "2025-10-23T08:28:33.060Z",
fulfillment_channel: "دراپ‌شیپ",
shipping_service: "تحویل دو‌روزه",
warehouse: "ATL-1",
order_total: 359.28,
currency: "IRR",
customer_email: "lisa.wang@example.com",
customer_segment: "سازمانی",
priority: "بالا",
coupon_code: "WELCOME10",
gift: false,
return_status: "تأیید‌شده",
assigned_to: "هستی سینگ",
risk_level: "کم",
tracking_number: "TRK2835974731",
last_updated: "2025-10-18T10:28:33.060Z",
notes: "لیلا رحیمی ارسال تحویل دو‌روزه را ترجیح می‌دهد.",
},
{
id: "#567890",
purchased: "ساعت نقره‌ای",
order_status: "آماده تحویل",
customer: "امیر نوری",
payment_method: "****8456",
payment_status: "در انتظار پیگیری",
items: 1,
order_date: "2025-10-16T20:28:33.060Z",
delivery_eta: "2025-10-22T20:28:33.060Z",
fulfillment_channel: "دراپ‌شیپ",
shipping_service: "ارسال عادی",
warehouse: "ATL-1",
order_total: 381.57,
currency: "IRR",
customer_email: "james.carter@example.com",
customer_segment: "سازمانی",
priority: "کم",
coupon_code: "VIPONLY",
gift: false,
return_status: "تأیید‌شده",
assigned_to: "مژگان بیت",
risk_level: "بالا",
tracking_number: "TRK1516495925",
last_updated: "2025-10-16T22:28:33.060Z",
notes: "امیر نوری ارسال عادی را ترجیح می‌دهد.",
},
{
id: "#234567",
purchased: "شال خاکستری",
order_status: "تحویل‌شده",
customer: "راحله موسوی",
payment_method: "****1234",
payment_status: "مسترد شده",
items: 3,
order_date: "2025-10-15T08:28:33.060Z",
delivery_eta: "2025-10-18T08:28:33.060Z",
fulfillment_channel: "شخص ثالث",
shipping_service: "تحویل دو‌روزه",
warehouse: "JFK-3",
order_total: 398.12,
currency: "IRR",
customer_email: "rachel.kim@example.com",
customer_segment: "سازمانی",
priority: "فوری",
coupon_code: "SPRING24",
gift: false,
return_status: "تأیید‌شده",
assigned_to: "رایلی نگوین",
risk_level: "متوسط",
tracking_number: "TRK2114884757",
last_updated: "2025-10-15T10:28:33.060Z",
notes: "راحله موسوی ارسال تحویل دو‌روزه را ترجیح می‌دهد.",
},
{
id: "#876543",
purchased: "پیراهن بنفش",
order_status: "تحویل‌نشده",
customer: "توماس علوی",
payment_method: "****5678",
payment_status: "مسترد جزئی",
items: 2,
order_date: "2025-10-13T20:28:33.060Z",
delivery_eta: "2025-10-19T20:28:33.060Z",
fulfillment_channel: "دراپ‌شیپ",
shipping_service: "تحویل یک‌روزه",
warehouse: "ORD-4",
order_total: 337.01,
currency: "IRR",
customer_email: "thomas.allen@example.com",
customer_segment: "عمده‌فروشی",
priority: "بالا",
coupon_code: null,
gift: false,
return_status: "درخواست‌شده",
assigned_to: "مژگان بیت",
risk_level: "متوسط",
tracking_number: "TRK0992177244",
last_updated: "2025-10-13T22:28:33.060Z",
notes: "توماس علوی ارسال تحویل یک‌روزه را ترجیح می‌دهد.",
},
{
id: "#345678",
purchased: "کلاه سفید",
order_status: "آماده تحویل",
customer: "آنا رحیمی",
payment_method: "****9012",
payment_status: "پرداخت‌شده",
items: 1,
order_date: "2025-10-12T08:28:33.060Z",
delivery_eta: "2025-10-18T08:28:33.060Z",
fulfillment_channel: "دراپ‌شیپ",
shipping_service: "ارسال عادی",
warehouse: "LAX-5",
order_total: 277.54,
currency: "IRR",
customer_email: "anna.patel@example.com",
customer_segment: "سازمانی",
priority: "فوری",
coupon_code: "WELCOME10",
gift: false,
return_status: "تأیید‌شده",
assigned_to: "هستی سینگ",
risk_level: "بالا",
tracking_number: "TRK8458630889",
last_updated: "2025-10-12T10:28:33.060Z",
notes: "آنا رحیمی ارسال عادی را ترجیح می‌دهد.",
},
{
id: "#456789",
purchased: "بوت قهوه‌ای",
order_status: "تحویل‌شده",
customer: "حامد سنگری",
payment_method: "****3456",
payment_status: "پرداخت‌شده",
items: 4,
order_date: "2025-10-10T20:28:33.060Z",
delivery_eta: "2025-10-13T20:28:33.060Z",
fulfillment_channel: "ارسال فروشنده",
shipping_service: "ارسال عادی",
warehouse: "ATL-1",
order_total: 377.76,
currency: "IRR",
customer_email: "robert.singh@example.com",
customer_segment: "بازارچه",
priority: "کم",
coupon_code: "WELCOME10",
gift: false,
return_status: "ندارد",
assigned_to: "رایلی نگوین",
risk_level: "متوسط",
tracking_number: "TRK1335228617",
last_updated: "2025-10-10T22:28:33.060Z",
notes: "حامد سنگری ارسال عادی را ترجیح می‌دهد.",
},
];
// Define the raw data interface
interface RawOrderData {
id: string;
purchased: string;
order_status: string;
customer: string;
payment_method: string;
payment_status: string;
items: number;
order_date: string;
delivery_eta: string;
fulfillment_channel: string;
shipping_service: string;
warehouse: string;
order_total: number;
currency: string;
customer_email: string;
customer_segment: string;
priority: string;
coupon_code: string | null;
gift: boolean;
return_status: string;
assigned_to: string;
risk_level: string;
tracking_number: string;
last_updated: string;
notes: string;
}
// Transform flat data into nested structure
export const transformedData = data.map((item: RawOrderData) => ({
id: item.id,
purchased: item.purchased,
order_status: item.order_status,
payment_status: item.payment_status,
order_total: item.order_total,
currency: item.currency,
priority: item.priority,
order_date: item.order_date,
last_updated: item.last_updated,
risk_level: item.risk_level,
customer: {
name: item.customer,
email: item.customer_email,
segment: item.customer_segment,
},
shipping: {
service: item.shipping_service,
fulfillment_channel: item.fulfillment_channel,
warehouse: item.warehouse,
delivery_eta: item.delivery_eta,
tracking_number: item.tracking_number,
assigned_to: item.assigned_to,
},
orderDetails: {
payment_method: item.payment_method,
items: item.items,
coupon_code: item.coupon_code,
gift: item.gift,
return_status: item.return_status,
notes: item.notes,
},
}));
export const validatedData = Orderschema.array().parse(transformedData);
const dateFormatter = new Intl.DateTimeFormat("fa-IR", {
dateStyle: "medium",
});
const formatDate = (value: string) => {
const date = new Date(value);
return Number.isNaN(date.getTime()) ? value : dateFormatter.format(date);
};
export type StatusOption = {
label: string;
value: string;
icon?: React.ComponentType<{ className?: string }>;
};
export const orderStatuses: StatusOption[] = [
{ label: "تحویل‌شده", value: "تحویل‌شده", icon: CheckCircle },
{ label: "آماده تحویل", value: "آماده تحویل", icon: Package },
{ label: "تحویل‌نشده", value: "تحویل‌نشده", icon: Clock },
];
export const paymentStatuses: StatusOption[] = [
{ label: "پرداخت‌شده", value: "پرداخت‌شده", icon: CheckCheckIcon },
{ label: "در انتظار پیگیری", value: "در انتظار پیگیری", icon: LoaderIcon },
{ label: "مسترد شده", value: "مسترد شده", icon: RefreshCcw },
{
label: "مسترد جزئی",
value: "مسترد جزئی",
icon: PieChart,
},
];
const createStatusLookup = (options: StatusOption[]) =>
options.reduce<Record<string, StatusOption>>((acc, option) => {
acc[option.value] = option;
return acc;
}, {});
const orderStatusLookup = createStatusLookup(orderStatuses);
export const getOrderStatusMeta = (status: string) => orderStatusLookup[status];
export const getStatusVariant = (status: string) => {
switch (status) {
case "تحویل‌شده":
return "default";
case "آماده تحویل":
return "secondary";
case "تحویل‌نشده":
return "outline";
default:
return "outline";
}
};
export const columns: ColumnDef<Order>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="انتخاب همه"
className="translate-y-[2px]"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="انتخاب رکورد"
className="translate-y-[2px]"
/>
),
enableSorting: false,
enableHiding: false,
meta: {
width: 56,
minWidth: 48,
headerClassName: "px-2",
cellClassName: "px-2",
align: "center",
},
},
{
accessorKey: "id",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="سفارش" />
),
cell: ({ row }) => (
<div className="w-[100px] font-mono text-sm">{row.original.id}</div>
),
enableSorting: true,
enableHiding: false,
},
{
accessorKey: "purchased",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="محصول" />
),
cell: ({ row }) => (
<div className="max-w-[200px] truncate text-sm font-medium">
{row.original.purchased}
</div>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "order_status",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="وضعیت معامله" />
),
cell: ({ row }) => {
const status = row.original.order_status;
const statusMeta = getOrderStatusMeta(status);
const StatusIcon = statusMeta?.icon;
return (
<Badge variant={getStatusVariant(status)} className="gap-1">
{StatusIcon ? <StatusIcon className="size-3" /> : null}
<span className="text-xs">{statusMeta?.label ?? status}</span>
</Badge>
);
},
enableSorting: false,
},
{
accessorKey: "order_total",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="مجموع" />
),
cell: ({ row }) => (
<span className="text-sm font-medium tabular-nums">
{formatPrice(row.original.order_total)}
</span>
),
meta: { align: "right", className: "tabular-nums" },
enableSorting: true,
},
{
accessorKey: "customer",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="جزئیات سفارش" />
),
cell: ({ row }) => {
const expandHandler = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
row.toggleExpanded();
};
return (
<div className="relative">
<Button
variant="outline"
size="sm"
className={cn(
"group w-full justify-start gap-2 transition-colors",
"cursor-pointer border-primary/20 hover:bg-primary/5",
)}
onClick={expandHandler}
>
<div className="truncate text-sm font-medium">
{row.original.customer.name}
</div>
<div className="truncate text-xs text-muted-foreground">
{row.original.customer.segment}
</div>
<ChevronLeft
className={cn(
"ms-auto h-4 w-4 text-primary transition-transform duration-200 rtl:rotate-180",
row.getIsExpanded() && "rotate-90 transform",
)}
/>
</Button>
</div>
);
},
},
{
id: "actions",
cell: ({ row }) => (
<div className="flex justify-center">
<DataTableRowActions
row={row}
schema={Orderschema}
itemName="سفارش"
idField="id"
/>
</div>
),
},
];
export function DataTable16({ className }: { className?: string }) {
const { table } = useDataTable({
data: validatedData,
columns,
getRowId: (row) => row.id.toString(),
});
return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container">
<div className="w-full">
<div className="mb-8 text-start">
<h2 className="text-xl font-bold tracking-tight">
جدول با رکورد گسترش‌یافته
</h2>
<p className="mt-2 text-muted-foreground">
جدول داده با رکورد گسترش‌یافته که در عرض ستون والد محدود می‌شود.
</p>
</div>
<div className="overflow-hidden rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<React.Fragment key={row.id}>
<TableRow data-state={row.getIsSelected() && "selected"}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
{row.getIsExpanded() && (
<TableRow className="bg-muted/50 transition-colors">
<TableCell className="p-0" colSpan={5} />
<TableCell className="py-4" colSpan={1}>
<div className="rounded-lg border border-border/50 bg-card p-4 shadow-sm">
<div className="grid grid-cols-2 gap-4">
{/* Left Column */}
<div className="space-y-3">
<div className="flex items-center gap-3">
<div className="rounded-md bg-primary/10 p-2">
<Package className="h-4 w-4 text-primary" />
</div>
<div>
<p className="text-xs text-muted-foreground">
سرویس حمل
</p>
<p className="text-sm font-medium">
{row.original.shipping.service}
</p>
</div>
</div>
<div className="flex items-center gap-3">
<div className="rounded-md bg-muted p-2">
<MapPin className="h-4 w-4 text-muted-foreground" />
</div>
<div>
<p className="text-xs text-muted-foreground">
رهگیری
</p>
<p className="rounded bg-muted px-2 py-1 font-mono text-sm font-medium">
{row.original.shipping.tracking_number}
</p>
</div>
</div>
<div className="flex items-center gap-3">
<div className="rounded-md bg-muted p-2">
<Calendar className="h-4 w-4 text-muted-foreground" />
</div>
<div>
<p className="text-xs text-muted-foreground">
تحویل
</p>
<p className="text-sm font-medium">
{formatDate(
row.original.shipping.delivery_eta,
)}
</p>
</div>
</div>
</div>
{/* Right Column */}
<div className="space-y-3">
<div className="flex items-center gap-3">
<div className="rounded-md bg-muted p-2">
<Package className="h-4 w-4 text-muted-foreground" />
</div>
<div>
<p className="text-xs text-muted-foreground">
انبار
</p>
<p className="text-sm font-medium">
{row.original.shipping.warehouse}
</p>
</div>
</div>
<div className="flex items-center gap-3">
<div className="rounded-md bg-muted p-2">
<Package className="h-4 w-4 text-muted-foreground" />
</div>
<div>
<p className="text-xs text-muted-foreground">
کانال ارسال
</p>
<Badge
variant="outline"
className="text-xs"
>
{
row.original.shipping
.fulfillment_channel
}
</Badge>
</div>
</div>
<div className="flex items-center gap-3">
<div className="rounded-md bg-muted p-2">
<User className="h-4 w-4 text-muted-foreground" />
</div>
<div>
<p className="text-xs text-muted-foreground">
مسئول
</p>
<p className="text-sm font-medium">
{row.original.shipping.assigned_to}
</p>
</div>
</div>
</div>
</div>
</div>
</TableCell>
<TableCell className="p-0" colSpan={1} />
</TableRow>
)}
</React.Fragment>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
نتیجه‌ای یافت نشد
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
</div>
</section>
);
}