feat: migrate tag management to server actions

- Completed migration of tag management to server actions by creating `actions/tags.ts` for CRUD operations.
- Removed obsolete API routes for tags (`/api/tags`, `/api/tags/[id]`) and updated related components to utilize new server actions.
- Updated `TagForm` and `useTags` hook to handle tag creation, updating, and deletion through server actions, improving performance and simplifying client-side logic.
- Cleaned up `tags-client.ts` by removing unused types and methods, focusing on validation only.
- Marked related TODO items as complete in `TODO.md`.
This commit is contained in:
Julien Froidefond
2025-09-18 21:00:28 +02:00
parent 8b98c467d0
commit b12dd4f8dc
8 changed files with 253 additions and 317 deletions

101
src/actions/tags.ts Normal file
View File

@@ -0,0 +1,101 @@
'use server';
import { tagsService } from '@/services/tags';
import { revalidatePath } from 'next/cache';
import { Tag } from '@/lib/types';
export type ActionResult<T = void> = {
success: boolean;
data?: T;
error?: string;
};
/**
* Créer un nouveau tag
*/
export async function createTag(
name: string,
color: string
): Promise<ActionResult<Tag>> {
try {
const tag = await tagsService.createTag({ name, color });
// Revalider les pages qui utilisent les tags
revalidatePath('/');
revalidatePath('/kanban');
revalidatePath('/tags');
return { success: true, data: tag };
} catch (error) {
console.error('Error creating tag:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to create tag'
};
}
}
/**
* Mettre à jour un tag existant
*/
export async function updateTag(
tagId: string,
data: { name?: string; color?: string; isPinned?: boolean }
): Promise<ActionResult<Tag>> {
try {
const tag = await tagsService.updateTag(tagId, data);
if (!tag) {
return { success: false, error: 'Tag non trouvé' };
}
// Revalider les pages qui utilisent les tags
revalidatePath('/');
revalidatePath('/kanban');
revalidatePath('/tags');
return { success: true, data: tag };
} catch (error) {
console.error('Error updating tag:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to update tag'
};
}
}
/**
* Supprimer un tag
*/
export async function deleteTag(tagId: string): Promise<ActionResult> {
try {
await tagsService.deleteTag(tagId);
// Revalider les pages qui utilisent les tags
revalidatePath('/');
revalidatePath('/kanban');
revalidatePath('/tags');
return { success: true };
} catch (error) {
console.error('Error deleting tag:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to delete tag'
};
}
}
/**
* Action rapide pour créer un tag depuis un input
*/
export async function quickCreateTag(formData: FormData): Promise<ActionResult<Tag>> {
const name = formData.get('name') as string;
const color = formData.get('color') as string;
if (!name?.trim()) {
return { success: false, error: 'Tag name is required' };
}
return createTag(name.trim(), color || '#3B82F6');
}