diff --git a/ajax/pwa_api.php b/ajax/pwa_api.php index eb2535f..62ed4a1 100644 --- a/ajax/pwa_api.php +++ b/ajax/pwa_api.php @@ -279,9 +279,9 @@ switch ($action) { } } - // Equipment-Typen laden (benötigt für Terminal-Position-Auflösung) + // Equipment-Typen laden (benötigt für Terminal-Position-Auflösung + Typ-Auswahl) $eqType = new EquipmentType($db); - $types = $eqType->fetchAllBySystem(1, 1); // System 1 = Elektro, nur aktive + $types = $eqType->fetchAllBySystem(0, 1); // Alle Systeme, nur aktive // Abgänge laden (Connections mit fk_target IS NULL = Ausgänge) $outputsData = array(); @@ -383,10 +383,39 @@ switch ($action) { 'label' => $t->label, 'label_short' => $t->label_short, 'width_te' => $t->width_te, - 'color' => $t->color + 'color' => $t->color, + 'category' => $t->category ); } + // Feld-Metadaten pro Typ laden (Labels, Typ, Optionen) + $fieldMetaData = array(); + $usedTypeIds = array_unique(array_map(function($e) { return (int) $e['fk_equipment_type']; }, $equipmentData)); + if (!empty($usedTypeIds)) { + $sql = "SELECT fk_equipment_type, field_code, field_label, field_type, field_options, show_on_block"; + $sql .= " FROM ".MAIN_DB_PREFIX."kundenkarte_equipment_type_field"; + $sql .= " WHERE fk_equipment_type IN (".implode(',', $usedTypeIds).")"; + $sql .= " AND active = 1"; + $sql .= " ORDER BY position ASC"; + $resql = $db->query($sql); + if ($resql) { + while ($obj = $db->fetch_object($resql)) { + $typeId = (int) $obj->fk_equipment_type; + if (!isset($fieldMetaData[$typeId])) { + $fieldMetaData[$typeId] = array(); + } + $fieldMetaData[$typeId][] = array( + 'code' => $obj->field_code, + 'label' => $obj->field_label, + 'type' => $obj->field_type, + 'options' => $obj->field_options, + 'show_on_block' => (int) $obj->show_on_block + ); + } + $db->free($resql); + } + } + $response['success'] = true; $response['panels'] = $panelsData; $response['carriers'] = $carriersData; @@ -394,6 +423,7 @@ switch ($action) { $response['outputs'] = $outputsData; $response['inputs'] = $inputsData; $response['types'] = $typesData; + $response['field_meta'] = $fieldMetaData; break; // ============================================ diff --git a/css/pwa.css b/css/pwa.css index 543433d..ddb6e68 100644 --- a/css/pwa.css +++ b/css/pwa.css @@ -1277,6 +1277,22 @@ body { text-align: center; } +.type-grid-category { + grid-column: 1 / -1; + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--colortextlink); + padding: 8px 0 2px; + border-bottom: 1px solid var(--colorborder); + margin-bottom: -2px; +} + +.type-grid-category:first-child { + padding-top: 0; +} + .te-grid { display: grid; grid-template-columns: repeat(2, 1fr); diff --git a/js/pwa.js b/js/pwa.js index a62233c..141acc5 100644 --- a/js/pwa.js +++ b/js/pwa.js @@ -29,6 +29,7 @@ equipmentTypes: [], outputs: [], inputs: [], + fieldMeta: {}, // Offline queue offlineQueue: [], @@ -653,6 +654,7 @@ App.equipmentTypes = response.types || []; App.outputs = response.outputs || []; App.inputs = response.inputs || []; + App.fieldMeta = response.field_meta || {}; // Cache for offline localStorage.setItem('kundenkarte_data_' + App.anlageId, JSON.stringify({ @@ -661,7 +663,8 @@ equipment: App.equipment, types: App.equipmentTypes, outputs: App.outputs, - inputs: App.inputs + inputs: App.inputs, + fieldMeta: App.fieldMeta })); renderEditor(); @@ -677,6 +680,7 @@ App.equipmentTypes = data.types || []; App.outputs = data.outputs || []; App.inputs = data.inputs || []; + App.fieldMeta = data.fieldMeta || {}; renderEditor(); showToast('Offline - Zeige gecachte Daten', 'warning'); } else { @@ -830,14 +834,34 @@ } function renderTypeGrid() { - let html = ''; + const categoryLabels = { + 'automat': 'Leitungsschutz', + 'schutz': 'Schutzgeräte', + 'steuerung': 'Steuerung & Sonstiges', + 'klemme': 'Klemmen' + }; + const categoryOrder = ['automat', 'schutz', 'steuerung', 'klemme']; + + // Typen nach Kategorie gruppieren + const groups = {}; App.equipmentTypes.forEach(type => { - html += ` - - `; + const cat = type.category || 'steuerung'; + if (!groups[cat]) groups[cat] = []; + groups[cat].push(type); + }); + + let html = ''; + categoryOrder.forEach(cat => { + if (!groups[cat] || !groups[cat].length) return; + html += `