diff --git a/CHANGELOG.md b/CHANGELOG.md index c8355cc..749ab47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ Alle nennenswerten Änderungen an diesem Projekt werden in dieser Datei dokumentiert. Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/). +## [1.4.3] – 2026-05-20 — Feature: Einzelne Symbole aus Bibliothek wählen + +### Neu +- **Admin → Symbol-Manager**: Neuer Tab „Bibliothek“ zeigt alle 117 globalen Symbole gruppiert nach Kategorie. Pro Symbol ein „+“-Button, um es mit einem Klick zu „Meinen Symbolen“ hinzuzufügen (via `POST /api/tenant/symbols` mit `iconId`). + ## [1.4.2] – 2026-05-20 — Hotfix: Admin leer & Legacy-Symbole ### Behoben diff --git a/package.json b/package.json index a26607f..c96fc79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lageplan", - "version": "1.4.2", + "version": "1.4.3", "description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation", "private": true, "scripts": { diff --git a/src/components/admin/symbol-manager.tsx b/src/components/admin/symbol-manager.tsx index 65f4d9f..a653b2b 100644 --- a/src/components/admin/symbol-manager.tsx +++ b/src/components/admin/symbol-manager.tsx @@ -35,6 +35,7 @@ import { Download, AlertCircle, Package, + Library, } from 'lucide-react' /* ─── Types ─── */ @@ -84,7 +85,7 @@ export function SymbolManager() { /* -- UI state -- */ const [search, setSearch] = useState('') const [expandedCats, setExpandedCats] = useState>(new Set()) - const [activeTab, setActiveTab] = useState<'symbols' | 'categories' | 'import'>('symbols') + const [activeTab, setActiveTab] = useState<'symbols' | 'categories' | 'import' | 'library'>('symbols') /* -- Symbol editing -- */ const [editingSymbolId, setEditingSymbolId] = useState(null) @@ -106,6 +107,12 @@ export function SymbolManager() { const [importOpen, setImportOpen] = useState(false) const [importingPkg, setImportingPkg] = useState(null) + /* -- Library -- */ + const [libraryIcons, setLibraryIcons] = useState([]) + const [librarySearch, setLibrarySearch] = useState('') + const [libraryLoading, setLibraryLoading] = useState(false) + const [addingIconId, setAddingIconId] = useState(null) + /* ─── Fetch ─── */ const fetchData = useCallback(async () => { setLoading(true) @@ -298,6 +305,46 @@ export function SymbolManager() { setImportingPkg(null) } + /* ─── Library ─── */ + const fetchLibrary = useCallback(async () => { + setLibraryLoading(true) + try { + const res = await fetch('/api/icons') + if (res.ok) { + const data = await res.json() + setLibraryIcons(data.categories || []) + } + } catch { + toast({ title: 'Fehler beim Laden der Bibliothek', variant: 'destructive' }) + } + setLibraryLoading(false) + }, [toast]) + + useEffect(() => { + if (activeTab === 'library') fetchLibrary() + }, [activeTab, fetchLibrary]) + + const addFromLibrary = async (iconId: string, name: string) => { + setAddingIconId(iconId) + try { + const res = await fetch('/api/tenant/symbols', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ iconId }), + }) + if (!res.ok) { + const err = await res.json().catch(() => ({})) + toast({ title: err.error || 'Fehler', variant: 'destructive' }) + } else { + toast({ title: `'${name}' hinzugefügt` }) + await fetchData() + } + } catch { + toast({ title: 'Fehler beim Hinzufügen', variant: 'destructive' }) + } + setAddingIconId(null) + } + /* ─── Derived data ─── */ const filteredGroups = symbolGroups.map(g => ({ ...g, @@ -326,6 +373,7 @@ export function SymbolManager() { {([ { key: 'symbols', label: 'Meine Symbole', icon: LayoutGrid }, { key: 'categories', label: 'Kategorien', icon: FolderOpen }, + { key: 'library', label: 'Bibliothek', icon: Library }, { key: 'import', label: 'Vorlagen importieren', icon: Download }, ] as const).map(t => ( + + ))} + + + + ) + })} + + )} + + )} + {/* ===== UPLOAD DIALOG ===== */}