refacto: passing by server actions on taskCard

This commit is contained in:
Julien Froidefond
2025-09-18 09:37:46 +02:00
parent 228e1563c6
commit 4a4eb9c8ad
15 changed files with 286 additions and 330 deletions

165
src/actions/tasks.ts Normal file
View File

@@ -0,0 +1,165 @@
'use server'
import { tasksService } from '@/services/tasks';
import { revalidatePath } from 'next/cache';
import { TaskStatus, TaskPriority } from '@/lib/types';
export type ActionResult<T = unknown> = {
success: boolean;
data?: T;
error?: string;
};
/**
* Server Action pour mettre à jour le statut d'une tâche
*/
export async function updateTaskStatus(
taskId: string,
status: TaskStatus
): Promise<ActionResult> {
try {
const task = await tasksService.updateTask(taskId, { status });
// Revalidation automatique du cache
revalidatePath('/');
revalidatePath('/tasks');
return { success: true, data: task };
} catch (error) {
console.error('Error updating task status:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to update task status'
};
}
}
/**
* Server Action pour mettre à jour le titre d'une tâche
*/
export async function updateTaskTitle(
taskId: string,
title: string
): Promise<ActionResult> {
try {
if (!title.trim()) {
return { success: false, error: 'Title cannot be empty' };
}
const task = await tasksService.updateTask(taskId, { title: title.trim() });
// Revalidation automatique du cache
revalidatePath('/');
revalidatePath('/tasks');
return { success: true, data: task };
} catch (error) {
console.error('Error updating task title:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to update task title'
};
}
}
/**
* Server Action pour supprimer une tâche
*/
export async function deleteTask(taskId: string): Promise<ActionResult> {
try {
await tasksService.deleteTask(taskId);
// Revalidation automatique du cache
revalidatePath('/');
revalidatePath('/tasks');
return { success: true };
} catch (error) {
console.error('Error deleting task:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to delete task'
};
}
}
/**
* Server Action pour mettre à jour une tâche complète (formulaire d'édition)
*/
export async function updateTask(data: {
taskId: string;
title?: string;
description?: string;
status?: TaskStatus;
priority?: TaskPriority;
tags?: string[];
dueDate?: Date;
}): Promise<ActionResult> {
try {
const updateData: Record<string, unknown> = {};
if (data.title !== undefined) {
if (!data.title.trim()) {
return { success: false, error: 'Title cannot be empty' };
}
updateData.title = data.title.trim();
}
if (data.description !== undefined) updateData.description = data.description.trim();
if (data.status !== undefined) updateData.status = data.status;
if (data.priority !== undefined) updateData.priority = data.priority;
if (data.tags !== undefined) updateData.tags = data.tags;
if (data.dueDate !== undefined) updateData.dueDate = data.dueDate;
const task = await tasksService.updateTask(data.taskId, updateData);
// Revalidation automatique du cache
revalidatePath('/');
revalidatePath('/tasks');
return { success: true, data: task };
} catch (error) {
console.error('Error updating task:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to update task'
};
}
}
/**
* Server Action pour créer une nouvelle tâche
*/
export async function createTask(data: {
title: string;
description?: string;
status?: TaskStatus;
priority?: TaskPriority;
tags?: string[];
}): Promise<ActionResult> {
try {
if (!data.title.trim()) {
return { success: false, error: 'Title is required' };
}
const task = await tasksService.createTask({
title: data.title.trim(),
description: data.description?.trim() || '',
status: data.status || 'todo',
priority: data.priority || 'medium',
tags: data.tags || []
});
// Revalidation automatique du cache
revalidatePath('/');
revalidatePath('/tasks');
return { success: true, data: task };
} catch (error) {
console.error('Error creating task:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to create task'
};
}
}

View File

@@ -65,112 +65,8 @@ export async function GET(request: Request) {
}
}
/**
* 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, ...updates } = body;
if (!taskId) {
return NextResponse.json({
success: false,
error: 'taskId est requis'
}, { status: 400 });
}
// 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 mise à jour avec succès'
});
} catch (error) {
console.error('❌ Erreur lors de la mise à jour de la tâche:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Erreur inconnue'
}, { 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 });
}
}
// POST, PATCH, DELETE methods have been migrated to Server Actions
// See /src/actions/tasks.ts for:
// - createTask (replaces POST)
// - updateTask, updateTaskStatus, updateTaskTitle (replaces PATCH)
// - deleteTask (replaces DELETE)

View File

@@ -5,7 +5,7 @@ import { useTasks } from '@/hooks/useTasks';
import { useTags } from '@/hooks/useTags';
import { useUserPreferences } from './UserPreferencesContext';
import { Task, Tag, TaskStats } from '@/lib/types';
import { CreateTaskData, UpdateTaskData, TaskFilters } from '@/clients/tasks-client';
import { CreateTaskData, TaskFilters } from '@/clients/tasks-client';
import { KanbanFilters } from '@/components/kanban/KanbanFilters';
import { sortTasks, getSortOption, DEFAULT_SORT, createSortKey } from '@/lib/sort-config';
@@ -17,9 +17,7 @@ interface TasksContextType {
syncing: boolean;
error: string | null;
createTask: (data: CreateTaskData) => Promise<Task | null>;
updateTask: (data: UpdateTaskData) => Promise<Task | null>;
updateTaskOptimistic: (data: UpdateTaskData) => Promise<Task | null>;
deleteTask: (taskId: string) => Promise<void>;
updateTaskOptimistic: (taskId: string, status: TaskStatus) => Promise<Task | null>;
refreshTasks: () => Promise<void>;
setFilters: (filters: TaskFilters) => void;
// Kanban filters