mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 15:15:24 +02:00
feat: manual Save All button in TopBar with pending change tracking
Changes are now queued locally (yellow highlight) and only persisted to Supabase when the user clicks the Save button in the top-right corner. The button shows the count of pending changes and a spinner while saving. EditPanel closes immediately after queuing — no Supabase call per edit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
c544b9b709
commit
acc1d06269
@@ -8,7 +8,7 @@ import { ConfirmModal } from './ConfirmModal';
|
||||
interface EditPanelProps {
|
||||
row: ExcelRow;
|
||||
rowIndex: number;
|
||||
onSave: (rowIndex: number, updatedRow: ExcelRow) => Promise<boolean>;
|
||||
onSave: (rowIndex: number, updatedRow: ExcelRow) => void;
|
||||
onClose: () => void;
|
||||
onCaptureState: (message: string) => void;
|
||||
}
|
||||
@@ -33,8 +33,6 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed
|
||||
|
||||
const [loadingField, setLoadingField] = useState<string | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [saveError, setSaveError] = useState(false);
|
||||
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
|
||||
const [pendingGeminiField, setPendingGeminiField] = useState<keyof typeof formData | null>(null);
|
||||
const [generatedFields, setGeneratedFields] = useState<Set<string>>(new Set());
|
||||
@@ -136,11 +134,8 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
const handleSave = () => {
|
||||
setIsConfirmOpen(false);
|
||||
setSaveError(false);
|
||||
setIsSaving(true);
|
||||
|
||||
const hasModifications = Object.keys(formData).some(k => isModified(k as keyof typeof formData));
|
||||
if (hasModifications) {
|
||||
onCaptureState(`Updated product ${row[COLUMNS.ARTICLE_NO]}`);
|
||||
@@ -160,13 +155,7 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed
|
||||
newRow[COLUMNS.MOQ] = formData.moq;
|
||||
newRow[COLUMNS.DETAILS_DE] = formData.detailsDe;
|
||||
newRow[COLUMNS.DETAILS_EN] = formData.detailsEn;
|
||||
|
||||
const success = await onSave(rowIndex, newRow);
|
||||
// If save failed, panel stays open — handleSaveRow in App.tsx won't call setEditingRowIndex(null)
|
||||
if (!success) {
|
||||
setSaveError(true);
|
||||
}
|
||||
setIsSaving(false);
|
||||
onSave(rowIndex, newRow);
|
||||
};
|
||||
|
||||
const DimensionInput = ({ label, field, placeholder }: { label: string, field: keyof typeof formData, placeholder?: string }) => (
|
||||
@@ -315,25 +304,18 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed
|
||||
</div>
|
||||
|
||||
<div className="p-6 border-t border-slate-700 bg-slate-800/50 flex justify-end gap-3">
|
||||
{saveError && (
|
||||
<span className="flex items-center text-sm text-red-400 mr-auto">
|
||||
Error saving — check your connection and retry.
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
onClick={onClose}
|
||||
disabled={isSaving}
|
||||
className="px-4 py-2 text-sm font-medium text-slate-300 hover:text-white hover:bg-slate-700 rounded-md transition-colors disabled:opacity-50"
|
||||
className="px-4 py-2 text-sm font-medium text-slate-300 hover:text-white hover:bg-slate-700 rounded-md transition-colors"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsConfirmOpen(true)}
|
||||
disabled={isSaving}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:opacity-60 text-white text-sm font-medium rounded-md shadow-lg shadow-blue-900/20 transition-colors"
|
||||
className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md shadow-lg shadow-blue-900/20 transition-colors"
|
||||
>
|
||||
{isSaving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Save className="w-4 h-4" />}
|
||||
{isSaving ? 'Saving...' : saveError ? 'Retry Save' : 'Save to Memory'}
|
||||
<Save className="w-4 h-4" />
|
||||
Queue Changes
|
||||
</button>
|
||||
</div>
|
||||
<ConfirmModal
|
||||
|
||||
Reference in New Issue
Block a user