feat: manage canvases with custom name and icon

Make designs (canvases) fully user-manageable: create with a chosen name
and icon, rename, change icon, and delete. Replaces the hardcoded
"New Electrical Design" button with a generic "New Canvas" flow.

- Add Design.icon column + migration that backfills legacy rows
  (electrical -> zap, others -> dashboard)
- DesignModal: name input + curated lucide icon picker (create + edit)
- Sidebar switcher gains per-canvas edit/delete; delete guards the last
  canvas and confirms
- designStore: addDesign/updateDesign/removeDesign with active reassignment
- Fix data loss on design switch: abort load when the save fails and keep
  unsaved edits; skip the save-old step when the previous canvas was deleted
- designsApi create/update carry icon; design_type kept for back-compat

Tests: backend design CRUD (icon + cascade + last-canvas guard), designStore
actions, designIcons resolver, DesignModal create/edit/validation.

ha-relevant: yes
This commit is contained in:
Pouzor
2026-06-02 15:47:57 +02:00
parent eb7b0c6d38
commit 12d527aad6
15 changed files with 693 additions and 42 deletions
+2 -2
View File
@@ -95,9 +95,9 @@ export const settingsApi = {
export const designsApi = {
list: () => api.get<import('@/types').Design[]>('/designs'),
create: (data: { name: string; design_type: string }) =>
create: (data: { name: string; icon?: string; design_type?: string }) =>
api.post<import('@/types').Design>('/designs', data),
update: (id: string, data: { name?: string }) =>
update: (id: string, data: { name?: string; icon?: string }) =>
api.put<import('@/types').Design>(`/designs/${id}`, data),
delete: (id: string) => api.delete(`/designs/${id}`),
}