"use client"; import { useRef, useState } from "react"; import { enqueueAction } from "@/lib/offline/queue"; import { syncPending } from "@/lib/offline/sync"; import { dispatchClientAction } from "@/actions/offline-dispatcher"; /** * Long-press stepper to adjust a product's `inventory` count. * * UI plumbing only: pressing +/- enqueues an `adjustProductStock` mutation * into the offline IndexedDB queue and triggers a sync pass. The server-side * `adjustProductStock` action is not yet wired into the dispatcher's * `listClientActions()` table (PR 3 deviation) — `dispatchClientAction` will * return `{ok: false, error: "Unknown action"}` for now, which surfaces in * the OfflineBanner conflict count. That's the known follow-up; the queue + * sync pipeline is the deliverable here. * * The "long press" affordance keeps accidental single-tap stock changes to * a minimum — a single tap on the trigger does nothing; the dialog only * opens after holding the button for LONG_PRESS_MS. Inside the dialog the * stepper buttons are large (64px) for gloved use. */ interface StockAdjustButtonProps { productId: string; currentStock: number; } const LONG_PRESS_MS = 500; export function StockAdjustButton({ productId, currentStock }: StockAdjustButtonProps) { const [open, setOpen] = useState(false); const [stock, setStock] = useState(currentStock); const [pending, setPending] = useState(false); const timer = useRef | null>(null); function onPointerDown() { timer.current = setTimeout(() => setOpen(true), LONG_PRESS_MS); } function onPointerUp() { if (timer.current) clearTimeout(timer.current); } async function adjust(delta: number) { const next = stock + delta; if (next < 0) return; setStock(next); setPending(true); try { await enqueueAction("adjustProductStock", { productId, delta }); await syncPending( (name, payload, id) => dispatchClientAction(name, payload, id), { online: navigator.onLine, sleep: (ms) => new Promise((r) => setTimeout(r, ms)) } ); } finally { setPending(false); } } return ( <> {open && (

Adjust stock

{stock}
)} ); } export default StockAdjustButton;