Spaces:
Running
Running
| "use client"; | |
| import { useActionState } from "react"; | |
| import { useFormStatus } from "react-dom"; | |
| import { useEffect } from "react"; | |
| import { useToast } from "@/hooks/use-toast"; | |
| import { submitContactForm } from "@/app/actions"; | |
| import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; | |
| import { Label } from "@/components/ui/label"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Textarea } from "@/components/ui/textarea"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Mail } from "lucide-react"; | |
| function SubmitButton() { | |
| const { pending } = useFormStatus(); | |
| return ( | |
| <Button type="submit" disabled={pending}> | |
| {pending ? "Sending..." : "Send Message"} | |
| </Button> | |
| ); | |
| } | |
| export function Contact() { | |
| const { toast } = useToast(); | |
| const initialState = { message: null, errors: {} }; | |
| const [state, dispatch] = useActionState(submitContactForm, initialState); | |
| useEffect(() => { | |
| if (state.message) { | |
| if (state.errors) { | |
| toast({ | |
| title: "Error", | |
| description: state.message, | |
| variant: "destructive", | |
| }); | |
| } else { | |
| toast({ | |
| title: "Success!", | |
| description: state.message, | |
| }); | |
| } | |
| } | |
| }, [state, toast]); | |
| return ( | |
| <section id="contact" className="w-full py-12 md:py-24 lg:py-32 bg-secondary"> | |
| <div className="container px-4 md:px-6"> | |
| <Card className="max-w-xl mx-auto"> | |
| <CardHeader className="text-center"> | |
| <Mail className="mx-auto h-12 w-12 text-primary mb-4" /> | |
| <CardTitle className="font-headline text-3xl">Get in Touch</CardTitle> | |
| <CardDescription> | |
| Have a question or want to work together? Send me a message. | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent> | |
| <form action={dispatch} className="space-y-4"> | |
| <div className="space-y-2"> | |
| <Label htmlFor="name">Name</Label> | |
| <Input id="name" name="name" placeholder="Your Name" /> | |
| {state.errors?.name && ( | |
| <p className="text-sm font-medium text-destructive"> | |
| {state.errors.name[0]} | |
| </p> | |
| )} | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="email">Email</Label> | |
| <Input id="email" name="email" type="email" placeholder="your@email.com" /> | |
| {state.errors?.email && ( | |
| <p className="text-sm font-medium text-destructive"> | |
| {state.errors.email[0]} | |
| </p> | |
| )} | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="message">Message</Label> | |
| <Textarea id="message" name="message" placeholder="Your message..." /> | |
| {state.errors?.message && ( | |
| <p className="text-sm font-medium text-destructive"> | |
| {state.errors.message[0]} | |
| </p> | |
| )} | |
| </div> | |
| <SubmitButton /> | |
| </form> | |
| </CardContent> | |
| </Card> | |
| </div> | |
| </section> | |
| ); | |
| } |