feat(topbar): add Discard button to BC sync queue dropdown

This commit is contained in:
Christian Vidal Wolf
2026-05-15 13:52:47 +02:00
parent 6d664c26f1
commit 1d105e19ae
2 changed files with 63 additions and 6 deletions
+38 -3
View File
@@ -52,7 +52,7 @@ const FORCED_ZERO_STOCK_SKUS = new Set([
const BC_SYNC_QUEUE_STORAGE_KEY = 'craze_bc_sync_queue';
type BcSyncStatus = 'queued' | 'previewed' | 'syncing' | 'synced' | 'failed';
type BcSyncStatus = 'queued' | 'previewed' | 'preview_only' | 'syncing' | 'synced' | 'failed';
interface BcSyncQueueEntry {
rowIndex: number;
@@ -63,6 +63,7 @@ interface BcSyncQueueEntry {
status: BcSyncStatus;
previewToken?: string;
error?: string;
warning?: string;
source: 'save_all' | 'cosmetic_items' | 'manual';
}
@@ -692,6 +693,19 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
});
};
const handleDiscardSelectedBcQueue = () => {
const selectedCount = Object.values(bcSyncQueue).filter(e => e.selected).length;
if (selectedCount === 0) return;
if (!window.confirm(`Discard ${selectedCount} pending BC sync(s)? They will be removed from the queue.`)) return;
setBcSyncQueue(prev => {
const next: BcSyncQueue = { ...prev };
(Object.keys(next) as string[]).forEach(articleNo => {
if (next[articleNo].selected) delete next[articleNo];
});
return next;
});
};
const handleSelectAllBcQueue = (selected: boolean) => {
setBcSyncQueue(prev => {
const next: BcSyncQueue = { ...prev };
@@ -749,6 +763,7 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
...item,
status: 'failed',
error: preview.error || 'Preview failed',
warning: undefined,
};
}
return;
@@ -759,6 +774,8 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
status: 'previewed',
previewToken: preview.previewToken,
error: undefined,
selected: item.selected,
warning: undefined,
};
});
return next;
@@ -785,7 +802,21 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
});
for (const [articleNo, item] of selectedBcQueueEntries) {
const result = await applyBusinessCentralSync(appState.headers, item.newData, item.previewToken);
const preview = await previewBusinessCentralSync(appState.headers, item.newData);
if (!preview.success) {
setBcSyncQueue(prev => ({
...prev,
[articleNo]: {
...prev[articleNo],
status: 'failed',
error: preview.error || 'Preview failed',
warning: undefined,
},
}));
continue;
}
const result = await applyBusinessCentralSync(appState.headers, item.newData, preview.previewToken);
if (!result.success) {
if (isPreviewTokenMismatchError(result.error)) {
const refreshedPreview = await previewBusinessCentralSync(appState.headers, item.newData);
@@ -797,6 +828,7 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
status: 'previewed',
previewToken: refreshedPreview.previewToken,
error: undefined,
warning: undefined,
},
}));
@@ -817,6 +849,7 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
...prev[articleNo],
status: 'failed',
error: retryResult.error || 'BC sync failed',
warning: retryResult.warning,
},
}));
continue;
@@ -828,6 +861,7 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
...prev[articleNo],
status: 'failed',
error: result.error || 'BC sync failed',
warning: result.warning,
},
}));
continue;
@@ -959,11 +993,12 @@ const articleNoIdx = resolvedCols.ARTICLE_NO;
onRevertRow={handleRevertRow}
isSavingAll={isSavingAll}
bcQueueCount={Object.keys(bcSyncQueue).length}
bcQueueEntries={Object.fromEntries((Object.entries(bcSyncQueue) as Array<[string, BcSyncQueueEntry]>).map(([k, v]) => [k, { articleName: v.articleName, selected: v.selected, status: v.status, error: v.error }]))}
bcQueueEntries={Object.fromEntries((Object.entries(bcSyncQueue) as Array<[string, BcSyncQueueEntry]>).map(([k, v]) => [k, { articleName: v.articleName, selected: v.selected, status: v.status, error: v.error, warning: v.warning }]))}
onToggleBcQueueSelection={handleToggleBcQueueSelection}
onSelectAllBcQueue={handleSelectAllBcQueue}
onPreviewSelectedBcSync={handlePreviewSelectedBcSync}
onSyncSelectedBcSync={handleSyncSelectedBcSync}
onDiscardSelectedBcQueue={handleDiscardSelectedBcQueue}
isSyncingBC={isSyncingBC}
isDownloadingBCExcel={isDownloadingBCExcel}
isMaximized={isMaximized}