feat: implement optimistic UI for checkbox toggling in DailyCheckboxItem

- Added optimistic state handling in `DailyCheckboxItem` for immediate feedback on checkbox toggles, improving user experience.
- Updated `useDaily` hook to handle checkbox state updates without blocking UI, ensuring smoother interactions.
- Enhanced error handling to rollback state on toggle failures, maintaining data integrity.
This commit is contained in:
Julien Froidefond
2025-09-26 11:32:22 +02:00
parent a01c0d83d0
commit b87fa64d4d
2 changed files with 62 additions and 33 deletions

View File

@@ -209,49 +209,48 @@ export function useDaily(initialDate?: Date, initialDailyView?: DailyView): UseD
if (!dailyView) return Promise.resolve();
return new Promise((resolve) => {
startTransition(async () => {
// Trouver la checkbox dans yesterday ou today
let checkbox = dailyView.yesterday.find(cb => cb.id === checkboxId);
if (!checkbox) {
checkbox = dailyView.today.find(cb => cb.id === checkboxId);
}
if (!checkbox) {
resolve();
return;
}
// Trouver la checkbox dans yesterday ou today
let checkbox = dailyView.yesterday.find(cb => cb.id === checkboxId);
if (!checkbox) {
checkbox = dailyView.today.find(cb => cb.id === checkboxId);
}
if (!checkbox) {
resolve();
return;
}
// Mise à jour optimiste IMMÉDIATE
const newCheckedState = !checkbox.isChecked;
const previousDailyView = dailyView;
setDailyView(prev => prev ? {
...prev,
yesterday: prev.yesterday.map(cb =>
cb.id === checkboxId ? { ...cb, isChecked: newCheckedState } : cb
),
today: prev.today.map(cb =>
cb.id === checkboxId ? { ...cb, isChecked: newCheckedState } : cb
)
} : null);
// Mise à jour optimiste IMMÉDIATE
const newCheckedState = !checkbox.isChecked;
const previousDailyView = dailyView;
setDailyView(prev => prev ? {
...prev,
yesterday: prev.yesterday.map(cb =>
cb.id === checkboxId ? { ...cb, isChecked: newCheckedState } : cb
),
today: prev.today.map(cb =>
cb.id === checkboxId ? { ...cb, isChecked: newCheckedState } : cb
)
} : null);
try {
const result = await toggleCheckboxAction(checkboxId);
// Appel serveur en arrière-plan (sans startTransition)
toggleCheckboxAction(checkboxId)
.then(result => {
if (!result.success) {
// Rollback en cas d'erreur
setDailyView(previousDailyView);
setError(result.error || 'Erreur lors de la mise à jour de la checkbox');
}
resolve();
} catch (err) {
})
.catch(err => {
// Rollback en cas d'erreur
setDailyView(previousDailyView);
setError(err instanceof Error ? err.message : 'Erreur lors de la mise à jour de la checkbox');
console.error('Erreur toggleCheckbox:', err);
resolve();
}
});
});
});
}, [dailyView]);