Skip to content

Neue Sektion hinzufügen

Diese Seite beschreibt die Implementierungs-Touchpoints, die beim Hinzufügen einer neuen persistierten Protokollsektion normalerweise notwendig sind.

Sie bildet die aktuelle Architektur in formtest ab. Der Generator nimmt die mechanischen Basisschritte ab, ersetzt aber nicht die fachliche Prüfung von Server-Vertrag, PDF-Ausgabe, Protokoll leeren und Tests.

Für die konzeptionelle Einordnung der Section-Registry, Wrapper und Form-Composables siehe auch /section-architecture.

Neue Sektion via Generator

Für normale persistierte Sektionen ist der Generator der bevorzugte Einstieg. Er erstellt das technische Grundgerüst und verdrahtet die wiederkehrenden Stellen, die sonst leicht vergessen werden.

bash
bun run generate:section --name=<entity> --type=table --component --accordion --i18n

Der Generator kann interaktiv laufen, wenn Flags fehlen. Dann fragt er fehlende Werte wie Typ, Component, Accordion, i18n, Section-Key, Icon und Label im Terminal ab. Für Reviews und wiederholbare Änderungen ist ein ausgeschriebener Command trotzdem besser, weil die Absicht direkt sichtbar ist.

Der Generator passt besonders gut, wenn die Section eine eigene persistierte Entity bekommt, über den normalen Store-/Dexie-Flow läuft und als Standard-Accordion-Section sichtbar werden soll. Wenn die Section eigene Sync-Regeln, Bildlogik, Spezialvalidierung, Setup-Editoren oder komplexe PDF-Regeln braucht, starte trotzdem mit dem Generator, aber plane danach die manuelle fachliche Verdrahtung ein.

WegWas passiert?Wann passt das?
GeneratorErstellt das technische Grundgerüst und verdrahtet die wiederkehrenden Registries.Standard-Sektion mit Persistenz, Store, Accordion-Anbindung und einfacher Start-Komponente.
ManuellJede Datei wird bewusst selbst angelegt oder erweitert.Sonderfälle, bestehende Stores, komplexe Fachlogik, spezielle Bild-/PDF-Regeln oder wenn der Generator bewusst nicht genutzt werden soll.

Eingaben für den Generator

EingabePflicht?BedeutungWerte/BeispieleCommand
Entity-NamejaTechnischer Basisname der Section. Daraus entstehen Schema, Store-ID, Dexie-Tabelle und Standardnamen.damage--name damage
UI-TypempfohlenGrundmuster der Form. Bestimmt, welches Component-Grundgerüst erzeugt wird.table, singleton, setup-driven--type table
Form-Komponente erzeugen?empfohlenLegt eine Vue-Komponente unter app/components/<Section>/ an. Ohne Komponente entstehen nur Persistenz-/Registry-Teile.ja/nein--component oder --no-component
Im Accordion sichtbar?empfohlenVerdrahtet Descriptor, Runtime und Component-Mapping, damit die Section in der Protokollansicht auftauchen kann.ja/nein--accordion oder --no-accordion
i18n-Grundtexte erzeugen?empfohlenErgänzt deutsche Basistexte in i18n/locales/de.json.ja/nein--i18n oder --no-i18n
sichtbarer Section-Keynur bei AbweichungKey, den Setup, Accordion, URL und PDF verwenden. Nur setzen, wenn er nicht dem Entity-Namen entspricht.schaeden--section-key schaeden
Server-Endpunktnur bei AbweichungAPI-Pfad zum Laden und Speichern der Section. Nur setzen, wenn die automatische Ableitung nicht passt./damages--server-endpoint /damages
Label-Keynur bei Abweichungi18n-Key für den Section-Titel.damage.title--label-key damage.title
i18n-Domainnur bei AbweichungObjektname im deutschen Locale-File.damage--i18n-domain damage
Komponentenordnernur bei AbweichungOrdnername unter app/components/.Damage--component-dir Damage
Komponentennamenur bei AbweichungBasisname der erzeugten Vue-Komponente.Damage--component-name Damage
Iconsinnvoll bei sichtbarer SectionIcon für Accordion, Fallback-Section und Empty-State.i-heroicons-exclamation-triangle--icon i-heroicons-exclamation-triangle

Unterschiede der UI-Typen

