Implementation Plan · Projektpartnerportal · 0001

Projektpartnerportal Listing
Figma-Alignment (Frame 985-50024)

proposed Datum: 2026-05-16 Owner: marc.philipps Go-Live: 08.07.2026 Figma: 985-50024 Refines: 2026-05-14-001 Slice 4
Slices
12
Breakpoint MVP
Desktop 1280
Figma-Frame
985-50024
Go-Live
08.07.2026
01

Problem & Goal

Warum dieser Plan existiert, was er löst und wer davon profitiert.

AspektDetails
ProblemDie Seite /projektpartnerportal rendert aktuell über views.view.project_offers_listing Display page_listing ohne Canvas-Chassis. Layout, Filter-Sidebar, Card-Darstellung und watchlist-bar weichen signifikant vom Figma-Frame 985-50024 ("Projektangebote", File SOLCOM — Design System — Layouts) ab. Freiberufler finden sich in der UI nicht zurecht; strukturierte Filtermechanismen und Matching-Rate fehlen im Frontend vollständig.
ZielDie Seite /projektpartnerportal so weit an Figma-Frame 985-50024 anzugleichen, dass ein visueller Side-by-Side-Verify bei 1280 px als "bestanden" gilt. Backend-Sync (Migrate, Sync-Hygiene) ist in Plan 2026-05-14-001 abgedeckt; dieser Plan fokussiert ausschließlich auf das Frontend-Alignment. Harter Go-Live-Termin: 08.07.2026.
StakeholderFreiberufler / externe Projektpartner (Primär-Nutzer der Listing-Page); SOLCOM-Redaktion (Pflege der Projektangebote); Projektleitung (Go-Live 08.07.2026 — kein Slip ohne Eskalation).
Figma-Quellefigma.com/design/CHHDfbpX8Ys2LBiGs5HVK0 · Node 985-50024
File: "SOLCOM — Design System — Layouts", Frame: "Projektangebote"
02

Decisions

Alle vier User-Decisions (2026-05-16) und das Customer-Lens-Verdict (Option B-Hybrid) sind bindend — werden hier nicht mehr in Frage gestellt.

#ThemaEntscheidungKonsequenz
D1Matching-RateEigener Matching-Service / neues Field (field_matching_score). MVP: Stub-Field mit computed-Fallback 0. Echter Service = Phase 2.S-11 liefert Stub; keine Blockade für S-01–S-10.
D2Laufzeit-FilterMulti-Select-Buckets (<3 Monate, 3–6 Monate, 6–12 Monate, >12 Monate) statt Range-Slider. Kein Datenmodell-Refactor nötig.Custom-BEF-Plugin (S-06) parst field_sf_duration zur Laufzeit in Bucket-Gruppen.
D3BreakpointsDesktop 1280 px im MVP. Mobile/Tablet adaptive best-effort. Visual-Verify ausschließlich bei 1280 px.S-12 prüft nur 1280 px; Responsive-Feinschliff ist Phase-2-Item.
D4Story-AnkerPlan-only, kein Jira-Push. Sub-Tasks optional via to-issues nach Stakeholder-Freigabe.Dieser Plan ist das verbindliche Implementierungs-Dokument; Jira-Tickets entstehen nachgelagert.
CLCustomer-Lens-Verdict
(Option B-Hybrid)
Canvas-Page-Template als Chassis für /projektpartnerportal. views_block:project_offers_listing-block_listing als Listing-Region (Block-Variante existiert bereits). BEF-Filter intern beibehalten — kein AJAX-Custom-SDC-Umbau. Slots: hero/intro, sidebar-meta (BEF-Form), listing-region (views_block), watchlist-region. Filter-Sidebar = BEF-Form mit Twig-Suggestion-Override + BEF-Widget-Overrides je Filter. Custom-BEF-Plugin für Laufzeit-Buckets als eigenständiges Slice. watchlist-bar bleibt in page.html.twig (unabhängig vom Chassis).Klar definierte Slot-Grenzen; kein Framework-Umbau; BEF bleibt wartbar.
03

