mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 13:35:25 +02:00
feat: persistent multi-step undo system in TopBar
fix: save all changes to Supabase with reliable upsert - Replace broken PATCH→POST fallback with single atomic upsert (POST + Prefer: resolution=merge-duplicates). The old PATCH returned 200 OK with empty body for new articles, causing silent data loss on every first save per article. - Fix getAllSyncedRows pagination: add explicit limit=10000 and Range header to bypass Supabase's default 1000-row cap. - Add fetchWithRetry helper (2 retries on 5xx/network errors). - handleSaveRow now returns Promise<boolean> and closes EditPanel only after a confirmed successful save. - Add 'error' save status: failed rows turn red (border-l-red-500) across ProductDescriptions, ArticleDetails, and PricingView. - EditPanel shows saving spinner, disables buttons while saving, and displays inline error message with "Retry Save" on failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
da4673f7c4
commit
c544b9b709
+10
-14
@@ -238,35 +238,31 @@ export default function App() {
|
||||
setAppState(prev => ({ ...prev, hasUnsavedChanges: false }));
|
||||
};
|
||||
|
||||
const handleSaveRow = async (rowIndex: number, updatedRow: ExcelRow) => {
|
||||
// 1. Update UI state
|
||||
const handleSaveRow = async (rowIndex: number, updatedRow: ExcelRow): Promise<boolean> => {
|
||||
// 1. Optimistically update UI
|
||||
setAppState(prev => {
|
||||
const newData = [...prev.data];
|
||||
newData[rowIndex] = updatedRow;
|
||||
return {
|
||||
...prev,
|
||||
data: newData,
|
||||
hasUnsavedChanges: true
|
||||
};
|
||||
return { ...prev, data: newData, hasUnsavedChanges: true };
|
||||
});
|
||||
setEditingRowIndex(null);
|
||||
|
||||
// 2. Persist to Supabase
|
||||
const articleNo = String(updatedRow[COLUMNS.ARTICLE_NO]);
|
||||
console.log(`Saving article ${articleNo} to Supabase...`);
|
||||
|
||||
// Update local status to pending
|
||||
setRowStatuses(prev => ({ ...prev, [articleNo]: 'pending' }));
|
||||
|
||||
// 2. Persist to Supabase
|
||||
const success = await saveRowToSupabase(articleNo, updatedRow);
|
||||
|
||||
if (success) {
|
||||
console.log(`Successfully saved ${articleNo}`);
|
||||
setRowStatuses(prev => ({ ...prev, [articleNo]: 'saved' }));
|
||||
setAppState(prev => ({ ...prev, hasUnsavedChanges: false }));
|
||||
setEditingRowIndex(null); // Close panel only after confirmed save
|
||||
} else {
|
||||
console.error(`Failed to save ${articleNo} to Supabase`);
|
||||
alert("Error saving to database. Local changes will be lost on refresh if not saved.");
|
||||
setRowStatuses(prev => ({ ...prev, [articleNo]: 'error' }));
|
||||
// Panel stays open so user can retry
|
||||
}
|
||||
|
||||
return success;
|
||||
};
|
||||
|
||||
const captureState = (message: string) => {
|
||||
|
||||
Reference in New Issue
Block a user