fix(issued-orders): correct status display after create-redirect + per-button loading state

Bug 1: creating an issued order as 'sent' redirected to the detail which showed
'Koncept' until a refresh — the component is reused across create→edit, so the
one-shot hydration (gated by dataReady) never reloaded the real status. Now the
just-saved status is reflected into local form state on every save with a target.

Bug 2: both edit-draft buttons shared one 'saving' flag, so pressing 'Uložit
koncept' made 'Odeslat' show 'Ukládání...'. Track which action is in flight so
only the clicked button spins (all stay disabled to block double-submit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-06-09 20:36:55 +02:00
parent 113edd9a0d
commit c270cb22e9

View File

@@ -534,6 +534,10 @@ export default function IssuedOrderDetail() {
]); ]);
const [errors, setErrors] = useState<Record<string, string>>({}); const [errors, setErrors] = useState<Record<string, string>>({});
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
// Which save action is in flight ("draft" | the live status | "save"), so
// only the clicked button shows its spinner — `saving` still disables all of
// them to prevent a concurrent double-submit.
const [savingAction, setSavingAction] = useState<string | null>(null);
const [dataReady, setDataReady] = useState(false); const [dataReady, setDataReady] = useState(false);
const [poNumber, setPoNumber] = useState(""); const [poNumber, setPoNumber] = useState("");
@@ -733,6 +737,7 @@ export default function IssuedOrderDetail() {
if (Object.keys(newErrors).length > 0) return; if (Object.keys(newErrors).length > 0) return;
setSaving(true); setSaving(true);
setSavingAction(targetStatus ?? "save");
try { try {
const payload: Record<string, unknown> = { const payload: Record<string, unknown> = {
customer_id: form.customer_id, customer_id: form.customer_id,
@@ -770,10 +775,14 @@ export default function IssuedOrderDetail() {
alert.success( alert.success(
isEdit ? "Objednávka byla uložena" : "Objednávka byla vytvořena", isEdit ? "Objednávka byla uložena" : "Objednávka byla vytvořena",
); );
// Finalizing a draft (draft → sent) assigns the PO number server-side; // Reflect the just-saved status locally. On CREATE the component is reused
// reflect the new status locally so the form switches out of the draft // for the redirect to the new order's detail and the one-shot edit-mode
// button branch (the invalidated query refetch repopulates the number). // hydration won't re-run (dataReady stays true), so without this the page
if (isEdit && targetStatus && targetStatus !== "draft") { // would show the stale create-mode status ("draft") even though the order
// was created as "sent" — until a manual refresh. On finalize (edit
// draft→live) it flips the form out of the draft button branch. The PO
// number is repopulated by the detail-query sync effect.
if (targetStatus) {
setForm((prev) => ({ ...prev, status: targetStatus })); setForm((prev) => ({ ...prev, status: targetStatus }));
} }
if (!isEdit) navigate(`/orders/issued/${data.id}`); if (!isEdit) navigate(`/orders/issued/${data.id}`);
@@ -787,6 +796,7 @@ export default function IssuedOrderDetail() {
); );
} finally { } finally {
setSaving(false); setSaving(false);
setSavingAction(null);
} }
}; };
@@ -946,7 +956,7 @@ export default function IssuedOrderDetail() {
onClick={() => handleSubmit("draft")} onClick={() => handleSubmit("draft")}
disabled={saving} disabled={saving}
> >
{saving ? ( {savingAction === "draft" ? (
<CircularProgress size={16} color="inherit" /> <CircularProgress size={16} color="inherit" />
) : ( ) : (
"Uložit koncept" "Uložit koncept"
@@ -956,7 +966,7 @@ export default function IssuedOrderDetail() {
onClick={() => handleSubmit(LIVE_STATUS)} onClick={() => handleSubmit(LIVE_STATUS)}
disabled={saving} disabled={saving}
> >
{saving ? ( {savingAction === LIVE_STATUS ? (
<> <>
<CircularProgress <CircularProgress
size={16} size={16}
@@ -984,7 +994,7 @@ export default function IssuedOrderDetail() {
onClick={() => handleSubmit("draft")} onClick={() => handleSubmit("draft")}
disabled={saving} disabled={saving}
> >
{saving ? ( {savingAction === "draft" ? (
<CircularProgress size={16} color="inherit" /> <CircularProgress size={16} color="inherit" />
) : ( ) : (
"Uložit koncept" "Uložit koncept"
@@ -995,7 +1005,7 @@ export default function IssuedOrderDetail() {
onClick={() => handleSubmit(LIVE_STATUS)} onClick={() => handleSubmit(LIVE_STATUS)}
disabled={saving} disabled={saving}
> >
{saving ? ( {savingAction === LIVE_STATUS ? (
<> <>
<CircularProgress <CircularProgress
size={16} size={16}
@@ -1017,7 +1027,7 @@ export default function IssuedOrderDetail() {
<> <>
{editable && ( {editable && (
<Button onClick={() => handleSubmit()} disabled={saving}> <Button onClick={() => handleSubmit()} disabled={saving}>
{saving ? ( {savingAction === "save" ? (
<> <>
<CircularProgress <CircularProgress
size={16} size={16}