- Added `PendingTasksSection` to `DailyPageClient` for displaying uncompleted tasks. - Implemented `getPendingCheckboxes` method in `DailyClient` and `DailyService` to fetch pending tasks. - Introduced `getDaysAgo` utility function for calculating elapsed days since a date. - Updated `TODO.md` to reflect the new task management features and adjustments. - Cleaned up and organized folder structure to align with Next.js 13+ best practices.
187 lines
5.4 KiB
TypeScript
187 lines
5.4 KiB
TypeScript
import { httpClient } from './base/http-client';
|
|
import { DailyCheckbox, DailyView, Task } from '@/lib/types';
|
|
import { formatDateForAPI, parseDate, getToday, addDays, subtractDays } from '@/lib/date-utils';
|
|
|
|
// Types pour les réponses API (avec dates en string)
|
|
interface ApiCheckbox {
|
|
id: string;
|
|
date: string;
|
|
text: string;
|
|
isChecked: boolean;
|
|
type: 'task' | 'meeting';
|
|
order: number;
|
|
taskId?: string;
|
|
task?: Task;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
interface ApiDailyView {
|
|
date: string;
|
|
yesterday: ApiCheckbox[];
|
|
today: ApiCheckbox[];
|
|
}
|
|
|
|
interface ApiHistoryItem {
|
|
date: string;
|
|
checkboxes: ApiCheckbox[];
|
|
}
|
|
|
|
export interface DailyHistoryFilters {
|
|
limit?: number;
|
|
}
|
|
|
|
export interface DailySearchFilters {
|
|
query: string;
|
|
limit?: number;
|
|
}
|
|
|
|
// Types conservés pour la compatibilité des hooks d'historique et de recherche
|
|
export interface ReorderCheckboxesData {
|
|
date: Date;
|
|
checkboxIds: string[];
|
|
}
|
|
|
|
/**
|
|
* Client HTTP pour les données Daily (lecture seule)
|
|
* Les mutations sont gérées par les server actions dans actions/daily.ts
|
|
*/
|
|
export class DailyClient {
|
|
/**
|
|
* Récupère la vue daily d'aujourd'hui (hier + aujourd'hui)
|
|
*/
|
|
async getTodaysDailyView(): Promise<DailyView> {
|
|
const result = await httpClient.get<ApiDailyView>('/daily');
|
|
return this.transformDailyViewDates(result);
|
|
}
|
|
|
|
/**
|
|
* Récupère la vue daily pour une date donnée
|
|
*/
|
|
async getDailyView(date: Date): Promise<DailyView> {
|
|
const dateStr = this.formatDateForAPI(date);
|
|
const result = await httpClient.get<ApiDailyView>(`/daily?date=${dateStr}`);
|
|
return this.transformDailyViewDates(result);
|
|
}
|
|
|
|
/**
|
|
* Récupère l'historique des checkboxes
|
|
*/
|
|
async getCheckboxHistory(filters?: DailyHistoryFilters): Promise<{ date: Date; checkboxes: DailyCheckbox[] }[]> {
|
|
const params = new URLSearchParams({ action: 'history' });
|
|
|
|
if (filters?.limit) params.append('limit', filters.limit.toString());
|
|
|
|
const result = await httpClient.get<ApiHistoryItem[]>(`/daily?${params}`);
|
|
return result.map(item => ({
|
|
date: parseDate(item.date),
|
|
checkboxes: item.checkboxes.map((cb: ApiCheckbox) => this.transformCheckboxDates(cb))
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Recherche dans les checkboxes
|
|
*/
|
|
async searchCheckboxes(filters: DailySearchFilters): Promise<DailyCheckbox[]> {
|
|
const params = new URLSearchParams({
|
|
action: 'search',
|
|
q: filters.query
|
|
});
|
|
|
|
if (filters.limit) params.append('limit', filters.limit.toString());
|
|
|
|
const result = await httpClient.get<ApiCheckbox[]>(`/daily?${params}`);
|
|
return result.map((cb: ApiCheckbox) => this.transformCheckboxDates(cb));
|
|
}
|
|
|
|
/**
|
|
* Formate une date pour l'API (évite les décalages timezone)
|
|
*/
|
|
formatDateForAPI(date: Date): string {
|
|
return formatDateForAPI(date);
|
|
}
|
|
|
|
/**
|
|
* Transforme les dates string d'une checkbox en objets Date
|
|
*/
|
|
private transformCheckboxDates(checkbox: ApiCheckbox): DailyCheckbox {
|
|
return {
|
|
...checkbox,
|
|
date: parseDate(checkbox.date),
|
|
createdAt: parseDate(checkbox.createdAt),
|
|
updatedAt: parseDate(checkbox.updatedAt)
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Transforme les dates string d'une vue daily en objets Date
|
|
*/
|
|
private transformDailyViewDates(view: ApiDailyView): DailyView {
|
|
return {
|
|
date: parseDate(view.date),
|
|
yesterday: view.yesterday.map((cb: ApiCheckbox) => this.transformCheckboxDates(cb)),
|
|
today: view.today.map((cb: ApiCheckbox) => this.transformCheckboxDates(cb))
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Récupère la vue daily d'une date relative (hier, aujourd'hui, demain)
|
|
*/
|
|
async getDailyViewByRelativeDate(relative: 'yesterday' | 'today' | 'tomorrow'): Promise<DailyView> {
|
|
let date: Date;
|
|
|
|
switch (relative) {
|
|
case 'yesterday':
|
|
date = subtractDays(getToday(), 1);
|
|
break;
|
|
case 'tomorrow':
|
|
date = addDays(getToday(), 1);
|
|
break;
|
|
case 'today':
|
|
default:
|
|
date = getToday();
|
|
break;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* Récupère les checkboxes en attente (non cochées)
|
|
*/
|
|
async getPendingCheckboxes(options?: {
|
|
maxDays?: number;
|
|
excludeToday?: boolean;
|
|
type?: 'task' | 'meeting';
|
|
limit?: number;
|
|
}): Promise<DailyCheckbox[]> {
|
|
const params = new URLSearchParams();
|
|
if (options?.maxDays) params.append('maxDays', options.maxDays.toString());
|
|
if (options?.excludeToday !== undefined) params.append('excludeToday', options.excludeToday.toString());
|
|
if (options?.type) params.append('type', options.type);
|
|
if (options?.limit) params.append('limit', options.limit.toString());
|
|
|
|
const queryString = params.toString();
|
|
const result = await httpClient.get<ApiCheckbox[]>(`/daily/pending${queryString ? `?${queryString}` : ''}`);
|
|
return result.map((cb: ApiCheckbox) => this.transformCheckboxDates(cb));
|
|
}
|
|
|
|
/**
|
|
* Archive une checkbox
|
|
*/
|
|
async archiveCheckbox(checkboxId: string): Promise<DailyCheckbox> {
|
|
const result = await httpClient.patch<ApiCheckbox>(`/daily/checkboxes/${checkboxId}/archive`);
|
|
return this.transformCheckboxDates(result);
|
|
}
|
|
}
|
|
|
|
// Instance singleton du client
|
|
export const dailyClient = new DailyClient(); |