Seed: services template (18 files)

This commit is contained in:
2026-07-23 22:11:18 +00:00
parent 9b69d74620
commit d86738560e
+200
View File
@@ -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">
Lets Build Something Great
</h1>
<p className="mt-6 text-lg text-muted-foreground leading-relaxed">
Have a project in mind? Wed love to hear about it. Reach out and lets 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>
);
}