From 496abc761b4ce8650ae130bb2b5fd6fe10c7e449 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 14 May 2026 21:10:27 +0300 Subject: [PATCH] fix(delivery): simplify public choice flow --- src/components/client/DeliveryChoiceFlow.jsx | 4 --- .../client/DeliveryChoiceFlow.test.jsx | 7 +---- src/components/client/DeliverySlotsPicker.jsx | 28 +++++++++++++------ .../client/DeliverySlotsPicker.test.jsx | 17 +++++++++++ src/pages/ClientDeliveryPage.jsx | 26 ++++++++++------- src/pages/ClientDeliveryPage.test.js | 11 ++++++++ 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/components/client/DeliveryChoiceFlow.jsx b/src/components/client/DeliveryChoiceFlow.jsx index 4e35489..5e2874c 100644 --- a/src/components/client/DeliveryChoiceFlow.jsx +++ b/src/components/client/DeliveryChoiceFlow.jsx @@ -52,7 +52,6 @@ export const DeliveryChoiceFlow = ({ invitation = {}, selectedSlot = null, onConfirmChoice = () => {}, - onRequestNewLink = () => {}, }) => { const state = invitation.state || "awaiting_choice"; const isActive = ACTIVE_STATES.has(state); @@ -108,9 +107,6 @@ export const DeliveryChoiceFlow = ({ > Сохранить - ); diff --git a/src/components/client/DeliveryChoiceFlow.test.jsx b/src/components/client/DeliveryChoiceFlow.test.jsx index f5aba7f..f242b32 100644 --- a/src/components/client/DeliveryChoiceFlow.test.jsx +++ b/src/components/client/DeliveryChoiceFlow.test.jsx @@ -13,13 +13,13 @@ describe("DeliveryChoiceFlow", () => { customerName: "Мария Волкова", }} onConfirmChoice={() => {}} - onRequestNewLink={() => {}} />, ); expect(markup).toContain("Выберите время доставки"); expect(markup).toContain("Сохранить"); expect(markup).toContain("Ожидает ответа клиента"); + expect(markup).not.toContain("Запросить новую ссылку"); }); it("renders a disabled save action when nothing is selected", () => { @@ -31,7 +31,6 @@ describe("DeliveryChoiceFlow", () => { customerName: "Мария Волкова", }} onConfirmChoice={() => {}} - onRequestNewLink={() => {}} />, ); @@ -54,7 +53,6 @@ describe("DeliveryChoiceFlow", () => { availableSlots: ["Первая половина дня", "Вторая половина дня"], }} onConfirmChoice={() => {}} - onRequestNewLink={() => {}} />, ); @@ -75,7 +73,6 @@ describe("DeliveryChoiceFlow", () => { customerName: "Мария Волкова", }} onConfirmChoice={() => {}} - onRequestNewLink={() => {}} />, ); @@ -92,7 +89,6 @@ describe("DeliveryChoiceFlow", () => { customerName: "Мария Волкова", }} onConfirmChoice={() => {}} - onRequestNewLink={() => {}} />, ); @@ -110,7 +106,6 @@ describe("DeliveryChoiceFlow", () => { availableSlots: ["15 апреля, первая половина дня"], }} onConfirmChoice={() => {}} - onRequestNewLink={() => {}} />, ); diff --git a/src/components/client/DeliverySlotsPicker.jsx b/src/components/client/DeliverySlotsPicker.jsx index 2a17951..8159faf 100644 --- a/src/components/client/DeliverySlotsPicker.jsx +++ b/src/components/client/DeliverySlotsPicker.jsx @@ -6,6 +6,20 @@ import { formatDeliverySlotGroupLabel } from "./deliveryDateFormatting"; const groupSlotsByDate = (slots) => { const groups = new Map(); + const getSlotPriority = (slot) => { + const time = String(slot?.time || "").toLowerCase(); + + if (time.includes("первая") || time.includes("до обеда")) { + return 0; + } + + if (time.includes("вторая") || time.includes("после обеда")) { + return 1; + } + + return 2; + }; + for (const slot of slots) { if (!groups.has(slot.date)) { groups.set(slot.date, []); @@ -14,7 +28,12 @@ const groupSlotsByDate = (slots) => { groups.get(slot.date).push(slot); } - return Array.from(groups.entries()).sort(([a], [b]) => a.localeCompare(b)); + return Array.from(groups.entries()) + .map(([date, dateSlots]) => [ + date, + [...dateSlots].sort((left, right) => getSlotPriority(left) - getSlotPriority(right)), + ]) + .sort(([a], [b]) => a.localeCompare(b)); }; export { formatDeliverySlotGroupLabel } from "./deliveryDateFormatting"; @@ -37,13 +56,6 @@ export const DeliverySlotsPicker = ({ return (
- -

Выберите день и половину дня доставки

-

- Раскройте нужный день, выберите подходящую половину и затем сохраните выбор ниже. -

-
- {grouped.map(([date, dateSlots]) => (
diff --git a/src/components/client/DeliverySlotsPicker.test.jsx b/src/components/client/DeliverySlotsPicker.test.jsx index 78ecb85..e44f21e 100644 --- a/src/components/client/DeliverySlotsPicker.test.jsx +++ b/src/components/client/DeliverySlotsPicker.test.jsx @@ -37,6 +37,23 @@ describe("DeliverySlotsPicker", () => { expect(markup).toContain("послезавтра · 15.04.2026"); expect(markup).toContain("первая половина дня"); expect(markup).toContain("вторая половина дня"); + expect(markup).not.toContain("выберите день и половину дня доставки"); + }); + + it("renders the first half of day before the second half", () => { + const markup = renderToStaticMarkup( + {}} + selectedSlotId={null} + referenceDate={new Date("2026-04-13T09:00:00Z")} + />, + ).toLowerCase(); + + expect(markup.indexOf("первая половина дня")).toBeLessThan(markup.indexOf("вторая половина дня")); }); it("marks the selected slot", () => { diff --git a/src/pages/ClientDeliveryPage.jsx b/src/pages/ClientDeliveryPage.jsx index 5efc373..019e72b 100644 --- a/src/pages/ClientDeliveryPage.jsx +++ b/src/pages/ClientDeliveryPage.jsx @@ -152,6 +152,16 @@ export const buildSelectedSlotFromInvitation = (invitation, slots = []) => { }; }; +export const getClientDeliveryHeroDescription = (isActiveState, isChoiceSaved) => { + if (isChoiceSaved) { + return ""; + } + + return isActiveState + ? "Вам предложены варианты доставки. Выберите удобную дату и время." + : "По этому заказу согласование доставки завершено или передано логисту."; +}; + export const ClientDeliveryPage = () => { const { token } = useParams(); const [invitation, setInvitation] = React.useState(null); @@ -216,6 +226,7 @@ export const ClientDeliveryPage = () => { const savedChoiceLabel = effectiveSelectedSlot ? `${formatDeliveryDate(effectiveSelectedSlot.date)} / ${effectiveSelectedSlot.time}` : ""; + const heroDescription = getClientDeliveryHeroDescription(isActiveState, isChoiceSaved); const handleSaveChoice = async () => { if (!token) { @@ -263,10 +274,6 @@ export const ClientDeliveryPage = () => { setError(""); }; - const handleRequestNewLink = () => { - setActionMessage("Если ссылка больше не работает, логист передаст новую ссылку вручную."); - }; - if (loading) { return (
@@ -301,11 +308,11 @@ export const ClientDeliveryPage = () => {

Доставка заказа

Согласование доставки

-

- {isActiveState - ? "Вам предложены варианты доставки. Выберите удобную дату и время." - : "По этому заказу согласование доставки завершено или передано логисту."} -

+ {heroDescription ? ( +

+ {heroDescription} +

+ ) : null}
{isChoiceSaved && savedChoiceLabel ? ( @@ -334,7 +341,6 @@ export const ClientDeliveryPage = () => { invitation={invitation} selectedSlot={effectiveSelectedSlot} onConfirmChoice={handleSaveChoice} - onRequestNewLink={handleRequestNewLink} /> ) : !isChoiceSaved ? ( diff --git a/src/pages/ClientDeliveryPage.test.js b/src/pages/ClientDeliveryPage.test.js index 2613222..e9b1d3e 100644 --- a/src/pages/ClientDeliveryPage.test.js +++ b/src/pages/ClientDeliveryPage.test.js @@ -3,6 +3,7 @@ import { getInvitationReferenceLabel } from "../components/client/invitationRefe import { buildDeliveryConfirmationPayload, buildSelectedSlotFromInvitation, + getClientDeliveryHeroDescription, groupSlotsFromInvitation, } from "./ClientDeliveryPage"; @@ -176,4 +177,14 @@ describe("ClientDeliveryPage helpers", () => { }), ).toBe("Счета: СФ Т\\ЕА-28687, СФ Т\\ЕА-28700"); }); + + it("hides the hero helper text after the client saves the choice", () => { + expect(getClientDeliveryHeroDescription(true, true)).toBe(""); + expect(getClientDeliveryHeroDescription(true, false)).toBe( + "Вам предложены варианты доставки. Выберите удобную дату и время.", + ); + expect(getClientDeliveryHeroDescription(false, false)).toBe( + "По этому заказу согласование доставки завершено или передано логисту.", + ); + }); });