fix: show saved client delivery choice

This commit is contained in:
Codex 2026-04-16 17:41:46 +03:00
parent 31388f267d
commit de0cf49490
4 changed files with 56 additions and 10 deletions

View File

@ -50,6 +50,7 @@ const splitOrderItem = (item) => {
export const DeliveryChoiceFlow = ({ export const DeliveryChoiceFlow = ({
invitation = {}, invitation = {},
selectedSlot = null, selectedSlot = null,
isChoiceSaved = false,
onConfirmChoice = () => {}, onConfirmChoice = () => {},
onRequestNewLink = () => {}, onRequestNewLink = () => {},
}) => { }) => {
@ -61,13 +62,16 @@ export const DeliveryChoiceFlow = ({
.map(splitOrderItem) .map(splitOrderItem)
.filter(Boolean); .filter(Boolean);
const slotSummary = selectedSlot ? formatDeliverySlotLabel(selectedSlot) : ""; const slotSummary = selectedSlot ? formatDeliverySlotLabel(selectedSlot) : "";
const isLocked = isChoiceSaved || !isActive;
const selectionCard = ( const selectionCard = (
<div className="space-y-3 rounded-[22px] border border-[var(--color-border)] bg-[var(--color-surface-strong)] p-4"> <div className="space-y-3 rounded-[22px] border border-[var(--color-border)] bg-[var(--color-surface-strong)] p-4">
<p className="text-sm uppercase tracking-[0.18em] text-[var(--color-text-muted)]">Выбранный слот</p> <p className="text-sm uppercase tracking-[0.18em] text-[var(--color-text-muted)]">
{isChoiceSaved ? "Сохранённый выбор" : "Выбранный слот"}
</p>
{slotSummary ? ( {slotSummary ? (
<p className="text-sm leading-6"> <p className="text-sm leading-6">
<span className="font-medium">Выбрано:</span> {slotSummary} <span className="font-medium">{isChoiceSaved ? "Сохранено:" : "Выбрано:"}</span> {slotSummary}
</p> </p>
) : ( ) : (
<p className="text-sm leading-6 text-[var(--color-text-muted)]"> <p className="text-sm leading-6 text-[var(--color-text-muted)]">
@ -119,6 +123,7 @@ export const DeliveryChoiceFlow = ({
{selectionCard} {selectionCard}
<div className="flex flex-col gap-3 sm:flex-row"> <div className="flex flex-col gap-3 sm:flex-row">
{!isLocked ? (
<Button <Button
className="w-full sm:w-auto" className="w-full sm:w-auto"
disabled={!slotSummary} disabled={!slotSummary}
@ -126,10 +131,13 @@ export const DeliveryChoiceFlow = ({
> >
Сохранить Сохранить
</Button> </Button>
) : null}
<Button variant="secondary" className="w-full sm:w-auto" onClick={onRequestNewLink}> <Button variant="secondary" className="w-full sm:w-auto" onClick={onRequestNewLink}>
Запросить новую ссылку Запросить новую ссылку
</Button> </Button>
</div> </div>
{isChoiceSaved ? <DeliveryStateNotice state="agreed" /> : null}
</Panel> </Panel>
); );
}; };

View File

@ -46,6 +46,30 @@ describe("DeliveryChoiceFlow", () => {
expect(markup).toContain("disabled"); expect(markup).toContain("disabled");
}); });
it("renders a saved selection in read-only mode", () => {
const markup = renderToStaticMarkup(
<DeliveryChoiceFlow
invitation={{
state: "agreed",
orderNumber: "CD-240031",
customerName: "Мария Волкова",
}}
selectedSlot={{
date: "2026-04-14",
time: "До обеда",
}}
isChoiceSaved
onConfirmChoice={() => {}}
onRequestNewLink={() => {}}
/>,
);
expect(markup).toContain("Сохранённый выбор");
expect(markup).toContain("14.04.2026");
expect(markup).toContain("До обеда");
expect(markup).not.toContain("Сохранить");
});
it("renders order items with quantities when they are provided", () => { it("renders order items with quantities when they are provided", () => {
const markup = renderToStaticMarkup( const markup = renderToStaticMarkup(
<DeliveryChoiceFlow <DeliveryChoiceFlow

View File

@ -22,6 +22,10 @@ const STATE_COPY = {
title: "Доставка уже согласована", title: "Доставка уже согласована",
description: "Выбор времени доставки уже сохранён в системе.", description: "Выбор времени доставки уже сохранён в системе.",
}, },
confirmed: {
title: "Доставка уже согласована",
description: "Выбор времени доставки уже сохранён в системе.",
},
default: { default: {
title: "Требуется ручная обработка", title: "Требуется ручная обработка",
description: "Сейчас по этому заказу недоступно самостоятельное согласование доставки.", description: "Сейчас по этому заказу недоступно самостоятельное согласование доставки.",

View File

@ -85,6 +85,7 @@ export const ClientDeliveryPage = () => {
const [actionMessage, setActionMessage] = React.useState(""); const [actionMessage, setActionMessage] = React.useState("");
const [selectedSlotId, setSelectedSlotId] = React.useState(null); const [selectedSlotId, setSelectedSlotId] = React.useState(null);
const [selectedSlot, setSelectedSlot] = React.useState(null); const [selectedSlot, setSelectedSlot] = React.useState(null);
const [choiceSaved, setChoiceSaved] = React.useState(false);
React.useEffect(() => { React.useEffect(() => {
let cancelled = false; let cancelled = false;
@ -98,6 +99,10 @@ export const ClientDeliveryPage = () => {
setLoading(true); setLoading(true);
setError(""); setError("");
setActionMessage("");
setSelectedSlotId(null);
setSelectedSlot(null);
setChoiceSaved(false);
try { try {
const loadedInvitation = await fetchDeliveryInvitation(token); const loadedInvitation = await fetchDeliveryInvitation(token);
@ -137,6 +142,7 @@ export const ClientDeliveryPage = () => {
); );
const effectiveSelectedSlot = selectedSlot || invitationSelectedSlot; const effectiveSelectedSlot = selectedSlot || invitationSelectedSlot;
const isChoiceSaved = choiceSaved || (!isActiveState && Boolean(invitationSelectedSlot));
const handleSaveChoice = React.useCallback( const handleSaveChoice = React.useCallback(
async () => { async () => {
@ -150,6 +156,7 @@ export const ClientDeliveryPage = () => {
} }
setActionMessage("Сохраняем выбор..."); setActionMessage("Сохраняем выбор...");
setChoiceSaved(false);
setError(""); setError("");
try { try {
@ -161,6 +168,7 @@ export const ClientDeliveryPage = () => {
const loadedInvitation = await fetchDeliveryInvitation(token); const loadedInvitation = await fetchDeliveryInvitation(token);
setInvitation(loadedInvitation); setInvitation(loadedInvitation);
setSelectedSlot(buildSelectedSlotFromInvitation(loadedInvitation, groupSlotsFromInvitation(loadedInvitation)) || effectiveSelectedSlot); setSelectedSlot(buildSelectedSlotFromInvitation(loadedInvitation, groupSlotsFromInvitation(loadedInvitation)) || effectiveSelectedSlot);
setChoiceSaved(true);
setActionMessage("Выбор сохранен, спасибо."); setActionMessage("Выбор сохранен, спасибо.");
} catch (confirmError) { } catch (confirmError) {
setActionMessage(""); setActionMessage("");
@ -174,6 +182,7 @@ export const ClientDeliveryPage = () => {
(slot) => { (slot) => {
setSelectedSlotId(slot.id); setSelectedSlotId(slot.id);
setSelectedSlot(slot); setSelectedSlot(slot);
setChoiceSaved(false);
setActionMessage( setActionMessage(
`Выбрано: ${slot.date ? `${formatDeliveryDate(slot.date)} / ${slot.time}` : slot.time}`, `Выбрано: ${slot.date ? `${formatDeliveryDate(slot.date)} / ${slot.time}` : slot.time}`,
); );
@ -227,7 +236,7 @@ export const ClientDeliveryPage = () => {
</p> </p>
</Panel> </Panel>
{isActiveState && slots.length ? ( {isActiveState && !isChoiceSaved && slots.length ? (
<DeliverySlotsPicker <DeliverySlotsPicker
slots={slots} slots={slots}
onSelectSlot={handleSlotSelect} onSelectSlot={handleSlotSelect}
@ -239,6 +248,7 @@ export const ClientDeliveryPage = () => {
<DeliveryChoiceFlow <DeliveryChoiceFlow
invitation={invitation} invitation={invitation}
selectedSlot={effectiveSelectedSlot} selectedSlot={effectiveSelectedSlot}
isChoiceSaved={isChoiceSaved}
onConfirmChoice={handleSaveChoice} onConfirmChoice={handleSaveChoice}
onRequestNewLink={handleRequestNewLink} onRequestNewLink={handleRequestNewLink}
/> />