@@ -21,6 +21,7 @@ Ziel ist die Implementierung einer Suchfunktion für das Föderale Entwicklungsp
...
@@ -21,6 +21,7 @@ Ziel ist die Implementierung einer Suchfunktion für das Föderale Entwicklungsp
***Durchsuchbare Inhalte:**
***Durchsuchbare Inhalte:**
***FIT-Standards:** Inhalte aus `content/fit-standards/from_openproject.json`. Durchsucht werden sollen die Felder `name`, `shortDescription` und `text`.
***FIT-Standards:** Inhalte aus `content/fit-standards/from_openproject.json`. Durchsucht werden sollen die Felder `name`, `shortDescription` und `text`.
***Ressourcen:** Inhalte aus den Markdown-Dateien (`.de.md` und `.en.md`) in den Unterverzeichnissen von `content/resources/`. Durchsucht werden sollen das Front Matter (`name`, `shortDescription`) sowie der Hauptinhalt (Body nach dem Front Matter).
***Ressourcen:** Inhalte aus den Markdown-Dateien (`.de.md` und `.en.md`) in den Unterverzeichnissen von `content/resources/`. Durchsucht werden sollen das Front Matter (`name`, `shortDescription`) sowie der Hauptinhalt (Body nach dem Front Matter).
* Bereitstellung für Drittanwendungen: Die genannten Inhalte stehen idealerweise auch Drittanwendungen zur Verfügung.
***Internationalisierung:**
***Internationalisierung:**
* Die gesamte Suchfunktionalität (Suchfelder, Ergebnisseite, durchsuchte Inhalte) muss für die unterstützten Sprachen Deutsch (`de`) und Englisch (`en`) funktionieren.
* Die gesamte Suchfunktionalität (Suchfelder, Ergebnisseite, durchsuchte Inhalte) muss für die unterstützten Sprachen Deutsch (`de`) und Englisch (`en`) funktionieren.
***Technologie:**
***Technologie:**
...
@@ -52,15 +53,28 @@ Aufgrund der Anforderungen (client-seitig, einfache Integration, gute Fehlertole
...
@@ -52,15 +53,28 @@ Aufgrund der Anforderungen (client-seitig, einfache Integration, gute Fehlertole
1.**Abhängigkeiten installieren:**
1.**Abhängigkeiten installieren:**
*`fuse.js` zu den Projektabhängigkeiten hinzufügen (`yarn add fuse.js`).
*`fuse.js` zu den Projektabhängigkeiten hinzufügen (`yarn add fuse.js`).
2.**Datenbeschaffung & Konsolidierung (Build Time / Serverseitig):**
***Skript erstellen:** Ein Skript implementieren (z.B. `scripts/build-search-data.js`). Dieses Skript benötigt Zugriff auf Dateisystemfunktionen (`fs`) und Pfadmanipulation (`path`).
***Funktionalität:**
* Das Skript iteriert durch die unterstützten Sprachen (z.B. `['de', 'en']`).
* Für jede Sprache (`lang`):
* Es ruft die notwendigen Funktionen auf (wahrscheinlich adaptiert aus `shared/use-content.ts`), um Markdown-Dateien für 'fit-standards' und 'resources' für diese spezifische Sprache zu lesen und zu parsen.
* Es kombiniert die Ergebnisse beider Quellen zu einem einzigen Array.
* Es reichert jeden Eintrag im Array an mit:
* Einem korrekt lokalisierten `link` (z.B. `/[lang]/resources/{slug}` oder `/[lang]/fit-standards/{slug}`).
* Einem `typeKey` (z.B. 'resource', 'fit-standard') zur einfachen Identifizierung und späteren Übersetzungs-Suche.
* Es stellt sicher, dass das Ausgabe-Verzeichnis (z.B. `public/search-data`) existiert.
* Es schreibt das finale, angereicherte Array für die Sprache in eine JSON-Datei (z.B. `public/search-data/[lang].json`).
***Integration:** Den Build-Befehl in `package.json` (z.B. das `build`-Skript) anpassen, um dieses Node.js-Skript (`node scripts/build-search-data.js`) _vor_ dem standardmäßigen `next build`-Befehl auszuführen. Dies stellt sicher, dass die JSON-Dateien existieren, wenn `getStaticProps` sie benötigt.
3.**Datenbeschaffung & Konsolidierung (Build Time / Serverseitig):**
***Strategie:** In `getStaticProps` der Suchseite (`pages/[lang]/search.tsx`) die Daten für die angeforderte Sprache sammeln.
***Strategie:** In `getStaticProps` der Suchseite (`pages/[lang]/search.tsx`) die Daten für die angeforderte Sprache sammeln.
***Aufruf:**`readMarkdownFilesFromResources('fit-standards', lang)` und `readMarkdownFilesFromResources('resources', lang)` aus `shared/use-content.ts` verwenden.
***Aufruf:**`readMarkdownFilesFromResources('fit-standards', lang)` und `readMarkdownFilesFromResources('resources', lang)` aus `shared/use-content.ts` verwenden.
***Kombinieren:** Die Ergebnisse beider Aufrufe zu einem einzigen Array zusammenführen. Jedes Objekt im Array ist vom Typ `ResourceContent` und enthält `name`, `shortDescription` und `text`. Einen `link` (korrekt lokalisiert, z.B. `/[lang]/resources/{slug}` oder `/fit-standards/{slug}`) und einen `type` ('standard' oder 'resource') hinzufügen.
***Kombinieren:** Die Ergebnisse beider Aufrufe zu einem einzigen Array zusammenführen. Jedes Objekt im Array ist vom Typ `ResourceContent` und enthält `name`, `shortDescription` und `text`. Einen `link` (korrekt lokalisiert, z.B. `/[lang]/resources/{slug}` oder `/fit-standards/{slug}`) und einen `type` ('standard' oder 'resource') hinzufügen.
***Props:** Dieses sprachspezifische Array als Prop an die Seitenkomponente übergeben.
***Props:** Dieses sprachspezifische Array als Prop an die Seitenkomponente übergeben.
3.**Fuse.js Index erstellen (Client-Seitig):**
4.**Fuse.js Index erstellen (Client-Seitig):**
* Auf der Suchergebnisseite (`pages/[lang]/search.tsx`) das sprachspezifische Datenarray aus den Props empfangen.
* Auf der Suchergebnisseite (`pages/[lang]/search.tsx`) das sprachspezifische Datenarray aus den Props empfangen.
* Mittels `useEffect` beim Laden der Komponente eine Fuse.js-Instanz erstellen. Fuse.js konfigurieren, um die Felder `name`, `shortDescription` und `text` zu durchsuchen.
* Mittels `useEffect` beim Laden der Komponente eine Fuse.js-Instanz erstellen. Fuse.js konfigurieren, um die Felder `name`, `shortDescription` und `text` zu durchsuchen.
* Fall "Keine Ergebnisse" (wenn `displayedResults` leer ist) behandeln.
* Fall "Keine Ergebnisse" (wenn `displayedResults` leer ist) behandeln.
***Hinweis für zukünftige Paginierung:** Die `displayedResults` können später einfach in Seiten aufgeteilt werden (z.B. mittels `slice()` und zusätzlichem State für die aktuelle Seite), ohne die Such- oder Filterlogik grundlegend ändern zu müssen. Die Paginierungskomponente würde dann vor und nach der Ergebnisliste eingefügt werden.
***Hinweis für zukünftige Paginierung:** Die `displayedResults` können später einfach in Seiten aufgeteilt werden (z.B. mittels `slice()` und zusätzlichem State für die aktuelle Seite), ohne die Such- oder Filterlogik grundlegend ändern zu müssen. Die Paginierungskomponente würde dann vor und nach der Ergebnisliste eingefügt werden.
6.**Feinschliff & Testen:**
7.**Feinschliff & Testen:**
* Funktionalität (Suche, Filterung, Reset-Filter, Links, **korrekte Pill-Counts**), Layout, Interaktionen (Hover, Tooltips, Pill-Aktivierung) und Styling in beiden Sprachen gründlich testen.
* Funktionalität (Suche, Filterung, Reset-Filter, Links, **korrekte Pill-Counts**), Layout, Interaktionen (Hover, Tooltips, Pill-Aktivierung) und Styling in beiden Sprachen gründlich testen.