Seed: services template (18 files)
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
||||
import { MapPin, Phone, ArrowRight } from "lucide-react";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useSaasMutation } from "@/hooks/use-tygarun";
|
||||
|
||||
const offices = [
|
||||
{ city: "San Francisco", address: "123 Design Street, Suite 400, SF, CA 94105", phone: "+1 (555) 123-4567" },
|
||||
{ city: "New York", address: "456 Creative Ave, Floor 12, NY, NY 10001", phone: "+1 (555) 987-6543" },
|
||||
];
|
||||
|
||||
const faqs = [
|
||||
{ q: "How long does a typical project take?", a: "Most projects take 8-12 weeks from kickoff to launch, depending on scope and complexity. We will provide a detailed timeline during our discovery phase." },
|
||||
{ q: "What is your design process?", a: "We follow a four-phase process: Discovery, Design, Development, and Delivery. Each phase includes client checkpoints to ensure alignment." },
|
||||
{ q: "Do you work with startups?", a: "Absolutely! We love working with startups. Our Starter plan is specifically designed for early-stage companies looking to establish their digital presence." },
|
||||
{ q: "Can you help with ongoing maintenance?", a: "Yes, we offer ongoing support and maintenance packages. Most clients stay with us well beyond the initial launch for continuous improvement." },
|
||||
{ q: "What technologies do you use?", a: "We work with modern frameworks like React, Next.js, and TypeScript on the frontend, with Node.js, Python, and cloud services on the backend." },
|
||||
{ q: "How do you handle project communication?", a: "Each project gets a dedicated Slack channel, weekly video check-ins, and access to our project management board for full transparency." },
|
||||
];
|
||||
|
||||
export default function ContactPage() {
|
||||
const { mutate: bookConsult, loading: sending } = useSaasMutation("scheduling", "/bookings");
|
||||
const [name, setName] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [company, setCompany] = useState("");
|
||||
const [budget, setBudget] = useState("");
|
||||
const [projectType, setProjectType] = useState("");
|
||||
const [message, setMessage] = useState("");
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
await bookConsult({ name, email, company, budget, projectType, message });
|
||||
setSubmitted(true);
|
||||
toast.success("Message sent! We'll get back to you within 24 hours.");
|
||||
} catch (err) {
|
||||
toast.error("Something went wrong. Please try again.");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground antialiased">
|
||||
<Header />
|
||||
|
||||
{/* ── CONTACT SECTION ── */}
|
||||
<section className="pt-32 pb-24">
|
||||
<div className="mx-auto max-w-7xl px-6">
|
||||
<div className="grid lg:grid-cols-2 gap-16">
|
||||
{/* LEFT: Info */}
|
||||
<div>
|
||||
<h1 className="text-4xl sm:text-5xl font-extrabold tracking-tight animate-fade-up">
|
||||
Let’s Build Something Great
|
||||
</h1>
|
||||
<p className="mt-6 text-lg text-muted-foreground leading-relaxed">
|
||||
Have a project in mind? We’d love to hear about it. Reach out and let’s start a conversation.
|
||||
</p>
|
||||
|
||||
<div className="mt-12 space-y-6">
|
||||
{offices.map((office, i) => (
|
||||
<Card key={i} className="border">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0">
|
||||
<MapPin className={`h-5 w-5 text-primary \${i === 0 ? "animate-bounce" : ""}`} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-bold">{office.city}</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1">{office.address}</p>
|
||||
<p className="text-sm text-muted-foreground flex items-center gap-2 mt-1">
|
||||
<Phone className="h-3.5 w-3.5" /> {office.phone}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Map Placeholder */}
|
||||
<div className="relative mt-8 aspect-[2/1] rounded-xl bg-muted border flex items-center justify-center text-sm text-muted-foreground overflow-hidden animate-scale-in">
|
||||
<div className="absolute inset-0 opacity-[0.06]" style={{ backgroundImage: "radial-gradient(circle, currentColor 1px, transparent 1px)", backgroundSize: "16px 16px" }} />
|
||||
<div className="absolute -top-8 -right-8 w-32 h-32 rounded-full bg-primary/10 blur-2xl" />
|
||||
Map Placeholder
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT: Form */}
|
||||
<div>
|
||||
<Card className="border shadow-sm backdrop-blur-sm bg-card/80">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl">Send us a message</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{submitted ? (
|
||||
<div className="py-12 text-center space-y-3 animate-fade-in">
|
||||
<div className="mx-auto w-14 h-14 rounded-full bg-primary/10 flex items-center justify-center mb-4">
|
||||
<ArrowRight className="h-6 w-6 text-primary" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Message Sent!</h3>
|
||||
<p className="text-sm text-muted-foreground">Thanks for reaching out. We will get back to you within 24 hours.</p>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-5">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Name</label>
|
||||
<Input placeholder="Your name" value={name} onChange={(e) => setName(e.target.value)} required />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Email</label>
|
||||
<Input type="email" placeholder="you@company.com" value={email} onChange={(e) => setEmail(e.target.value)} required />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Company</label>
|
||||
<Input placeholder="Company name" value={company} onChange={(e) => setCompany(e.target.value)} />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Budget</label>
|
||||
<Select value={budget} onValueChange={setBudget}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select budget range" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="5k-10k">$5K - $10K</SelectItem>
|
||||
<SelectItem value="10k-25k">$10K - $25K</SelectItem>
|
||||
<SelectItem value="25k-50k">$25K - $50K</SelectItem>
|
||||
<SelectItem value="50k+">$50K+</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Project Type</label>
|
||||
<Select value={projectType} onValueChange={setProjectType}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select project type" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="brand">Brand & Design</SelectItem>
|
||||
<SelectItem value="web">Web Development</SelectItem>
|
||||
<SelectItem value="marketing">Digital Marketing</SelectItem>
|
||||
<SelectItem value="mobile">Mobile App</SelectItem>
|
||||
<SelectItem value="other">Other</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Message</label>
|
||||
<Textarea
|
||||
placeholder="Tell us about your project..."
|
||||
rows={5}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" disabled={sending} className="w-full active:scale-[0.98]" size="lg">
|
||||
{sending ? "Sending..." : "Send Message"} <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
<p className="text-center text-xs text-muted-foreground mt-3">Average response time: <span className="font-semibold text-primary">4 hours</span></p>
|
||||
</form>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FAQ ── */}
|
||||
<section className="py-24 bg-muted/30">
|
||||
<div className="mx-auto max-w-3xl px-6">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight animate-fade-up">Frequently Asked Questions</h2>
|
||||
</div>
|
||||
<div className="backdrop-blur-sm bg-card/80 border border-border/50 rounded-2xl p-6">
|
||||
<Accordion type="single" collapsible className="space-y-4">
|
||||
{faqs.map((faq, i) => (
|
||||
<AccordionItem key={i} value={`faq-\${i}`} className="bg-background border rounded-lg px-6">
|
||||
<AccordionTrigger className="text-sm font-medium hover:no-underline">{faq.q}</AccordionTrigger>
|
||||
<AccordionContent className="text-sm text-muted-foreground leading-relaxed">
|
||||
{faq.a}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
))}
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user