Scope / Out-of-Scope

In-Scope (MVP, Go-Live 08.07.2026)
  • Figma-Frame 985-50024, Desktop 1280 px
  • Canvas-Page-Chassis für Route /projektpartnerportal
  • BEF-Filter-Sidebar (Twig-Override + Widget-Overrides: Search, Dropdown, Checkbox-Gruppe)
  • Custom-BEF-Plugin Laufzeit-Buckets (Multi-Select, 4 Gruppen)
  • Project-Card-Variante (Field-Inventory A–E inkl. Stub Matching-Rate)
  • Result-Counter-SDC
  • Pagination Twig-Override (Views Pager → Figma-Style)
  • watchlist-bar Rebuild (top-sticky, Backdrop-Blur, Slot, Schliessen-Icon)
  • Matching-Rate Stub-Field (field_matching_score int, Fallback 0)
  • Visual-Verify Pass Desktop 1280 px (Side-by-Side Pixel-Diff)
Out-of-Scope (Phase 2 / bewusst ausgelagert)
  • Mobile / Tablet pixel-genaue Layouts
  • Echter Matching-Service / Open-Risk-Integration
  • Range-Slider für Laufzeit (erfordert Datenmodell-Refactor)
  • Filter-AJAX mit Custom-SDC-Wrapper (kein BEF-Ersatz)
  • Login-gebundene Watchlist-Persistenz
  • Drucklayout / Export
04

Tracer-Bullet-Slices

12 unabhängig deploybare Slices in Abhängigkeitsreihenfolge. S-12 setzt alle vorherigen voraus; S-11 kann parallel zu S-02–S-10 gebaut werden.

S-01

Canvas-Page-Chassis für /projektpartnerportal

Neues Canvas-Page-Template (route-spezifisch, nicht node.project_offer.full) mit vier Slot-Regionen: hero/intro, sidebar-meta (BEF-Form), listing-region (views_block:project_offers_listing-block_listing), watchlist-region. Block-Variante der View ist bereits vorhanden.

Akzeptanzkriterien
  • /projektpartnerportal rendert via Canvas-Chassis
  • Vier Slot-Regionen im Template definiert und im Browser sichtbar
  • views_block:project_offers_listing-block_listing landet in listing-region
  • Keine 404 — bestehende Routing-Konfiguration intakt
Visual-Verify
Chrome 1280 px: Slot-Umrisse sichtbar, kein unbelegter weißer Bereich.
Test
Functional: GET /projektpartnerportal → HTTP 200, Body enthält Canvas-Chassis-Klasse.
Abhängigkeiten
Keine (Baseline-Slice).
Config-Cleanup
Der bisherige page_listing-Display in views.view.project_offers_listing.yml entfällt mit diesem Slice: das Canvas-Chassis übernimmt die Page-Rolle, die Listing-Region nutzt die Block-Variante (block_listing). Der Drop ist irreversibel via config:import: nach Merge entfernt der nächste drush cim den Display aus produktiven Mittwald-Umgebungen. Backout würde einen manuellen Display-Re-Export aus einer Pre-Merge-Datenbank verlangen. Begründung des einseitigen Drops: der Display wurde durch den Customer-Lens-Verdict (Abschnitt 02, Row CL) abgelöst und war bereits funktional toter Code (kein Aufrufer mehr nach Canvas-Chassis-Switch).
canvaspage-templatedrupal
S-02

BEF-Form Twig-Override — Sidebar-Look

Twig-Suggestion-Override für das BEF-Exposed-Form (views-exposed-form--project-offers-listing.html.twig). Ziel: 288 px Sidebar-Breite, Figma-Spacing (24 px innen, 16 px zwischen Feldern), Label-Typografie, Filter-Heading.

Akzeptanzkriterien
  • Sidebar: 288 px Breite (DevTools)
  • Filter-Heading "Filter" mit korrekter Typografie
  • Padding/Spacing laut Figma ±4 px
  • Formular submittet korrekt (Filter wirkt auf Listing)
