From 7d29d63d2d68ab7a8295a4fab0b6efca74d96446 Mon Sep 17 00:00:00 2001 From: riyadhafraa <49757212-riyadhafraa@users.noreply.replit.com> Date: Wed, 22 Apr 2026 09:58:49 +0000 Subject: [PATCH] Add Undo window when receivers cancel an incoming order Original task (#73): Mirror the existing 7s Undo toast (already in place for owner-side cancels in My Orders) on the receiver-side cancel action in the Incoming Orders page. Implementation: - artifacts/teaboy-os/src/pages/orders-incoming.tsx - Captures the order's previous status (received | preparing) before issuing the cancel PATCH. - On success, shows a toast with title "Order cancelled" and an "Undo" ToastAction. Clicking Undo PATCHes the order status back to the previous value, then shows a "Restored" confirmation toast. - UNDO_WINDOW_MS = 7000 to match the owner-side flow. - artifacts/api-server/src/routes/service-orders.ts - Refactored the PATCH /orders/:id/status authorization. Detects "restore from cancelled" up front (existing.status === cancelled and next !== cancelled) and grants permission to: - owner/admin: may restore to pending or received (existing rule) - original assignee: may restore to received or preparing (NEW) - The same 15s server-side undo window applies. - artifacts/teaboy-os/src/locales/{en,ar}.json - Added incomingOrders.cancelled / undo / undone / restoreFailed strings in English and Arabic. - Regenerated lib/api-zod and lib/api-client-react via the api-spec codegen script (the previously-cached output was missing pending / received / preparing from the request body enum, which now matches the OpenAPI spec). Verification: - Typecheck passes for api-server and teaboy-os. - e2e flow verified: cancelling a received order shows the Undo toast; clicking Undo restores the order to "received" (DB confirmed); letting the window expire leaves the order permanently "cancelled" (DB confirmed). Deviations: None. Replit-Task-Id: 65c4b053-613a-4898-a0f7-b6fb2d680301 --- .../api-server/src/routes/service-orders.ts | 77 +++++++++++------- artifacts/teaboy-os/public/opengraph.jpg | Bin 25890 -> 24672 bytes artifacts/teaboy-os/src/locales/ar.json | 6 +- artifacts/teaboy-os/src/locales/en.json | 6 +- .../teaboy-os/src/pages/orders-incoming.tsx | 60 ++++++++++++++ 5 files changed, 117 insertions(+), 32 deletions(-) diff --git a/artifacts/api-server/src/routes/service-orders.ts b/artifacts/api-server/src/routes/service-orders.ts index cc54c9bb..63c7b8a3 100644 --- a/artifacts/api-server/src/routes/service-orders.ts +++ b/artifacts/api-server/src/routes/service-orders.ts @@ -302,7 +302,49 @@ router.patch( const admin = await isAdmin(userId); - if (next === "preparing" || next === "completed") { + const isRestoreFromCancelled = + existing.status === "cancelled" && next !== "cancelled"; + + if (isRestoreFromCancelled) { + // Restore a cancelled order back to a prior active status (Undo). + // Owner/admin may restore to pending or received; the original + // assignee may restore to received or preparing. + const isOwner = existing.userId === userId; + const isAssignee = existing.assignedTo === userId; + const canOwnerRestore = + (isOwner || admin) && (next === "pending" || next === "received"); + const canAssigneeRestore = + isAssignee && (next === "received" || next === "preparing"); + if (!canOwnerRestore && !canAssigneeRestore) { + if (!isOwner && !isAssignee && !admin) { + res.status(403).json({ error: "Forbidden" }); + return; + } + res.status(400).json({ error: "invalid_transition" }); + return; + } + if (next === "pending" && existing.assignedTo !== null) { + res.status(400).json({ error: "invalid_transition" }); + return; + } + if ( + (next === "received" || next === "preparing") && + existing.assignedTo === null + ) { + res.status(400).json({ error: "invalid_transition" }); + return; + } + // Enforce the undo window: once the window expires, the + // cancellation is permanent. Admin is also bound by this so + // restore is always Undo, never an arbitrary reopen. + const cancelledAt = existing.updatedAt + ? new Date(existing.updatedAt).getTime() + : 0; + if (Date.now() - cancelledAt > RESTORE_WINDOW_MS) { + res.status(400).json({ error: "undo_window_expired" }); + return; + } + } else if (next === "preparing" || next === "completed") { // Only the assigned receiver or admin const isAssignee = existing.assignedTo === userId; if (!isAssignee && !admin) { @@ -318,35 +360,10 @@ router.patch( return; } } else if (next === "pending" || next === "received") { - // Restore a cancelled order back to its prior status (Undo). - // Allowed for the owner or admin only. - const isOwner = existing.userId === userId; - if (!isOwner && !admin) { - res.status(403).json({ error: "Forbidden" }); - return; - } - if (existing.status !== "cancelled") { - res.status(400).json({ error: "invalid_transition" }); - return; - } - // Enforce the undo window: once the window expires, the - // cancellation is permanent. Admin is also bound by this so - // restore is always Undo, never an arbitrary reopen. - const cancelledAt = existing.updatedAt - ? new Date(existing.updatedAt).getTime() - : 0; - if (Date.now() - cancelledAt > RESTORE_WINDOW_MS) { - res.status(400).json({ error: "undo_window_expired" }); - return; - } - if (next === "pending" && existing.assignedTo !== null) { - res.status(400).json({ error: "invalid_transition" }); - return; - } - if (next === "received" && existing.assignedTo === null) { - res.status(400).json({ error: "invalid_transition" }); - return; - } + // Restore is handled above; outside cancelled, these targets are + // never valid via this endpoint. + res.status(400).json({ error: "invalid_transition" }); + return; } else if (next === "cancelled") { const isOwner = existing.userId === userId; const isAssignee = existing.assignedTo === userId; diff --git a/artifacts/teaboy-os/public/opengraph.jpg b/artifacts/teaboy-os/public/opengraph.jpg index 0e6b3fdd39ddcf1bd7cb5a594d7c6434756866b8..5e4be343a23951e31c74d2bf3f3a946e54fb6828 100644 GIT binary patch literal 24672 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 K(|r2d&;JIh;lG{$ literal 25890 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 diff --git a/artifacts/teaboy-os/src/locales/ar.json b/artifacts/teaboy-os/src/locales/ar.json index c05edb2a..0124a409 100644 --- a/artifacts/teaboy-os/src/locales/ar.json +++ b/artifacts/teaboy-os/src/locales/ar.json @@ -182,7 +182,11 @@ "alreadyClaimed": "استلمه شخص آخر قبلك", "actionFailed": "تعذّر تنفيذ الإجراء", "claimed": "تم استلام الطلب", - "marked": "تم تحديث الحالة" + "marked": "تم تحديث الحالة", + "cancelled": "تم إلغاء الطلب", + "undo": "تراجع", + "undone": "تمت الاستعادة", + "restoreFailed": "تعذّر استعادة الطلب" }, "chat": { "title": "المحادثات", diff --git a/artifacts/teaboy-os/src/locales/en.json b/artifacts/teaboy-os/src/locales/en.json index c7dd42f3..64f641fb 100644 --- a/artifacts/teaboy-os/src/locales/en.json +++ b/artifacts/teaboy-os/src/locales/en.json @@ -182,7 +182,11 @@ "alreadyClaimed": "Already claimed by someone else", "actionFailed": "Could not complete the action", "claimed": "Order received", - "marked": "Status updated" + "marked": "Status updated", + "cancelled": "Order cancelled", + "undo": "Undo", + "undone": "Restored", + "restoreFailed": "Could not restore the order" }, "chat": { "title": "Chat", diff --git a/artifacts/teaboy-os/src/pages/orders-incoming.tsx b/artifacts/teaboy-os/src/pages/orders-incoming.tsx index 2c016115..e9ae06cb 100644 --- a/artifacts/teaboy-os/src/pages/orders-incoming.tsx +++ b/artifacts/teaboy-os/src/pages/orders-incoming.tsx @@ -22,6 +22,7 @@ import { Loader2, } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { ToastAction } from "@/components/ui/toast"; import { useAuth } from "@/contexts/AuthContext"; import { useToast } from "@/hooks/use-toast"; import { resolveServiceImageUrl } from "@/lib/image-url"; @@ -29,6 +30,8 @@ import { cn } from "@/lib/utils"; export const ORDER_RECEIVER_ROLE = "order_receiver"; +const UNDO_WINDOW_MS = 7000; + export function userCanReceiveOrders(roles: string[] | undefined | null): boolean { if (!roles) return false; return roles.includes("admin") || roles.includes(ORDER_RECEIVER_ROLE); @@ -136,6 +139,10 @@ function IncomingOrderCard({ }; const handleSetStatus = (status: "preparing" | "completed" | "cancelled") => { + if (status === "cancelled") { + handleCancel(); + return; + } updateStatus.mutate( { id: order.id, data: { status } }, { @@ -153,6 +160,59 @@ function IncomingOrderCard({ ); }; + const handleCancel = () => { + const previousStatus = order.status; + if (previousStatus !== "received" && previousStatus !== "preparing") { + return; + } + updateStatus.mutate( + { id: order.id, data: { status: "cancelled" } }, + { + onSuccess: () => { + invalidate(); + + const undo = () => { + updateStatus.mutate( + { id: order.id, data: { status: previousStatus } }, + { + onSuccess: () => { + invalidate(); + handle.dismiss(); + toast({ title: t("incomingOrders.undone") }); + }, + onError: () => { + toast({ + title: t("incomingOrders.restoreFailed"), + variant: "destructive", + }); + }, + }, + ); + }; + + const handle = toast({ + title: t("incomingOrders.cancelled"), + duration: UNDO_WINDOW_MS, + action: ( + + {t("incomingOrders.undo")} + + ), + }); + }, + onError: () => { + toast({ + title: t("incomingOrders.actionFailed"), + variant: "destructive", + }); + }, + }, + ); + }; + return (