import type { ActionFunctionArgs } from "@remix-run/node"; import type { Method } from "@prisma/client"; import { authenticate } from "../shopify.server"; import { resolveHoldRequest } from "../services/hold-request.server"; // POS UI Extension endpoint — see pos.scheduling.availability.tsx for the // session-token/CORS rationale. Calls the exact same resolveHoldRequest() // as the storefront's apps.scheduling.hold.tsx, so a staff-booked slot and // a shopper-booked slot compete for the same Redis-backed capacity — a POS // order can't double-book a slot an online shopper already holds, or vice // versa (IMPLEMENTATION_PLAN.md Phase 7 accept criteria). const VALID_METHODS = new Set(["SHIPPING", "LOCAL_DELIVERY", "PICKUP"]); export const action = async ({ request }: ActionFunctionArgs) => { const { sessionToken, cors } = await authenticate.public.pos(request); const shopDomain = sessionToken.dest.replace(/^https?:\/\//, ""); const body = await request.json(); const { intent, locationId, method, date, startMin, cartToken } = body as { intent?: "create" | "release"; locationId?: string; method?: string; date?: string; startMin?: number; cartToken?: string; }; if (!locationId || !method || !VALID_METHODS.has(method as Method) || !date || typeof startMin !== "number" || !cartToken) { return cors(Response.json({ error: "Missing or invalid parameters" }, { status: 400 })); } const result = await resolveHoldRequest(shopDomain, { intent: intent === "release" ? "release" : "create", locationId, method: method as Method, date, startMin, cartToken, }); return cors(Response.json(result.body, { status: result.status })); };