# Unified Skills Hub — Plan

## Anforderungsanalyse

**Was:** Die zwei getrennten Skill-Seiten (`/analytics/skills` = SkillsAnalytics, `/analytics/skill-marketplace` = SkillMarketplace) zu **einer einzigen, nutzerfreundlichen Skills-Hub-Seite** zusammenfuehren.

**Problem heute:**
- **SkillsAnalytics** (496 LOC): Skill-Tabelle mit Filtern, People Finder (AND/OR Suche), XLSX Export, Skill Distribution Chart, Skill Gap Alerts
- **SkillMarketplace** (346 LOC): Skill-Suche mit Verfuegbarkeitsfilter, Skill Gap Heat Map (Supply vs Demand), Skill Distribution Chart (dupliziert!)
- **Ueberlappung:** Beide haben `ProficiencyBadge`, `PROFICIENCY_CLASSES`, `SkillDistributionChart`, aehnliche Tabellen
- **Verwirrung:** User muss zwei Seiten besuchen fuer zusammenhaengende Informationen
- **Inkonsistenz:** Analytics hat kein Dark-Theme auf manchen Elementen, Marketplace hat es

**Ziel:** Eine Seite `/analytics/skills` mit Tab-basiertem Layout:

```
+-------------------------------------------------------------+
|  Skills Hub                                        [Export]  |
|  125 resources . 47 distinct skills                          |
+----------+----------+----------+-------------+--------------+
| Overview |  Search  |  Gaps    |  People     | Distribution |
+----------+----------+----------+-------------+--------------+
|                                                              |
|  [Tab content area]                                          |
|                                                              |
+--------------------------------------------------------------+
```

### Betroffene Pakete & Dateien

| Paket | Dateien | Art der Aenderung |
|-------|---------|------------------|
| `apps/web` | `src/components/analytics/SkillsHub.tsx` | **create** — neue unified component |
| `apps/web` | `src/components/analytics/skills/OverviewTab.tsx` | **create** — KPI cards + distribution chart |
| `apps/web` | `src/components/analytics/skills/SearchTab.tsx` | **create** — skill search + availability (from Marketplace) |
| `apps/web` | `src/components/analytics/skills/GapsTab.tsx` | **create** — supply/demand gap analysis (from Marketplace) |
| `apps/web` | `src/components/analytics/skills/PeopleFinderTab.tsx` | **create** — AND/OR skill search (from Analytics) |
| `apps/web` | `src/components/analytics/skills/shared.tsx` | **create** — ProficiencyBadge, GapIndicator, constants |
| `apps/web` | `src/app/(app)/analytics/skills/page.tsx` | **edit** — render SkillsHub statt SkillsAnalytics |
| `apps/web` | `src/app/(app)/analytics/skill-marketplace/page.tsx` | **edit** — redirect to /analytics/skills |
| `apps/web` | `src/components/layout/AppShell.tsx` | **edit** — remove "Skill Marketplace" nav link |
| `packages/api` | `src/router/resource.ts` | **edit** — add unified getSkillsHub query |

### Task-Liste

- [ ] **Task 1:** Shared utilities extrahieren -> `skills/shared.tsx`
  - `ProficiencyBadge`, `GapIndicator`, `PROFICIENCY_CLASSES`, `PROFICIENCY_LABELS`, `proficiencyClasses()`
  - Einmal definieren, ueberall nutzen

- [ ] **Task 2:** API: neuen `getSkillsHub` Query -> `resource.ts`
  - Kombiniert alle Daten in einem Call:
    - `aggregated` (from getSkillsAnalytics)
    - `searchResults` (from getSkillMarketplace)
    - `gapData` (from getSkillMarketplace)
    - `distribution` (from both, dedupliziert)
    - `totalResources`, `totalSkillEntries`
  - Alte Queries behalten (AI Assistant nutzt sie)

