Update components/contact.tsx
This commit is contained in:
parent
0033a16e80
commit
5887c18183
|
|
@ -0,0 +1,279 @@
|
|||
"use client";
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
import {
|
||||
IconBrandGithub,
|
||||
IconBrandLinkedin,
|
||||
IconBrandX,
|
||||
} from "@tabler/icons-react";
|
||||
|
||||
import { Button } from "./ui/button";
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z
|
||||
.string({
|
||||
message: "Please enter your name",
|
||||
})
|
||||
.min(1, "Please enter email"),
|
||||
email: z
|
||||
.string({
|
||||
message: "Please enter email",
|
||||
})
|
||||
.email("Please enter valid email")
|
||||
.min(1, "Please enter email"),
|
||||
company: z
|
||||
.string({
|
||||
message: "Please enter your company's name",
|
||||
})
|
||||
.min(1, "Please enter your company's name"),
|
||||
message: z
|
||||
.string({
|
||||
message: "Please enter your message",
|
||||
})
|
||||
.min(1, "Please enter your message"),
|
||||
});
|
||||
|
||||
export type LoginUser = z.infer<typeof formSchema>;
|
||||
|
||||
export function ContactForm() {
|
||||
const form = useForm<LoginUser>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: "",
|
||||
email: "",
|
||||
company: "",
|
||||
message: "",
|
||||
},
|
||||
});
|
||||
|
||||
async function onSubmit(values: LoginUser) {
|
||||
try {
|
||||
// Get app_id from environment or URL
|
||||
const appId =
|
||||
process.env.NEXT_PUBLIC_APP_ID ||
|
||||
new URLSearchParams(window.location.search).get("app_id") ||
|
||||
"";
|
||||
|
||||
// Create form data
|
||||
const formData = new FormData();
|
||||
formData.append("app_id", appId);
|
||||
formData.append("name", values.name);
|
||||
formData.append("email", values.email);
|
||||
formData.append("company", values.company);
|
||||
formData.append("message", values.message);
|
||||
formData.append("form_type", "contact"); // Help identify form type in Kleap
|
||||
|
||||
// Submit to Kleap's form API
|
||||
const response = await fetch("https://form.kleap.co", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Success! Reset form and show success message
|
||||
form.reset();
|
||||
// You can add a toast notification here
|
||||
alert("Thank you for your message! We'll get back to you soon.");
|
||||
} else {
|
||||
throw new Error("Failed to submit form");
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle error
|
||||
console.error("Form submission error:", e);
|
||||
alert(
|
||||
"Sorry, there was an error submitting your message. Please try again.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const socials = [
|
||||
{
|
||||
title: "twitter",
|
||||
href: "https://twitter.com/mannupaaji",
|
||||
icon: (
|
||||
<IconBrandX className="h-5 w-5 text-muted dark:text-muted-dark hover:text-black" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "github",
|
||||
href: "https://github.com/manuarora700",
|
||||
icon: (
|
||||
<IconBrandGithub className="h-5 w-5 text-muted dark:text-muted-dark hover:text-black" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "linkedin",
|
||||
href: "https://linkedin.com/manuarora28",
|
||||
icon: (
|
||||
<IconBrandLinkedin className="h-5 w-5 text-muted dark:text-muted-dark hover:text-black" />
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<div className="flex relative z-20 items-center w-full justify-center px-4 py-4 lg:py-12 sm:px-6 lg:flex-none lg:px-20 xl:px-24">
|
||||
<div className="mx-auto w-full max-w-md">
|
||||
<div>
|
||||
<h1 className="mt-8 text-2xl font-bold leading-9 tracking-tight text-black dark:text-white">
|
||||
Contact Us
|
||||
</h1>
|
||||
<p className="mt-4 text-muted dark:text-muted-dark text-sm max-w-sm">
|
||||
Please reach out to us and we will get back to you at the speed of
|
||||
light.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="py-10">
|
||||
<div>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-6"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-6 text-neutral-700 dark:text-muted-dark"
|
||||
>
|
||||
Full Name
|
||||
</label>
|
||||
<FormControl>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="name"
|
||||
type="name"
|
||||
placeholder="Manu Arora"
|
||||
className="block w-full bg-white dark:bg-neutral-900 px-4 rounded-md border-0 py-1.5 shadow-aceternity text-black placeholder:text-gray-400 focus:ring-2 focus:ring-neutral-400 focus:outline-none sm:text-sm sm:leading-6 dark:text-white"
|
||||
{...field}
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-medium leading-6 text-neutral-700 dark:text-muted-dark"
|
||||
>
|
||||
Email address
|
||||
</label>
|
||||
<FormControl>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="hello@johndoe.com"
|
||||
className="block w-full bg-white dark:bg-neutral-900 px-4 rounded-md border-0 py-1.5 shadow-aceternity text-black placeholder:text-gray-400 focus:ring-2 focus:ring-neutral-400 focus:outline-none sm:text-sm sm:leading-6 dark:text-white"
|
||||
{...field}
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="company"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<label
|
||||
htmlFor="company"
|
||||
className="block text-sm font-medium leading-6 text-neutral-700 dark:text-muted-dark"
|
||||
>
|
||||
Company
|
||||
</label>
|
||||
<FormControl>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="company"
|
||||
type="company"
|
||||
placeholder="Aceternity Labs, LLC"
|
||||
className="block w-full bg-white dark:bg-neutral-900 px-4 rounded-md border-0 py-1.5 shadow-aceternity text-black placeholder:text-gray-400 focus:ring-2 focus:ring-neutral-400 focus:outline-none sm:text-sm sm:leading-6 dark:text-white"
|
||||
{...field}
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="message"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<label
|
||||
htmlFor="message"
|
||||
className="block text-sm font-medium leading-6 text-neutral-700 dark:text-muted-dark"
|
||||
>
|
||||
message
|
||||
</label>
|
||||
<FormControl>
|
||||
<div className="mt-2">
|
||||
<textarea
|
||||
rows={5}
|
||||
id="message"
|
||||
placeholder="Enter your message here"
|
||||
className="block w-full bg-white dark:bg-neutral-900 px-4 rounded-md border-0 py-1.5 shadow-aceternity text-black placeholder:text-gray-400 focus:ring-2 focus:ring-neutral-400 focus:outline-none sm:text-sm sm:leading-6 dark:text-white"
|
||||
{...field}
|
||||
/>
|
||||
</div>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Honeypot field to catch bots - hidden from users */}
|
||||
<input
|
||||
type="text"
|
||||
name="_honeypot"
|
||||
style={{ display: "none" }}
|
||||
tabIndex={-1}
|
||||
autoComplete="off"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<Button className="w-full" type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center space-x-4 py-4">
|
||||
{socials.map((social) => (
|
||||
<Link href={social.href} key={social.title}>
|
||||
{social.icon}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue