125 lines
4.7 KiB
JavaScript
125 lines
4.7 KiB
JavaScript
import React from "react";
|
|
import {
|
|
filterOrderGroups,
|
|
getOrderGroupDisplayStatusLabel,
|
|
getOrderGroupDisplayStatusValue,
|
|
getOrderGroupStatusTone,
|
|
ORDER_GROUP_DISPLAY_STATUS_OPTIONS,
|
|
} from "../../services/orderGroupViews";
|
|
import { Badge } from "../UI/Badge";
|
|
import { Panel } from "../UI/Panel";
|
|
import { OrderFilters } from "../orders/OrderFilters";
|
|
|
|
const renderOrderNumbers = (group) => {
|
|
if (!Array.isArray(group.orderNumbers) || !group.orderNumbers.length) {
|
|
return <span>Номера не указаны</span>;
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-wrap gap-2">
|
|
{group.orderNumbers.map((number) => (
|
|
<span
|
|
key={number}
|
|
className="rounded-full bg-[var(--color-surface)] px-3 py-1 text-xs text-[var(--color-text-muted)]"
|
|
>
|
|
{number}
|
|
</span>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusOptions = ORDER_GROUP_DISPLAY_STATUS_OPTIONS }) => {
|
|
const [filters, setFilters] = React.useState({ query: "", displayStatus: "all" });
|
|
|
|
const filteredGroups = React.useMemo(
|
|
() => filterOrderGroups(orderGroups, filters),
|
|
[filters, orderGroups],
|
|
);
|
|
|
|
// Group by display status value
|
|
const statusGroups = React.useMemo(() => {
|
|
const map = new Map();
|
|
for (const group of filteredGroups) {
|
|
const statusValue = getOrderGroupDisplayStatusValue(group);
|
|
if (!map.has(statusValue)) {
|
|
const label = getOrderGroupDisplayStatusLabel(group);
|
|
map.set(statusValue, { label, groups: [] });
|
|
}
|
|
map.get(statusValue).groups.push(group);
|
|
}
|
|
return map;
|
|
}, [filteredGroups]);
|
|
|
|
const totalGroups = filteredGroups.length;
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<Panel className="space-y-4 p-5">
|
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
<div className="min-w-0">
|
|
<h2 className="text-lg font-semibold">Наборы доставки</h2>
|
|
</div>
|
|
<Badge tone="neutral">{totalGroups} групп</Badge>
|
|
</div>
|
|
|
|
<OrderFilters
|
|
filters={filters}
|
|
setFilters={setFilters}
|
|
statusOptions={statusOptions}
|
|
/>
|
|
</Panel>
|
|
|
|
{!totalGroups ? (
|
|
<div className="rounded-[28px] border border-dashed border-[var(--color-border)] bg-[var(--color-surface-strong)] p-4 text-sm text-[var(--color-text-muted)]">
|
|
По этому поиску ничего не найдено.
|
|
</div>
|
|
) : (
|
|
<div className="grid gap-6 xl:grid-cols-2">
|
|
{Array.from(statusGroups.entries()).map(([statusValue, { label, groups }]) => {
|
|
if (!groups.length) return null;
|
|
|
|
return (
|
|
<div key={statusValue} className="space-y-3">
|
|
<div className="flex items-center gap-2">
|
|
<h3 className="font-semibold">{label}</h3>
|
|
<Badge tone="neutral">{groups.length}</Badge>
|
|
</div>
|
|
|
|
{groups.map((group) => (
|
|
<button
|
|
key={group.id}
|
|
className="w-full rounded-[24px] border border-[var(--color-border)] bg-[var(--color-surface-strong)] p-4 !text-left !text-[var(--color-text)] transition hover:bg-[var(--color-accent-soft)] sm:p-5"
|
|
onClick={() => {
|
|
if (onSelectSet) {
|
|
onSelectSet(group.id);
|
|
}
|
|
}}
|
|
type="button"
|
|
>
|
|
<div className="space-y-2">
|
|
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-3">
|
|
<div className="break-words text-base font-semibold leading-tight !text-[var(--color-text)] sm:text-lg">
|
|
{group.displayTitle || group.customerName || group.groupKey}
|
|
</div>
|
|
<Badge className="self-start" tone={getOrderGroupStatusTone(group)}>
|
|
{getOrderGroupDisplayStatusLabel(group)}
|
|
</Badge>
|
|
</div>
|
|
<div className="text-sm leading-6 text-[var(--color-text-muted)]">
|
|
{group.customerDate || "—"} · {group.customerPhone || "—"} · {group.ordersCount || 0}{" "}
|
|
{group.ordersCount === 1 ? "заказ" : group.ordersCount < 5 ? "заказа" : "заказов"}
|
|
</div>
|
|
<div>{renderOrderNumbers(group)}</div>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|