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:
@@ -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]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user