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:
@@ -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}
|
||||||
|
|||||||
Reference in New Issue
Block a user