feat: overhaul TODO.md and enhance Kanban components

- Updated TODO.md to reflect the new project structure and phases, marking several tasks as completed.
- Enhanced Kanban components with a tech-inspired design, including new styles for columns and task cards.
- Removed the obsolete reminders service and task processor, streamlining the codebase for better maintainability.
- Introduced a modern API for task management, including CRUD operations and improved error handling.
- Updated global styles for a cohesive dark theme and added custom scrollbar styles.
This commit is contained in:
Julien Froidefond
2025-09-14 08:15:22 +02:00
parent d645fffd87
commit 124e8baee8
18 changed files with 857 additions and 1154 deletions

View File

@@ -1,100 +0,0 @@
import { NextResponse } from 'next/server';
import { getConfig, getTargetRemindersList, getEnabledRemindersLists } from '@/lib/config';
import { remindersService } from '@/services/reminders';
/**
* API route pour récupérer la configuration actuelle
*/
export async function GET() {
try {
const config = getConfig();
const availableLists = await remindersService.getReminderLists();
return NextResponse.json({
success: true,
config,
availableLists,
currentTarget: getTargetRemindersList(),
enabledLists: getEnabledRemindersLists()
});
} catch (error) {
console.error('❌ Erreur lors de la récupération de la config:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { status: 500 });
}
}
/**
* API route pour tester l'accès à une liste spécifique
*/
export async function POST(request: Request) {
try {
const body = await request.json();
const { listName, action } = body;
if (!listName) {
return NextResponse.json({
success: false,
error: 'listName est requis'
}, { status: 400 });
}
let result: any = {};
switch (action) {
case 'test':
// Tester l'accès à une liste spécifique
const reminders = await remindersService.getRemindersByList(listName);
result = {
listName,
accessible: true,
reminderCount: reminders.length,
sample: reminders.slice(0, 3).map(r => ({
title: r.title,
completed: r.completed,
priority: r.priority
}))
};
break;
case 'preview':
// Prévisualiser les rappels d'une liste
const previewReminders = await remindersService.getRemindersByList(listName);
result = {
listName,
reminders: previewReminders.map(r => ({
id: r.id,
title: r.title,
completed: r.completed,
priority: r.priority,
tags: r.tags || []
}))
};
break;
default:
return NextResponse.json({
success: false,
error: 'Action non supportée. Utilisez "test" ou "preview"'
}, { status: 400 });
}
return NextResponse.json({
success: true,
action,
result
});
} catch (error) {
console.error('❌ Erreur lors du test de liste:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { status: 500 });
}
}

View File

@@ -1,60 +0,0 @@
import { NextResponse } from 'next/server';
import { taskProcessorService } from '@/services/task-processor';
/**
* API route pour synchroniser les rappels macOS avec la base de données
*/
export async function POST() {
try {
console.log('🔄 Début de la synchronisation des rappels...');
const syncResult = await taskProcessorService.syncRemindersToDatabase();
return NextResponse.json({
success: true,
message: 'Synchronisation des rappels terminée',
syncLog: syncResult
});
} catch (error) {
console.error('❌ Erreur lors de la synchronisation:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue lors de la synchronisation'
}, { status: 500 });
}
}
/**
* API route pour obtenir le statut de la dernière synchronisation
*/
export async function GET() {
try {
// Récupérer les derniers logs de sync
const { prisma } = await import('@/services/database');
const lastSyncLogs = await prisma.syncLog.findMany({
where: { source: 'reminders' },
orderBy: { createdAt: 'desc' },
take: 5
});
const taskStats = await taskProcessorService.getTaskStats();
return NextResponse.json({
success: true,
lastSyncLogs,
taskStats,
message: 'Statut de synchronisation récupéré'
});
} catch (error) {
console.error('❌ Erreur lors de la récupération du statut:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { status: 500 });
}
}

View File

@@ -1,6 +1,6 @@
import { NextResponse } from 'next/server';
import { taskProcessorService } from '@/services/task-processor';
import { TaskStatus } from '@/lib/types';
import { tasksService } from '@/services/tasks';
import { TaskStatus, TaskPriority } from '@/lib/types';
/**
* API route pour récupérer les tâches avec filtres optionnels
@@ -10,7 +10,13 @@ export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
// Extraire les paramètres de filtre
const filters: any = {};
const filters: {
status?: TaskStatus[];
source?: string[];
search?: string;
limit?: number;
offset?: number;
} = {};
const status = searchParams.get('status');
if (status) {
@@ -38,8 +44,8 @@ export async function GET(request: Request) {
}
// Récupérer les tâches
const tasks = await taskProcessorService.getTasks(filters);
const stats = await taskProcessorService.getTaskStats();
const tasks = await tasksService.getTasks(filters);
const stats = await tasksService.getTaskStats();
return NextResponse.json({
success: true,
@@ -60,26 +66,71 @@ export async function GET(request: Request) {
}
/**
* API route pour mettre à jour le statut d'une tâche
* API route pour créer une nouvelle tâche
*/
export async function POST(request: Request) {
try {
const body = await request.json();
const { title, description, status, priority, tags, dueDate } = body;
if (!title) {
return NextResponse.json({
success: false,
error: 'Le titre est requis'
}, { status: 400 });
}
const task = await tasksService.createTask({
title,
description,
status: status as TaskStatus,
priority: priority as TaskPriority,
tags,
dueDate: dueDate ? new Date(dueDate) : undefined
});
return NextResponse.json({
success: true,
data: task,
message: 'Tâche créée avec succès'
});
} catch (error) {
console.error('❌ Erreur lors de la création de la tâche:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { status: 500 });
}
}
/**
* API route pour mettre à jour une tâche
*/
export async function PATCH(request: Request) {
try {
const body = await request.json();
const { taskId, status } = body;
const { taskId, ...updates } = body;
if (!taskId || !status) {
if (!taskId) {
return NextResponse.json({
success: false,
error: 'taskId et status sont requis'
error: 'taskId est requis'
}, { status: 400 });
}
const updatedTask = await taskProcessorService.updateTaskStatus(taskId, status);
// Convertir dueDate si présent
if (updates.dueDate) {
updates.dueDate = new Date(updates.dueDate);
}
const updatedTask = await tasksService.updateTask(taskId, updates);
return NextResponse.json({
success: true,
data: updatedTask,
message: `Tâche ${taskId} mise à jour avec le statut ${status}`
message: 'Tâche mise à jour avec succès'
});
} catch (error) {
@@ -91,3 +142,35 @@ export async function PATCH(request: Request) {
}, { status: 500 });
}
}
/**
* API route pour supprimer une tâche
*/
export async function DELETE(request: Request) {
try {
const { searchParams } = new URL(request.url);
const taskId = searchParams.get('taskId');
if (!taskId) {
return NextResponse.json({
success: false,
error: 'taskId est requis'
}, { status: 400 });
}
await tasksService.deleteTask(taskId);
return NextResponse.json({
success: true,
message: 'Tâche supprimée avec succès'
});
} catch (error) {
console.error('❌ Erreur lors de la suppression de la tâche:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { status: 500 });
}
}

View File

@@ -1,59 +0,0 @@
import { NextResponse } from 'next/server';
import { testDatabaseConnection } from '@/services/database';
import { remindersService } from '@/services/reminders';
import { taskProcessorService } from '@/services/task-processor';
/**
* API route de test pour vérifier que tous les services fonctionnent
*/
export async function GET() {
try {
const results = {
timestamp: new Date().toISOString(),
database: false,
reminders: false,
taskProcessor: false,
reminderLists: [] as string[],
taskStats: null as any
};
// Test de la base de données
try {
results.database = await testDatabaseConnection();
} catch (error) {
console.error('Test DB failed:', error);
}
// Test de l'accès aux rappels
try {
results.reminders = await remindersService.testRemindersAccess();
if (results.reminders) {
results.reminderLists = await remindersService.getReminderLists();
}
} catch (error) {
console.error('Test Reminders failed:', error);
}
// Test du service de traitement des tâches
try {
results.taskStats = await taskProcessorService.getTaskStats();
results.taskProcessor = true;
} catch (error) {
console.error('Test TaskProcessor failed:', error);
}
return NextResponse.json({
success: true,
message: 'Tests des services terminés',
results
});
} catch (error) {
console.error('Erreur dans l\'API de test:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { status: 500 });
}
}