Visual-Verify
Side-by-Side Figma 985-50024 (Sidebar-Bereich) vs. Screenshot 1280 px.
Test
Functional: BEF-Submit mit Branche-Filter → Listing zeigt gefilterte Ergebnisse.
Abhängigkeiten
S-01 (Canvas-Chassis mit sidebar-meta-Slot).
beftwigsidebar
S-03

BEF-Widget-Override — Search-Input

Twig-Override für das BEF-Widget-Search-Input-Feld. Icon-Prefix (Lupe), Placeholder-Text, Border-Radius, Focus-State laut Figma.

Akzeptanzkriterien
  • Lupen-Icon links im Input-Feld sichtbar
  • Placeholder "Stichwortsuche..." vorhanden
  • Focus-Ring laut Figma (Clay, 2 px)
  • Suche funktioniert (Submit + Autosubmit)
Visual-Verify
Side-by-Side Search-Widget 1280 px.
Test
Functional: Suchbegriff eingeben → Listing filtert korrekt.
Abhängigkeiten
S-02 (Sidebar-Twig als Parent-Context).
befsearch-inputtwig
S-04

BEF-Widget-Override — Dropdown-Select

Twig-Override für alle BEF-Dropdown-Widgets (Branche, Stadt, Auslastung, Projektstart). Custom-Select mit Chevron-Icon, Figma-Border, Hover-State.

Akzeptanzkriterien
  • Alle Dropdown-Filter mit Custom-Styling (nicht Vanilla-<select>)
  • Chevron-Icon sichtbar, Hover-State aktiv
  • Filter-Submit und Autosubmit funktionieren
  • Keyboard-Navigation (Tab, Enter, Escape) intakt
Visual-Verify
Side-by-Side Dropdown-Bereich 1280 px.
Test
Functional: Branche-Filter wählen → Listing zeigt nur passende Angebote.
Abhängigkeiten
S-02.
befdropdowntwig
S-05

BEF-Widget-Override — Checkbox-Gruppe (Branche)

Twig-Override für BEF-Checkboxgroup-Widget (field_sf_industry). Custom-Checkbox mit Clay-Check, Label-Typografie, Mehrfachauswahl.

Akzeptanzkriterien
  • Checkboxen mit Custom-Style (Clay-Farbe, korrekte Größe)
  • Mehrfachauswahl möglich und funktional
  • Autosubmit nach Checkbox-Klick aktiv
  • Leerer Zustand = alle Branchen sichtbar
Visual-Verify
Side-by-Side Checkbox-Gruppe 1280 px.
Test
Functional: Zwei Branchen wählen → Listing-Ergebnismenge entsprechend reduziert.
Abhängigkeiten
S-02.
befcheckboxbranche
S-06

Custom-BEF-Plugin — Laufzeit-Buckets

Neues BEF-Plugin (BefLaufzeitBuckets) das field_sf_duration (String) zur Laufzeit in vier Buckets gruppiert: <3 Monate, 3–6 Monate, 6–12 Monate, >12 Monate. Multi-Select, kein Datenmodell-Refactor. Eigene ADR wenn Plugin-Architektur nicht-triviale Entscheidungen erfordert (R3).

Akzeptanzkriterien
  • Plugin erscheint im BEF-Admin als wählbarer Widget-Typ
  • Vier Bucket-Optionen rendern korrekt
  • Multi-Select (mehrere Buckets kombinierbar)
  • Bucket-Logik: "3–6 Monate" matcht Durations ≥ 3 und ≤ 6
  • Leerer Bucket-State = alle Laufzeiten sichtbar
Visual-Verify
Side-by-Side Laufzeit-Filter-Bereich 1280 px; alle vier Optionen sichtbar.
Test
Unit: BefLaufzeitBuckets::parseDuration() mit Randfällen (null, "0", "12+"). Functional: Bucket-Filter → korrekte Listing-Einschränkung.
Abhängigkeiten
S-02; field_sf_duration befüllt (aus Plan 2026-05-14-001).
befcustom-pluginlaufzeitphp
S-07

