compact: logistics readiness cards — single-line on desktop, stacked on mobile

This commit is contained in:
root 2026-05-27 14:12:39 +00:00
parent 0930ea9c26
commit f8c6c538b7
1 changed files with 26 additions and 24 deletions

View File

@ -10,23 +10,14 @@ import { Badge } from "../UI/Badge";
import { Panel } from "../UI/Panel"; import { Panel } from "../UI/Panel";
import { OrderFilters } from "../orders/OrderFilters"; import { OrderFilters } from "../orders/OrderFilters";
const renderOrderNumbers = (group) => { const renderOrderNumbersCompact = (group) => {
if (!Array.isArray(group.orderNumbers) || !group.orderNumbers.length) { if (!Array.isArray(group.orderNumbers) || !group.orderNumbers.length) {
return <span>Номера не указаны</span>; return null;
} }
const text = group.orderNumbers.length <= 3
return ( ? group.orderNumbers.join(", ")
<div className="flex flex-wrap gap-2"> : group.orderNumbers.slice(0, 3).join(", ") + ` +${group.orderNumbers.length - 3}`;
{group.orderNumbers.map((number) => ( return <span className="text-xs text-[var(--color-text-muted)]">{text}</span>;
<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 }) => { export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusOptions = ORDER_GROUP_DISPLAY_STATUS_OPTIONS }) => {
@ -38,7 +29,6 @@ export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusO
[filters, orderGroups], [filters, orderGroups],
); );
// Group by display status value
const statusGroups = React.useMemo(() => { const statusGroups = React.useMemo(() => {
const map = new Map(); const map = new Map();
for (const group of filteredGroups) { for (const group of filteredGroups) {
@ -104,7 +94,7 @@ export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusO
const isCollapsed = collapsedSections.has(statusValue); const isCollapsed = collapsedSections.has(statusValue);
return ( return (
<div key={statusValue} className="space-y-3"> <div key={statusValue} className="space-y-2">
<button <button
type="button" type="button"
className="flex w-full items-center justify-between text-left" className="flex w-full items-center justify-between text-left"
@ -139,7 +129,7 @@ export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusO
{!isCollapsed && groups.map((group) => ( {!isCollapsed && groups.map((group) => (
<button <button
key={group.id} 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" className="w-full rounded-[16px] border border-[var(--color-border)] bg-[var(--color-surface-strong)] px-4 py-2 !text-left !text-[var(--color-text)] transition hover:bg-[var(--color-accent-soft)]"
onClick={() => { onClick={() => {
if (onSelectSet) { if (onSelectSet) {
onSelectSet(group.id); onSelectSet(group.id);
@ -147,20 +137,32 @@ export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusO
}} }}
type="button" type="button"
> >
<div className="space-y-2"> {/* Desktop: single-line compact row */}
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-3"> <div className="hidden md:flex md:items-center md:gap-3 md:text-sm">
<div className="break-words text-base font-semibold leading-tight !text-[var(--color-text)] sm:text-lg"> <span className="min-w-0 truncate font-semibold">{group.displayTitle || group.customerName || group.groupKey}</span>
<span className="shrink-0 text-[var(--color-text-muted)]">{group.customerDate || "—"}</span>
<span className="shrink-0 text-[var(--color-text-muted)]">{group.customerPhone || "—"}</span>
<span className="shrink-0">{group.ordersCount || 0} {group.ordersCount === 1 ? "заказ" : group.ordersCount < 5 ? "заказа" : "заказов"}</span>
{renderOrderNumbersCompact(group)}
{group.assignedDriverName && <span className="text-[var(--color-accent)]">{group.assignedDriverName}</span>}
<span className="ml-auto shrink-0"><Badge tone={getOrderGroupStatusTone(group)}>{getOrderGroupDisplayStatusLabel(group)}</Badge></span>
</div>
{/* Mobile: stacked */}
<div className="space-y-1 md:hidden">
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2">
<div className="break-words font-semibold leading-tight !text-[var(--color-text)]">
{group.displayTitle || group.customerName || group.groupKey} {group.displayTitle || group.customerName || group.groupKey}
</div> </div>
<Badge className="self-start" tone={getOrderGroupStatusTone(group)}> <Badge className="self-start" tone={getOrderGroupStatusTone(group)}>
{getOrderGroupDisplayStatusLabel(group)} {getOrderGroupDisplayStatusLabel(group)}
</Badge> </Badge>
</div> </div>
<div className="text-sm leading-6 text-[var(--color-text-muted)]"> <div className="text-sm leading-5 text-[var(--color-text-muted)]">
{group.customerDate || "—"} · {group.customerPhone || "—"} · {group.ordersCount || 0}{" "} {group.customerDate || "—"} · {group.customerPhone || "—"} · {group.ordersCount || 0}{" "}
{group.ordersCount === 1 ? "заказ" : group.ordersCount < 5 ? "заказа" : "заказов"} {group.ordersCount === 1 ? "заказ" : group.ordersCount < 5 ? "заказа" : "заказов"}
{group.assignedDriverName ? ` · ${group.assignedDriverName}` : ""}
</div> </div>
<div>{renderOrderNumbers(group)}</div> {renderOrderNumbersCompact(group)}
</div> </div>
</button> </button>
))} ))}
@ -171,4 +173,4 @@ export const LogisticsReadinessBoard = ({ orderGroups = [], onSelectSet, statusO
)} )}
</div> </div>
); );
}; };