From d2d4f3be144f88979adea3413778ce8cbcdc04bd Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Fri, 30 Jan 2026 19:15:39 +0100 Subject: [PATCH] form --- src/components/ContactForm.tsx | 84 ++++++++------- .../ContactForm/components/Input.tsx | 2 +- .../components/PriceCalculation.tsx | 6 +- src/components/ContactForm/constants.tsx | 3 +- src/components/ContactForm/steps/ApiStep.tsx | 12 ++- .../ContactForm/steps/AssetsStep.tsx | 24 +++-- src/components/ContactForm/steps/BaseStep.tsx | 34 ++++-- .../ContactForm/steps/CompanyStep.tsx | 1 + .../ContactForm/steps/ContactStep.tsx | 54 +++++++--- .../ContactForm/steps/ContentStep.tsx | 10 +- .../ContactForm/steps/DesignStep.tsx | 44 +++++--- .../ContactForm/steps/FeaturesStep.tsx | 59 +++-------- .../ContactForm/steps/FunctionsStep.tsx | 100 +++++++----------- .../ContactForm/steps/LanguageStep.tsx | 3 +- .../ContactForm/steps/PresenceStep.tsx | 97 +++++++++-------- .../ContactForm/steps/TimelineStep.tsx | 21 +++- src/components/ContactForm/steps/TypeStep.tsx | 5 +- .../ContactForm/steps/WebAppStep.tsx | 9 +- src/components/ContactForm/types.ts | 9 ++ 19 files changed, 325 insertions(+), 252 deletions(-) diff --git a/src/components/ContactForm.tsx b/src/components/ContactForm.tsx index 1883e97..c970632 100644 --- a/src/components/ContactForm.tsx +++ b/src/components/ContactForm.tsx @@ -200,20 +200,28 @@ export function ContactForm() { }; const steps: Step[] = [ - { id: 'type', title: 'Das Ziel', description: 'Was möchten Sie realisieren?', illustration: }, - { id: 'company', title: 'Unternehmen', description: 'Wer sind Sie?', illustration: }, - { id: 'presence', title: 'Präsenz', description: 'Bestehende Kanäle.', illustration: }, - { id: 'features', title: 'Die Systeme', description: 'Welche inhaltlichen Bereiche planen wir?', illustration: }, - { id: 'base', title: 'Die Seiten', description: 'Welche Seiten benötigen wir?', illustration: }, - { id: 'design', title: 'Design-Wünsche', description: 'Wie soll die Seite wirken?', illustration: }, - { id: 'assets', title: 'Ihre Assets', description: 'Was bringen Sie bereits mit?', illustration: }, - { id: 'functions', title: 'Die Logik', description: 'Welche Funktionen werden benötigt?', illustration: }, - { id: 'api', title: 'Schnittstellen', description: 'Datenaustausch mit Drittsystemen.', illustration: }, - { id: 'content', title: 'Die Pflege', description: 'Wer kümmert sich um die Daten?', illustration: }, - { id: 'language', title: 'Sprachen', description: 'Globale Reichweite planen.', illustration: }, - { id: 'timeline', title: 'Zeitplan', description: 'Wann soll das Projekt live gehen?', illustration: }, - { id: 'contact', title: 'Abschluss', description: 'Erzählen Sie mir mehr über Ihr Vorhaben.', illustration: }, - { id: 'webapp', title: 'Web App Details', description: 'Spezifische Anforderungen für Ihre Anwendung.', illustration: }, + { id: 'type', title: 'Das Ziel', description: 'Was möchten Sie realisieren?', illustration: , chapter: 'strategy' }, + { id: 'company', title: 'Unternehmen', description: 'Wer sind Sie?', illustration: , chapter: 'strategy' }, + { id: 'presence', title: 'Präsenz', description: 'Bestehende Kanäle von {company}.', illustration: , chapter: 'strategy' }, + { id: 'features', title: 'Die Systeme', description: 'Welche inhaltlichen Bereiche planen wir für {company}?', illustration: , chapter: 'scope' }, + { id: 'base', title: 'Die Seiten', description: 'Welche Seiten benötigen wir?', illustration: , chapter: 'scope' }, + { id: 'design', title: 'Design-Wünsche', description: 'Wie soll die neue Präsenz von {company} wirken?', illustration: , chapter: 'creative' }, + { id: 'assets', title: 'Ihre Assets', description: 'Was bringen Sie bereits mit?', illustration: , chapter: 'creative' }, + { id: 'functions', title: 'Die Logik', description: 'Welche Funktionen werden benötigt?', illustration: , chapter: 'tech' }, + { id: 'api', title: 'Schnittstellen', description: 'Datenaustausch mit Drittsystemen.', illustration: , chapter: 'tech' }, + { id: 'content', title: 'Die Pflege', description: 'Wer kümmert sich um die Daten?', illustration: , chapter: 'tech' }, + { id: 'language', title: 'Sprachen', description: 'Globale Reichweite planen.', illustration: , chapter: 'tech' }, + { id: 'timeline', title: 'Zeitplan', description: 'Wann soll das Projekt live gehen?', illustration: , chapter: 'final' }, + { id: 'contact', title: 'Abschluss', description: 'Erzählen Sie mir mehr über Ihr Vorhaben.', illustration: , chapter: 'final' }, + { id: 'webapp', title: 'Web App Details', description: 'Spezifische Anforderungen für {company}.', illustration: , chapter: 'scope' }, + ]; + + const chapters = [ + { id: 'strategy', title: 'Strategie' }, + { id: 'scope', title: 'Umfang' }, + { id: 'creative', title: 'Design' }, + { id: 'tech', title: 'Technik' }, + { id: 'final', title: 'Start' }, ]; const activeSteps = useMemo(() => { @@ -231,7 +239,7 @@ export function ContactForm() { steps.find(s => s.id === 'timeline')!, steps.find(s => s.id === 'contact')!, ]; - }, [state.projectType]); + }, [state.projectType, state.companyName]); useEffect(() => { if (stepIndex >= activeSteps.length) setStepIndex(activeSteps.length - 1); @@ -312,17 +320,31 @@ export function ContactForm() {
-
{activeSteps[stepIndex].illustration}
+
+ {activeSteps[stepIndex].illustration} +
+ {stepIndex + 1} +
+
- Schritt {stepIndex + 1} von {activeSteps.length} -

{activeSteps[stepIndex].title}

-

{activeSteps[stepIndex].description}

+
+ + Schritt {stepIndex + 1} von {activeSteps.length} + +
+

+ {activeSteps[stepIndex].title.replace('{company}', state.companyName || 'Ihr Unternehmen')} +

+

+ {activeSteps[stepIndex].description.replace('{company}', state.companyName || 'Ihr Unternehmen')} +

-
+ +
{activeSteps.map((step, i) => ( -
setHoveredStep(i)} onMouseLeave={() => setHoveredStep(null)} @@ -333,21 +355,11 @@ export function ContactForm() { setStepIndex(i); setTimeout(scrollToTop, 50); }} - className={`w-full h-full rounded-full transition-all duration-700 ${i <= stepIndex ? 'bg-slate-900' : 'bg-slate-100'} cursor-pointer focus:outline-none p-0 border-none`} + className={`w-full h-full rounded-full transition-all duration-700 ${ + i === stepIndex ? 'bg-slate-900 scale-y-150' : + i < stepIndex ? 'bg-slate-400' : 'bg-slate-100' + } cursor-pointer focus:outline-none p-0 border-none`} /> - - {hoveredStep === i && ( - - {step.title} -
- - )} -
))}
diff --git a/src/components/ContactForm/components/Input.tsx b/src/components/ContactForm/components/Input.tsx index 0c3af34..ab0a8b0 100644 --- a/src/components/ContactForm/components/Input.tsx +++ b/src/components/ContactForm/components/Input.tsx @@ -22,7 +22,7 @@ export function Input({ label, icon: Icon, isTextArea, className = '', ...props )}
{Icon && ( -
+
)} diff --git a/src/components/ContactForm/components/PriceCalculation.tsx b/src/components/ContactForm/components/PriceCalculation.tsx index 630f555..0effd08 100644 --- a/src/components/ContactForm/components/PriceCalculation.tsx +++ b/src/components/ContactForm/components/PriceCalculation.tsx @@ -80,7 +80,11 @@ export function PriceCalculation({ document={} fileName={`kalkulation-${state.name.toLowerCase().replace(/\s+/g, '-') || 'projekt'}.pdf`} className="w-full flex items-center justify-center gap-3 px-8 py-4 rounded-full border border-slate-200 text-slate-900 font-bold text-sm uppercase tracking-widest hover:bg-white hover:border-slate-900 transition-all focus:outline-none overflow-hidden relative" - onClick={() => { + onClick={(e) => { + if (pdfLoading) { + e.preventDefault(); + return; + } setPdfLoading(true); setTimeout(() => setPdfLoading(false), 2000); }} diff --git a/src/components/ContactForm/constants.tsx b/src/components/ContactForm/constants.tsx index 7786e73..1cd78c0 100644 --- a/src/components/ContactForm/constants.tsx +++ b/src/components/ContactForm/constants.tsx @@ -69,6 +69,8 @@ export const initialState: FormState = { platformType: 'web-only', // Meta dontKnows: [], + visualStaging: 'standard', + complexInteractions: 'standard', }; export const PAGE_SAMPLES = [ @@ -107,7 +109,6 @@ export const API_OPTIONS = [ { id: 'social', label: 'Social Media Sync', desc: 'Automatisierte Posts oder Feeds.' }, { id: 'maps', label: 'Google Maps / Places', desc: 'Standortsuche und Kartenintegration.' }, { id: 'analytics', label: 'Custom Analytics', desc: 'Anbindung an spezialisierte Tracking-Tools.' }, - { id: 'auth', label: 'Auth-Provider', desc: 'NextAuth, Clerk, Auth0 Integration.' }, ]; export const ASSET_OPTIONS = [ diff --git a/src/components/ContactForm/steps/ApiStep.tsx b/src/components/ContactForm/steps/ApiStep.tsx index 396699d..54d89f1 100644 --- a/src/components/ContactForm/steps/ApiStep.tsx +++ b/src/components/ContactForm/steps/ApiStep.tsx @@ -35,16 +35,19 @@ export function ApiStep({ state, updateState, toggleItem }: ApiStepProps) {
-

- {isWebApp ? 'Integrationen & Datenquellen' : 'Schnittstellen (API)'} -

+
+

+ {isWebApp ? 'Integrationen & Datenquellen' : 'Schnittstellen (API)'} +

+ Optional +
toggleDontKnow('api')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('api') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > @@ -63,7 +66,6 @@ export function ApiStep({ state, updateState, toggleItem }: ApiStepProps) { { id: 'marketing', label: 'Marketing', desc: 'Newsletter (Mailchimp), Social Media Sync.' }, { id: 'ecommerce', label: 'E-Commerce', desc: 'Shopify, WooCommerce, Lagerbestand-Sync.' }, { id: 'maps', label: 'Google Maps / Places', desc: 'Standortsuche und Kartenintegration.' }, - { id: 'auth', label: 'Auth-Provider', desc: 'NextAuth, Clerk, Auth0 Integration.' }, ].map((opt, index) => ( toggleDontKnow('assets')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('assets') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > @@ -56,11 +56,18 @@ export function AssetsStep({ state, updateState, toggleItem }: AssetsStepProps) animate={{ opacity: 1, y: 0 }} transition={{ delay: index * 0.05 }} > - updateState({ assets: toggleItem(state.assets, opt.id) })} - /> +
+ updateState({ assets: toggleItem(state.assets, opt.id) })} + /> + {['logo', 'styleguide', 'content_concept'].includes(opt.id) && ( +
+ Wichtig +
+ )} +
))}
@@ -84,12 +91,13 @@ export function AssetsStep({ state, updateState, toggleItem }: AssetsStepProps) />
- +

Anzahl weiterer Assets

diff --git a/src/components/ContactForm/steps/BaseStep.tsx b/src/components/ContactForm/steps/BaseStep.tsx index f5ef14f..00c9a48 100644 --- a/src/components/ContactForm/steps/BaseStep.tsx +++ b/src/components/ContactForm/steps/BaseStep.tsx @@ -5,7 +5,7 @@ import { FormState } from '../types'; import { Checkbox } from '../components/Checkbox'; import { RepeatableList } from '../components/RepeatableList'; import { motion, AnimatePresence } from 'framer-motion'; -import { Minus, Plus, FileText, ListPlus } from 'lucide-react'; +import { Minus, Plus, FileText, ListPlus, HelpCircle } from 'lucide-react'; import { Input } from '../components/Input'; interface BaseStepProps { @@ -31,12 +31,17 @@ export function BaseStep({ state, updateState, toggleItem }: BaseStepProps) { animate={{ opacity: 1, y: 0 }} className="space-y-8" > - updateState({ websiteTopic: e.target.value })} - /> +
+ updateState({ websiteTopic: e.target.value })} + /> +
+ Wichtig +
+
@@ -45,14 +50,23 @@ export function BaseStep({ state, updateState, toggleItem }: BaseStepProps) {
-

Die Seiten

+
+
+

Die Seiten

+ Wichtig +
+
+ + Warum ist das wichtig? Die Anzahl der Seiten bestimmt maßgeblich den Design- und Umsetzungsaufwand. +
+
- toggleDontKnow('pages')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('pages') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > diff --git a/src/components/ContactForm/steps/CompanyStep.tsx b/src/components/ContactForm/steps/CompanyStep.tsx index 406f962..0bc64f9 100644 --- a/src/components/ContactForm/steps/CompanyStep.tsx +++ b/src/components/ContactForm/steps/CompanyStep.tsx @@ -23,6 +23,7 @@ export function CompanyStep({ state, updateState }: CompanyStepProps) {

Unternehmen

+ Wichtig
+ +
+

Fast geschafft! 🚀

+

+ Ich habe alle Details für das Projekt von {state.companyName || 'Ihrem Unternehmen'} erhalten. + Hinterlassen Sie mir noch Ihre Kontaktdaten, damit ich Ihnen ein konkretes Angebot erstellen kann. +

+
+
+
- updateState({ name: e.target.value })} - /> +
+ updateState({ name: e.target.value })} + /> +
+ Wichtig +
+
- updateState({ email: e.target.value })} - /> +
+ updateState({ email: e.target.value })} + /> +
+ Wichtig +
+
diff --git a/src/components/ContactForm/steps/ContentStep.tsx b/src/components/ContactForm/steps/ContentStep.tsx index f321bea..96a733a 100644 --- a/src/components/ContactForm/steps/ContentStep.tsx +++ b/src/components/ContactForm/steps/ContentStep.tsx @@ -32,7 +32,10 @@ export function ContentStep({ state, updateState }: ContentStepProps) {

Inhalte selbst verwalten (CMS)

-

Möchten Sie Datensätze (z.B. Blogartikel, Produkte) selbst über eine einfache Oberfläche pflegen?

+

+ Ein CMS (Content Management System) ermöglicht es Ihnen, Texte, Bilder und Blogartikel selbst zu ändern, ohne programmieren zu müssen. + Ideal, wenn Sie Ihre Website aktuell halten möchten. +

Inhalte einpflegen

-

Für wie viele Datensätze soll ich die initiale Befüllung übernehmen?

+

+ Wer kümmert sich um die erste Befüllung? Wenn ich das übernehmen soll, geben Sie hier die Anzahl der Datensätze (z.B. fertige Blogartikel oder Produkte) an. + Ansonsten übergeben wir Ihnen eine leere, aber einsatzbereite Struktur. +

toggleDontKnow('design_vibe')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('design_vibe') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > @@ -137,7 +139,7 @@ export function DesignStep({ state, updateState }: DesignStepProps) { whileTap={{ scale: 0.95 }} type="button" onClick={() => toggleDontKnow('color_scheme')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('color_scheme') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > @@ -206,15 +208,33 @@ export function DesignStep({ state, updateState }: DesignStepProps) {
- {/* Wishes */} + {/* References */} +
+
+

Referenz-Websites

+

Gibt es Websites, die Ihnen besonders gut gefallen?

+
+
+ updateState({ references: [...(state.references || []), v] })} + onRemove={(i) => updateState({ references: (state.references || []).filter((_, idx) => idx !== i) })} + placeholder="https://beispiel.de" + /> +
+
+
+ + {/* Wishes */} + updateState({ designWishes: e.target.value })} + placeholder="Haben Sie weitere konkrete Vorstellungen?" + value={state.designWishes} + onChange={(e) => updateState({ designWishes: e.target.value })} />
diff --git a/src/components/ContactForm/steps/FeaturesStep.tsx b/src/components/ContactForm/steps/FeaturesStep.tsx index ba0c493..a551b59 100644 --- a/src/components/ContactForm/steps/FeaturesStep.tsx +++ b/src/components/ContactForm/steps/FeaturesStep.tsx @@ -6,7 +6,7 @@ import { FEATURE_OPTIONS } from '../constants'; import { Checkbox } from '../components/Checkbox'; import { RepeatableList } from '../components/RepeatableList'; import { motion, AnimatePresence } from 'framer-motion'; -import { Minus, Plus, LayoutGrid, ListPlus } from 'lucide-react'; +import { Minus, Plus, LayoutGrid, ListPlus, HelpCircle } from 'lucide-react'; interface FeaturesStepProps { state: FormState; @@ -32,14 +32,23 @@ export function FeaturesStep({ state, updateState, toggleItem }: FeaturesStepPro
-

System-Module

+
+
+

System-Module

+ Optional +
+
+ + Module sind funktionale Einheiten, die über einfache Textseiten hinausgehen. +
+
toggleDontKnow('features')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('features') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > @@ -80,50 +89,6 @@ export function FeaturesStep({ state, updateState, toggleItem }: FeaturesStepPro /> - -
-
-

Anzahl weiterer Module

-

Falls Sie weitere Systeme planen, diese aber noch nicht benennen können.

-
-
- updateState({ otherFeaturesCount: Math.max(0, state.otherFeaturesCount - 1) })} - className="w-14 h-14 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center hover:border-slate-900 transition-colors focus:outline-none" - > - - - - - {state.otherFeaturesCount} - - - updateState({ otherFeaturesCount: state.otherFeaturesCount + 1 })} - className="w-14 h-14 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center hover:border-slate-900 transition-colors focus:outline-none" - > - - -
-
-
); diff --git a/src/components/ContactForm/steps/FunctionsStep.tsx b/src/components/ContactForm/steps/FunctionsStep.tsx index 24a92a9..79cd8d0 100644 --- a/src/components/ContactForm/steps/FunctionsStep.tsx +++ b/src/components/ContactForm/steps/FunctionsStep.tsx @@ -39,12 +39,12 @@ export function FunctionsStep({ state, updateState, toggleItem }: FunctionsStepP {isWebApp ? 'Funktionale Anforderungen' : 'Erweiterte Funktionen'} - toggleDontKnow('functions')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('functions') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > @@ -77,25 +77,45 @@ export function FunctionsStep({ state, updateState, toggleItem }: FunctionsStepP ) : ( <> - updateState({ functions: toggleItem(state.functions, 'search') })} + updateState({ functions: toggleItem(state.functions, 'search') })} /> - updateState({ functions: toggleItem(state.functions, 'filter') })} + updateState({ functions: toggleItem(state.functions, 'filter') })} /> - updateState({ functions: toggleItem(state.functions, 'pdf') })} + updateState({ functions: toggleItem(state.functions, 'pdf') })} /> - updateState({ functions: toggleItem(state.functions, 'forms') })} + updateState({ functions: toggleItem(state.functions, 'forms') })} + /> + updateState({ functions: toggleItem(state.functions, 'members') })} + /> + updateState({ functions: toggleItem(state.functions, 'calendar') })} + /> + updateState({ functions: toggleItem(state.functions, 'multilang') })} + /> + updateState({ functions: toggleItem(state.functions, 'chat') })} /> )} @@ -120,50 +140,6 @@ export function FunctionsStep({ state, updateState, toggleItem }: FunctionsStepP /> - -
-
-

Anzahl weiterer Funktionen

-

Falls Sie weitere Logik-Bausteine planen, diese aber noch nicht benennen können.

-
-
- updateState({ otherFunctionsCount: Math.max(0, state.otherFunctionsCount - 1) })} - className="w-14 h-14 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center hover:border-slate-900 transition-colors focus:outline-none" - > - - - - - {state.otherFunctionsCount} - - - updateState({ otherFunctionsCount: state.otherFunctionsCount + 1 })} - className="w-14 h-14 rounded-full bg-slate-50 border border-slate-100 flex items-center justify-center hover:border-slate-900 transition-colors focus:outline-none" - > - - -
-
-
diff --git a/src/components/ContactForm/steps/LanguageStep.tsx b/src/components/ContactForm/steps/LanguageStep.tsx index 45da31a..8ffab53 100644 --- a/src/components/ContactForm/steps/LanguageStep.tsx +++ b/src/components/ContactForm/steps/LanguageStep.tsx @@ -52,13 +52,14 @@ export function LanguageStep({ state, updateState }: LanguageStepProps) {

Sprachen

+ Optional toggleDontKnow('languages')} - className={`px-6 py-3 rounded-full text-sm font-bold transition-all ${ + className={`px-6 py-3 rounded-full text-sm font-bold transition-all whitespace-nowrap shrink-0 ${ state.dontKnows?.includes('languages') ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-500 hover:bg-slate-200' }`} > diff --git a/src/components/ContactForm/steps/PresenceStep.tsx b/src/components/ContactForm/steps/PresenceStep.tsx index 2830e7d..aba9ed4 100644 --- a/src/components/ContactForm/steps/PresenceStep.tsx +++ b/src/components/ContactForm/steps/PresenceStep.tsx @@ -42,6 +42,7 @@ export function PresenceStep({ state, updateState, toggleItem }: PresenceStepPro

Bestehende Website

+ Optional -
+

Social Media Accounts

-

Welche Kanäle nutzen Sie bereits? Bitte geben Sie die URLs an.

-
- {SOCIAL_PLATFORMS.map((option, index) => { - const isSelected = state.socialMedia.includes(option.id); + +
+ {SOCIAL_PLATFORMS.map((platform) => { + const isSelected = state.socialMedia.includes(platform.id); return ( - updateState({ socialMedia: toggleItem(state.socialMedia, platform.id) })} + className={`flex flex-col items-center gap-3 p-6 rounded-[2rem] border-2 transition-all duration-300 ${ + isSelected ? 'border-slate-900 bg-slate-900 text-white shadow-lg' : 'border-slate-100 bg-white text-slate-400 hover:border-slate-200' }`} > -
-
- updateState({ socialMedia: toggleItem(state.socialMedia, option.id) })} - /> -
- - {isSelected && ( - -
-
- -
- updateUrl(option.id, e.target.value)} - className="w-full p-4 pl-14 bg-white border border-slate-200 rounded-2xl focus:outline-none focus:border-slate-900 transition-all duration-300 text-base" - /> -
-
- )} -
-
-
+ {platform.label} + ); })}
+ +
+ + {state.socialMedia.map((id) => { + const platform = SOCIAL_PLATFORMS.find(p => p.id === id); + if (!platform) return null; + return ( + +
+ {platform.label} +
+ +
+ updateUrl(id, e.target.value)} + className="w-full p-6 pl-40 bg-white border border-slate-100 rounded-[2rem] focus:outline-none focus:border-slate-900 transition-all duration-500 text-lg focus:shadow-xl" + /> + + ); + })} + + + {state.socialMedia.length === 0 && ( +
+

Wählen Sie oben Ihre Kanäle aus, um die Links hinzuzufügen.

+
+ )} +
diff --git a/src/components/ContactForm/steps/TimelineStep.tsx b/src/components/ContactForm/steps/TimelineStep.tsx index 991b2de..200903a 100644 --- a/src/components/ContactForm/steps/TimelineStep.tsx +++ b/src/components/ContactForm/steps/TimelineStep.tsx @@ -10,6 +10,9 @@ interface TimelineStepProps { } export function TimelineStep({ state, updateState }: TimelineStepProps) { + const isMissingAssets = !state.assets.includes('logo') || !state.assets.includes('content_concept'); + const isMissingPages = state.selectedPages.length === 0 && state.otherPages.length === 0 && state.otherPagesCount === 0; + const toggleDontKnow = (id: string) => { const current = state.dontKnows || []; if (current.includes(id)) { @@ -24,10 +27,10 @@ export function TimelineStep({ state, updateState }: TimelineStepProps) {

Zeitplan

-
)} + + {(isMissingAssets || isMissingPages) && ( +
+
+ +
+
+

Mögliche Verzögerungen

+

+ Da noch wichtige Informationen (z.B. {isMissingAssets ? 'Logo/Inhaltskonzept' : ''} {isMissingAssets && isMissingPages ? 'und' : ''} {isMissingPages ? 'Seitenstruktur' : ''}) fehlen, kann sich der Projektstart verzögern, bis diese vorliegen. +

+
+
+ )}
); } diff --git a/src/components/ContactForm/steps/TypeStep.tsx b/src/components/ContactForm/steps/TypeStep.tsx index b5d4df8..d327831 100644 --- a/src/components/ContactForm/steps/TypeStep.tsx +++ b/src/components/ContactForm/steps/TypeStep.tsx @@ -29,7 +29,10 @@ export function TypeStep({ state, updateState }: TypeStepProps) { }`} >
{type.illustration}
-

{type.label}

+
+

{type.label}

+ Wichtig +

{type.desc}

{state.projectType === type.id && ( diff --git a/src/components/ContactForm/steps/WebAppStep.tsx b/src/components/ContactForm/steps/WebAppStep.tsx index 7150a86..3b4de65 100644 --- a/src/components/ContactForm/steps/WebAppStep.tsx +++ b/src/components/ContactForm/steps/WebAppStep.tsx @@ -22,9 +22,12 @@ export function WebAppStep({ state, updateState }: WebAppStepProps) {
{/* Target Audience */}
-

- Zielgruppe -

+
+

+ Zielgruppe +

+ Wichtig +
{[ { id: 'internal', label: 'Internes Tool', desc: 'Für Mitarbeiter & Prozesse.' }, diff --git a/src/components/ContactForm/types.ts b/src/components/ContactForm/types.ts index 101d65e..9590aba 100644 --- a/src/components/ContactForm/types.ts +++ b/src/components/ContactForm/types.ts @@ -56,6 +56,8 @@ export interface FormState { platformType: string; // Meta dontKnows: string[]; + visualStaging: string; + complexInteractions: string; } export interface Step { @@ -63,4 +65,11 @@ export interface Step { title: string; description: string; illustration: React.ReactNode; + chapter?: string; +} + +export interface Chapter { + id: string; + title: string; + steps: string[]; }