const DriverShipmentReport = ({ shipmentData }) => { if (!Array.isArray(shipmentData) || shipmentData.length === 0) return null; return (
Проблемы с доставкой позиций

Не доставлено {shipmentData.length} {shipmentData.length === 1 ? "позиция" : shipmentData.length < 5 ? "позиции" : "позиций"}. Остальное — доставлено.

{shipmentData.map((item) => (
{item.name} {item.quantity || item.unit ? ( {[item.quantity, item.unit].filter(Boolean).join(" ")} ) : null}
{item.comment ? (

Причина: {item.comment}

) : (

Причина не указана

)}
))}
); }; import React from "react"; import { formatDateTime } from "../../utils/formatters"; import { Badge } from "../UI/Badge"; import { Button } from "../UI/Button"; import { Select } from "../UI/Select"; import { Panel } from "../UI/Panel"; import { DriverShipmentPanel } from "../driver/DriverShipmentPanel"; import { supabase } from "../../supabaseClient"; import { getOrderGroupDeliveryStatusLabel, getOrderGroupDisplayStatusLabel, getOrderGroupStatusTone, } from "../../services/orderGroupViews"; const DELIVERY_TIME_OPTIONS = ["Первая половина дня", "Вторая половина дня"]; const WEEK_DAY_LABELS = ["ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ", "ВС"]; const DELIVERY_TIME_ALIASES = { "До обеда": "Первая половина дня", "После обеда": "Вторая половина дня", }; const renderList = (values) => { if (!Array.isArray(values) || !values.length) { return

Нет данных

; } return (
{values.map((value, index) => ( {value} ))}
); }; const renderValue = (value) => value || "Нет данных"; const normalizeNom = (nom) => { if (!nom) return ''; // 1C escapes backslashes: "СФ Т\\ЕА-33584" → normalize for comparison return String(nom).replace(/\\\\/g, '\\').trim(); }; const getAllBillNumbers = (order) => { const orders = parseOrderList(order); if (!orders.length) return order.orderNumbers || []; return orders.map((o) => o.nom || o.name || '').filter(Boolean); }; const parseOrderList = (order) => { if (!order) return []; // Try orderList first (Supabase JSONB array of positions) if (order.orderList) { let parsed = order.orderList; if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { /* ignore */ } } if (Array.isArray(parsed)) return parsed; } // Fallback: orderListStructured (JSONB with { orders: [...] }) if (order.orderListStructured) { let parsed = order.orderListStructured; if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { /* ignore */ } } if (parsed && Array.isArray(parsed.orders)) return parsed.orders; } // Fallback: sourceOrders (1C exchange data) // 1C sends the FULL order composition (main + associated bills) in EVERY source order's orderList. // We must deduplicate by nom to avoid showing the same items multiple times. if (order.sourceOrders) { let parsed = order.sourceOrders; if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { /* ignore */ } } if (Array.isArray(parsed) && parsed.length > 0) { const seen = new Set(); const allItems = []; for (const src of parsed) { if (src && Array.isArray(src.orderList)) { for (const ol of src.orderList) { if (ol && (ol.items || ol.nom || ol.name)) { const normalizedNom = normalizeNom(ol.nom || ol.name || ''); // Deduplicate by nom — 1C repeats same orderList in every source order if (seen.has(normalizedNom)) continue; seen.add(normalizedNom); allItems.push(ol); } } } } if (allItems.length > 0) return allItems; // Legacy: return whole array if no orderList structure if (parsed[0].orderList && Array.isArray(parsed[0].orderList)) { return parsed[0].orderList; } return parsed; } } return []; }; const getErrorMessage = (error, fallbackMessage) => { if (!error) { return fallbackMessage; } if (error instanceof Error) { return error.message || fallbackMessage; } if (typeof error === "string") { return error || fallbackMessage; } return error?.message || fallbackMessage; }; const normalizeDeliveryTimeChoice = (value) => { const normalized = value ? String(value).trim() : ""; const deliveryTime = DELIVERY_TIME_ALIASES[normalized] || normalized; return DELIVERY_TIME_OPTIONS.includes(deliveryTime) ? deliveryTime : DELIVERY_TIME_OPTIONS[0]; }; const toDateKey = (date) => { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, "0"); const day = String(date.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }; const fromDateKey = (value) => { const normalized = normalizeDateForInput(value); if (!normalized) { return null; } const [year, month, day] = normalized.split("-").map(Number); return new Date(year, month - 1, day); }; const addDays = (date, amount) => { const nextDate = new Date(date); nextDate.setDate(nextDate.getDate() + amount); return nextDate; }; const isWeekendDate = (date) => { const day = date.getDay(); return day === 0 || day === 6; }; export const getNextSelectableDateKey = (referenceDate = new Date()) => { let current = addDays(referenceDate, 1); while (isWeekendDate(current)) { current = addDays(current, 1); } return toDateKey(current); }; const normalizePhoneForTel = (phone) => { const cleaned = String(phone || "").trim(); if (!cleaned) return ""; if (cleaned.startsWith("+7")) return cleaned; if (cleaned.startsWith("8")) return "+7" + cleaned.slice(1); return "+7" + cleaned; }; const isFutureDeliveryDate = (value) => { const parsedDate = fromDateKey(value); if (!parsedDate) { return false; } return !isWeekendDate(parsedDate) && toDateKey(parsedDate) >= getNextSelectableDateKey(); }; const isSelectableCalendarDate = (date, minDateKey) => { const dateKey = toDateKey(date); return dateKey >= minDateKey && !isWeekendDate(date); }; const formatDateForDisplay = (value) => { if (!value) { return "Выберите дату"; } const [year, month, day] = value.split("-").map(Number); if (!year || !month || !day) { return value; } return new Date(year, month - 1, day).toLocaleDateString("ru-RU", { day: "2-digit", month: "2-digit", year: "numeric", }); }; const formatDeliveryDateDisplay = (value) => { const normalized = normalizeDateForInput(value); if (!normalized) { return renderValue(value); } return formatDateForDisplay(normalized); }; const startOfMonth = (date) => new Date(date.getFullYear(), date.getMonth(), 1); const addMonths = (date, amount) => new Date(date.getFullYear(), date.getMonth() + amount, 1); const buildCalendarDays = (currentMonth) => { const firstDay = startOfMonth(currentMonth); const lastDay = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 0); const firstWeekDay = (firstDay.getDay() + 6) % 7; const totalDays = lastDay.getDate(); const cells = []; for (let index = 0; index < firstWeekDay; index += 1) { cells.push(null); } for (let day = 1; day <= totalDays; day += 1) { cells.push(new Date(currentMonth.getFullYear(), currentMonth.getMonth(), day)); } while (cells.length % 7 !== 0) { cells.push(null); } return cells; }; const normalizeDateForInput = (value) => { if (!value) { return ""; } const normalized = String(value).trim(); if (/^\d{4}-\d{2}-\d{2}$/.test(normalized)) { return normalized; } const shortDateMatch = normalized.match(/^(\d{2})\.(\d{2})\.(\d{2})$/); if (shortDateMatch) { const [, day, month, year] = shortDateMatch; return `20${year}-${month}-${day}`; } return ""; }; const matchesStopWord = (name, stopWords) => { if (!stopWords || !stopWords.length) return false; const lower = name.toLowerCase(); return stopWords.some((sw) => lower.includes(sw.toLowerCase())); }; const useStopWords = () => { const [stopWords, setStopWords] = React.useState([]); const [active, setActive] = React.useState(true); React.useEffect(() => { if (!supabase) return; Promise.all([ supabase.from("stop_words").select("word").then(r => r.data || []), supabase.from("stop_words_scope").select("scope").eq("id", 1).single().then(r => r.data), ]).then(([words, scopeRow]) => { setStopWords(words.map((d) => d.word)); setActive(scopeRow?.scope !== "client_only"); }); }, []); return { stopWords, active }; }; const CollapsibleOrderComposition = ({ order }) => { const [isExpanded, setIsExpanded] = React.useState(false); const { stopWords, active } = useStopWords(); const orders = parseOrderList(order); const allPositions = orders.reduce((sum, o) => sum + (o.items?.length || 0), 0); const filteredPositions = active ? orders.reduce((sum, o) => { if (!o.items) return sum; return sum + o.items.filter((item) => { const name = String(item.product_name || item.name || item.title || ""); return !matchesStopWord(name, stopWords); }).length; }, 0) : allPositions; return (
{isExpanded && (
{!orders.length ? (

Позиции не указаны

) : ( orders.map((orderItem, idx) => (

{orderItem.nom || orderItem.name || `Заказ ${idx + 1}`}

{(() => { const filtered = (orderItem.items || []).filter((item) => { const name = String(item.product_name || item.name || item.title || ""); return active ? !matchesStopWord(name, stopWords) : true; }); if (filtered.length === 0 && active && (orderItem.items || []).length > 0) { return

Только услуги — скрыты стоп-словами

; } if (filtered.length === 0) { return

Позиции не указаны

; } return (
{filtered.map((item, itemIdx) => (
{item.product_name || item.name || item.title || ''} {item.product_quantity || item.quantity || item.count || item.amount || ""} {item.product_ed || item.unit || ""}
))}
); })()}
)) )}
)}
); }; const PaidStoragePanel = ({ order, onChangeDeliveryStatus, isSavingDeliveryChoice, setFormMessage }) => { const [showConfirm, setShowConfirm] = React.useState(false); const isPaidStorage = (order.deliveryStatus || order.delivery_status) === "paid_storage"; if (isPaidStorage) { return (
Платное хранение
{order.paidStorageAt && (

Переведено: {formatDateTime(order.paidStorageAt)}

)}
); } return (
Платное хранение

Переведите заказ в статус платного хранения, если клиент не забрал товар в срок.

{showConfirm ? (

Перевести заказ в платное хранение? Клиент получит уведомление.

) : ( )}
); }; const PROBLEM_REASONS = [ { value: "client_absent", label: "Клиент не принял", description: "Клиент отказался или не вышел на связь" }, { value: "damage", label: "Повреждение заказа", description: "Товар повреждён при транспортировке" }, { value: "wrong_address", label: "Неверный адрес", description: "Адрес доставки указан неверно" }, { value: "other", label: "Другое", description: "Иная причина проблемы доставки" }, ]; const ProblemReasonModal = ({ onSelect, onCancel }) => (
e.stopPropagation()}>

