Když provozujete B2B e-shop s autodíly, zboží nekončí u výdejního okénka — vozíte ho zákazníkům. A každý zákazník má jiné místo, jiný čas, jiné požadavky. Když jich máte desítky, potřebujete systém, který hlídá, kdo kam patří a co se veze.
Nedávno jsem do white-label e-shopu s autodíly přidal správu doručovacích tras — a tady je, jak to vypadá.
Problém
E-shop měl objednávky, dodací listy, faktury — ale chyběla mu vrstva, která by propojila zákazníka s konkrétní trasou rozvozu. Admin věděl, že má někomu něco dovézt, ale musel si pamatovat, jestli je to „Kolín-jih” nebo „Kutná Hora”. Na dokladech chyběla adresa doručení, kontakt a poznámka k rozvozu.
Řešení: tři vrstvy
1. Definice tras
V admin sekci přibyla stránka pro správu tras. Každá trasa má název, adresu, kontaktní osobu, telefon a poznámku. Trasu lze zapnout a vypnout — neaktivní trasy se nenabízejí při přiřazování.
// Schema
model DeliveryRoute {
id String @id @default(cuid())
name String
deliveryAddress String?
contactName String?
contactPhone String?
note String?
active Boolean @default(true)
sortOrder Int @default(0)
customers Customer[]
}
2. Přiřazení zákazníka k trase
V detailu zákazníka přibyl samostatný záložka Doručení. Admin tu nastaví:
- Trasa — výběr z aktivních tras
- Adresa doručení — může se lišit od fakturační
- Kontaktní osoba a telefon — kdo na místě přebírá zboží
- Poznámka k doručení — volný text (třeba „zavolat 30 minut před příjezdem”)
Doručovací údaje jsou oddělené od fakturačních — B2B zákazníci často mají sklad jinde než sídlo firmy.
3. Zobrazení na dokladech
Trasa a doručovací údaje se propsaly do:
- Detailu objednávky — admin vidí rovnou název trasy
- Dodacích listů a faktur — na dokumentu je adresa doručení, kontakt a poznámka
- PDF exportu — stejné údaje v tisknutelné podobě
Zpětná vazba u server actions
Spolu s doručovacími trasami jsem sjednotil UX zpětnou vazby u server actions. Vznikl komponent ActionFeedbackForm, který obaluje <form> s action a automaticky zobrazuje:
- Pending stav — tlačítko se změní na „Ukládám…” a zneaktivní se
- Success stav — krátké zelené potvrzení „Uloženo”
- Error stav — fallback hláška při selhání
Druhý komponent PendingSubmitButton řeší stejný problém na úrovni jednoho tlačítka — hodí se tam, kde celý formulář není potřeba obalovat.
// Použití
<ActionFeedbackForm
action={updateDeliveryRoute}
pendingLabel="Ukládám…"
successLabel="Uloženo"
errorFallback="Chyba při ukládání"
>
{/* formulářová pole */}
<Button type="submit">Uložit</Button>
</ActionFeedbackForm>
Co to přineslo
- Admin vidí na první pohled, která trasa ke které objednávce patří
- Zákazníci mají na dokladech správnou adresu doručení
- Řidič dostane u každé zásilky kontakt a poznámku
- Nové trasy se přidávají bez zásahu do kódu
Celá změna proběhla čistě v databázi (Prisma migrace), API vrstvě (server actions) a UI — žádný externí systém, žádná další závislost.