feat: redesign Clients admin — drag-and-drop, inline edit, tags

Schema:
- Client model: add tags String[] field
- Shared types + Zod schemas updated for tags

API:
- client.create/update: accept tags array
- client.delete: with safety checks (no projects, no children)
- client.batchUpdateSortOrder: batch reorder in transaction

UI (complete redesign of ClientsAdminClient):
- Drag-and-drop reordering via @dnd-kit (sortable)
- Inline editing: click name/sortOrder to edit in-place
- Tag pills: auto-colored by hash, add/remove inline
- Tag auto-suggest from existing tags across all clients
- Sticky "Add Client" input row at top
- Search/filter by name, code, or tag
- Delete with inline confirmation
- Optimistic reorder (instant UI update)
- Full dark theme support

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-03-22 21:04:20 +01:00
parent a9a8a13424
commit 03922764db
7 changed files with 731 additions and 217 deletions
@@ -5,6 +5,7 @@ export const CreateClientSchema = z.object({
code: z.string().max(50).optional(),
parentId: z.string().optional(),
sortOrder: z.number().int().default(0),
tags: z.array(z.string().max(50)).optional(),
});
export const UpdateClientSchema = z.object({
@@ -13,6 +14,7 @@ export const UpdateClientSchema = z.object({
sortOrder: z.number().int().optional(),
isActive: z.boolean().optional(),
parentId: z.string().nullable().optional(),
tags: z.array(z.string().max(50)).optional(),
});
export type CreateClientInput = z.infer<typeof CreateClientSchema>;
+1
View File
@@ -5,6 +5,7 @@ export interface Client {
parentId?: string | null;
isActive: boolean;
sortOrder: number;
tags: string[];
createdAt: Date;
updatedAt: Date;
}