- [ ] **Task 3:** OverviewTab bauen -> `skills/OverviewTab.tsx`
  - KPI Cards: Total Resources, Total Skills, Avg Proficiency, Skill Gaps Count
  - Top 10 Skills Tabelle (sortierbar)
  - Skill Distribution Chart (lazy-loaded)
  - Quick filters: Category, Min Count

- [ ] **Task 4:** SearchTab bauen -> `skills/SearchTab.tsx`
  - Skill name Suche (debounced)
  - Min Proficiency Filter (1-5 Buttons)
  - "Available in 30 days" Toggle
  - Ergebnis-Tabelle: Resource, Chapter, Skill, Proficiency, Utilization, Available From
  - Links zu `/resources/[id]`

- [ ] **Task 5:** GapsTab bauen -> `skills/GapsTab.tsx`
  - Supply vs Demand Tabelle
  - Supply/Demand Bar Visualisierung
  - Gap Indicator (shortage/surplus/balanced)
  - Sortierbar nach groesstem Gap
  - Click auf Skill -> fuellt Search Tab

- [ ] **Task 6:** PeopleFinderTab bauen -> `skills/PeopleFinderTab.tsx`
  - Multi-rule Builder: Skill + Min Proficiency pro Regel
  - AND/OR Operator Toggle
  - Chapter Filter
  - Ergebnis-Tabelle mit Match Score
  - XLSX Export Button

- [ ] **Task 7:** SkillsHub zusammenfuegen -> `SkillsHub.tsx`
  - Tab Navigation (Overview, Search, Gaps, People Finder)
  - Header mit KPI Summary + Export Button
  - Tab State via URL search params
  - Lazy-load Tabs fuer Performance

- [ ] **Task 8:** Routing + Navigation aktualisieren
  - `/analytics/skills/page.tsx` -> rendert `<SkillsHub />`
  - `/analytics/skill-marketplace/page.tsx` -> redirect zu `/analytics/skills?tab=search`
  - AppShell: "Skill Marketplace" entfernen, "Skills Analytics" umbenennen zu "Skills Hub"

- [ ] **Task 9:** Dark Theme durchgaengig
  - Alle Elemente mit `dark:` Varianten
  - Konsistenz mit dem Rest der App

### Abhaengigkeiten
- Task 1 muss zuerst (shared utilities fuer alle Tabs)
- Task 2 kann parallel zu Task 1 (API aendern)
- Tasks 3-6 koennen parallel nach Task 1 (4 Tabs, unabhaengige Dateien)
- Task 7 benoetigt Tasks 3-6 (importiert alle Tabs)
- Task 8 benoetigt Task 7 (Routing zeigt auf neue Komponente)
- Task 9 kann parallel zu Task 8

### Akzeptanzkriterien
- [ ] `pnpm --filter @planarchy/web exec tsc --noEmit` — keine neuen Errors
- [ ] `/analytics/skills` zeigt die vereinte Seite mit 4 Tabs
- [ ] `/analytics/skill-marketplace` redirected zu `/analytics/skills?tab=search`
- [ ] Alle Features beider Seiten sind auf der neuen Seite verfuegbar
- [ ] Dark Theme funktioniert durchgehend
- [ ] Sidebar zeigt nur noch "Skills Hub" statt zwei Links
- [ ] XLSX Export funktioniert weiterhin
- [ ] People Finder AND/OR Suche funktioniert
- [ ] Skill Gap Heat Map mit Supply/Demand funktioniert
- [ ] Availability Filter (30 Tage) funktioniert

### Risiken & offene Fragen
- **API Performance:** Ein kombinierter Query koennte langsamer sein -> Loesung: Lazy-load per Tab, Query nur wenn Tab aktiv
- **URL State:** Aktiver Tab via `?tab=search` Query Param persistiert
- **Export:** Nur aktiver Tab exportierbar
- **Backwards-Kompatibilitaet:** AI Assistant Tools nutzen alte Queries -> behalten