UI-TypWann verwenden?Typischer Store-InhaltTypisches UI
tableWenn eine Section mehrere gleichartige Einträge hat, zum Beispiel Schäden, Zähler oder Anlagen.Viele Datensätze pro Protokoll.CollectionSection mit Tabellenzeilen, Add-Button und Löschen pro Zeile.
singletonWenn es pro Protokoll genau einen fachlichen Datensatz gibt, zum Beispiel eine einzelne Bewertung oder ein einzelner Textblock.Ein aktiver Datensatz pro Protokoll.SectionWrapper mit Formularfeldern, ohne klassische Tabellenliste.
setup-drivenWenn Felder, Optionen oder Sichtbarkeit stark aus /setup kommen.Persistierte Daten plus Setup-Konfiguration.Komponente liest Setup-Daten über useSetupStore() und baut daraus die Eingabe.

Daraus entsteht zum Beispiel:

bash
bun run generate:section --name damage --type table --component --accordion --i18n --section-key schaeden --server-endpoint /damages --label-key damage.title --i18n-domain damage --component-dir Damage --component-name Damage --icon i-heroicons-exclamation-triangle

Wenn ein Feld der Standardableitung entspricht, kann die Flag weggelassen werden. Für Reviews ist ein vollständig ausgeschriebener Command trotzdem oft besser, weil er die Absicht eindeutig zeigt.

Kurzreferenz der Flags:

  • --name=<entity>: fachlicher Entity-Name; wird zu camelCase/PascalCase normalisiert
  • --type=table|singleton|setup-driven: UI-Grundmuster der Sektion. table ist für mehrere Zeilen, singleton für genau einen Datensatz, setup-driven für setupgesteuerte Sektionen.
  • --component oder --no-component: ob eine Form-Komponente erzeugt wird
  • --accordion oder --no-accordion: ob sectionDescriptors.ts, sectionRuntime.ts und sectionComponents.ts verdrahtet werden
  • --i18n oder --no-i18n: ob deutsche Grundtexte in i18n/locales/de.json ergänzt werden
  • --section-key=<key>: kanonischer Section-Key, falls er vom Entity-Namen abweicht
  • --server-endpoint=/pfad: Endpoint, falls die automatische Pluralisierung nicht passt
  • --component-dir=<name>: Komponentenordner, falls der PascalCase-Standardname nicht passt
  • --component-name=<name>: Komponentenname, falls er vom Ordnernamen abweichen soll
  • --label-key=<key>: i18n-Key für den sichtbaren Section-Titel
  • --i18n-domain=<key>: i18n-Objekt, in dem die Grundtexte erzeugt werden
  • --icon=<icon>: Icon für sichtbare Sections, Fallback-Sections und Empty-States

Das Script erzeugt bzw. aktualisiert Schema, Entity-Registry, Store, Standard-Store-Registry, Dexie-Version, optionale Komponente, Section-Descriptor, Runtime-Registry, Komponenten-Mapping und i18n-Grundgerüst. Danach müssen Server-/Mock-Server-Vertrag, PDF-Ausgabe, spezielle Validierung, Setup-Wiring und fachliche UI-Logik weiterhin geprüft werden.

Generierte Form-Komponenten zeigen im Dev-Modus bewusst eine Warnung:

Diese generierte Sektion ist nur ein technisches Grundgerüst. Nächste Schritte: 1. Server-Endpunkt in app/utils/sectionRuntime.ts prüfen und im Mock-Server W:/Protocol_App/protocols-mock-srv umsetzen. 2. Felder in app/schemas/<entity>.ts und app/components/<Section>/<Section>Form.vue fachlich ersetzen. 3. Falls die Section ins PDF gehört: Generator in app/utils/pdf/sections/ anlegen, in app/utils/pdf/section-generators.ts registrieren und Daten in app/utils/pdf/section-data.ts ergänzen. 4. Speichern, Löschen und Protokoll leeren manuell prüfen. 5. passende Tests unter test/unit oder test/nuxt ergänzen.

Die Warnung darf erst entfernt werden, wenn diese Punkte erledigt oder bewusst als nicht zutreffend dokumentiert wurden.

Zum Entfernen eines generierten Grundgerüsts gibt es:

bash
bun run remove:section --name=<entity>

Wenn beim Anlegen abweichende Optionen wie --section-key, --component-dir, --component-name, --label-key oder --i18n-domain verwendet wurden, müssen dieselben Werte auch beim Entfernen angegeben werden.

Typische Touchpoints

