feat: add toggle all functionality for daily checkboxes

- Implemented `toggleAllToday` and `toggleAllYesterday` methods in `useDaily` for batch checkbox state management.
- Updated `DailySection` to include a button for toggling all checkboxes, enhancing user interaction.
- Integrated new toggle functions in `DailyPageClient` to support the updated checkbox handling.
This commit is contained in:
Julien Froidefond
2025-09-16 08:09:13 +02:00
parent c2f949325a
commit 11200f85ac
3 changed files with 95 additions and 3 deletions

View File

@@ -2,6 +2,7 @@
import { DailyCheckbox, DailyCheckboxType } from '@/lib/types';
import { Card } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { DailyCheckboxItem } from './DailyCheckboxItem';
import { DailyAddForm } from './DailyAddForm';
@@ -13,6 +14,7 @@ interface DailySectionProps {
onToggleCheckbox: (checkboxId: string) => Promise<void>;
onUpdateCheckbox: (checkboxId: string, text: string, type: DailyCheckboxType, taskId?: string) => Promise<void>;
onDeleteCheckbox: (checkboxId: string) => Promise<void>;
onToggleAll?: () => Promise<void>;
saving: boolean;
refreshing?: boolean;
}
@@ -25,6 +27,7 @@ export function DailySection({
onToggleCheckbox,
onUpdateCheckbox,
onDeleteCheckbox,
onToggleAll,
saving,
refreshing = false
}: DailySectionProps) {
@@ -47,9 +50,24 @@ export function DailySection({
<div className="w-4 h-4 border-2 border-[var(--primary)] border-t-transparent rounded-full animate-spin"></div>
)}
</h2>
<span className="text-xs text-[var(--muted-foreground)] font-mono">
{checkboxes.filter(cb => cb.isChecked).length}/{checkboxes.length}
</span>
<div className="flex items-center gap-2">
<span className="text-xs text-[var(--muted-foreground)] font-mono">
{checkboxes.filter(cb => cb.isChecked).length}/{checkboxes.length}
</span>
{onToggleAll && checkboxes.length > 0 && (
<Button
type="button"
onClick={onToggleAll}
variant="ghost"
size="sm"
disabled={saving}
className="text-xs px-2 py-1 h-6"
title="Tout cocher/décocher"
>
</Button>
)}
</div>
</div>
</div>

View File

@@ -20,6 +20,8 @@ interface UseDailyActions {
updateCheckbox: (checkboxId: string, data: UpdateDailyCheckboxData) => Promise<DailyCheckbox | null>;
deleteCheckbox: (checkboxId: string) => Promise<void>;
toggleCheckbox: (checkboxId: string) => Promise<void>;
toggleAllToday: () => Promise<void>;
toggleAllYesterday: () => Promise<void>;
reorderCheckboxes: (data: ReorderCheckboxesData) => Promise<void>;
goToPreviousDay: () => Promise<void>;
goToNextDay: () => Promise<void>;
@@ -278,6 +280,72 @@ export function useDaily(initialDate?: Date, initialDailyView?: DailyView): UseD
}
}, [dailyView]);
const toggleAllToday = useCallback(async (): Promise<void> => {
if (!dailyView) return;
const todayCheckboxes = dailyView.today;
if (todayCheckboxes.length === 0) return;
// Déterminer si on coche tout ou on décoche tout
const allChecked = todayCheckboxes.every(cb => cb.isChecked);
const newCheckedState = !allChecked;
const previousDailyView = dailyView;
// Mise à jour optimiste IMMÉDIATE
setDailyView(prev => prev ? {
...prev,
today: prev.today.map(cb => ({ ...cb, isChecked: newCheckedState }))
} : null);
try {
// Appeler l'API pour chaque checkbox en parallèle
await Promise.all(
todayCheckboxes.map(checkbox =>
dailyClient.updateCheckbox(checkbox.id, { isChecked: newCheckedState })
)
);
} catch (err) {
// Rollback en cas d'erreur
setDailyView(previousDailyView);
setError(err instanceof Error ? err.message : 'Erreur lors de la mise à jour des checkboxes');
console.error('Erreur toggleAllToday:', err);
}
}, [dailyView]);
const toggleAllYesterday = useCallback(async (): Promise<void> => {
if (!dailyView) return;
const yesterdayCheckboxes = dailyView.yesterday;
if (yesterdayCheckboxes.length === 0) return;
// Déterminer si on coche tout ou on décoche tout
const allChecked = yesterdayCheckboxes.every(cb => cb.isChecked);
const newCheckedState = !allChecked;
const previousDailyView = dailyView;
// Mise à jour optimiste IMMÉDIATE
setDailyView(prev => prev ? {
...prev,
yesterday: prev.yesterday.map(cb => ({ ...cb, isChecked: newCheckedState }))
} : null);
try {
// Appeler l'API pour chaque checkbox en parallèle
await Promise.all(
yesterdayCheckboxes.map(checkbox =>
dailyClient.updateCheckbox(checkbox.id, { isChecked: newCheckedState })
)
);
} catch (err) {
// Rollback en cas d'erreur
setDailyView(previousDailyView);
setError(err instanceof Error ? err.message : 'Erreur lors de la mise à jour des checkboxes');
console.error('Erreur toggleAllYesterday:', err);
}
}, [dailyView]);
const reorderCheckboxes = useCallback(async (data: ReorderCheckboxesData): Promise<void> => {
try {
setSaving(true);
@@ -350,6 +418,8 @@ export function useDaily(initialDate?: Date, initialDailyView?: DailyView): UseD
updateCheckbox,
deleteCheckbox,
toggleCheckbox,
toggleAllToday,
toggleAllYesterday,
reorderCheckboxes,
goToPreviousDay,
goToNextDay,

View File

@@ -32,6 +32,8 @@ export function DailyPageClient({
addTodayCheckbox,
addYesterdayCheckbox,
toggleCheckbox,
toggleAllToday,
toggleAllYesterday,
updateCheckbox,
deleteCheckbox,
goToPreviousDay,
@@ -218,6 +220,7 @@ export function DailyPageClient({
onToggleCheckbox={handleToggleCheckbox}
onUpdateCheckbox={handleUpdateCheckbox}
onDeleteCheckbox={handleDeleteCheckbox}
onToggleAll={toggleAllYesterday}
saving={saving}
refreshing={refreshing}
/>
@@ -231,6 +234,7 @@ export function DailyPageClient({
onToggleCheckbox={handleToggleCheckbox}
onUpdateCheckbox={handleUpdateCheckbox}
onDeleteCheckbox={handleDeleteCheckbox}
onToggleAll={toggleAllToday}
saving={saving}
refreshing={refreshing}
/>