import React from "react"; import { getOrderGroupDeliveryHalfDay, getOrderGroupDeliveryStatusLabel, getOrderGroupDeliveryStatusTone, DRIVER_VISIBLE_DELIVERY_STATUSES, isOrderGroupVisibleToDriver, groupOrderGroupsByDate, parseGroupDate, } from "../../services/orderGroupViews"; import { Badge } from "../UI/Badge"; import { Input } from "../UI/Input"; import { Select } from "../UI/Select"; import { Panel } from "../UI/Panel"; const extractCity = (address) => { if (!address || typeof address !== "string") return null; const trimmed = address.trim(); if (!trimmed) return null; // Patterns: "г.Ялта", "г. Ялта", "г Ялта", "г Ялта ", "Ялта,", "г.Севастополь", etc. const cityMatch = trimmed.match(/(?:г\.?\s*|г\s+)([А-ЯЁA-Z][а-яёa-zA-Z\s\-]+?)(?:\s*[,;.]|$)/i); if (cityMatch) { return cityMatch[1].trim(); } // Try common city names directly in the address const knownCities = [ "Севастополь", "Ялта", "Симферополь", "Феодосия", "Евпатория", "Керчь", "Алушта", "Бахчисарай", "Судак", "Инкерман", "Джанкой", "Красногвардейское", "Раздольное", "Черноморское", ]; for (const city of knownCities) { if (trimmed.toLowerCase().includes(city.toLowerCase())) { return city; } } // Fallback: first comma-separated segment if it looks like a city const firstSegment = trimmed.split(/[,;]/)[0].trim(); if (firstSegment.length > 2 && firstSegment.length < 30 && !/^\d/.test(firstSegment)) { return firstSegment; } return null; }; const normalizeCity = (address) => { const city = extractCity(address); return city || "Севастополь"; }; const DRIVER_DELIVERY_STATUS_OPTIONS = [ { value: "all", label: "Все статусы" }, ...DRIVER_VISIBLE_DELIVERY_STATUSES.map((status) => ({ value: status, label: status === "driver_assigned" ? "Назначено вам" : getOrderGroupDeliveryStatusLabel(status), })), ]; export const DriverDeliveryPlanner = ({ orderGroups = [], onOpenOrder, currentUser }) => { const [filters, setFilters] = React.useState({ selectedDate: "", deliveryStatus: "all", selectedCity: "", }); const driverOrderGroups = React.useMemo( () => orderGroups.filter((group) => { const isVisible = isOrderGroupVisibleToDriver(group); const isAssignedToMe = currentUser && group.assignedDriverId === currentUser.id; return isVisible && isAssignedToMe; }), [orderGroups, currentUser], ); // Build map of date -> count const dateDeliveryMap = React.useMemo(() => { const map = new Map(); driverOrderGroups.forEach((group) => { const date = group.deliveryDate; if (date) { map.set(date, (map.get(date) || 0) + 1); } }); return map; }, [driverOrderGroups]); const sortedDeliveryDates = React.useMemo(() => { return Array.from(dateDeliveryMap.keys()).sort(); }, [dateDeliveryMap]); // Build map of city -> count const cityDeliveryMap = React.useMemo(() => { const map = new Map(); driverOrderGroups.forEach((group) => { const city = normalizeCity(group.deliveryAddress || group.delivery_address); map.set(city, (map.get(city) || 0) + 1); }); return map; }, [driverOrderGroups]); const sortedCities = React.useMemo(() => { return Array.from(cityDeliveryMap.keys()).sort((a, b) => { // Севастополь first, then alphabetical if (a === "Севастополь") return -1; if (b === "Севастополь") return 1; return a.localeCompare(b, "ru"); }); }, [cityDeliveryMap]); const filteredOrderGroups = React.useMemo(() => { let result = [...driverOrderGroups]; if (filters.selectedDate) { result = result.filter((group) => group.deliveryDate === filters.selectedDate); } if (filters.deliveryStatus !== "all") { result = result.filter((group) => (group.deliveryStatus || group.delivery_status) === filters.deliveryStatus); } if (filters.selectedCity) { result = result.filter((group) => { const city = normalizeCity(group.deliveryAddress || group.delivery_address); return city === filters.selectedCity; }); } return result; }, [driverOrderGroups, filters.selectedDate, filters.deliveryStatus, filters.selectedCity]); const groupedOrderGroups = React.useMemo( () => groupOrderGroupsByDate(filteredOrderGroups), [filteredOrderGroups], ); const deliveryCountLabel = `${filteredOrderGroups.length} ${ filteredOrderGroups.length === 1 ? "доставка" : filteredOrderGroups.length < 5 ? "доставки" : "доставок" }`; const isDateSelected = (date) => filters.selectedDate === date; return (

Мои доставки

{deliveryCountLabel}

Показываем только назначенные вам группы доставки. Выберите дату и город.

{/* Date pills */} {sortedDeliveryDates.length > 0 && (
{sortedDeliveryDates.map((date) => { const count = dateDeliveryMap.get(date) || 0; const selected = isDateSelected(date); return ( ); })}
)} {/* City pills */} {sortedCities.length > 1 && (
{sortedCities.map((city) => { const count = cityDeliveryMap.get(city) || 0; const selected = filters.selectedCity === city; return ( ); })}
)}
{groupedOrderGroups.length ? ( groupedOrderGroups.map((group) => { // Group items by delivery status within each date const statusBuckets = new Map(); for (const item of group.items) { const s = item.deliveryStatus || item.delivery_status || "unknown"; const label = s === "driver_assigned" ? "Назначено вам" : getOrderGroupDeliveryStatusLabel(s); const tone = getOrderGroupDeliveryStatusTone(s); if (!statusBuckets.has(s)) { statusBuckets.set(s, { label, tone, items: [] }); } statusBuckets.get(s).items.push(item); } // Sort status buckets in driver-relevant order const statusOrder = ["driver_assigned", "loaded", "on_route", "delivered", "problem"]; const sortedBuckets = Array.from(statusBuckets.entries()).sort(([a], [b]) => { const ia = statusOrder.indexOf(a); const ib = statusOrder.indexOf(b); if (ia === -1 && ib === -1) return a.localeCompare(b); if (ia === -1) return 1; if (ib === -1) return -1; return ia - ib; }); return (

{parseGroupDate(group.date)?.toLocaleDateString("ru-RU", { day: "numeric", month: "long", weekday: "long", }) || "Без даты"}

{group.items.length} {group.items.length === 1 ? "группа" : "группы"}

{(() => { const d = parseGroupDate(group.date); if (!d) return group.date || "—"; const day = String(d.getDate()).padStart(2, "0"); const month = String(d.getMonth() + 1).padStart(2, "0"); const year = d.getFullYear(); return `${day}.${month}.${year}`; })()}
{sortedBuckets.map(([statusValue, { label, tone, items }]) => (
{label} {items.length} {items.length === 1 ? "группа" : "группы"}
{items.map((item) => ( ))}
))}
); }) ) : (

Доставки не найдены

Сейчас у вас нет назначенных групп доставки.

)}
); };