Wenn eine neue persistierte Sektion hinzukommt, braucht die Codebasis normalerweise Änderungen in diesen Bereichen:

  • app/schemas/<entity>.ts
  • app/schemas/entities.ts
  • app/stores/entityStores.ts oder ein spezialisierter Store unter app/stores/<entity>.ts
  • optional app/stores/<entity>.ts als expliziter Wrapper-Exportpfad fuer Standard-Stores
  • app/stores/registry.ts, falls die Sektion nicht ueber die Standard-Store-Registry laeuft
  • app/db/index.ts
  • app/utils/sectionDescriptors.ts
  • app/utils/sectionRuntime.ts
  • app/utils/sectionComponents.ts
  • app/utils/pdf/section-data.ts
  • app/utils/pdf/section-generators.ts
  • i18n/locales/de.json

Je nach Sektion kann zusätzlich Setup-/Config-Wiring in app/schemas/setup.ts, in Setup-Editoren und im /setup-Handling nötig sein. Wenn die Sektion Verantwortlichkeiten verwenden soll, folgt sie dem Scope-Vertrag aus /responsibility-scopes.

Neue Sektion manuell anlegen

Der manuelle Weg ist für Sektionen gedacht, die nicht sauber in das Generator-Grundmuster passen. Typische Gründe sind setup-getriebene Felder, eigene Store-Logik, Sondervalidierung, Bildlogik oder eine PDF-Ausgabe mit Fachregeln. Der Ablauf ist trotzdem immer derselbe: erst den Vertrag festlegen, dann Persistenz und Store, danach UI, Server, PDF und Tests.

Die Beispiele verwenden durchgehend eine fiktive Section damage. Sie zeigen alle nötigen Imports. Wenn du ein Beispiel in eine bestehende Datei einfügst, übernimm nur die Imports, die dort noch fehlen.

1. Erst den Vertrag festlegen

Bevor du Dateien anlegst, lege die technischen Namen fest. Das spart später Umbauten in Aliassen, Store-IDs und Endpunkten.

EntscheidungBeispielBedeutung
Entity-/Store-KeydamagePersistenz-Key, Store-ID und Dexie-Tabelle
Descriptor-IDdamageinterner Key in Descriptor, Runtime, Component und PDF-Mapping
sichtbarer Section-KeyschaedenKey aus Setup, Accordion, URL und PDF
Aliase['damage']Zusätzliche Keys, die dieselbe Section meinen. Nötig, wenn Setup/PDF den sichtbaren Key schaeden verwenden, Store/Entity oder Backend aber weiterhin damage liefern.
Server-Endpunkt/damagesLade-/Speicher-Endpunkt der Section
i18n-DomaindamageTextblock in i18n/locales/de.json
UI-MustertableFormaufbau: Tabelle, Singleton oder setup-getrieben

Wenn der Server bereits einen Section-Key liefert, verwende diesen als sichtbaren key. Wenn Entity-Name und sichtbarer Key unterschiedlich sind, löse das über aliases, nicht über doppelte Einträge in Consumer-Dateien.

aliases sind nur alternative Eingangsnamen für dieselbe fachliche Section. Sie erzeugen keine zweite Section, keinen zweiten Store, keinen zweiten Endpoint und keinen zweiten PDF-Block. Typische Fälle sind: der Store heißt technisch damage, das Setup liefert aber schaeden; ein Backend-Payload verwendet noch einen alten Key; oder bestehende lokale Daten enthalten einen früheren Namen. Der kanonische sichtbare Name bleibt immer key.

2. Persistenz anlegen

Persistenz besteht aus drei Schritten: eigenes Schema, Registrierung in ENTITIES, dann Dexie-Version erhöhen.

Lege zuerst app/schemas/damage.ts an:

ts
import * as v from 'valibot'
import { BaseEntitySchema, DBEntitySchema, defineEntity } from './core'

export const DamageSchema = v.object({
  ...BaseEntitySchema.entries,
  name: v.pipe(v.string(), v.minLength(0)),
  description: v.pipe(v.string(), v.minLength(0)),
})

export const DamageDBSchema = v.object({
  ...DamageSchema.entries,
  ...DBEntitySchema.entries,
})

export type IDamage = v.InferOutput<typeof DamageSchema>

export const DamageEntity = defineEntity({
  name: 'damage',
  schema: DamageSchema,
  createEmpty: (): IDamage => {
    const now = new Date().toISOString()
    return {
      id: crypto.randomUUID(),
      clientCreatedAt: now,
      clientUpdatedAt: now,
      name: '',
      description: '',
    }
  },
})

Der name in defineEntity(...) ist der Entity-/Store-Key. Er muss zu Store-ID, Dexie-Tabelle und Registry passen.

