Skip to content

Commit e4d7d07

Browse files
aster-voidclaude
andcommitted
modules/admin: prevent double-click on start migration button
Add isStarting state to disable button while request is in flight, preventing race condition where user could click twice before status updates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent d0843a0 commit e4d7d07

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

src/routes/(admin)/admin/migrate/+page.svelte

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
let migrationState: MigrationState | null = $state(null);
1414
let pollInterval: ReturnType<typeof setInterval> | null = $state(null);
1515
let logsContainer: HTMLPreElement | null = $state(null);
16+
let isStarting = $state(false);
17+
18+
const isRunning = $derived.by(() => migrationState?.status === "running");
19+
const isDisabled = $derived.by(() => isStarting || isRunning);
1620
1721
async function fetchStatus() {
1822
migrationState = await getStatus();
@@ -24,9 +28,15 @@
2428
}
2529
2630
async function handleStart() {
27-
const result = await start();
28-
if (result.started) {
29-
await fetchStatus();
31+
if (isDisabled) return;
32+
isStarting = true;
33+
try {
34+
const result = await start();
35+
if (result.started) {
36+
await fetchStatus();
37+
}
38+
} finally {
39+
isStarting = false;
3040
}
3141
}
3242
@@ -118,9 +128,13 @@
118128
<button
119129
class="btn gap-2 btn-warning"
120130
onclick={handleStart}
121-
disabled={migrationState?.status === "running"}
131+
disabled={isDisabled}
122132
>
123-
<Play class="h-4 w-4" />
133+
{#if isStarting}
134+
<span class="loading loading-spinner loading-xs"></span>
135+
{:else}
136+
<Play class="h-4 w-4" />
137+
{/if}
124138
Start Migration
125139
</button>
126140
{#if migrationState?.status === "completed" || migrationState?.status === "error"}

0 commit comments

Comments
 (0)