1+ "use client" ;
2+
3+ import { useState } from "react" ;
4+ import {
5+ IconActivityLog ,
6+ IconApplicant ,
7+ IconHuman ,
8+ } from "@/public/assets/svgs" ;
9+
10+ import InquiryForm from "./ContactInquiryInform" ;
11+ import ShortSurvey from "./ContactShortSurvey" ;
12+ import Appointment from "./ContactAppointment" ;
13+
14+ const steps = [
15+ { label : "Inquiry Form" , icon : < IconHuman /> } ,
16+ { label : "Short Survey" , icon : < IconApplicant /> } ,
17+ { label : "Set an Appointment" , icon : < IconActivityLog /> } ,
18+ ] ;
19+
20+ export interface ContactFormData {
21+ // Step 1
22+ firstName : string ;
23+ lastName : string ;
24+ email : string ;
25+ companyName : string ;
26+ phoneNumber : string ;
27+ industry : string ;
28+ // Step 2
29+ serviceInterest : string ;
30+ projectType : string ;
31+ featuresNeeded : string ;
32+ referralSource : string ;
33+ interestLevel : number ;
34+ otherRequirements : string ;
35+ }
36+
37+ const ContactPage = ( ) => {
38+ const [ currentStep , setCurrentStep ] = useState ( 0 ) ;
39+ const [ formData , setFormData ] = useState < ContactFormData > ( {
40+ firstName : "" , lastName : "" , email : "" ,
41+ companyName : "" , phoneNumber : "" , industry : "" ,
42+ serviceInterest : "" , projectType : "" , featuresNeeded : "" ,
43+ referralSource : "" , interestLevel : 0 , otherRequirements : "" ,
44+ } ) ;
45+
46+ const goNext = ( ) => setCurrentStep ( ( s ) => Math . min ( s + 1 , steps . length - 1 ) ) ;
47+ const goBack = ( ) => setCurrentStep ( ( s ) => Math . max ( s - 1 , 0 ) ) ;
48+
49+ const updateFormData = ( data : Partial < ContactFormData > ) =>
50+ setFormData ( ( prev ) => ( { ...prev , ...data } ) ) ;
51+
52+ const progressWidth = `${ ( currentStep / ( steps . length - 1 ) ) * 100 } %` ;
53+
54+ return (
55+ < div className = "min-h-screen w-full bg-[#030303] text-white" >
56+ < div className = "mx-auto flex max-w-xl flex-col items-center gap-8 px-5 py-10" >
57+
58+ { /* Stepper */ }
59+ < div className = "relative w-full" >
60+ { /* Connector: circle 1 → circle 2 */ }
61+ < div
62+ className = { `absolute top-5 h-[2px] transition-all duration-500 ${ currentStep > 0 ? "bg-violet-600" : "bg-white/5"
63+ } `}
64+ style = { { left : "calc(16.666% + 20px)" , right : "calc(33.333% + 20px)" } }
65+ />
66+ { /* Connector: circle 2 → circle 3 */ }
67+ < div
68+ className = { `absolute top-5 h-[2px] transition-all duration-500 ${ currentStep > 1 ? "bg-violet-600" : "bg-white/5"
69+ } `}
70+ style = { { left : "calc(50% + 20px)" , right : "calc(16.666% + 20px)" } }
71+ />
72+
73+ < div className = "relative flex items-start" >
74+ { steps . map ( ( step , i ) => {
75+ const isDone = i < currentStep ;
76+ const isActive = i === currentStep ;
77+
78+ return (
79+ < div key = { i } className = "relative z-10 flex flex-1 flex-col items-center gap-2" >
80+ < div
81+ className = { `flex h-10 w-10 items-center justify-center rounded-full border text-sm font-medium transition-all duration-300 ${ isDone
82+ ? "border-violet-600 bg-violet-600 text-white"
83+ : isActive
84+ ? "border-violet-500 bg-violet-500 text-white ring-4 ring-violet-500/25"
85+ : "border-white/5 bg-white/5 text-white/30"
86+ } `}
87+ >
88+ { isDone ? (
89+ < svg className = "h-4 w-4" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
90+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2.5 } d = "M5 13l4 4L19 7" />
91+ </ svg >
92+ ) : (
93+ step . icon
94+ ) }
95+ </ div >
96+ < p
97+ className = { `text-center text-xs transition-colors duration-300 ${ isDone
98+ ? "font-medium text-violet-500"
99+ : isActive
100+ ? "font-semibold text-violet-400"
101+ : "font-medium text-white/30"
102+ } `}
103+ >
104+ { step . label }
105+ </ p >
106+ </ div >
107+ ) ;
108+ } ) }
109+ </ div >
110+ </ div >
111+
112+ { /* Progress Bar */ }
113+ < div className = "h-[2px] w-full rounded-full bg-white/5" >
114+ < div
115+ className = "h-full rounded-full bg-violet-600 transition-all duration-500"
116+ style = { { width : progressWidth } }
117+ />
118+ </ div >
119+
120+ { /* Step Panels */ }
121+ { currentStep === 0 && (
122+ < InquiryForm
123+ defaultValues = { formData }
124+ onNext = { ( data ) => { updateFormData ( data ) ; goNext ( ) ; } }
125+ />
126+ ) }
127+ { currentStep === 1 && (
128+ < ShortSurvey
129+ defaultValues = { formData }
130+ onNext = { ( data ) => { updateFormData ( data ) ; goNext ( ) ; } }
131+ onBack = { goBack }
132+ />
133+ ) }
134+ { currentStep === 2 && (
135+ < Appointment
136+ formData = { formData }
137+ onBack = { goBack }
138+ />
139+ ) }
140+
141+ { /* Security note */ }
142+ < div className = "flex w-full items-center gap-2 rounded-lg border border-white/5 bg-white/5 px-4 py-3" >
143+ < svg className = "h-4 w-4 shrink-0 text-violet-400" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
144+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 }
145+ d = "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
146+ </ svg >
147+ < p className = "text-xs text-white/40" >
148+ We prioritize the security of your information. Rest assured, we will ensure that your data remains safe with us.
149+ </ p >
150+ </ div >
151+
152+ </ div >
153+ </ div >
154+ ) ;
155+ } ;
156+
157+ export default ContactPage ;
0 commit comments