Причина проблемы

Укажите причину возникшей проблемы с доставкой.

{PROBLEM_REASONS.map((reason) => ( ))}
); export const OrderDetailPanel = ({ order, canManageDelivery = false, onSaveManualDeliveryChoice, isSavingDeliveryChoice = false, drivers = [], onAssignDriver, onChangeDeliveryStatus, userRole, }) => { const [problemReason, setProblemReason] = React.useState(null); const [pendingStatus, setPendingStatus] = React.useState(null); const [deliveryDate, setDeliveryDate] = React.useState(""); const [deliveryTime, setDeliveryTime] = React.useState(DELIVERY_TIME_OPTIONS[0]); const [formMessage, setFormMessage] = React.useState(""); const [shipmentState, setShipmentState] = React.useState(null); const [isCalendarOpen, setIsCalendarOpen] = React.useState(false); const [driverMessage, setDriverMessage] = React.useState(""); const [selectedDriverId, setSelectedDriverId] = React.useState(order?.assignedDriverId || ""); const [deliveryType, setDeliveryType] = React.useState(order?.deliveryType || "delivery"); const [pickupDate, setPickupDate] = React.useState(order?.pickupDate || ""); const [pickupTimeSlot, setPickupTimeSlot] = React.useState(DELIVERY_TIME_OPTIONS[0]); const [deliveryAddress, setDeliveryAddress] = React.useState(order?.deliveryAddress || order?.customerAddress || ""); const minSelectableDateKey = React.useMemo(() => getNextSelectableDateKey(), []); const [currentMonth, setCurrentMonth] = React.useState(() => { const existingDeliveryDate = fromDateKey(order?.deliveryDate); const fallbackDate = fromDateKey(minSelectableDateKey) || new Date(); const sourceDate = existingDeliveryDate && isFutureDeliveryDate(toDateKey(existingDeliveryDate)) ? existingDeliveryDate : fallbackDate; return startOfMonth(sourceDate); }); const calendarDays = React.useMemo(() => buildCalendarDays(currentMonth), [currentMonth]); const monthLabel = React.useMemo( () => currentMonth.toLocaleDateString("ru-RU", { month: "long", year: "numeric", }), [currentMonth], ); const canGoBack = toDateKey(currentMonth) > toDateKey(startOfMonth(fromDateKey(minSelectableDateKey) || new Date())); React.useEffect(() => { setSelectedDriverId(order?.assignedDriverId || ""); setIsEditingDate(false); }, [order?.id, order?.assignedDriverId]); React.useEffect(() => { const normalizedDeliveryDate = normalizeDateForInput(order?.deliveryDate); const nextSelectableDateKey = getNextSelectableDateKey(); const selectedDateKey = isFutureDeliveryDate(normalizedDeliveryDate) ? normalizedDeliveryDate : nextSelectableDateKey; setDeliveryDate(selectedDateKey); const selectedDate = fromDateKey(selectedDateKey) || new Date(); setCurrentMonth(startOfMonth(selectedDate)); setDeliveryTime(normalizeDeliveryTimeChoice(order?.deliveryTime || order?.deliveryHalfDay)); setDeliveryType(order?.deliveryType || "delivery"); setPickupDate(order?.pickupDate || ""); setPickupTimeSlot(normalizeDeliveryTimeChoice(order?.pickupTimeSlot || order?.deliveryTime || order?.deliveryHalfDay)); setFormMessage(""); }, [order?.id, order?.deliveryDate, order?.deliveryHalfDay, order?.deliveryTime, order?.deliveryType, order?.pickupDate, order?.pickupTimeSlot]); if (!order) { return (

Выберите группу для просмотра деталей.

); } const isDeliveryAgreed = ["agreed", "driver_assigned", "loaded", "on_route", "delivered"].includes(order.deliveryStatus || order.delivery_status); const canEditDelivery = canManageDelivery && ["admin", "mega_admin", "logistician"].includes(userRole); const [isEditingDate, setIsEditingDate] = React.useState(false); const agreedDeliveryLabel = [ formatDeliveryDateDisplay(order.deliveryDate), order.deliveryTime || order.deliveryHalfDay, ].filter((value) => value && value !== "Нет данных").join(" · "); const handleShipmentChange = React.useCallback((state) => { setShipmentState(state); }, []); const handleSaveDeliveryChoice = async () => { const effectiveDate = deliveryType === "pickup" ? pickupDate : deliveryDate; const effectiveTime = deliveryType === "pickup" ? pickupTimeSlot : deliveryTime; if (!effectiveDate || !effectiveTime) { setFormMessage(deliveryType === "pickup" ? "Укажите дату и время самовывоза." : "Укажите дату и половину дня доставки."); return; } if (!isFutureDeliveryDate(effectiveDate)) { setFormMessage(deliveryType === "pickup" ? "Выберите дату самовывоза позже сегодняшнего дня." : "Выберите дату доставки позже сегодняшнего дня."); return; } try { const result = await onSaveManualDeliveryChoice?.({ orderGroupId: order.id, deliveryDate: deliveryType === "pickup" ? pickupDate : deliveryDate, deliveryTime: deliveryType === "pickup" ? pickupTimeSlot : deliveryTime, deliveryType, ...(deliveryType === "pickup" ? { pickupDate, pickupTimeSlot } : {}), ...(deliveryType === "delivery" && deliveryAddress.trim() ? { deliveryAddress: deliveryAddress.trim() } : {}), }); if (result?.success) { setFormMessage(deliveryType === "pickup" ? "Самовывоз согласован вручную." : "Доставка согласована вручную."); return; } setFormMessage(getErrorMessage(result?.error, "Не удалось сохранить согласование доставки.")); } catch (error) { setFormMessage(getErrorMessage(error, "Не удалось сохранить согласование доставки.")); } }; const handleAssignDriver = async () => { if (!selectedDriverId) { setDriverMessage("Выберите водителя"); return; } if (!order.deliveryDate) { setDriverMessage("Сначала укажите дату и время доставки."); return; } setDriverMessage(""); const response = await onAssignDriver({ orderGroupId: order.id, driverId: selectedDriverId, }); if (!response.success) { setDriverMessage(response.error || "Не удалось назначить водителя"); } else { setDriverMessage("Водитель назначен"); } }; return (

{(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "Карточка группы самовывоза" : "Карточка группы доставки"}

{order.displayTitle || order.customerName || order.groupKey}

{(() => { const parts = []; if (order.orderNumbers && order.orderNumbers.length > 0) parts.push(order.orderNumbers.join(", ")); const sub = order.displaySubtitle || [order.customerPhone, order.customerDate].filter(Boolean).join(" · "); if (sub) parts.push(sub); return parts.join(" · ") || "Не указано"; })()}

{getOrderGroupDisplayStatusLabel(order)}
{(() => { const isPickup = order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup"; const deliveryTypeLabel = isPickup ? "Самовывоз" : (order.deliveryStatus === "requires_address" || order.delivery_status === "requires_address") ? "Доставка (требуется адрес)" : "Доставка"; const dateLabel = isPickup ? "Дата самовывоза" : "Дата доставки"; const timeLabel = isPickup ? "Время самовывоза" : "Время доставки"; const addressLabel = isPickup ? "Адрес самовывоза" : "Адрес доставки"; // For pickup orders, hide the delivery address if it's just a placeholder like "Самовывоз" const effectiveAddress = isPickup ? (order.deliveryAddress && order.deliveryAddress !== "Самовывоз" && order.deliveryAddress !== "самовывоз" ? order.deliveryAddress : "") : order.deliveryAddress; return (

{dateLabel}

{formatDeliveryDateDisplay(order.deliveryDate)}

{timeLabel}

{renderValue(order.deliveryTime || order.deliveryHalfDay)}

Тип

{deliveryTypeLabel}

{(order.deliveryStatus === "requires_address" || order.delivery_status === "requires_address") && (
📍

Адрес доставки не указан

Клиент выбрал доставку, но адрес отсутствует. Уточните адрес у клиента и заполните поле ниже.

)}

Водитель

{order.assignedDriverId ? renderValue(order.assignedDriverName) : (isPickup ? "Не нужен" : "Не назначен")}

Телефон

{renderValue(order.customerPhone)}
{!isPickup || effectiveAddress ? (

{addressLabel}

{renderValue(effectiveAddress)}

) : null}
); })()}

Заказ

{(() => { const mainNumbers = order.orderNumbers || []; const allNumbers = order.allBillNumbers || []; const mainSet = new Set(mainNumbers.map(String)); const extraNumbers = allNumbers.filter((n) => !mainSet.has(String(n))); if (mainNumbers.length > 0) { return ( {mainNumbers.join(", ")} {extraNumbers.length > 0 && ( +{extraNumbers.length} сч. )} ); } return renderValue(order.orderNumberSummary); })()}

Клиент

{renderValue(order.customerName)}

Дата счёта

{renderValue(order.customerDate)}

Всего заказов

{order.ordersCount ?? 0}

Готово

{order.readyCount ?? 0}

Не готово

{order.notReadyCount ?? 0}

Обновлена

{formatDateTime(order.updatedAt)}

{(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "Статус самовывоза" : "Статус доставки"}

{getOrderGroupDeliveryStatusLabel(order.deliveryStatus || order.delivery_status)}

{canManageDelivery ? (
Ручное согласование

{isDeliveryAgreed ? "Дата и время уже зафиксированы." : "Если клиент согласовал доставку или самовывоз по телефону, сохраните дату и время здесь."}

{/* Delivery type tabs */}
{deliveryType === "pickup" && (

ℹ️ Условия хранения

Бесплатное хранение — 2 рабочих дня с даты готовности.

Начиная с 3-го рабочего дня — 300 ₽/день платного хранения.

)} {isDeliveryAgreed && !isEditingDate ? (

{(order.deliveryType === "pickup" || order.deliveryStatus === "pickup" || order.delivery_status === "pickup") ? "Самовывоз согласован" : "Доставка согласована"}

{agreedDeliveryLabel || "Дата и время сохранены"}

Согласовано
{canEditDelivery ? ( ) : null}
) : deliveryType === "delivery" ? (
{isCalendarOpen ? (

Календарь доставки

{monthLabel}

{WEEK_DAY_LABELS.map((day) => (
{day}
))}
{calendarDays.map((day, index) => { if (!day) { return
; } const dateKey = toDateKey(day); const isWeekend = isWeekendDate(day); const isSelectable = isSelectableCalendarDate(day, minSelectableDateKey); const isSelected = dateKey === deliveryDate; const isDisabled = !isSelectable; const dayNumber = String(day.getDate()).padStart(2, "0"); return ( ); })}

Выходные отмечены пунктиром и недоступны.

) : null}
{DELIVERY_TIME_OPTIONS.map((option) => ( ))}
) : (
{isCalendarOpen ? (

Календарь самовывоза

{monthLabel}

{WEEK_DAY_LABELS.map((day) => (
{day}
))}
{calendarDays.map((day, index) => { if (!day) return
; const dateKey = toDateKey(day); const isWeekend = isWeekendDate(day); const isSelectable = isSelectableCalendarDate(day, minSelectableDateKey); const isSelected = dateKey === pickupDate; const isDisabled = !isSelectable; const dayNumber = String(day.getDate()).padStart(2, "0"); return ( ); })}

Выходные отмечены пунктиром и недоступны.

) : null}
{DELIVERY_TIME_OPTIONS.map((option) => ( ))}
)} {formMessage ? (

{formMessage}

) : null} ) : null} {canManageDelivery && ["manager", "logistician", "admin", "mega_admin"].includes(userRole) ? (
Назначение водителя

{(() => { const ds = order.deliveryStatus || order.delivery_status; if (["loaded", "on_route", "delivered"].includes(ds)) { return "Доставка в процессе — сменить водителя нельзя."; } return order.assignedDriverId ? "Назначен водитель. Вы можете изменить назначение." : "Выберите водителя для доставки."; })()}

{order.assignedDriverId ? (

Водитель назначен

{order.assignedDriverName || "Неизвестно"}

Назначен
) : null} {(() => { const ds = order.deliveryStatus || order.delivery_status; const isDriverLocked = ["loaded", "on_route", "delivered"].includes(ds); return !isDriverLocked ? (
) : null; })()} {driverMessage ? (

{driverMessage}

) : null}
) : null} {["manager", "logistician", "admin", "mega_admin"].includes(userRole) && order && onChangeDeliveryStatus ? (
Статус доставки

Измените статус, если водитель забыл обновить или нужна корректировка.

{[ { value: "pending_confirmation", label: "Ожидает согласования", manual: true }, { value: "agreed", label: "Согласовано", manual: false, hint: "Согласуйте дату доставки выше" }, { value: "driver_assigned", label: "Назначен водитель", manual: false, hint: "Назначьте водителя из списка" }, { value: "loaded", label: "Загружено", manual: true }, { value: "on_route", label: "В пути", manual: true }, { value: "delivered", label: "Доставлено", manual: true }, { value: "pickup", label: "Самовывоз", manual: true }, { value: "requires_address", label: "Требуется адрес", manual: true }, { value: "problem", label: "Проблема", manual: true }, { value: "cancelled", label: "Отменено", manual: true }, ].map((statusOption) => { const isCurrent = (order.deliveryStatus || order.delivery_status) === statusOption.value; const isClickable = statusOption.manual !== false && !isCurrent; return (
); })}
{formMessage ? (

{formMessage}

) : null}
) : null} {["manager", "logistician", "admin", "mega_admin"].includes(userRole) && order && onChangeDeliveryStatus ? ( ) : null} {userRole === "driver" && order ? ( ) : null} {userRole === "driver" && order && onChangeDeliveryStatus ? (
Статус доставки

Выберите статус и нажмите «Сохранить».

{problemReason !== null ? ( { setPendingStatus({ value: "problem", reason: reasonValue, reasonLabel }); setProblemReason(null); }} onCancel={() => setProblemReason(null)} /> ) : null}
{(() => { const currentStatus = order.deliveryStatus || order.delivery_status; const IN_TRANSIT_STATUSES = ["loaded", "on_route"]; const isOnRoute = IN_TRANSIT_STATUSES.includes(currentStatus); let statusOptions = []; if (currentStatus === "delivered" || currentStatus === "problem" || currentStatus === "cancelled" || currentStatus === "paid_storage") { statusOptions = []; } else { statusOptions = [ { value: "delivered", label: "Доставлено" }, { value: "problem", label: "Проблема" }, ]; } if (statusOptions.length === 0) return null; return statusOptions.map((statusOption) => { const isSelected = pendingStatus?.value === statusOption.value; const isDeliveredBtn = statusOption.value === "delivered"; const deliveryBlocked = isDeliveredBtn && shipmentState && !shipmentState.canMarkDelivered; return ( ); }); })()}
{pendingStatus ? (
) : null} {formMessage ? (

{formMessage}

) : null}
) : null} Счета {(() => { const mainNumbers = order.orderNumbers || []; const allNumbers = getAllBillNumbers(order); const mainSet = new Set(mainNumbers.map(String)); const extraNumbers = allNumbers.filter((n) => !mainSet.has(String(n))); return (
{mainNumbers.length > 0 && (

Основной счёт

{mainNumbers.map((num, idx) => ( {num} ))}
)} {extraNumbers.length > 0 && (

{mainNumbers.length > 0 ? "Составные заказы" : "Все счета"}

{extraNumbers.map((num, idx) => ( {num} ))}
)} {mainNumbers.length === 0 && extraNumbers.length === 0 && (

Нет данных

)}
); })()}
{userRole !== "driver" && (order?.driver_shipment_data || order?.driverShipmentData) ? ( ) : null} {userRole !== "driver" ? ( Дополнительные данные
{order.firstSmsSentAt ? (

1-е SMS отправлено

{formatDateTime(order.firstSmsSentAt)}

) : null} {order.secondSmsSentAt ? (

2-е SMS отправлено

{formatDateTime(order.secondSmsSentAt)}

) : null} {!order.firstSmsSentAt && !order.secondSmsSentAt ? (

SMS отправлено

Нет

) : null}

Ручное согласование выполнено

{order.manualConfirmationAt ? formatDateTime(order.manualConfirmationAt) : "Нет"}

Платное хранение

{order.paidStorageAt ? formatDateTime(order.paidStorageAt) : "Нет"}

{order.createdFromExchangeAt ? (

Создано из обмена

{formatDateTime(order.createdFromExchangeAt)}

) : null}
) : null}
); };