Files
gastro-bot/src/features/about/ui/AboutPage.tsx
Samandar Turgunboyev ecc0029322 bug fix
2026-01-24 16:46:02 +05:00

285 lines
9.2 KiB
TypeScript

'use client';
import formatPhone from '@/shared/lib/formatPhone';
import onlyNumber from '@/shared/lib/onlyNumber';
import { Button } from '@/shared/ui/button';
import { Card } from '@/shared/ui/card';
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/shared/ui/form';
import { Input } from '@/shared/ui/input';
import { Label } from '@/shared/ui/label';
import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation } from '@tanstack/react-query';
import { Loader2, Upload } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { useForm } from 'react-hook-form';
import { toast } from 'sonner';
import * as z from 'zod';
import { partner_api } from '../lib/api';
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const ACCEPTED_FILE_TYPES = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
];
const partnershipFormSchema = z.object({
companyName: z.string().min(2, {
message: "Kompaniya nomi kamida 2 ta belgidan iborat bo'lishi kerak",
}),
// website: z
// .string()
// .url({ message: "To'g'ri website manzilini kiriting" })
// .optional()
// .or(z.literal('')),
contactPerson: z
.string()
.min(2, { message: "Ism kamida 2 ta belgidan iborat bo'lishi kerak" }),
// email: z
// .string()
// .email({ message: "To'g'ri email manzilini kiriting" })
// .optional(),
phone: z
.string()
.min(9, { message: "To'g'ri telefon raqamini kiriting" })
.regex(/^[\d\s+\-$$$$]+$/, {
message: "Telefon raqami faqat raqamlardan iborat bo'lishi kerak",
}),
companyFile: z
.custom<FileList>()
.refine((files) => files?.length === 1, 'File yuklash majburiy')
.refine(
(files) => files?.[0]?.size <= MAX_FILE_SIZE,
'File hajmi 5MB dan oshmasligi kerak',
)
.refine(
(files) => ACCEPTED_FILE_TYPES.includes(files?.[0]?.type),
'Faqat PDF yoki Word formatidagi fayllar qabul qilinadi',
),
});
type PartnershipFormValues = z.infer<typeof partnershipFormSchema>;
export function PartnershipForm() {
const t = useTranslations();
const form = useForm<PartnershipFormValues>({
resolver: zodResolver(partnershipFormSchema),
defaultValues: {
companyName: '',
contactPerson: '',
phone: '+998',
},
});
const { mutate, isPending } = useMutation({
mutationFn: (body: FormData) => partner_api.send(body),
onSuccess: () => {
toast.success(t("So'rov yuborildi!"), {
richColors: true,
position: 'top-center',
});
form.reset();
},
onError: () => {
toast.error(t('Xatolik yuz berdi'), {
richColors: true,
position: 'top-center',
});
},
});
async function onSubmit(data: PartnershipFormValues) {
const formData = new FormData();
formData.append('company_name', data.companyName);
formData.append('full_name', data.contactPerson);
formData.append('phone_number', onlyNumber(data.phone));
if (data.companyFile && data.companyFile.length > 0) {
formData.append('file', data.companyFile[0]);
}
mutate(formData);
}
return (
<section className="px-4 mb-5" id="contact">
<div className="max-w-3xl mx-auto">
<div className="text-center mb-5">
<h2 className="text-2xl md:text-5xl font-bold mb-2 text-balance">
{t(`Hamkor bo'ling`)}
</h2>
<p className="text-md text-muted-foreground leading-relaxed">
{t(`Gastro Market bilan hamkorlik qilishni xohlaysizmi?`)}
</p>
</div>
<Card className="p-8 md:p-12">
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField
control={form.control}
name="companyName"
render={({ field }) => (
<FormItem>
<Label>{t('Kompaniya nomi')}</Label>
<FormControl>
<Input
placeholder="Kompaniyangiz nomini kiriting"
{...field}
className="h-12"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* <FormField
control={form.control}
name="website"
render={({ field }) => (
<FormItem>
<Label>{t('Website')}</Label>
<FormControl>
<Input
placeholder="https://example.com"
type="url"
className="h-12"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/> */}
<FormField
control={form.control}
name="contactPerson"
render={({ field }) => (
<FormItem>
<Label>{t('Ism Familiya')}</Label>
<FormControl>
<Input
placeholder="Ism va familiya"
className="h-12"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="grid md:grid-cols-1 gap-6">
{/* <FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem className="flex flex-col justify-start">
<Label>{t('Email')}</Label>
<FormControl>
<Input
placeholder="example@email.com"
type="email"
className="h-12"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/> */}
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem className="flex flex-col justify-start">
<Label>{t('Telefon raqami')}</Label>
<FormControl>
<Input
placeholder="+998 90 123 45 67"
className="h-12"
{...field}
value={formatPhone(field.value)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="companyFile"
render={({ field: { onChange, value, ...field } }) => (
<FormItem>
<Label>{t('Kompaniya hujjati')}</Label>
<FormControl>
<div>
<Input
type="file"
id="company file"
accept=".pdf,.doc,.docx"
onChange={(e) => {
const files = e.target.files;
onChange(files);
}}
{...field}
className="hidden"
/>
<FormLabel
className="w-full flex justify-center items-center flex-col h-36 border border-gray-200 rounded-2xl cursor-pointer"
htmlFor="company file"
>
<Upload className="size-10 text-muted-foreground" />
<p className="text-muted-foreground text-lg">
{t('Faylni tanlang')}
</p>
{value && value.length > 0 && (
<p className="mt-2 text-sm text-gray-500">
{t('Tanlangan fayl')}: {value[0].name}
</p>
)}
</FormLabel>
</div>
</FormControl>
<FormDescription>
{t('PDF yoki Word formatida (maksimal 5MB)')}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
size="lg"
className="w-full cursor-pointer"
disabled={isPending}
>
{isPending ? (
<Loader2 className="animate-spin" />
) : (
t("So'rov yuborish")
)}
</Button>
</form>
</Form>
</Card>
</div>
</section>
);
}