feat: update Daily management features and enhance date handling
- Marked the calendar/history view of dailies as completed in the TODO list. - Improved date formatting in `formatDateForAPI` to avoid timezone issues. - Added `getDailyDates` method in `DailyClient` and `DailyService` to retrieve all dates with dailies. - Enhanced `POST` route to robustly parse date input for better error handling. - Integrated daily dates loading in `DailyPageClient` for calendar display.
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -108,7 +108,7 @@
|
|||||||
- [x] Navigation par date (daily précédent/suivant)
|
- [x] Navigation par date (daily précédent/suivant)
|
||||||
- [x] Auto-création du daily du jour si inexistant
|
- [x] Auto-création du daily du jour si inexistant
|
||||||
- [x] UX améliorée : édition au clic, focus persistant, input large
|
- [x] UX améliorée : édition au clic, focus persistant, input large
|
||||||
- [ ] Vue calendar/historique des dailies
|
- [x] Vue calendar/historique des dailies
|
||||||
- [ ] Templates de daily personnalisables
|
- [ ] Templates de daily personnalisables
|
||||||
- [ ] Recherche dans l'historique des dailies
|
- [ ] Recherche dans l'historique des dailies
|
||||||
|
|
||||||
|
|||||||
@@ -123,10 +123,13 @@ export class DailyClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formate une date pour l'API
|
* Formate une date pour l'API (évite les décalages timezone)
|
||||||
*/
|
*/
|
||||||
formatDateForAPI(date: Date): string {
|
formatDateForAPI(date: Date): string {
|
||||||
return date.toISOString().split('T')[0]; // YYYY-MM-DD
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`; // YYYY-MM-DD
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,6 +150,14 @@ export class DailyClient {
|
|||||||
|
|
||||||
return this.getDailyView(date);
|
return this.getDailyView(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère toutes les dates qui ont des dailies
|
||||||
|
*/
|
||||||
|
async getDailyDates(): Promise<string[]> {
|
||||||
|
const response = await httpClient.get<{ dates: string[] }>('/daily/dates');
|
||||||
|
return response.dates;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance singleton du client
|
// Instance singleton du client
|
||||||
|
|||||||
218
components/daily/DailyCalendar.tsx
Normal file
218
components/daily/DailyCalendar.tsx
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Button } from '@/components/ui/Button';
|
||||||
|
import { Card } from '@/components/ui/Card';
|
||||||
|
|
||||||
|
interface DailyCalendarProps {
|
||||||
|
currentDate: Date;
|
||||||
|
onDateSelect: (date: Date) => void;
|
||||||
|
dailyDates: string[]; // Liste des dates qui ont des dailies (format YYYY-MM-DD)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DailyCalendar({ currentDate, onDateSelect, dailyDates }: DailyCalendarProps) {
|
||||||
|
const [viewDate, setViewDate] = useState(new Date(currentDate));
|
||||||
|
|
||||||
|
// Formatage des dates pour comparaison (éviter le décalage timezone)
|
||||||
|
const formatDateKey = (date: Date) => {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentDateKey = formatDateKey(currentDate);
|
||||||
|
|
||||||
|
// Navigation mois
|
||||||
|
const goToPreviousMonth = () => {
|
||||||
|
const newDate = new Date(viewDate);
|
||||||
|
newDate.setMonth(newDate.getMonth() - 1);
|
||||||
|
setViewDate(newDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToNextMonth = () => {
|
||||||
|
const newDate = new Date(viewDate);
|
||||||
|
newDate.setMonth(newDate.getMonth() + 1);
|
||||||
|
setViewDate(newDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToToday = () => {
|
||||||
|
const today = new Date();
|
||||||
|
setViewDate(today);
|
||||||
|
onDateSelect(today);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Obtenir les jours du mois
|
||||||
|
const getDaysInMonth = () => {
|
||||||
|
const year = viewDate.getFullYear();
|
||||||
|
const month = viewDate.getMonth();
|
||||||
|
|
||||||
|
// Premier jour du mois
|
||||||
|
const firstDay = new Date(year, month, 1);
|
||||||
|
// Dernier jour du mois
|
||||||
|
const lastDay = new Date(year, month + 1, 0);
|
||||||
|
|
||||||
|
// Premier lundi de la semaine contenant le premier jour
|
||||||
|
const startDate = new Date(firstDay);
|
||||||
|
const dayOfWeek = firstDay.getDay();
|
||||||
|
const daysToSubtract = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Lundi = 0
|
||||||
|
startDate.setDate(firstDay.getDate() - daysToSubtract);
|
||||||
|
|
||||||
|
// Générer toutes les dates du calendrier (6 semaines)
|
||||||
|
const days = [];
|
||||||
|
const currentDay = new Date(startDate);
|
||||||
|
|
||||||
|
for (let i = 0; i < 42; i++) { // 6 semaines × 7 jours
|
||||||
|
days.push(new Date(currentDay));
|
||||||
|
currentDay.setDate(currentDay.getDate() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { days, firstDay, lastDay };
|
||||||
|
};
|
||||||
|
|
||||||
|
const { days, firstDay, lastDay } = getDaysInMonth();
|
||||||
|
|
||||||
|
const handleDateClick = (date: Date) => {
|
||||||
|
onDateSelect(date);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isToday = (date: Date) => {
|
||||||
|
const today = new Date();
|
||||||
|
return formatDateKey(date) === formatDateKey(today);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isCurrentMonth = (date: Date) => {
|
||||||
|
return date.getMonth() === viewDate.getMonth();
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasDaily = (date: Date) => {
|
||||||
|
return dailyDates.includes(formatDateKey(date));
|
||||||
|
};
|
||||||
|
|
||||||
|
const isSelected = (date: Date) => {
|
||||||
|
return formatDateKey(date) === currentDateKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatMonthYear = () => {
|
||||||
|
return viewDate.toLocaleDateString('fr-FR', {
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const weekDays = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="p-4">
|
||||||
|
{/* Header avec navigation */}
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<Button
|
||||||
|
onClick={goToPreviousMonth}
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="text-[var(--foreground)]"
|
||||||
|
>
|
||||||
|
←
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<h3 className="text-lg font-bold text-[var(--foreground)] capitalize">
|
||||||
|
{formatMonthYear()}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={goToNextMonth}
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="text-[var(--foreground)]"
|
||||||
|
>
|
||||||
|
→
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bouton Aujourd'hui */}
|
||||||
|
<div className="mb-4 text-center">
|
||||||
|
<Button
|
||||||
|
onClick={goToToday}
|
||||||
|
variant="primary"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
Aujourd'hui
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Jours de la semaine */}
|
||||||
|
<div className="grid grid-cols-7 gap-1 mb-2">
|
||||||
|
{weekDays.map((day) => (
|
||||||
|
<div
|
||||||
|
key={day}
|
||||||
|
className="text-center text-xs font-medium text-[var(--muted-foreground)] p-2"
|
||||||
|
>
|
||||||
|
{day}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Grille du calendrier */}
|
||||||
|
<div className="grid grid-cols-7 gap-1">
|
||||||
|
{days.map((date, index) => {
|
||||||
|
const dateKey = formatDateKey(date);
|
||||||
|
const isCurrentMonthDay = isCurrentMonth(date);
|
||||||
|
const isTodayDay = isToday(date);
|
||||||
|
const hasCheckboxes = hasDaily(date);
|
||||||
|
const isSelectedDay = isSelected(date);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={index}
|
||||||
|
onClick={() => handleDateClick(date)}
|
||||||
|
className={`
|
||||||
|
relative p-2 text-sm rounded transition-all hover:bg-[var(--muted)]/50
|
||||||
|
${isCurrentMonthDay
|
||||||
|
? 'text-[var(--foreground)]'
|
||||||
|
: 'text-[var(--muted-foreground)]'
|
||||||
|
}
|
||||||
|
${isTodayDay
|
||||||
|
? 'bg-[var(--primary)]/20 border border-[var(--primary)]'
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
${isSelectedDay
|
||||||
|
? 'bg-[var(--primary)] text-white'
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
${hasCheckboxes
|
||||||
|
? 'font-bold'
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{date.getDate()}
|
||||||
|
|
||||||
|
{/* Indicateur de daily existant */}
|
||||||
|
{hasCheckboxes && (
|
||||||
|
<div className={`
|
||||||
|
absolute bottom-1 right-1 w-2 h-2 rounded-full
|
||||||
|
${isSelectedDay
|
||||||
|
? 'bg-white'
|
||||||
|
: 'bg-[var(--primary)]'
|
||||||
|
}
|
||||||
|
`} />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Légende */}
|
||||||
|
<div className="mt-4 text-xs text-[var(--muted-foreground)] space-y-1">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-2 h-2 rounded-full bg-[var(--primary)]"></div>
|
||||||
|
<span>Jour avec des tâches</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="w-4 h-4 rounded border border-[var(--primary)] bg-[var(--primary)]/20"></div>
|
||||||
|
<span>Aujourd'hui</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -11,17 +11,17 @@ datasource db {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Task {
|
model Task {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
title String
|
title String
|
||||||
description String?
|
description String?
|
||||||
status String @default("todo")
|
status String @default("todo")
|
||||||
priority String @default("medium")
|
priority String @default("medium")
|
||||||
source String // "reminders" | "jira"
|
source String // "reminders" | "jira"
|
||||||
sourceId String? // ID dans le système source
|
sourceId String? // ID dans le système source
|
||||||
dueDate DateTime?
|
dueDate DateTime?
|
||||||
completedAt DateTime?
|
completedAt DateTime?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
// Métadonnées Jira
|
// Métadonnées Jira
|
||||||
jiraProject String?
|
jiraProject String?
|
||||||
@@ -29,7 +29,7 @@ model Task {
|
|||||||
assignee String?
|
assignee String?
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
taskTags TaskTag[]
|
taskTags TaskTag[]
|
||||||
dailyCheckboxes DailyCheckbox[]
|
dailyCheckboxes DailyCheckbox[]
|
||||||
|
|
||||||
@@unique([source, sourceId])
|
@@unique([source, sourceId])
|
||||||
@@ -37,11 +37,11 @@ model Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Tag {
|
model Tag {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String @unique
|
name String @unique
|
||||||
color String @default("#6b7280")
|
color String @default("#6b7280")
|
||||||
isPinned Boolean @default(false) // Tag pour objectifs principaux
|
isPinned Boolean @default(false) // Tag pour objectifs principaux
|
||||||
taskTags TaskTag[]
|
taskTags TaskTag[]
|
||||||
|
|
||||||
@@map("tags")
|
@@map("tags")
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,8 @@ model TaskTag {
|
|||||||
|
|
||||||
model SyncLog {
|
model SyncLog {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
source String // "reminders" | "jira"
|
source String // "reminders" | "jira"
|
||||||
status String // "success" | "error"
|
status String // "success" | "error"
|
||||||
message String?
|
message String?
|
||||||
tasksSync Int @default(0)
|
tasksSync Int @default(0)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@@ -70,15 +70,15 @@ model SyncLog {
|
|||||||
model DailyCheckbox {
|
model DailyCheckbox {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
date DateTime // Date de la checkbox (YYYY-MM-DD)
|
date DateTime // Date de la checkbox (YYYY-MM-DD)
|
||||||
text String // Texte de la checkbox
|
text String // Texte de la checkbox
|
||||||
isChecked Boolean @default(false)
|
isChecked Boolean @default(false)
|
||||||
order Int @default(0) // Ordre d'affichage pour cette date
|
order Int @default(0) // Ordre d'affichage pour cette date
|
||||||
taskId String? // Liaison optionnelle vers une tâche
|
taskId String? // Liaison optionnelle vers une tâche
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
task Task? @relation(fields: [taskId], references: [id], onDelete: SetNull)
|
task Task? @relation(fields: [taskId], references: [id], onDelete: SetNull)
|
||||||
|
|
||||||
@@index([date])
|
@@index([date])
|
||||||
@@map("daily_checkboxes")
|
@@map("daily_checkboxes")
|
||||||
|
|||||||
@@ -139,8 +139,7 @@ export class DailyService {
|
|||||||
const checkboxes = await prisma.dailyCheckbox.findMany({
|
const checkboxes = await prisma.dailyCheckbox.findMany({
|
||||||
where: {
|
where: {
|
||||||
text: {
|
text: {
|
||||||
contains: query,
|
contains: query
|
||||||
mode: 'insensitive'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
include: { task: true },
|
include: { task: true },
|
||||||
@@ -238,6 +237,29 @@ export class DailyService {
|
|||||||
updatedAt: checkbox.updatedAt
|
updatedAt: checkbox.updatedAt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupère toutes les dates qui ont des checkboxes (pour le calendrier)
|
||||||
|
*/
|
||||||
|
async getDailyDates(): Promise<string[]> {
|
||||||
|
const checkboxes = await prisma.dailyCheckbox.findMany({
|
||||||
|
select: {
|
||||||
|
date: true
|
||||||
|
},
|
||||||
|
distinct: ['date'],
|
||||||
|
orderBy: {
|
||||||
|
date: 'desc'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return checkboxes.map(checkbox => {
|
||||||
|
const date = checkbox.date;
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance singleton du service
|
// Instance singleton du service
|
||||||
|
|||||||
20
src/app/api/daily/dates/route.ts
Normal file
20
src/app/api/daily/dates/route.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { dailyService } from '@/services/daily';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API route pour récupérer toutes les dates avec des dailies
|
||||||
|
* GET /api/daily/dates
|
||||||
|
*/
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const dates = await dailyService.getDailyDates();
|
||||||
|
return NextResponse.json({ dates });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la récupération des dates:', error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Erreur interne du serveur' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,7 +68,16 @@ export async function POST(request: Request) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const date = new Date(body.date);
|
// Parser la date de façon plus robuste
|
||||||
|
let date: Date;
|
||||||
|
if (typeof body.date === 'string') {
|
||||||
|
// Si c'est une string YYYY-MM-DD, créer une date locale
|
||||||
|
const [year, month, day] = body.date.split('-').map(Number);
|
||||||
|
date = new Date(year, month - 1, day); // month est 0-indexé
|
||||||
|
} else {
|
||||||
|
date = new Date(body.date);
|
||||||
|
}
|
||||||
|
|
||||||
if (isNaN(date.getTime())) {
|
if (isNaN(date.getTime())) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'Format de date invalide. Utilisez YYYY-MM-DD' },
|
{ error: 'Format de date invalide. Utilisez YYYY-MM-DD' },
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState, useRef } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useDaily } from '@/hooks/useDaily';
|
import { useDaily } from '@/hooks/useDaily';
|
||||||
import { DailyCheckbox } from '@/lib/types';
|
import { DailyCheckbox } from '@/lib/types';
|
||||||
@@ -8,8 +8,7 @@ import { Button } from '@/components/ui/Button';
|
|||||||
import { Input } from '@/components/ui/Input';
|
import { Input } from '@/components/ui/Input';
|
||||||
import { Card } from '@/components/ui/Card';
|
import { Card } from '@/components/ui/Card';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { formatDistanceToNow } from 'date-fns';
|
import { DailyCalendar } from '@/components/daily/DailyCalendar';
|
||||||
import { fr } from 'date-fns/locale';
|
|
||||||
|
|
||||||
interface DailySectionProps {
|
interface DailySectionProps {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -212,22 +211,62 @@ export function DailyPageClient() {
|
|||||||
error,
|
error,
|
||||||
saving,
|
saving,
|
||||||
currentDate,
|
currentDate,
|
||||||
addTodayCheckbox,
|
refreshDaily,
|
||||||
addYesterdayCheckbox,
|
|
||||||
toggleCheckbox,
|
toggleCheckbox,
|
||||||
updateCheckbox,
|
updateCheckbox,
|
||||||
deleteCheckbox,
|
deleteCheckbox,
|
||||||
goToPreviousDay,
|
goToPreviousDay,
|
||||||
goToNextDay,
|
goToNextDay,
|
||||||
goToToday
|
goToToday,
|
||||||
|
setDate
|
||||||
} = useDaily();
|
} = useDaily();
|
||||||
|
|
||||||
|
const [dailyDates, setDailyDates] = useState<string[]>([]);
|
||||||
|
|
||||||
|
// Charger les dates avec des dailies pour le calendrier
|
||||||
|
useEffect(() => {
|
||||||
|
import('@/clients/daily-client').then(({ dailyClient }) => {
|
||||||
|
return dailyClient.getDailyDates();
|
||||||
|
}).then(setDailyDates).catch(console.error);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleAddTodayCheckbox = async (text: string) => {
|
const handleAddTodayCheckbox = async (text: string) => {
|
||||||
await addTodayCheckbox(text);
|
try {
|
||||||
|
const { dailyClient } = await import('@/clients/daily-client');
|
||||||
|
await dailyClient.addCheckbox({
|
||||||
|
date: currentDate,
|
||||||
|
text,
|
||||||
|
isChecked: false
|
||||||
|
});
|
||||||
|
// Recharger la vue daily après ajout
|
||||||
|
await refreshDaily();
|
||||||
|
// Recharger aussi les dates pour le calendrier
|
||||||
|
const updatedDates = await dailyClient.getDailyDates();
|
||||||
|
setDailyDates(updatedDates);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de l\'ajout de la tâche:', error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddYesterdayCheckbox = async (text: string) => {
|
const handleAddYesterdayCheckbox = async (text: string) => {
|
||||||
await addYesterdayCheckbox(text);
|
try {
|
||||||
|
const yesterday = new Date(currentDate);
|
||||||
|
yesterday.setDate(yesterday.getDate() - 1);
|
||||||
|
|
||||||
|
const { dailyClient } = await import('@/clients/daily-client');
|
||||||
|
await dailyClient.addCheckbox({
|
||||||
|
date: yesterday,
|
||||||
|
text,
|
||||||
|
isChecked: false
|
||||||
|
});
|
||||||
|
// Recharger la vue daily après ajout
|
||||||
|
await refreshDaily();
|
||||||
|
// Recharger aussi les dates pour le calendrier
|
||||||
|
const updatedDates = await dailyClient.getDailyDates();
|
||||||
|
setDailyDates(updatedDates);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de l\'ajout de la tâche:', error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleCheckbox = async (checkboxId: string) => {
|
const handleToggleCheckbox = async (checkboxId: string) => {
|
||||||
@@ -252,6 +291,10 @@ export function DailyPageClient() {
|
|||||||
return currentDate;
|
return currentDate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDateSelect = (date: Date) => {
|
||||||
|
setDate(date);
|
||||||
|
};
|
||||||
|
|
||||||
const formatCurrentDate = () => {
|
const formatCurrentDate = () => {
|
||||||
return currentDate.toLocaleDateString('fr-FR', {
|
return currentDate.toLocaleDateString('fr-FR', {
|
||||||
weekday: 'long',
|
weekday: 'long',
|
||||||
@@ -330,7 +373,7 @@ export function DailyPageClient() {
|
|||||||
onClick={goToToday}
|
onClick={goToToday}
|
||||||
className="text-xs text-[var(--primary)] hover:text-[var(--primary)]/80 font-mono"
|
className="text-xs text-[var(--primary)] hover:text-[var(--primary)]/80 font-mono"
|
||||||
>
|
>
|
||||||
Aller à aujourd'hui
|
Aller à aujourd'hui
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -350,8 +393,19 @@ export function DailyPageClient() {
|
|||||||
|
|
||||||
{/* Contenu principal */}
|
{/* Contenu principal */}
|
||||||
<main className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-4 py-8">
|
||||||
{dailyView && (
|
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
{/* Calendrier - toujours visible */}
|
||||||
|
<div className="xl:col-span-1">
|
||||||
|
<DailyCalendar
|
||||||
|
currentDate={currentDate}
|
||||||
|
onDateSelect={handleDateSelect}
|
||||||
|
dailyDates={dailyDates}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sections daily */}
|
||||||
|
{dailyView && (
|
||||||
|
<div className="xl:col-span-2 grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
{/* Section Hier */}
|
{/* Section Hier */}
|
||||||
<DailySectionComponent
|
<DailySectionComponent
|
||||||
title="📋 Hier"
|
title="📋 Hier"
|
||||||
@@ -375,8 +429,9 @@ export function DailyPageClient() {
|
|||||||
onDeleteCheckbox={handleDeleteCheckbox}
|
onDeleteCheckbox={handleDeleteCheckbox}
|
||||||
saving={saving}
|
saving={saving}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Footer avec stats */}
|
{/* Footer avec stats */}
|
||||||
{dailyView && (
|
{dailyView && (
|
||||||
|
|||||||
Reference in New Issue
Block a user