Moshavereh sazmani

This commit is contained in:
2026-02-19 17:56:02 +03:30
parent 21390bd024
commit b39e261ebf
12 changed files with 1265 additions and 531 deletions
+200
View File
@@ -0,0 +1,200 @@
'use client'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { Alert, AlertDescription } from '@/components/ui/alert'
import { CheckCircle2, Loader2 } from 'lucide-react'
const consultingAreas = [
'اینتگریشن',
'هوشمندسازی',
'RAG',
'Performance',
'امنیت',
'معماری نرم‌افزار',
'داده و تحلیل',
'سایر',
] as const
const formSchema = z.object({
fullName: z.string().min(2, 'نام و نام خانوادگی الزامی است'),
organization: z.string().min(1, 'نام سازمان الزامی است'),
phone: z.string().min(10, 'شماره تماس معتبر وارد کنید'),
area: z.string().min(1, 'حوزه مشاوره را انتخاب کنید'),
description: z.string().optional(),
})
type FormValues = z.infer<typeof formSchema>
export function ConsultingForm() {
const [submitted, setSubmitted] = useState(false)
const [isSubmitting, setIsSubmitting] = useState(false)
const [submitError, setSubmitError] = useState<string | null>(null)
const form = useForm<FormValues>({
resolver: zodResolver(formSchema),
defaultValues: {
fullName: '',
organization: '',
phone: '',
area: '',
description: '',
},
})
async function onSubmit(data: FormValues) {
setSubmitError(null)
setIsSubmitting(true)
try {
const res = await fetch('/api/consulting', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
const json = await res.json().catch(() => ({}))
if (!res.ok) {
setSubmitError(json.error || 'ارسال درخواست ناموفق بود. لطفاً دوباره تلاش کنید.')
return
}
setSubmitted(true)
form.reset()
} catch {
setSubmitError('خطا در ارتباط با سرور. لطفاً دوباره تلاش کنید.')
} finally {
setIsSubmitting(false)
}
}
if (submitted) {
return (
<Alert className="border-primary/50 bg-primary/5 text-center">
<CheckCircle2 className="h-5 w-5 text-primary" />
<AlertDescription className="text-base font-medium">
در سریع‌ترین زمان ممکن با شما تماس می‌گیریم.
</AlertDescription>
</Alert>
)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
{submitError && (
<Alert variant="destructive">
<AlertDescription>{submitError}</AlertDescription>
</Alert>
)}
<FormField
control={form.control}
name="fullName"
render={({ field }) => (
<FormItem>
<FormLabel>نام و نام خانوادگی</FormLabel>
<FormControl>
<Input placeholder="نام و نام خانوادگی" {...field} className="h-11" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="organization"
render={({ field }) => (
<FormItem>
<FormLabel>نام سازمان</FormLabel>
<FormControl>
<Input placeholder="نام سازمان یا شرکت" {...field} className="h-11" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem>
<FormLabel>شماره تماس</FormLabel>
<FormControl>
<Input type="tel" placeholder="۰۹۱۲۳۴۵۶۷۸۹" {...field} className="h-11" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="area"
render={({ field }) => (
<FormItem>
<FormLabel>در چه حوزه‌ای مشاوره می‌خواهید؟</FormLabel>
<Select onValueChange={field.onChange} value={field.value}>
<FormControl>
<SelectTrigger className="h-11 w-full">
<SelectValue placeholder="انتخاب حوزه" />
</SelectTrigger>
</FormControl>
<SelectContent>
{consultingAreas.map((area) => (
<SelectItem key={area} value={area}>
{area}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>توضیحات (اختیاری)</FormLabel>
<FormControl>
<Textarea
placeholder="در صورت نیاز توضیح بیشتری بنویسید..."
className="min-h-24"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" size="lg" className="w-full" disabled={isSubmitting}>
{isSubmitting ? (
<>
<Loader2 className="size-5 animate-spin" aria-hidden />
در حال ارسال...
</>
) : (
'ثبت درخواست'
)}
</Button>
</form>
</Form>
)
}
+10 -7
View File
@@ -10,13 +10,16 @@ export default function ContentSection() {
<div className="grid gap-6 sm:grid-cols-2 md:gap-12 lg:gap-24">
<div className="relative mb-6 sm:mb-0">
<div className="bg-linear-to-b aspect-76/59 relative rounded-2xl from-zinc-300 to-transparent p-px dark:from-zinc-700">
<Image
src="/assets/Echosystem.png"
className="rounded-[15px] object-cover"
alt="اکوسیستم یکپارچه فیپ"
width={1207}
height={929}
/>
<div className="relative aspect-[1207/929] w-full overflow-hidden rounded-[15px] bg-muted flex items-center justify-center">
<Image
src="/assets/Echosystem.png"
className="rounded-[15px] object-cover"
alt="اکوسیستم یکپارچه فیپ"
width={1207}
height={929}
unoptimized
/>
</div>
</div>
</div>
+1
View File
@@ -12,6 +12,7 @@ const menuItems = [
{ name: 'صفحه اصلی', href: '/' },
{ name: 'دانشنامه', href: '/blog' },
{ name: 'راه حل‌ها', href: '/solutions' },
{ name: 'مشاوره سازمانی', href: '/consulting' },
// { name: 'قیمت‌گذاری', href: '/pricing' },
{ name: 'درباره ما', href: '/about' },
]