Registriere die Entity danach in app/schemas/entities.ts:

ts
import { DamageEntity } from './damage'

export * from './damage'

export const ENTITIES = {
  // ...
  damage: DamageEntity,
} as const

Wenn eine neue persistierte Entity in ENTITIES hinzukommt, erhöhe in app/db/index.ts die Dexie-Version:

ts
import { buildStoresFromConfig } from '@/schemas/entities'

this.version(31).stores({
  acceptances: 'id',
  ...buildStoresFromConfig(),
  // ...
})

Keine Versionserhöhung ist nötig, wenn du nur UI, Labels, PDF-Ausgabe oder eine nicht persistierte Ansicht ergänzt.

3. Store anbinden

Starte immer mit der Frage: Reicht ein Standard-Store? Für einfache Collection- oder Singleton-Sektionen ist die Antwort meistens ja. Ein Standard-Store kann Einträge anlegen, Felder aktualisieren, löschen, laden, speichern und Dirty-State verwalten.

Für Standard-Stores ergänze app/stores/entityStores.ts:

ts
import { DamageEntity } from '@/schemas/damage'
import { getSectionStoreDexieOptions } from '@/utils/sectionRuntime'

const STANDARD_ENTITY_STORE_DEFINITIONS = {
  // ...
  damage: {
    createEmpty: DamageEntity.createEmpty!,
    ...getSectionStoreDexieOptions('damage'),
  },
} as const

export const STANDARD_ENTITY_STORE_REGISTRY = {
  // ...
  damage: createStandardEntityStore('damage', STANDARD_ENTITY_STORE_DEFINITIONS.damage),
} as const

getSectionStoreDexieOptions(...) kommt immer aus @/utils/sectionRuntime. Wenn dieser Import in entityStores.ts schon vorhanden ist, füge nur die neue Entity hinzu. createStandardEntityStore(...) ist ein lokaler Helper in entityStores.ts; dafür gibt es keinen Import.

Lege zusätzlich den expliziten Store-Export app/stores/damage.ts an:

ts
import { STANDARD_ENTITY_STORE_REGISTRY } from './entityStores'

export const useDamageStore = STANDARD_ENTITY_STORE_REGISTRY.damage

Ein Spezialstore ist erst nötig, wenn der Store mehr leisten muss als generisches CRUD. Beispiele: eigene computed values, gruppierte Einträge, addEmpty() mit Setup-Daten, gemeinsame Feldupdates, eigenes Reset-Verhalten, isSectionInvalid oder ein Spezialvertrag beim Sync. Andere Spalten, Labels oder einfache Felder sind noch kein Spezialstore; das gehört in Schema, Component oder PDF.

Für Spezialstores sieht das Grundmuster so aus:

ts
import { acceptHMRUpdate, defineStore } from 'pinia'
import { DamageEntity } from '@/schemas/entities'
import { getSectionStoreDexieOptions } from '@/utils/sectionRuntime'
import { createBaseStoreSetup } from '@/utils/storeFactory'

export const useDamageStore = defineStore(
  'damage',
  () => {
    const base = createBaseStoreSetup('damage', {
      createEmpty: DamageEntity.createEmpty!,
    })

    return {
      ...base,
      // eigene computed values/actions hier ergänzen
    }
  },
  {
    dexie: {
      ...getSectionStoreDexieOptions('damage'),
      autoHardDelete: true,
    },
  },
)

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useDamageStore, import.meta.hot))
}

Spezialstores müssen zusätzlich direkt in app/stores/registry.ts stehen. Standard-Stores sind über STANDARD_ENTITY_STORE_REGISTRY bereits für getStoreInstances() sichtbar. Diese Sichtbarkeit ist wichtig für Acceptance-Hydration, IndexedDB-Fallback, Dirty-State, Speichern, Protokoll leeren und PDF-Datenaufbau.

4. Section sichtbar machen

Damit die Section im Editor auftaucht, braucht sie drei Metadaten-Einträge: Descriptor, Runtime und Component. useMainAccordionSections.ts baut daraus die sichtbare Accordion-/Sidebar-Registry. Neue Standardsektionen werden dort nicht mehr direkt eingetragen.

Ergänze zuerst app/utils/sectionDescriptors.ts:

ts
damage: {
  key: 'schaeden',
  aliases: ['damage'],
  defaultLabelKey: 'damage.title',
},