Result-Counter-SDC

Neues SDC (result-counter) das die Treffermenge der View anzeigt (z.B. "47 Projektangebote"). Platzierung in listing-region oberhalb der Card-Liste, laut Figma-Frame.

Akzeptanzkriterien
  • Counter zeigt korrekte Anzahl der gefundenen Projektangebote
  • Aktualisiert sich bei Filter-Änderungen (BEF-Submit)
  • Typografie und Position laut Figma ±4 px
Visual-Verify
Counter-SDC sichtbar; Zahl korrekt nach Filter-Änderung.
Test
Functional: Ungefiltert → N Angebote; nach Branche-Filter → reduzierte Zahl.
Abhängigkeiten
S-01 (listing-region Slot).
sdcresult-counter
S-08

Pagination Twig-Override (Views Pager → Figma-Style)

Twig-Suggestion-Override für den Views-Pager: Prev/Next-Buttons mit Chevron-Icon, Page-Numbers, aktiver State laut Figma.

Akzeptanzkriterien
  • Prev/Next-Buttons mit Chevron-Icons sichtbar
  • Aktive Seiten-Nummer hervorgehoben (Clay-Farbe)
  • Navigation funktioniert (Seite 2, 3 … laden korrekt)
  • ARIA-Labels vorhanden (aria-current="page")
Visual-Verify
Side-by-Side Pagination-Bereich 1280 px.
Test
Functional: Klick "Nächste Seite" → korrekte Items, URL-Param ?page=1.
Abhängigkeiten
S-01, S-07.
pagertwigviews
S-09

Project-Card-Variante (Field-Inventory A–E)

card-bubble-profile erweitern oder neue Variante anlegen die alle Field-Inventory-Felder rendert: Matching-Rate-Stub (A), Badge Branche field_sf_industry (B), Heading field_sf_job_title + Fallback title (C), Dauer/Startdatum/Arbeitsmodell/Einsatzort field_sf_duration/field_sf_estimated_start/field_remote_share/field_sf_city (D1–D4), Teaser field_sf_long_description (E). field_remote_share (0–100 %) → Remote/Hybrid/Onsite-Label.

Akzeptanzkriterien
  • Alle fünf Field-Groups (A–E) rendern in der Card
  • Matching-Rate-Pill sichtbar (Stub-Wert 0 %)
  • Branche-Badge mit Taxonomy-Label
  • Remote-Share-Mapping: 0 = Onsite, 1–49 = Hybrid, 50–100 = Remote
  • Teaser auf max. 3 Zeilen abgeschnitten (CSS line-clamp)
  • CTA "Jetzt bewerben" verlinkt auf Detail-Page
Visual-Verify
Side-by-Side Card-Komponente Figma vs. 1280 px; alle 5 Field-Groups sichtbar.
Test
Twig-Unit-Test: Card rendert alle Felder; Teaser-Clamp aktiv; Remote-Label-Logik korrekt für 0, 25, 75.
Abhängigkeiten
S-01 (Listing-Region); S-11 (Matching-Rate-Stub-Field muss existieren).
sdccardtwigfield-inventory
S-10

watchlist-bar Rebuild

watchlist-bar als SDC neu aufbauen: top-sticky (statt bottom-sticky), Backdrop-Blur-Hintergrund, Slot für Counter + CTA, Schliessen-Icon. Bleibt in page.html.twig verankert (unabhängig vom Canvas-Chassis). Vor Implementierung: Live-Usage-Audit (R2).

Akzeptanzkriterien
  • watchlist-bar ist top-sticky (bleibt beim Scrollen oben)
  • Backdrop-Blur-Effekt aktiv (backdrop-filter:blur())
  • Schliessen-Icon vorhanden und funktional (Bar blendet aus)
  • Counter zeigt korrekte Anzahl gemerkter Angebote
  • Kein Regression auf anderen Pages mit watchlist-bar
