Seed: resume template (10 files)
This commit is contained in:
@@ -0,0 +1,417 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { Progress } from "@/components/ui/progress";
|
||||||
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
||||||
|
import {
|
||||||
|
Menu, ArrowRight, Mail, Linkedin, Github, Twitter, Download,
|
||||||
|
ExternalLink, MapPin, Calendar, Briefcase, GraduationCap, Award,
|
||||||
|
Figma, Globe, Database, Terminal, Layers, Cpu, Send, CheckCircle
|
||||||
|
} from "lucide-react";
|
||||||
|
import { ThemeToggle } from "@/components/ThemeToggle";
|
||||||
|
import { useSaasMutation } from "@/hooks/use-tygarun";
|
||||||
|
|
||||||
|
export default function ResumePage() {
|
||||||
|
const { mutate: createLead, loading: sending } = useSaasMutation("crm", "/leads");
|
||||||
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
|
const [scrolled, setScrolled] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const onScroll = () => setScrolled(window.scrollY > 20);
|
||||||
|
window.addEventListener("scroll", onScroll);
|
||||||
|
return () => window.removeEventListener("scroll", onScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const navLinks = [
|
||||||
|
{ label: "Experience", href: "#experience" },
|
||||||
|
{ label: "Education", href: "#education" },
|
||||||
|
{ label: "Skills", href: "#skills" },
|
||||||
|
{ label: "Contact", href: "#contact" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const certifications = [
|
||||||
|
{ name: "AWS Solutions Architect", issuer: "Amazon Web Services", year: "2024" },
|
||||||
|
{ name: "Google Cloud Professional", issuer: "Google Cloud", year: "2023" },
|
||||||
|
{ name: "PMP Certified", issuer: "Project Management Institute", year: "2022" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const experience = [
|
||||||
|
{
|
||||||
|
company: "Stripe", role: "Senior Software Engineer", dates: "2022 – Present",
|
||||||
|
bullets: ["Led the redesign of the merchant dashboard serving 2M+ users, improving task completion by 35%.", "Architected a real-time analytics pipeline processing 500K events per second.", "Mentored a team of 6 engineers and established code review best practices."],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
company: "Vercel", role: "Software Engineer", dates: "2020 – 2022",
|
||||||
|
bullets: ["Built core deployment infrastructure handling 10M+ builds per month.", "Shipped the Edge Functions runtime adopted by 50K+ projects in first quarter."],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
company: "Airbnb", role: "Frontend Engineer", dates: "2018 – 2020",
|
||||||
|
bullets: ["Developed the new search experience increasing booking conversion by 18%.", "Created a shared component library used across 12 product teams."],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
company: "Freelance", role: "Web Developer", dates: "2016 – 2018",
|
||||||
|
bullets: ["Delivered 30+ client projects ranging from e-commerce to SaaS dashboards.", "Achieved a 100% on-time delivery rate with 5-star average client rating."],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const projects = [
|
||||||
|
{ title: "FinTrack Dashboard", desc: "Real-time financial analytics platform with interactive charts and alerts.", tags: ["React", "TypeScript", "D3.js"], gradient: "from-violet-500 to-indigo-600" },
|
||||||
|
{ title: "MedConnect", desc: "Telemedicine platform connecting patients with specialists worldwide.", tags: ["Next.js", "Prisma", "WebRTC"], gradient: "from-rose-500 to-orange-500" },
|
||||||
|
{ title: "EcoShop", desc: "Sustainable e-commerce marketplace with carbon-neutral shipping tracker.", tags: ["Remix", "Stripe", "PostgreSQL"], gradient: "from-emerald-500 to-teal-500" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const technicalSkills = [
|
||||||
|
{ name: "React / Next.js", value: 95 },
|
||||||
|
{ name: "TypeScript", value: 90 },
|
||||||
|
{ name: "Node.js", value: 85 },
|
||||||
|
{ name: "Python", value: 88 },
|
||||||
|
{ name: "PostgreSQL", value: 80 },
|
||||||
|
{ name: "AWS / Cloud", value: 75 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const tools = [
|
||||||
|
{ icon: Figma, label: "Figma" },
|
||||||
|
{ icon: Globe, label: "Vercel" },
|
||||||
|
{ icon: Database, label: "Supabase" },
|
||||||
|
{ icon: Terminal, label: "Docker" },
|
||||||
|
{ icon: Layers, label: "Terraform" },
|
||||||
|
{ icon: Cpu, label: "GitHub" },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-background text-foreground antialiased">
|
||||||
|
{/* ── HEADER ── */}
|
||||||
|
<header
|
||||||
|
className={`fixed top-0 inset-x-0 z-50 transition-all duration-300 \${
|
||||||
|
scrolled
|
||||||
|
? "bg-background/95 backdrop-blur-lg border-b shadow-sm"
|
||||||
|
: "bg-transparent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="mx-auto max-w-5xl flex items-center justify-between px-6 py-4">
|
||||||
|
<a href="/" className="text-lg font-bold tracking-tight">
|
||||||
|
Taylor Morgan
|
||||||
|
</a>
|
||||||
|
<div className="hidden md:flex items-center gap-8">
|
||||||
|
<nav className="flex items-center gap-8">
|
||||||
|
{navLinks.map((l) => (
|
||||||
|
<a
|
||||||
|
key={l.href}
|
||||||
|
href={l.href}
|
||||||
|
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
{l.label}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
<ThemeToggle />
|
||||||
|
</div>
|
||||||
|
<Sheet open={mobileOpen} onOpenChange={setMobileOpen}>
|
||||||
|
<SheetTrigger asChild className="md:hidden">
|
||||||
|
<Button variant="ghost" size="icon"><Menu className="h-5 w-5" /></Button>
|
||||||
|
</SheetTrigger>
|
||||||
|
<SheetContent side="right" className="w-72">
|
||||||
|
<nav className="mt-8 flex flex-col gap-4">
|
||||||
|
{navLinks.map((l) => (
|
||||||
|
<a key={l.href} href={l.href} className="text-lg font-medium" onClick={() => setMobileOpen(false)}>
|
||||||
|
{l.label}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
<ThemeToggle />
|
||||||
|
</nav>
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* ── HERO ── */}
|
||||||
|
<section className="relative pt-32 pb-24 overflow-hidden">
|
||||||
|
<div className="absolute inset-0 pointer-events-none">
|
||||||
|
<div className="absolute top-1/4 right-1/4 w-80 h-80 rounded-full bg-primary/8 blur-[100px]" />
|
||||||
|
<div className="absolute bottom-0 left-1/3 w-64 h-64 rounded-full bg-violet-500/6 blur-[80px]" />
|
||||||
|
</div>
|
||||||
|
<div className="relative z-10 mx-auto max-w-5xl px-6">
|
||||||
|
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-8 animate-fade-up">
|
||||||
|
<div className="relative w-32 h-32 shrink-0">
|
||||||
|
<div className="absolute inset-0 rounded-full bg-gradient-to-br from-primary via-violet-500 to-rose-500 shadow-xl ring-4 ring-primary/20 animate-pulse" />
|
||||||
|
<div className="absolute inset-0 rounded-full opacity-20" style={{ backgroundImage: "radial-gradient(circle, currentColor 1px, transparent 1px)", backgroundSize: "8px 8px" }} />
|
||||||
|
<div className="absolute bottom-2 right-2 w-4 h-4 rounded-full bg-emerald-500 ring-2 ring-background" />
|
||||||
|
<div className="absolute -bottom-1 -left-1 w-3 h-3 rounded-full bg-violet-400 border-2 border-background" />
|
||||||
|
</div>
|
||||||
|
<div className="text-center sm:text-left">
|
||||||
|
<h1 className="text-5xl md:text-7xl font-black tracking-tighter leading-[1.05]">
|
||||||
|
Taylor Morgan
|
||||||
|
</h1>
|
||||||
|
<p className="mt-3 text-xl text-muted-foreground leading-relaxed">Senior Full-Stack Engineer</p>
|
||||||
|
<p className="mt-4 text-muted-foreground leading-relaxed max-w-lg">
|
||||||
|
Passionate engineer with 8+ years building scalable web applications. I love clean architecture, great UX, and shipping products that make a difference.
|
||||||
|
</p>
|
||||||
|
<div className="mt-6 flex flex-wrap items-center justify-center sm:justify-start gap-3">
|
||||||
|
<Button variant="outline" size="icon" asChild className="hover:text-primary hover:scale-110 transition-all">
|
||||||
|
<a href="mailto:taylor@example.com"><Mail className="h-4 w-4" /></a>
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="icon" asChild className="hover:text-primary hover:scale-110 transition-all">
|
||||||
|
<a href="#"><Linkedin className="h-4 w-4" /></a>
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" size="icon" asChild className="hover:text-primary hover:scale-110 transition-all">
|
||||||
|
<a href="#"><Github className="h-4 w-4" /></a>
|
||||||
|
</Button>
|
||||||
|
<Button className="ml-2">
|
||||||
|
<Download className="mr-2 h-4 w-4" /> Download CV
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── EXPERIENCE ── */}
|
||||||
|
<section id="experience" className="py-24">
|
||||||
|
<div className="mx-auto max-w-5xl px-6">
|
||||||
|
<div className="flex items-center gap-3 mb-12 animate-fade-up">
|
||||||
|
<Briefcase className="h-6 w-6 text-primary" />
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight">Experience</h2>
|
||||||
|
</div>
|
||||||
|
<div className="relative border-l-2 border-primary/20 ml-4">
|
||||||
|
{experience.map((job, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className={`relative pl-8 pb-12 last:pb-0 rounded-lg hover:bg-muted/50 transition-colors \${i % 2 === 1 ? "bg-muted/30 -ml-4 pl-12 py-8 rounded-r-xl" : ""}`}
|
||||||
|
>
|
||||||
|
<div className="absolute -left-[9px] top-1 w-4 h-4 rounded-full bg-primary ring-4 ring-primary/20 border-2 border-background" />
|
||||||
|
<div className="flex flex-wrap items-center gap-3 mb-2">
|
||||||
|
<h3 className="font-semibold text-lg">{job.company}</h3>
|
||||||
|
<Badge variant="outline" className="text-xs">{job.dates}</Badge>
|
||||||
|
</div>
|
||||||
|
<p className="text-primary font-medium text-sm mb-3">{job.role}</p>
|
||||||
|
<ul className="space-y-1.5 border-l-2 border-primary/10 pl-3">
|
||||||
|
{job.bullets.map((b, j) => (
|
||||||
|
<li key={j} className="text-sm text-muted-foreground flex items-start gap-2">
|
||||||
|
<span className="mt-1.5 w-1.5 h-1.5 rounded-full bg-primary/40 shrink-0" />
|
||||||
|
{b}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── PROJECTS ── */}
|
||||||
|
<section className="py-24 bg-muted/30">
|
||||||
|
<div className="mx-auto max-w-5xl px-6">
|
||||||
|
<div className="flex items-center gap-3 mb-12 animate-fade-up">
|
||||||
|
<Layers className="h-6 w-6 text-primary" />
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight">Featured Projects</h2>
|
||||||
|
</div>
|
||||||
|
<div className="grid md:grid-cols-3 gap-6 stagger">
|
||||||
|
{projects.map((p, i) => (
|
||||||
|
<Card key={i} className="group overflow-hidden hover-lift hover:shadow-lg transition-all duration-300 backdrop-blur-sm bg-card/80 border-border/50">
|
||||||
|
<div className={`aspect-video bg-gradient-to-br \${p.gradient} rounded-t-xl flex items-center justify-center relative overflow-hidden`}>
|
||||||
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-24 h-24 rounded-full bg-white/10 blur-2xl" />
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-white/20 backdrop-blur group-hover:scale-110 transition-transform relative z-10" />
|
||||||
|
</div>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<CardTitle className="text-base">{p.title}</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<CardDescription className="text-sm leading-relaxed mb-3">{p.desc}</CardDescription>
|
||||||
|
<div className="flex flex-wrap gap-1.5 mb-3">
|
||||||
|
{p.tags.map((tag, j) => (
|
||||||
|
<Badge key={j} variant="secondary" className="text-xs">{tag}</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<a href="#" className="inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:gap-3 transition-all">
|
||||||
|
View Project <ArrowRight className="h-3.5 w-3.5" />
|
||||||
|
</a>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── EDUCATION ── */}
|
||||||
|
<section id="education" className="py-24">
|
||||||
|
<div className="mx-auto max-w-5xl px-6">
|
||||||
|
<div className="flex items-center gap-3 mb-12 animate-fade-up">
|
||||||
|
<GraduationCap className="h-6 w-6 text-primary" />
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight">Education</h2>
|
||||||
|
</div>
|
||||||
|
<div className="grid sm:grid-cols-2 gap-6 mb-10">
|
||||||
|
<Card className="hover-lift hover:shadow-md transition-shadow backdrop-blur-sm bg-card/80">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-base flex items-center gap-2">
|
||||||
|
<GraduationCap className="h-4 w-4 text-primary" /> Stanford University
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="text-muted-foreground leading-relaxed">M.S. Computer Science</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-wrap items-center gap-2">
|
||||||
|
<Badge variant="outline" className="text-xs">2014 – 2016</Badge>
|
||||||
|
<Badge className="text-xs">With Distinction</Badge>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<Card className="hover-lift hover:shadow-md transition-shadow backdrop-blur-sm bg-card/80">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-base flex items-center gap-2">
|
||||||
|
<GraduationCap className="h-4 w-4 text-primary" /> UC Berkeley
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="text-muted-foreground leading-relaxed">B.S. Computer Science</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex flex-wrap items-center gap-2">
|
||||||
|
<Badge variant="outline" className="text-xs">2010 – 2014</Badge>
|
||||||
|
<Badge className="text-xs">Magna Cum Laude</Badge>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold mb-3 flex items-center gap-2">
|
||||||
|
<Award className="h-5 w-5 text-primary" /> Certifications
|
||||||
|
</h3>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{["AWS Solutions Architect", "Google Cloud Professional", "PMP Certified"].map((cert, i) => (
|
||||||
|
<Badge key={i} variant="secondary" className="px-3 py-1">{cert}</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── SKILLS ── */}
|
||||||
|
<section id="skills" className="py-24 bg-muted/30">
|
||||||
|
<div className="mx-auto max-w-5xl px-6">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight mb-12 animate-fade-up">Skills & Tools</h2>
|
||||||
|
<div className="grid lg:grid-cols-3 gap-12">
|
||||||
|
{/* Technical */}
|
||||||
|
<div className="lg:col-span-1">
|
||||||
|
<h3 className="font-semibold mb-6 flex items-center gap-2 text-sm uppercase tracking-wider text-muted-foreground">
|
||||||
|
<Terminal className="h-4 w-4 text-primary" /> Development
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-5">
|
||||||
|
{technicalSkills.map((s, i) => (
|
||||||
|
<div key={i}>
|
||||||
|
<div className="flex justify-between mb-1.5">
|
||||||
|
<span className="text-sm font-medium">{s.name}</span>
|
||||||
|
<span className="text-xs text-muted-foreground tabular-nums">{s.value}%</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 rounded-full bg-muted overflow-hidden">
|
||||||
|
<div className="h-full rounded-full bg-gradient-to-r from-primary via-violet-500 to-rose-500 transition-all duration-500" style={{ width: `\${s.value}%` }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* Soft Skills + Tools */}
|
||||||
|
<div className="lg:col-span-2 space-y-10">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold mb-4 flex items-center gap-2 text-sm uppercase tracking-wider text-muted-foreground">
|
||||||
|
<Figma className="h-4 w-4 text-primary" /> Design & Soft Skills
|
||||||
|
</h3>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{["Leadership", "Communication", "Problem Solving", "Mentoring"].map((s, i) => (
|
||||||
|
<Badge key={i} variant="outline" className="px-4 py-1.5 text-sm">{s}</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold mb-4 text-sm uppercase tracking-wider text-muted-foreground">Tools & Platforms</h3>
|
||||||
|
<div className="grid grid-cols-3 sm:grid-cols-6 gap-4 stagger">
|
||||||
|
{tools.map((t, i) => (
|
||||||
|
<div key={i} className="flex flex-col items-center gap-2 p-3 rounded-xl bg-background border hover:border-primary/40 hover:shadow-sm transition-all">
|
||||||
|
<t.icon className="h-5 w-5 text-muted-foreground" />
|
||||||
|
<span className="text-xs font-medium text-center">{t.label}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── CERTIFICATIONS ── */}
|
||||||
|
<section className="py-24">
|
||||||
|
<div className="mx-auto max-w-5xl px-6">
|
||||||
|
<div className="flex items-center gap-3 mb-12 animate-fade-up">
|
||||||
|
<Award className="h-6 w-6 text-primary" />
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight">Certifications & Awards</h2>
|
||||||
|
</div>
|
||||||
|
<div className="grid sm:grid-cols-3 gap-6 stagger">
|
||||||
|
{certifications.map((c, i) => (
|
||||||
|
<Card key={i} className="hover-lift hover:shadow-lg hover:shadow-primary/5 transition-all backdrop-blur-sm bg-card/80 border-border/50">
|
||||||
|
<CardHeader className="flex flex-row items-start gap-4">
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-gradient-to-br from-primary/20 to-violet-500/20 flex items-center justify-center shrink-0">
|
||||||
|
<Award className="h-6 w-6 text-primary" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<CardTitle className="text-base flex items-center gap-1.5">
|
||||||
|
{c.name} <CheckCircle className="h-4 w-4 text-emerald-500" />
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="text-muted-foreground leading-relaxed">{c.issuer}</CardDescription>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<Badge variant="outline" className="text-xs">{c.year}</Badge>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── CONTACT ── */}
|
||||||
|
<section id="contact" className="py-24">
|
||||||
|
<div className="mx-auto max-w-xl px-6 text-center">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight mb-2 animate-fade-up">Let's Connect</h2>
|
||||||
|
<p className="text-muted-foreground leading-relaxed mb-2">Have a project in mind? I’d love to hear from you.</p>
|
||||||
|
<a href="mailto:taylor@example.com" className="inline-flex items-center gap-2 text-primary font-medium hover:underline">
|
||||||
|
<Mail className="h-4 w-4 shadow-lg shadow-primary/10" /> taylor@example.com
|
||||||
|
</a>
|
||||||
|
<Card className="mt-8 backdrop-blur-sm bg-card/80 border-border/50">
|
||||||
|
<CardContent className="pt-6">
|
||||||
|
<form onSubmit={async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const form = e.currentTarget;
|
||||||
|
const fd = new FormData(form);
|
||||||
|
try {
|
||||||
|
await createLead({ name: fd.get("name"), email: fd.get("email"), message: fd.get("message") });
|
||||||
|
toast.success("Message sent! I'll get back to you within 24 hours.");
|
||||||
|
form.reset();
|
||||||
|
} catch (err) {
|
||||||
|
toast.error("Something went wrong. Please try again.");
|
||||||
|
}
|
||||||
|
}} className="text-left space-y-4">
|
||||||
|
<Input name="name" placeholder="Your Name" className="h-11" required />
|
||||||
|
<Input name="email" placeholder="Your Email" type="email" className="h-11" required />
|
||||||
|
<Textarea name="message" placeholder="Your message..." className="min-h-[120px] resize-none" required />
|
||||||
|
<Button type="submit" disabled={sending} className="w-full h-11 active:scale-[0.97] transition-transform">
|
||||||
|
<Send className="mr-2 h-4 w-4" /> {sending ? "Sending..." : "Send Message"}
|
||||||
|
</Button>
|
||||||
|
<p className="text-xs text-muted-foreground text-center">Typically responds within 24 hours</p>
|
||||||
|
</form>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ── FOOTER ── */}
|
||||||
|
<footer className="py-12 border-t">
|
||||||
|
<div className="mx-auto max-w-5xl px-6 text-center">
|
||||||
|
<p className="text-muted-foreground mb-4">Let's build something great together.</p>
|
||||||
|
<div className="flex justify-center gap-2 mb-6">
|
||||||
|
{[Github, Linkedin, Twitter, Mail].map((Icon, i) => (
|
||||||
|
<Button key={i} variant="ghost" size="icon" className="h-9 w-9 text-muted-foreground hover:text-foreground">
|
||||||
|
<Icon className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-muted-foreground">© 2026 Taylor Morgan. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user