import { OverlayTrigger, Tooltip } from 'react-bootstrap'; import { TrackingProvider } from '../../../types'; import './OrderProgress.scss'; const STEPS = ['Přijato', 'Příprava', 'Vyzvedávání', 'Na cestě', 'Doručeno']; /** Lidský název rozvozové služby do tooltipu. */ export const PROVIDER_LABEL: Record = { bolt: 'Bolt Food', wolt: 'Wolt', }; /** * Známé stavy objednávky z Bolt API → index kroku ve stepperu. * Pozor: waiting_delivery znamená "jídlo čeká v podniku na vyzvednutí", * nikoli "na cestě" — tu signalizuje až stav kurýra (picked_up apod.). * Krok „Vyzvedávání" je vyhrazen pro kombinaci „kurýr u podniku + jídlo hotové" * (viz logika níže), samotný order_state ho neudělí — jinak bychom hlásili * vyzvedávání i když se ještě peče (chování, na které si Bolt sám občas stěžuje). */ const BOLT_STATE_TO_STEP: Record = { created: 0, pending: 0, waiting_acceptance: 0, accepted: 0, waiting_preparation: 0, preparing: 1, waiting_delivery: 1, ready_for_pickup: 1, waiting_courier: 1, waiting_pickup: 1, picked_up: 3, in_delivery: 3, delivering: 3, heading_to_client: 3, delivered: 4, finished: 4, }; /** Stavy kurýra z Bolt API → index kroku. Kurýr u podniku ještě neznamená "na cestě". */ const BOLT_COURIER_STATE_TO_STEP: Record = { matched: 0, accepted: 0, heading_to_provider: 1, arrived_to_provider: 1, picked_up: 3, heading_to_client: 3, delivering: 3, arrived_to_client: 3, delivered: 4, }; /** * Známé stavy objednávky z Wolt tracking API → index kroku ve stepperu. * Pozor: Wolt hlásí stav podniku, ne rozvozu — "ready" (jídlo hotové) zůstává * i celou dobu, co kurýr objednávku veze. Kroky „Vyzvedávání" a „Na cestě" proto * neurčuje status, ale odvozený stav kurýra (viz trackingProviders.ts). */ const WOLT_STATE_TO_STEP: Record = { received: 0, acknowledged: 0, confirmed: 0, waiting: 0, production: 1, preparing: 1, ready: 1, picked_up: 3, transport: 3, delivering: 3, delivered: 4, }; /** Popis odvozeného stavu kurýra u Woltu do tooltipu. */ const WOLT_COURIER_INFO: Record = { assigned: 'kurýr přiřazen', delivering: 'kurýr veze objednávku', delivering_other: 'kurýr veze objednávku, ale nejdřív doručuje jinou', }; /** Stavy, ve kterých už jídlo čeká připravené na kurýra. */ const PICKUP_READY_STATES: Record> = { bolt: new Set(['waiting_delivery', 'ready_for_pickup', 'waiting_courier', 'waiting_pickup']), wolt: new Set(['ready']), }; /** Neznámé stavy se mapují heuristicky podle klíčových slov. */ function stepForOrderState(provider: TrackingProvider, state: string): number | 'cancelled' { const s = state.toLowerCase(); const known = provider === 'wolt' ? WOLT_STATE_TO_STEP : BOLT_STATE_TO_STEP; if (s in known) return known[s]; if (/cancel|reject|fail/.test(s)) return 'cancelled'; if (/delivered|finished/.test(s)) return 4; if (/accept|pending|created|received/.test(s)) return 0; if (/^waiting|prepar|ready|cook|production/.test(s)) return 1; if (/picked|delivering|heading_to_client|transport/.test(s)) return 3; return 0; } function stepForCourierState(provider: TrackingProvider, state?: string): number { if (!state) return 0; const s = state.toLowerCase(); // Wolt má jen odvozené stavy: 'assigned' o kroku nic neříká, 'delivering' // i 'delivering_other' znamenají, že kurýr naši objednávku už veze if (provider === 'wolt') return s.startsWith('delivering') ? 3 : 0; if (s in BOLT_COURIER_STATE_TO_STEP) return BOLT_COURIER_STATE_TO_STEP[s]; if (/picked|client|delivering|transport/.test(s)) return 3; return 0; } interface Props { /** Rozvozová služba, ze které stav pochází */ provider: TrackingProvider; /** Raw stav objednávky (Bolt order_state, Wolt status) */ state: string; /** Raw stav kurýra (Bolt courier.state, Wolt 'assigned') */ courierState?: string; /** Zda sledování stále běží (skupina má trackingCode) */ tracking: boolean; } /** Mini progress stepper se stavem objednávky u rozvozové služby. */ export default function OrderProgress({ provider, state, courierState, tracking }: Props) { const label = PROVIDER_LABEL[provider] ?? provider; const orderStep = stepForOrderState(provider, state); if (orderStep === 'cancelled') { return Objednávka {label} byla zrušena; } // Stav kurýra může krok jen zpřesnit dopředu (např. waiting_delivery + picked_up → Na cestě) let step = Math.max(orderStep, stepForCourierState(provider, courierState)); // Vyzvedávání = kurýr u podniku a jídlo skutečně hotové. Sám arrived_to_provider // (bez toho, že by jídlo bylo hotové) nestačí — viz komentář u BOLT_STATE_TO_STEP. const courierAtProvider = provider === 'wolt' ? !!courierState : courierState?.toLowerCase() === 'arrived_to_provider'; const foodReadyForPickup = PICKUP_READY_STATES[provider]?.has(state.toLowerCase()); if (step < 3 && courierAtProvider && foodReadyForPickup) step = 2; const courierInfo = provider === 'wolt' ? WOLT_COURIER_INFO[courierState ?? ''] ?? 'kurýr přiřazen' : `kurýr: ${courierState}`; const rawInfo = courierState ? `${state} / ${courierInfo}` : state; return ( Stav z {label}: {rawInfo}}>
{STEPS.map((stepLabel, i) => (
{stepLabel}
))}
); }