Visual-Verify
Side-by-Side watchlist-bar Figma vs. 1280 px; Sticky-Verhalten per Scroll-Test.
Test
Regression: watchlist-bar auf allen betroffenen Routes korrekt. Functional: Schliessen → Bar hidden.
Abhängigkeiten
S-01; R2-Prüfung (Live-Usage-Audit) abgeschlossen.
sdcwatchlist-barstickybackdrop-blur
S-11

Matching-Rate-Field Stub

Neues Drupal-Field field_matching_score (Integer, 0–100) auf Bundle project_offer. Computed-Fallback 0 für alle Datensätze. Echter Matching-Service = Phase 2 (R1). Kann parallel zu S-02–S-10 gebaut werden.

Akzeptanzkriterien
  • field_matching_score existiert auf project_offer
  • Default-Wert 0 für alle bestehenden und neuen Nodes
  • Field sichtbar in Field-UI (Admin), nicht auf Detail-Page exponiert
Visual-Verify
Admin: Field in Field-List unter project_offer sichtbar.
Test
Config-Schema-Test: Field-Config exportiert korrekt nach config/sync/.
Abhängigkeiten
Keine. S-09 konsumiert dieses Field.
drupal-fieldmatching-ratestub
S-12

Visual-Verify Pass Desktop 1280

Abschluss-Slice: Pixel-Diff Figma-Frame 985-50024 vs. Live-Screenshot https://solcom.ddev.site/projektpartnerportal bei 1280 px. Side-by-Side via agent-browser. Lighthouse-Run. Vollständiger BEF-Filter-Funktionstest. watchlist-bar Regression-Check.

Akzeptanzkriterien
  • Side-by-Side: keine offensichtlichen Layout-Abweichungen (> 8 px)
  • Lighthouse Performance ≥ 75, Accessibility ≥ 90
  • Alle BEF-Filter funktionsfähig (Branche, Stadt, Auslastung, Dauer-Buckets, Projektstart)
  • watchlist-bar regression-frei auf allen betroffenen Routes
  • 0 JS-Fehler in DevTools Console
Visual-Verify
agent-browser: Screenshot 1280 px → Side-by-Side Figma-Export. Befund-Liste bei Abweichungen > 8 px.
Test
Lighthouse-CI-Run; alle funktionalen Tests aus S-01–S-11 grün.
Abhängigkeiten
S-01 bis S-11 abgeschlossen.
visual-verifylighthouseqa
05

Open Risks / Blockers

Vier identifizierte Risiken. R2 muss vor S-10 adressiert sein.

ID
Risiko
Sev
Mitigation
R1
Matching-Rate-Service-Datenquelle (Open Risk) nicht spezifiziert. S-11 liefert nur Stub — echter Service blockiert den MVP nicht.
MED
Stub-Field mit Fallback 0; Phase-2-ADR oder -PRD für Integration anlegen. UI zeigt "–" bis Service live ist.
R2
watchlist-bar Live-Usage unklar — heute bottom-sticky vorhanden. Umbau auf top-sticky (S-10) kann Regression auf anderen Pages auslösen.
HIGH
Vor S-10: Audit aller Pages mit watchlist-bar (grep template-includes). Entscheidung: globaler Umbau vs. page-spezifische Variante. Regression-Tests vor Merge.
R3
Custom-BEF-Plugin (S-06) ist nicht-trivial: BEF-Plugin-API, Views-Query-Alter-Integration, Bucket-Logik für unstrukturierte Duration-Strings. Eigene ADR ggf. nötig.
MED
Spike (max. 2h) vor S-06 um Plugin-API-Umfang zu validieren. Falls > 1 Tag Aufwand: ADR anlegen, Stakeholder informieren. Fallback: Textsuche-Filter als Interim.
R4
Mobile/Tablet-Layout post-Go-Live unfertig (D3: Desktop-only MVP). Freiberufler nutzen Mobile — schlechte UX-Qualität kann Akzeptanz gefährden.
LOW
Responsive best-effort in allen Slices (kein gezielter Bruch). Phase-2-Refinement-Ticket anlegen. Go-Live-Kommunikation auf Desktop-Nutzung hinweisen.
06

