|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace App\Http\Controllers\Demo; |
| 4 | + |
| 5 | +use App\Actions\PageAction; |
| 6 | +use App\Http\Controllers\Controller; |
| 7 | +use App\Models\Product; |
| 8 | +use Illuminate\View\View; |
| 9 | +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
| 10 | + |
| 11 | +class FlowsLayoutDemoController extends Controller |
| 12 | +{ |
| 13 | + /** |
| 14 | + * @return array<string, array{title: string, description: string}> |
| 15 | + */ |
| 16 | + public static function variants(): array |
| 17 | + { |
| 18 | + return [ |
| 19 | + 'saas-landing' => [ |
| 20 | + 'title' => 'Klassische SaaS-Landingpage', |
| 21 | + 'description' => 'Grosser Gradient-Hero, Feature-Grid, sticky CTA-Leiste — vertraute Marketing-Rhythmik.', |
| 22 | + ], |
| 23 | + 'editorial' => [ |
| 24 | + 'title' => 'Editorial / Long-Form', |
| 25 | + 'description' => 'Magazin-artige einspaltige Leseerfahrung mit Initiale, Zwischentiteln und viel Weissraum.', |
| 26 | + ], |
| 27 | + 'bento' => [ |
| 28 | + 'title' => 'Bento-Grid', |
| 29 | + 'description' => 'Asymmetrisches Kachelraster im Stil moderner Produktseiten (Apple/Linear).', |
| 30 | + ], |
| 31 | + 'terminal' => [ |
| 32 | + 'title' => 'Terminal / Dev-Konsole', |
| 33 | + 'description' => 'Dunkles, monospace-geprägtes Layout mit Terminal-Fenster-Chrome — technische Zielgruppe.', |
| 34 | + ], |
| 35 | + 'big-statement' => [ |
| 36 | + 'title' => 'Grosse Aussagen / Scroll-Story', |
| 37 | + 'description' => 'Überdimensionierte Typografie, eine Kernaussage pro Abschnitt, filmisches Scrollen.', |
| 38 | + ], |
| 39 | + 'docs-split' => [ |
| 40 | + 'title' => 'Split Sticky Docs', |
| 41 | + 'description' => 'Linke fixierte Mini-Navigation, rechts scrollender Inhalt — wie moderne Doku-Seiten.', |
| 42 | + ], |
| 43 | + 'journey' => [ |
| 44 | + 'title' => 'Nummerierte Reise', |
| 45 | + 'description' => 'Alles als durchnummerierte Schritte mit verbindender Zeitlinie erzählt.', |
| 46 | + ], |
| 47 | + 'before-after' => [ |
| 48 | + 'title' => 'Vorher / Nachher', |
| 49 | + 'description' => 'Kontrastreiche Zweispalten-Gegenüberstellung als Erzählprinzip.', |
| 50 | + ], |
| 51 | + 'swiss-grid' => [ |
| 52 | + 'title' => 'Swiss Minimalist Grid', |
| 53 | + 'description' => 'Strenges Raster, feine Linien, Kapitälchen-Labels — reduziert und hochwertig.', |
| 54 | + ], |
| 55 | + 'tabs-dashboard' => [ |
| 56 | + 'title' => 'Interaktives Tab-Dashboard', |
| 57 | + 'description' => 'Abschnitte als Tabs/Accordion erkundbar — produkttour-artiges Gefühl.', |
| 58 | + ], |
| 59 | + ]; |
| 60 | + } |
| 61 | + |
| 62 | + /** |
| 63 | + * @return array<string, mixed> |
| 64 | + */ |
| 65 | + public static function content(): array |
| 66 | + { |
| 67 | + return [ |
| 68 | + 'headline' => 'Dokumentenprozesse, gesteuert von Agenten. Auf Infrastruktur, die du kontrollierst.', |
| 69 | + 'subheadline' => 'Flows ist eine Orchestrierungsplattform für dokumentenbasierte Prozesse — verbinde dein DMS und lass KI-Agenten Dokumente automatisch extrahieren, validieren und verarbeiten.', |
| 70 | + 'problem' => [ |
| 71 | + 'heading' => 'Extraktionstools lesen Dokumente. Sie verstehen dein Geschäft nicht.', |
| 72 | + 'intro' => 'Zwei Probleme halten Dokumentenprozesse manuell.', |
| 73 | + 'paragraphs' => [ |
| 74 | + 'Das erste ist der Aufwand: Dein DMS speichert Dokumente zuverlässig, aber die Arbeit drumherum – Lesen, Indexieren, Validieren, Übertragen von Daten in andere Systeme – hängt weiterhin von Personen ab, die Dateien öffnen und Daten eintippen. Das skaliert nur durch zusätzliches Personal.', |
| 75 | + 'Das zweite Problem liegt tiefer: Klassische Dokumentenextraktion liefert Felder, nicht mehr. Sie versteht den Inhalt nicht und kann das Ergebnis nicht gegen deine eigenen Daten prüfen – existiert dieser Lieferant, stimmt der Betrag mit der Bestellung überein, ist das die richtige Kostenstelle? Selbst mit einem Extraktionstool muss also weiterhin eine Person jedes Ergebnis prüfen, bevor es vertrauenswürdig ist.', |
| 76 | + ], |
| 77 | + ], |
| 78 | + 'features' => [ |
| 79 | + 'heading' => 'Orchestrierte Agenten-Workflows – extrahieren, verstehen, validieren, zurückschreiben.', |
| 80 | + 'intro' => 'Flows verbindet sich mit deinem bestehenden DMS. Keine Migration; dein Archiv bleibt, wo es ist. Darauf konfigurierst du Workflows, die auslösen, sobald ein Dokument eintrifft.', |
| 81 | + 'items' => [ |
| 82 | + ['title' => 'Agentische Extraktion mit Validierung', 'description' => 'Definiere das Schema, das du brauchst. Agenten extrahieren die Daten, validieren sie gegen deine eigenen Systeme und Daten und schreiben geprüfte Ergebnisse zurück – strukturiert und passend zu deinen Feldnamen.'], |
| 83 | + ['title' => 'Multi-Agenten-Workflow-Orchestrierung', 'description' => 'Für komplexe Prozesse verkettest du spezialisierte Agenten – Klassifizierung, Validierung, Anreicherung, Routing. Die Orchestrierung basiert auf dem Microsoft Agent Framework, und MCP-Tool-Integrationen verbinden deine Workflows direkt mit deinen Geschäftssystemen und Daten.'], |
| 84 | + ['title' => 'Prompt- und Agenten-Engineering', 'description' => 'Verbessere Prompts anhand echter Produktionsdaten, generiere sie aus dem Wissen in deinem Datenpool oder DMS und verwalte Prompts und Schemas in einer versionierten, wiederverwendbaren Knowledge-Bibliothek.'], |
| 85 | + ['title' => 'Modell- und Anbieterfreiheit', 'description' => 'Führe Workflows bei dem Anbieter aus, der zu deinen Anforderungen an Genauigkeit, Kosten und Datenresidenz passt – und vergleiche denselben Workflow über mehrere Modelle hinweg, um zu sehen, welches bei deinen Dokumenten am besten abschneidet. Ein Wechsel bedeutet keinen Neuaufbau. Eigene lokale Modelle (Bring-your-own) folgen als Nächstes.'], |
| 86 | + ['title' => 'Vollständige Nachvollziehbarkeit', 'description' => 'Jeder Lauf wird lückenlos protokolliert: Dokument, Modell, Tokens, Dauer, Ergebnis.'], |
| 87 | + ], |
| 88 | + ], |
| 89 | + 'deployment' => [ |
| 90 | + 'heading' => 'Drei Wege, Flows zu betreiben. Alle isoliert.', |
| 91 | + 'intro' => 'Jede Bereitstellung erhält ihre eigene Datenbank, Schlüsselverwaltung, Speicher und Endpunkte – automatisch bereitgestellt, mit Firewalling und automatischer Rotation der Secrets. Du entscheidest, wo sie läuft, und wählst bei jeder Option die Azure-Region deiner Bereitstellung, sofern diese die benötigten Dienste unterstützt.', |
| 92 | + 'options' => [ |
| 93 | + ['title' => 'Auf deiner eigenen Azure-Infrastruktur', 'description' => 'Flows wird in deine bestehende Azure-Umgebung integriert. Dein Abonnement, deine Governance, deine Kontrolle.'], |
| 94 | + ['title' => 'Dediziertes Azure-Abonnement', 'description' => 'Ein vollständig isoliertes Abonnement, das für dich betrieben wird – maximale Trennung, ohne dass du es selbst betreiben musst.'], |
| 95 | + ['title' => 'Gemeinsames Abonnement, dedizierte Ressourcengruppe', 'description' => 'Deine eigene Ressourcengruppe und Bereitstellungen innerhalb eines gemeinsamen Abonnements – isolierte Ressourcen bei geringerem Fussabdruck.'], |
| 96 | + ], |
| 97 | + ], |
| 98 | + 'cta' => [ |
| 99 | + 'heading' => 'Interessiert?', |
| 100 | + 'body' => 'Wir zeigen dir Flows anhand deiner eigenen Dokumente.', |
| 101 | + 'buttonLabel' => 'Kontaktiere uns', |
| 102 | + ], |
| 103 | + ]; |
| 104 | + } |
| 105 | + |
| 106 | + public function index(): View |
| 107 | + { |
| 108 | + return view('demo.flows.index', [ |
| 109 | + 'variants' => self::variants(), |
| 110 | + ]); |
| 111 | + } |
| 112 | + |
| 113 | + public function show(string $variant): View |
| 114 | + { |
| 115 | + if (! array_key_exists($variant, self::variants())) { |
| 116 | + throw new NotFoundHttpException; |
| 117 | + } |
| 118 | + |
| 119 | + return view("demo.flows.variants.{$variant}", [ |
| 120 | + 'content' => self::content(), |
| 121 | + 'variantTitle' => self::variants()[$variant]['title'], |
| 122 | + ]); |
| 123 | + } |
| 124 | + |
| 125 | + /** |
| 126 | + * @return array<string, array{title: string, description: string}> |
| 127 | + */ |
| 128 | + public static function v2Variants(): array |
| 129 | + { |
| 130 | + return [ |
| 131 | + 'flow-diagram' => [ |
| 132 | + 'title' => 'Fluss-Diagramm', |
| 133 | + 'description' => 'Dokument → Agent → geprüftes Ergebnis als technisches Node-Diagramm im Hero.', |
| 134 | + ], |
| 135 | + 'line-icons' => [ |
| 136 | + 'title' => 'Line-Icon-Set', |
| 137 | + 'description' => 'Ein eigenes, konsistentes Strich-Icon für jedes Feature und jede Deployment-Option.', |
| 138 | + ], |
| 139 | + 'blueprint' => [ |
| 140 | + 'title' => 'Blueprint', |
| 141 | + 'description' => 'Millimeterpapier-Textur, Massketten und Eckmarken — technische Zeichnung.', |
| 142 | + ], |
| 143 | + 'isometric' => [ |
| 144 | + 'title' => 'Isometrisch', |
| 145 | + 'description' => 'Isometrische Dokumentenstapel- und Server-Illustrationen für Hero & Deployment.', |
| 146 | + ], |
| 147 | + 'organic-blobs' => [ |
| 148 | + 'title' => 'Organische Blobs', |
| 149 | + 'description' => 'Weiche Verlaufsflächen in Markenfarben hinter den nummerierten Sektionen.', |
| 150 | + ], |
| 151 | + 'dot-halftone' => [ |
| 152 | + 'title' => 'Halbton-Raster', |
| 153 | + 'description' => 'Punktraster-Illustration im Hero, Plakat-artige Druck-Ästhetik.', |
| 154 | + ], |
| 155 | + 'network-nodes' => [ |
| 156 | + 'title' => 'Netzwerk-Knoten', |
| 157 | + 'description' => 'Verbundene Knoten als Sinnbild für Multi-Agenten-Orchestrierung.', |
| 158 | + ], |
| 159 | + 'stamp-seal' => [ |
| 160 | + 'title' => 'Stempel/Siegel', |
| 161 | + 'description' => 'Kreisrunde Stempelmarken mit perforiertem Rand markieren jede Sektion.', |
| 162 | + ], |
| 163 | + 'data-bars' => [ |
| 164 | + 'title' => 'Daten-Balken', |
| 165 | + 'description' => 'Abstrakte Balken-/Wellenformen als Sinnbild für Dokumentenverarbeitung.', |
| 166 | + ], |
| 167 | + 'doc-stack' => [ |
| 168 | + 'title' => 'Dokumentenstapel', |
| 169 | + 'description' => 'Stilisierte Dokumente mit Eselsohr als durchgehendes Bildmotiv.', |
| 170 | + ], |
| 171 | + ]; |
| 172 | + } |
| 173 | + |
| 174 | + public function indexV2(): View |
| 175 | + { |
| 176 | + return view('demo.flows.v2.index', [ |
| 177 | + 'variants' => self::v2Variants(), |
| 178 | + ]); |
| 179 | + } |
| 180 | + |
| 181 | + public function showV2(string $variant): View |
| 182 | + { |
| 183 | + if (! array_key_exists($variant, self::v2Variants())) { |
| 184 | + throw new NotFoundHttpException; |
| 185 | + } |
| 186 | + |
| 187 | + $product = Product::where('locale', 'de_CH')->where('slug', 'flows')->first(); |
| 188 | + |
| 189 | + $page = $product |
| 190 | + ? (new PageAction)->product(product: $product) |
| 191 | + : (new PageAction(locale: null, routeName: 'products.index'))->default(); |
| 192 | + |
| 193 | + return view("demo.flows.v2.variants.{$variant}", [ |
| 194 | + 'content' => self::content(), |
| 195 | + 'variantTitle' => self::v2Variants()[$variant]['title'], |
| 196 | + 'page' => $page, |
| 197 | + ]); |
| 198 | + } |
| 199 | +} |
0 commit comments