Files
towercontrol/src/clients/daily-client.ts
Julien Froidefond 3cfed60f43 feat: refactor daily task management with new pending tasks section
- 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.
2025-09-21 19:55:04 +02:00

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();