key ist der sichtbare Setup-/Accordion-/PDF-Key. aliases nehmen zusätzliche Namen auf, unter denen dieselbe Section erkannt werden soll. Im Beispiel ist schaeden der sichtbare Section-Key, während damage als Entity-/Store- oder Backend-Key weiterhin auf dieselbe Section zeigt. defaultLabelKey muss in i18n/locales/de.json existieren.

Ergänze danach app/utils/sectionRuntime.ts:

ts
damage: {
  icon: 'i-heroicons-exclamation-triangle',
  store: {
    storeId: 'damage',
    serverEndpoint: '/damages',
    loadText: 'damage.title',
  },
},

Ergänze zuletzt app/utils/sectionComponents.ts:

ts
import type { Component } from 'vue'
import type { SectionDescriptorId } from '@/utils/sectionDescriptors'
import DamageForm from '@/components/Damage/DamageForm.vue'

export const SECTION_COMPONENTS = {
  // ...
  damage: DamageForm,
} satisfies Record<SectionDescriptorId, Component>

Wenn der Server die Section noch nicht im Setup liefert, wird sie als Fallback-Section angezeigt. Wenn der Server sie mit isActive: false liefert, bleibt sie bewusst ausgeblendet.

5. Form-Komponente bauen

Die Form-Komponente ist nur für UI und Store-Aufrufe zuständig. Sie schreibt nicht direkt in Dexie und ruft keine APIs direkt auf.

Für Tabellen-Sektionen ist CollectionSection.vue der Standard. Ein minimales Beispiel mit allen Imports:

vue
<script setup lang="ts">
import type { IDamage } from '@/schemas/damage'
import type { TableColumn } from '@nuxt/ui'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import CollectionSection from '@/components/Section/CollectionSection.vue'
import { useDamageStore } from '@/stores/damage'
import { entityActionsColumn, textColumn } from '@/utils/sectionTableColumns'

const { t } = useI18n()
const damageStore = useDamageStore()

const columns = computed<TableColumn<IDamage>[]>(() => [
  textColumn<IDamage, 'name'>('name', t('damage.columns.name'), {
    update: damageStore.updateFieldByKey,
    placeholder: t('damage.placeholders.name'),
  }),
  entityActionsColumn<IDamage>((entry) => ({
    deleteTitle: t('damage.deleteConfirm'),
    onDelete: () => damageStore.remove(entry.id),
  })),
])
</script>

<template>
  <CollectionSection
    :store="damageStore"
    :data="damageStore.activeEntries"
    :columns="columns"
    :empty-title="t('damage.emptyTitle')"
    :empty-description="t('damage.emptyDescription')"
    :add-label="t('damage.add')"
    empty-icon="i-heroicons-exclamation-triangle"
    by="id"
    @add="damageStore.addEmpty()"
  />
</template>

Für Singleton-Sektionen nimm useSingletonSection(store) zusammen mit SectionWrapper.vue. Für setup-getriebene Sektionen kommt die Konfiguration aus useSetupStore(); lege dafür keine zweite Setup-Ladelogik an.

6. Texte ergänzen

Alle sichtbaren Texte gehören in i18n/locales/de.json. Keine Inline-Fallbacktexte in Komponenten verwenden.

json
"damage": {
  "title": "Schäden",
  "add": "Schaden hinzufügen",
  "deleteConfirm": "Schaden löschen?",
  "emptyTitle": "Keine Schäden vorhanden",
  "emptyDescription": "Dokumentieren Sie Schäden für dieses Protokoll.",
  "columns": {
    "name": "Bezeichnung",
    "description": "Beschreibung"
  },
  "placeholders": {
    "name": "Bezeichnung eingeben",
    "description": "Beschreibung eingeben"
  }
}

7. Server und Mock-Server umsetzen

Wenn die Section persistiert und synchronisiert wird, muss auch W:\Protocol_App\protocols-mock-srv den Vertrag kennen. Für Collection-Endpunkte sind normalerweise diese Pfade nötig:

  • GET /damages?acceptanceId=<id>
  • POST /damages?acceptanceId=<id>

Die Antwort sollte success, data und bei Hard-Deletes optional deletedIds enthalten. deletedAt-Tombstones müssen serverseitig vorhandene Einträge löschen. Aktive Einträge werden je nach Endpoint-Vertrag upserted oder ersetzen den Serverstand.

Ein 404 auf einem neuen Section-Endpunkt darf die Acceptance-Seite nicht als fehlend behandeln. Der Client fällt dafür auf lokale Section-Daten zurück. Trotzdem ist der Endpunkt vor fachlicher Freigabe Pflicht, sonst sind Laden und Speichern nicht vollständig.

