Files
reui-blocks/blocks/contact17.tsx
T

389 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { Check, LoaderIcon } from "lucide-react";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import {
Field,
FieldError,
FieldGroup,
FieldLabel,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
const contactFormSchema = z.object({
firstName: z.string().min(1, "نام الزامی است"),
lastName: z.string().min(1, "نام خانوادگی الزامی است"),
email: z
.string()
.min(1, "ایمیل الزامی است")
.email("آدرس ایمیل نامعتبر است"),
companySize: z.string().optional(),
message: z.string().min(1, "پیام الزامی است"),
referrer: z.string().optional(),
});
type ContactFormData = z.infer<typeof contactFormSchema>;
interface Contact17Props {
className?: string;
onSubmit?: (data: ContactFormData) => Promise<void>;
}
const Contact17 = ({ className, onSubmit }: Contact17Props) => {
const [isSubmitted, setIsSubmitted] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const form = useForm<ContactFormData>({
resolver: zodResolver(contactFormSchema),
mode: "onSubmit",
reValidateMode: "onSubmit",
defaultValues: {
firstName: "",
lastName: "",
email: "",
companySize: "",
message: "",
referrer: "",
},
});
const handleFormSubmit = async (data: ContactFormData) => {
try {
if (onSubmit) {
await onSubmit(data);
} else {
console.log("Form submitted:", data);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
setIsSubmitted(true);
setShowSuccess(true);
form.reset();
setTimeout(() => setShowSuccess(false), 4500);
setTimeout(() => setIsSubmitted(false), 5000);
} catch {
form.setError("root", {
message: "مشکلی پیش آمد. لطفاً دوباره تلاش کنید.",
});
}
};
return (
<section dir="rtl" lang="fa" className={cn("bg-muted/50 py-32", className)}>
<div className="container">
<span className="text-xs text-muted-foreground">شروع همکاری /</span>
<div className="mt-8 grid grid-cols-1 gap-8 md:gap-10 lg:grid-cols-2 lg:grid-rows-[min-content_1fr]">
<h2 className="order-1 text-xl font-medium tracking-tight md:order-none md:text-2xll">
ارسال درخواست
</h2>
<div className="order-2 md:order-none md:row-span-2">
<div className="rounded-lg border border-border bg-background p-6">
{isSubmitted && (
<div
className={cn(
"mb-6 rounded-lg border border-green-500/20 bg-green-500/10 p-4 text-center transition-opacity duration-500",
showSuccess ? "opacity-100" : "opacity-0",
)}
>
<p className="text-sm font-medium text-green-600 dark:text-green-400">
درخواست شما با موفقیت ثبت شد. کارشناسان ما در اولین فرصت با شما تماس خواهند گرفت.
</p>
</div>
)}
<form onSubmit={form.handleSubmit(handleFormSubmit)}>
<FieldGroup className="grid gap-6 sm:grid-cols-2">
<Controller
control={form.control}
name="firstName"
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>
نام و نام خانوادگی <span className="text-destructive">*</span>
</FieldLabel>
<Input
{...field}
id={field.name}
aria-invalid={fieldState.invalid}
placeholder="علی"
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="lastName"
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>
نام خانوادگی{" "}
<span className="text-destructive">*</span>
</FieldLabel>
<Input
{...field}
id={field.name}
aria-invalid={fieldState.invalid}
placeholder="محمدی"
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="email"
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>
ایمیل کاری <span className="text-destructive">*</span>
</FieldLabel>
<Input
{...field}
id={field.name}
type="email"
aria-invalid={fieldState.invalid}
placeholder="example@email.com"
dir="rtl"
className="text-start"
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="companySize"
render={({ field }) => (
<Field>
<FieldLabel htmlFor={field.name}>
بودجه پروژه
</FieldLabel>
<Select
onValueChange={field.onChange}
value={field.value}
>
<SelectTrigger id={field.name} className="w-full">
<SelectValue placeholder="انتخاب بازه بودجه" />
</SelectTrigger>
<SelectContent>
<SelectItem value="5k-15k">
۵ تا ۱۵ هزار دلار
</SelectItem>
<SelectItem value="15k-30k">
۱۵ تا ۳۰ هزار دلار
</SelectItem>
<SelectItem value="30k-50k">
۳۰ تا ۵۰ هزار دلار
</SelectItem>
<SelectItem value="50k-100k">
۵۰ تا ۱۰۰ هزار دلار
</SelectItem>
<SelectItem value="100k-250k">
۱۰۰ تا ۲۵۰ هزار دلار
</SelectItem>
<SelectItem value="250k+">
بیش از ۲۵۰ هزار دلار
</SelectItem>
</SelectContent>
</Select>
</Field>
)}
/>
<Controller
control={form.control}
name="message"
render={({ field, fieldState }) => (
<Field
data-invalid={fieldState.invalid}
className="sm:col-span-2"
>
<FieldLabel htmlFor={field.name}>
پیام <span className="text-destructive">*</span>
</FieldLabel>
<Textarea
{...field}
id={field.name}
aria-invalid={fieldState.invalid}
placeholder="اهداف، نیازها و جزئیات پروژه خود را شرح دهید."
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={form.control}
name="referrer"
render={({ field }) => (
<Field className="sm:col-span-2">
<FieldLabel htmlFor={field.name}>
چطور ما را پیدا کردید؟
</FieldLabel>
<Input
{...field}
id={field.name}
placeholder="مثال: جستجوی گوگل، معرفی یا شبکه‌های اجتماعی"
/>
</Field>
)}
/>
{form.formState.errors.root && (
<p className="text-sm text-destructive sm:col-span-2">
{form.formState.errors.root.message}
</p>
)}
<Button
type="submit"
className="gap-2 sm:col-span-2"
disabled={form.formState.isSubmitting}
>
{form.formState.isSubmitting ? (
<>
<LoaderIcon className="size-4 animate-spin" />
در حال ارسال...
</>
) : (
"ارسال پیام"
)}
</Button>
<p className="text-xs text-muted-foreground sm:col-span-2">
با ارسال این فرم، تأیید می‌کنید که{" "}
<a href="#" className="text-primary hover:underline">
حریم خصوصی
</a>{" "}
و{" "}
<a href="#" className="text-primary hover:underline">
شرایط استفاده
</a>{" "}
ما را مطالعه کرده و پذیرفته‌اید.
</p>
</FieldGroup>
</form>
</div>
</div>
<div className="order-3 my-6 md:order-none">
<ul className="space-y-2 font-medium">
<li className="flex items-center gap-2">
<span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-background">
<Check className="size-4" />
</span>
نیازهای کسب‌وکار و اهداف پروژه خود را با ما مطرح کنید.
</li>
<li className="flex items-center gap-2">
<span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-background">
<Check className="size-4" />
</span>
راهکار و پیشنهاد متناسب با نیاز خود دریافت کنید.
</li>
<li className="flex items-center gap-2">
<span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-background">
<Check className="size-4" />
</span>
برای بررسی پروژه، جلسه مشاوره تخصصی رزرو کنید.
</li>
</ul>
<p className="my-6 font-bold">
بیش از ۳۰۰۰ کسب‌وکار به خدمات و راهکارهای ما اعتماد کرده‌اند.
</p>
<div className="grid grid-cols-2 place-items-center gap-8 md:grid-cols-4">
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-1.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-2.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-3.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-4.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-5.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-6.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-7.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
<img
src="/block-media/shadcnblocks/block/logos/company/fictional-company-logo-8.svg"
alt="لوگوی مشتری"
className="max-w-24 dark:invert"
/>
</div>
</div>
</div>
<div className="mt-16 grid gap-8 md:gap-12 lg:w-1/2 lg:grid-cols-2">
<div>
<h3 className="mb-1.5 font-bold">سوالات متداول</h3>
<p className="text-sm text-muted-foreground">
پاسخ پرسش‌های رایج را در{" "}
<a href="#" className="text-primary underline hover:underline">
سوالات متداول
</a>{" "}
مطالعه کنید و با روند همکاری و اجرای پروژه آشنا شوید.
</p>
</div>
<div>
<h3 className="mb-1.5 font-bold">منابع</h3>
<p className="text-sm text-muted-foreground">
به مجموعه مقالات، راهنماها و مستندات ما در{" "}
<a href="#" className="text-primary underline hover:underline">
مرکز منابع
</a>{" "}
دسترسی داشته باشید و از آموزش‌ها، مقالات و تجربیات تخصصی استفاده کنید.
</p>
</div>
</div>
</div>
</section>
);
};
export { Contact17 };