Skip to content

Raum-Erfassung

Die Raumsektion ist eine zusammengesetzte Sektion aus room und roomDetail. Die UI liegt in RoomForm.vue und RoomDetailsList.vue, während beide Stores getrennt persistieren und synchronisieren.

Zusammengesetzter Store-Zustand

RoomForm.vue bindet roomStore und roomDetailStore als gemeinsamen Wrapper an SectionWrapper.vue.

Der zusammengesetzte Wrapper:

  • gilt als dirty, wenn einer der beiden Stores dirty ist
  • speichert beide Stores parallel über $saveToServer()
  • markiert beide Stores über $markClean()
  • zeigt den jüngsten Client-Zeitstempel aus beiden Stores

Dadurch fühlt sich die Raumsektion wie eine Sektion an, bleibt technisch aber in zwei Entity-Tabellen getrennt.

Räume hinzufügen

Neue Räume werden aus setupStore.activeSortedRooms ausgewählt. Mehrfachauswahl ist möglich.

Beim Hinzufügen:

  1. roomStore.addEmpty() erzeugt den Raum
  2. roomTypeId und classIds werden aus dem Setup übernommen
  3. Default-Raumdetails werden anhand der Raumklasse erzeugt

Default-Komponenten kommen aus setupStore.roomDetailComponents mit isDefault. Allgemeine Komponenten werden über Raumklassen eingeschränkt, Elektroinstallationen werden zusätzlich immer berücksichtigt.

Raumdetails

RoomDetailsList.vue rendert die Detailtabelle eines Raums.

Die Detailinhalte eines Raums werden erst gemountet, wenn der jeweilige Raum im inneren Accordion geöffnet wird. Bereits geöffnete Räume bleiben danach gemountet, damit Eingaben und Tab-Zustand erhalten bleiben, ohne beim Öffnen der gesamten Raumsektion alle Detailtabellen gleichzeitig zu rendern. Die inneren Raum-Accordions behalten ihre normale Height-Animation.

Es gibt zwei Gruppen:

  • general: allgemeine Raumdetails
  • electrical_installations: Elektroinstallationen

Die Gruppe bestimmt:

  • welche Setup-Komponenten sichtbar sind
  • welcher Verantwortlichkeits-Scope verwendet wird
  • ob Materialien auswählbar sind

Für general verwendet die App den Scope room_general. Für electrical_installations verwendet sie electrical_installation.

Innerhalb eines Raums zeigt die App Raumdetails stabil nach ihrer Erfassungszeit an. Die Sortierung der Setup-Komponenten wird hier bewusst nicht verwendet, damit sich die Eingabereihenfolge nach Aktualisieren oder Offline-Hydration nicht verändert.

Detail-Editor

app/composables/room/useRoomDetailEditor.ts kapselt den Add/Edit-Zustand für Raumdetails.

Beim Öffnen eines neuen Details:

  • Zustand ist standardmäßig good
  • Verantwortlichkeit kommt aus getDefaultResponsibilityIdForScope(...)
  • Materialien werden aus den Default-Materialien der Komponente vorbelegt

Beim Speichern validiert der Editor:

  • eine Komponente muss ausgewählt sein
  • eine Verantwortlichkeit muss gesetzt sein, wenn der Scope sie verlangt

Elektroinstallationen speichern immer eine leere Materialliste, weil diese Gruppe keine Materialien verwendet.

Materialien und Verantwortlichkeiten

Materialien werden über setupStore.getMaterialsForComponent(componentId) geladen. In der Tabelle wird nur eine kompakte Vorschau gezeigt; weitere Materialien erscheinen über Popover.

Verantwortlichkeiten werden über setupStore.getSelectableResponsibilityOptionsForScope(scope, currentId) geladen. In Ausgaben wird das fachliche Label über getResponsibilityOptionById(...) aufgelöst.

Clone aus anderem Raum

app/composables/room/useRoomDetailClone.ts unterstützt die Übernahme von Detailwerten aus anderen Räumen.

Clone-Kandidaten werden gefunden, wenn:

  • die Komponente oder eine äquivalente Komponente in einem anderen Raum existiert
  • der Quellraum in der aktuellen Acceptance vorhanden ist
  • Quelle und Ziel nicht derselbe Detaildatensatz sind

Äquivalenz läuft über den technischen Komponentennamen. Dadurch können Komponenten mit gleicher fachlicher Bedeutung über unterschiedliche IDs hinweg gematcht werden.

Übernehmbare Gruppen:

  • Zustand
  • Verantwortlichkeit
  • Materialien
  • Bemerkungen

Der gespeicherte cloneSource enthält Quellraum, Quelldetail, Komponente und Kopierzeitpunkt. Die Tabelle zeigt daraus einen Badge mit dem Quellraum.

Bilder

Jedes Raumdetail kann über die expandierte Tabellenzeile ein ImageUploadPanel öffnen.

Die Bilder werden mit:

  • parentType: 'roomDetail'
  • parentId: detail.id

gespeichert. Für AI-Bildbeschreibungen erzeugt die Liste einen Kontext aus Komponente und Materialien.

PDF-Ausgabe

Die PDF-Ausgabe liest Räume und Raumdetails über section-data.ts.

Der Raumgenerator trennt allgemeine Details und Elektroinstallationen in der Ausgabe. Innerhalb der Gruppen sortiert er Raumdetails nach der Komponenten-Sortierung aus den Einstellungen; bei gleicher oder fehlender Sortierung bleibt die Erfassungszeit der Fallback. Bilder werden pro Raumdetail aus IndexedDB geladen und über die gemeinsame PDF-Bildertabelle gerendert.

Die globale PDF-Bildkonfiguration aus den Settings steuert dabei Spaltenzahl, Maximalhöhe und Beschriftungen.