Verifikation

Diese Kriterien entscheiden ob das Feature go-live-ready ist.

Visual-Verify-Pass (S-12)
Side-by-Side agent-browser: Figma-Frame 985-50024 Export (1280 px) vs. Live-Screenshot /projektpartnerportal. Keine Layout-Abweichung > 8 px. Befunde dokumentiert in S-12-Worklog.
Lighthouse-Run
Performance ≥ 75, Accessibility ≥ 90, Best Practices ≥ 85. Run via Lighthouse-CLI gegen https://solcom.ddev.site/projektpartnerportal.
BEF-Filter funktionsfähig
Manuelle Verifikation aller fünf Filter (Branche, Stadt, Auslastung, Dauer-Buckets, Projektstart) + Autosubmit. Kombinierte Filter-Abfragen liefern korrekte Ergebnismengen.
watchlist-bar Regression-frei
watchlist-bar auf allen Routes die sie vor diesem Plan nutzten korrekt. Automatisierter Smoke-Test oder manuelle Stichprobe nach S-10.
Keine JS-Fehler in Console
Chrome DevTools Console auf /projektpartnerportal: 0 Errors nach vollständig geladenem DOM.
07

Cross-References

Verwandte Docs, Decisions und External Sources. Dieser Plan ersetzt keines der referenzierten Dokumente.

ADR
ADR-0031 — SF-Publication Frontend-Decomposition — Decision-Doc; überlappende Sub-Tasks P2503-140 / -141 / -143 / -144 / -151. Dieser Plan verfeinert Slice 4 daraus.
Plan
Plan 2026-05-14-001 — project_offer-Sync (BH4SF) — 12 Slices Backend-Sync; Listing-Page-Komposition war in Slice 4 nur skizziert. Dieser Plan ist die Frontend-Vertiefung (#slice-4).
Figma
Frame 985-50024 — "Projektangebote" (SOLCOM Design System — Layouts) — Einzige Design-Referenz für Visual-Verify; Desktop 1280 px.
Customer-Lens
Option B-Hybrid Verdict (2026-05-16) — Canvas-Chassis + BEF-intern + Slot-Architektur. Verankert in Decisions-Tabelle (Abschnitt 02, Row CL).
08

Follow-up / Open Gaps (post-Wave-D, 2026-05-17)

Figma-MCP-Audit Frame 985-50024 (2026-05-17) hat einen signifikanten Diff zwischen der aktuellen BEF-Filter-Konfiguration und den Figma-Sidebar-Filtern aufgedeckt. User-Entscheidung: Status-quo halten, kein sofortiger Realign. Der Befund wird hier als Follow-up dokumentiert und dient als Grundlage für die Stakeholder-Entscheidung über den nächsten Schritt.

Figma-Filter (985:50024) View-Filter (aktuell, views.view.project_offers_listing) Status
1. Jobbezeichnung — Search-Inputeinsatzort (Stichwortsuche-Text)gap
2. PLZ oder Standort — Select-Dropdownnicht vorhandengap
3. Suchradius km — Slider (5/25/50/75/100+)nicht vorhandengap
4. Skills — Select-Dropdownnicht vorhandengap
5. Branche — Select-Dropdownbranche (Select) ✓match
6. Remote-Anteil % — Slider (30/60/90/100)nicht vorhandengap
7. "Nur meine Projektliste anzeigen" — Checkboxnicht vorhandengap
— (kein Figma-Pendant)dauer-bucket (Pills via bef_links)phantom
— (kein Figma-Pendant)field_sf_utilisation_value (Auslastung)phantom
— (kein Figma-Pendant)field_sf_estimated_start_value (Wunschstart)phantom

Empfehlungen: