From 2097b571f3f27a6820eafc4fd3f190c16b6fa5c3 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Tue, 7 Apr 2026 23:08:04 +0200 Subject: [PATCH] feat(web): streamline contact form and integrate identity fields --- apps/web/src/actions/contact.ts | 6 + apps/web/src/components/ContactForm.tsx | 23 +- .../components/ContactForm/ContactGateway.tsx | 63 +++--- .../ContactForm/DirectMessageFlow.tsx | 199 ++++++++++++++---- .../components/ContactForm/EmailTemplates.tsx | 6 +- apps/web/src/components/ContactForm/types.ts | 1 + apps/web/src/logic/pricing/constants.ts | 1 + apps/web/src/logic/pricing/types.ts | 163 +++++++------- apps/web/src/payload/collections/Inquiries.ts | 12 ++ 9 files changed, 318 insertions(+), 156 deletions(-) diff --git a/apps/web/src/actions/contact.ts b/apps/web/src/actions/contact.ts index ca7969a..6207fe3 100644 --- a/apps/web/src/actions/contact.ts +++ b/apps/web/src/actions/contact.ts @@ -11,8 +11,11 @@ import configPromise from "@payload-config"; export async function sendContactInquiry(data: { name: string; email: string; + phone?: string; + role?: string; companyName: string; projectType: string; + deadline?: string; message: string; isFreeText: boolean; config?: any; @@ -25,8 +28,11 @@ export async function sendContactInquiry(data: { data: { name: data.name, email: data.email, + phone: data.phone, + role: data.role, companyName: data.companyName, projectType: data.projectType, + deadline: data.deadline, message: data.message, isFreeText: data.isFreeText, config: data.config || null, diff --git a/apps/web/src/components/ContactForm.tsx b/apps/web/src/components/ContactForm.tsx index fe3462d..ea44ab9 100644 --- a/apps/web/src/components/ContactForm.tsx +++ b/apps/web/src/components/ContactForm.tsx @@ -62,7 +62,7 @@ export function ContactForm({ initialStepIndex = 0, initialState: injectedState, }: ContactFormProps) { - const [flow, setFlow] = useState("discovery"); + const [flow, setFlow] = useState("direct-message"); const [stepIndex, setStepIndex] = useState(initialStepIndex); const [state, setState] = useState({ ...initialState, @@ -125,8 +125,11 @@ export function ContactForm({ const result = await sendContactInquiry({ name: state.name, email: state.email, + phone: state.phone, + role: state.role, companyName: state.companyName, projectType: state.projectType, + deadline: state.deadline, message: state.message, isFreeText: flow === "direct-message", config: flow === "configurator" ? state : undefined, @@ -190,7 +193,7 @@ export function ContactForm({ +

+ System-Konfigurator +

+

+ Dieser Modus wird aktuell optimiert und steht in Kürze wieder + zur Verfügung. +

+ +
+ Konfigurator offline +
+ + {/* Direct Mail Path */} diff --git a/apps/web/src/components/ContactForm/DirectMessageFlow.tsx b/apps/web/src/components/ContactForm/DirectMessageFlow.tsx index 5090254..396c80c 100644 --- a/apps/web/src/components/ContactForm/DirectMessageFlow.tsx +++ b/apps/web/src/components/ContactForm/DirectMessageFlow.tsx @@ -3,13 +3,33 @@ import { motion } from "framer-motion"; import { cn } from "../../utils/cn"; import { Reveal } from "../Reveal"; -import { Mail, MessageSquare, ArrowLeft, Send } from "lucide-react"; +import { ProjectType } from "./types"; +import { + Mail, + MessageSquare, + ArrowLeft, + Send, + Phone, + User as UserIcon, + Calendar, + Layers, +} from "lucide-react"; interface DirectMessageFlowProps { name: string; + setName: (val: string) => void; email: string; setEmail: (val: string) => void; + phone: string; + setPhone: (val: string) => void; + role: string; + setRole: (val: string) => void; company: string; + setCompany: (val: string) => void; + projectType: ProjectType; + setProjectType: (val: ProjectType) => void; + deadline: string; + setDeadline: (val: string) => void; message: string; setMessage: (val: string) => void; onBack: () => void; @@ -19,9 +39,19 @@ interface DirectMessageFlowProps { export const DirectMessageFlow = ({ name, + setName, email, setEmail, + phone, + setPhone, + role, + setRole, company, + setCompany, + projectType, + setProjectType, + deadline, + setDeadline, message, setMessage, onBack, @@ -30,72 +60,167 @@ export const DirectMessageFlow = ({ }: DirectMessageFlowProps) => { return (
- - - -
-
+
- DIREKTNACHRICHT // MODUS_AKTIVIERT + DIREKTANFRAGE // SCHRITT_01 -

- Wie kann ich helfen, {name.split(" ")[0]}? +

+ Lassen Sie uns sprechen.

-

- Sende mir eine Nachricht zu {company || "deinem Projekt"} und ich - melde mich in Kürze. +

+ Senden Sie mir eine Nachricht und ich melde mich zeitnah zurück.

-
- {/* Email Input */} +
+ {/* Section: Mission Focus */} -
+
- setEmail(e.target.value)} - placeholder="ihre@email.de" - className="w-full bg-slate-50 border border-slate-100 rounded-2xl px-6 py-4 text-lg font-medium focus:outline-none focus:ring-2 focus:ring-slate-900/5 focus:border-slate-900 transition-all" - /> +
+ {(["website", "web-app", "ecommerce"] as ProjectType[]).map( + (type) => { + const labels = { + website: "Website", + "web-app": "Web Application", + ecommerce: "E-Commerce", + }; + return ( + + ); + }, + )} +
- {/* Message Input */} + {/* Section: Identity Details */} +
+
+ + setName(e.target.value)} + placeholder="Max Mustermann" + className="w-full bg-slate-50 border border-slate-100 rounded-xl px-4 py-3 text-base font-medium focus:outline-none focus:ring-2 focus:ring-slate-900/5 focus:border-slate-900 transition-all" + /> +
+
+ + setCompany(e.target.value)} + placeholder="Beispiel GmbH" + className="w-full bg-slate-50 border border-slate-100 rounded-xl px-4 py-3 text-base font-medium focus:outline-none focus:ring-2 focus:ring-slate-900/5 focus:border-slate-900 transition-all" + /> +
+
+ + setEmail(e.target.value)} + placeholder="name@firma.de" + className="w-full bg-slate-50 border border-slate-100 rounded-xl px-4 py-3 text-base font-medium focus:outline-none focus:ring-2 focus:ring-slate-900/5 focus:border-slate-900 transition-all" + /> +
+
+ + setPhone(e.target.value)} + placeholder="+49 123 456789" + className="w-full bg-slate-50 border border-slate-100 rounded-xl px-4 py-3 text-base font-medium focus:outline-none focus:ring-2 focus:ring-slate-900/5 focus:border-slate-900 transition-all" + /> +
+
+
+ + {/* Section: Additional Context */} + +
+
+ + setRole(e.target.value)} + placeholder="z.B. Gründer, Marketing Lead..." + className="w-full bg-slate-50 border border-slate-100 rounded-xl px-4 py-3 text-base font-medium focus:outline-none focus:ring-2 focus:ring-slate-900/5 focus:border-slate-900 transition-all" + /> +
+
+ + +
+
+
+ + {/* Section: Payload */} +