8. Clear- und Save-Verhalten prüfen

Neue persistierte Sektionen müssen mit Aktionen -> Protokoll leeren zusammenspielen. Der Clear-Flow löscht nicht sofort serverseitig, sondern erzeugt lokal einen Löschentwurf:

  • bestehende Server-Einträge werden im Store mit deletedAt markiert
  • rein lokale, noch nicht gespeicherte Einträge werden entfernt
  • Bilder werden lokal ausgeblendet und erst beim manuellen Speichern als Pending-Deletes verarbeitet
  • Auto-Save wird für diesen Zustand übersprungen
  • Auf Server speichern öffnet ein Entscheidungsmodal; erst dessen Bestätigung schreibt den aktuellen lokalen Stand nach dem Leeren auf den Server
  • Zurücknehmen beziehungsweise Abbrechen verwirft den lokalen Löschentwurf und stellt den Stand von vor dem Leeren wieder her

Der Server-Endpunkt muss deletedAt-Tombstones akzeptieren. Wenn der Client autoHardDelete nutzt, sollte der Server gelöschte IDs in deletedIds zurückgeben.

9. PDF ergänzen, falls die Section ausgegeben werden soll

Wenn die Section ins PDF gehört, ergänze zuerst einen Generator unter app/utils/pdf/sections/<entity>.ts:

ts
import type { Content } from 'pdfmake/interfaces'
import type { SectionGenerator } from '@/utils/pdf/types'

export const damageGenerator: SectionGenerator = (data, section, createHeader) => {
  const damages = data.damages ?? []
  if (damages.length === 0) return []

  const content: Content[] = [createHeader(section.label)]

  content.push({
    ul: damages.map((damage) => damage.name || '-'),
    margin: [0, 0, 0, 8],
  })

  return content
}

Registriere ihn danach in app/utils/pdf/section-generators.ts:

ts
import { damageGenerator } from './sections/damage'

export const SECTION_PDF_GENERATORS = {
  // ...
  damage: damageGenerator,
}

Wenn neue Daten gebraucht werden, erweitere SectionData in app/utils/pdf/types.ts und befülle sie zentral in app/utils/pdf/section-data.ts. pdfTextTop und pdfTextBottom nicht im Generator rendern; das macht app/utils/pdf/section-registry.ts.

Wenn die Section Bildanhänge hat, verwende buildPdfImagesForEntries(...) aus app/utils/pdf/singlePageImages.ts für normale Tabellenbilder und pdfSinglePage.

10. Tests und manuelle Prüfung

Wähle die kleinste sinnvolle Testebene:

  • Metadaten/Reihenfolge: test/unit/sections
  • Store- oder Sync-Sonderlogik: test/unit/stores
  • Nuxt-, Component- oder IndexedDB-Verhalten: test/nuxt
  • echte Editor-Flows nur bei Bedarf als E2E

Prüfe manuell mindestens:

  • Section ist im Accordion oder in der Sidebar sichtbar
  • Section bleibt sichtbar, wenn sie nur lokal als Fallback existiert
  • Speichern lädt keinen 404-Redirect auf /history
  • Protokoll leeren -> Auf Server speichern -> Modal bestätigen löscht Serverdaten
  • Protokoll leeren -> Zurücknehmen lädt Serverdaten zurück
  • Offline-Fallback lädt lokale Daten
  • PDF enthält die Section oder die Nicht-PDF-Entscheidung ist dokumentiert

Nach dem Generator: Mindestprüfung

Nach generate:section ist die Sektion erst dann vollständig, wenn diese Punkte bewusst erledigt oder als nicht zutreffend markiert wurden:

  • Server-Endpoint im Client passt zu W:\Protocol_App\protocols-mock-srv
  • Mock-Server kann aktive Einträge speichern und deletedAt-Tombstones löschen
  • Protokoll leeren -> Auf Server speichern -> Modal bestätigen löscht die Sektion serverseitig
  • Protokoll leeren -> Zurücknehmen lädt den aktuellen Serverstand wieder
  • Store ist in STORE_REGISTRY oder über STANDARD_ENTITY_STORE_REGISTRY sichtbar
  • PDF-Ausgabe ist ergänzt oder bewusst nicht vorgesehen
  • deutsche i18n-Keys sind vollständig
  • Dexie-Version ist erhöht
  • sinnvoller Regressionstest ist ergänzt oder als späterer Task benannt