api ulandi

This commit is contained in:
Samandar Turgunboyev
2025-12-22 11:35:55 +05:00
parent 37c7120d1b
commit 9978b4e3fe
75 changed files with 10255 additions and 11924 deletions

View File

@@ -0,0 +1,9 @@
import httpClient from '@/shared/config/api/httpClient';
import { API_URLS } from '@/shared/config/api/URLs';
export const partner_api = {
async send(body: FormData) {
const res = httpClient.post(API_URLS.Partners, body);
return res;
},
};

View File

@@ -0,0 +1,6 @@
export interface PartnerSendBody {
company_name: string;
full_name: string;
phone_number: string;
file: File;
}

View File

@@ -1,7 +1,9 @@
import { Card } from '@/shared/ui/card';
import { useTranslations } from 'next-intl';
import Image from 'next/image';
export function AboutContent() {
const t = useTranslations();
const features = [
{
number: '1',
@@ -44,7 +46,7 @@ export function AboutContent() {
{/* Mission Section */}
<div className="mb-20">
<h2 className="text-4xl md:text-5xl font-bold text-center mb-16 text-balance">
Bizning maqsadimiz
{t('Bizning maqsadimiz')}
</h2>
<div className="grid md:grid-cols-3 gap-8">
{features.map((feature) => (
@@ -55,9 +57,11 @@ export function AboutContent() {
<div className="text-6xl font-bold text-primary mb-4">
{feature.number}
</div>
<h3 className="text-2xl font-semibold mb-4">{feature.title}</h3>
<h3 className="text-2xl font-semibold mb-4">
{t(feature.title)}
</h3>
<p className="text-muted-foreground leading-relaxed">
{feature.description}
{t(feature.description)}
</p>
</Card>
))}
@@ -67,25 +71,22 @@ export function AboutContent() {
{/* About Text */}
<div className="mb-20 max-w-4xl mx-auto text-center">
<h2 className="text-3xl md:text-4xl font-bold mb-8 text-balance">
Innovatsiya, sifat va professionallik
{t('Innovatsiya, sifat va professionallik')}
</h2>
<p className="text-lg text-muted-foreground leading-relaxed mb-6">
{`Gastro Market bu gastronomiya dunyosidagi eng so'nggi
yangiliklarni, retseptlarni va tendentsiyalarni taqdim etuvchi
onlayn platforma. Biz o'quvchilarimizga sifatli va qiziqarli kontent
taqdim etishga intilamiz.`}
{t(
`Gastro Market bu gastronomiya dunyosidagi eng so'nggi yangiliklarni`,
)}
</p>
<p className="text-lg text-muted-foreground leading-relaxed">
{`Bizning jamoamiz tajribali kulinariya mutaxassislari, oshpazlar va
gastronomiya sohasidagi ekspertlardan iborat. Biz har bir maqolada
sifat va professionallikka e'tibor qaratamiz.`}
{t(`Bizning jamoamiz tajribali kulinariya mutaxassislari`)}
</p>
</div>
{/* Image Gallery */}
<div className="mb-20">
<h3 className="text-3xl font-bold text-center mb-12 text-balance">
Bizning dunyo
{t('Bizning dunyo')}
</h3>
<div className="grid md:grid-cols-3 gap-6">
{images.map((image, idx) => (

View File

@@ -1,6 +1,8 @@
import { useTranslations } from 'next-intl';
import Image from 'next/image';
export function AboutHero() {
const t = useTranslations();
return (
<section className="relative h-[60vh] min-h-[500px] flex items-center justify-center overflow-hidden">
<div className="absolute inset-0 z-0">
@@ -17,9 +19,9 @@ export function AboutHero() {
Gastro Market
</h1>
<p className="text-xl md:text-2xl text-white/90 font-light leading-relaxed text-balance">
{
"Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin"
}
{t(
"Gastronomiya va kulinariya san'ati haqidagi yetakchi onlayn magazin",
)}
</p>
</div>
</section>

View File

@@ -1,6 +1,7 @@
'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 {
@@ -15,11 +16,13 @@ import {
import { Input } from '@/shared/ui/input';
import { Label } from '@/shared/ui/label';
import { zodResolver } from '@hookform/resolvers/zod';
import { Upload } from 'lucide-react';
import { useState } from 'react';
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 = [
@@ -32,18 +35,18 @@ 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('')),
// 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(),
// email: z
// .string()
// .email({ message: "To'g'ri email manzilini kiriting" })
// .optional(),
phone: z
.string()
.min(9, { message: "To'g'ri telefon raqamini kiriting" })
@@ -66,53 +69,56 @@ const partnershipFormSchema = z.object({
type PartnershipFormValues = z.infer<typeof partnershipFormSchema>;
export function PartnershipForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const t = useTranslations();
const form = useForm<PartnershipFormValues>({
resolver: zodResolver(partnershipFormSchema),
defaultValues: {
companyName: '',
website: '',
contactPerson: '',
email: '',
phone: '+998',
},
});
async function onSubmit(data: PartnershipFormValues) {
console.log(data);
setIsSubmitting(true);
try {
await new Promise((resolve) => setTimeout(resolve, 2000));
toast.success("So'rov yuborildi!", {
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();
} catch {
},
onError: () => {
toast.error('Xatolik yuz berdi', {
richColors: true,
position: 'top-center',
});
} finally {
setIsSubmitting(false);
},
});
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">
<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">
{`Hamkor bo'ling`}
{t(`Hamkor bo'ling`)}
</h2>
<p className="text-md text-muted-foreground leading-relaxed">
{`Gastro Market bilan hamkorlik qilishni xohlaysizmi? Quyidagi formani
to'ldiring va biz siz bilan tez orada bog'lanamiz.`}
{t(`Gastro Market bilan hamkorlik qilishni xohlaysizmi?`)}
</p>
</div>
@@ -124,7 +130,7 @@ export function PartnershipForm() {
name="companyName"
render={({ field }) => (
<FormItem>
<Label>Kompaniya nomi</Label>
<Label>{t('Kompaniya nomi')}</Label>
<FormControl>
<Input
placeholder="Kompaniyangiz nomini kiriting"
@@ -137,12 +143,12 @@ export function PartnershipForm() {
)}
/>
<FormField
{/* <FormField
control={form.control}
name="website"
render={({ field }) => (
<FormItem>
<Label>Website</Label>
<Label>{t('Website')}</Label>
<FormControl>
<Input
placeholder="https://example.com"
@@ -154,14 +160,14 @@ export function PartnershipForm() {
<FormMessage />
</FormItem>
)}
/>
/> */}
<FormField
control={form.control}
name="contactPerson"
render={({ field }) => (
<FormItem>
<Label>Ism Familiya</Label>
<Label>{t('Ism Familiya')}</Label>
<FormControl>
<Input
placeholder="Ism va familiya"
@@ -174,13 +180,13 @@ export function PartnershipForm() {
)}
/>
<div className="grid md:grid-cols-2 gap-6">
<FormField
<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>Email</Label>
<Label>{t('Email')}</Label>
<FormControl>
<Input
placeholder="example@email.com"
@@ -192,14 +198,14 @@ export function PartnershipForm() {
<FormMessage />
</FormItem>
)}
/>
/> */}
<FormField
control={form.control}
name="phone"
render={({ field }) => (
<FormItem className="flex flex-col justify-start">
<Label>Telefon raqami</Label>
<Label>{t('Telefon raqami')}</Label>
<FormControl>
<Input
placeholder="+998 90 123 45 67"
@@ -219,7 +225,7 @@ export function PartnershipForm() {
name="companyFile"
render={({ field: { onChange, value, ...field } }) => (
<FormItem>
<Label>Kompaniya hujjati</Label>
<Label>{t('Kompaniya hujjati')}</Label>
<FormControl>
<div>
<Input
@@ -239,18 +245,18 @@ export function PartnershipForm() {
>
<Upload className="size-10 text-muted-foreground" />
<p className="text-muted-foreground text-lg">
Faylni tanlang
{t('Faylni tanlang')}
</p>
{value && value.length > 0 && (
<p className="mt-2 text-sm text-gray-500">
Tanlangan fayl: {value[0].name}
{t('Tanlangan fayl')}: {value[0].name}
</p>
)}
</FormLabel>
</div>
</FormControl>
<FormDescription>
PDF yoki Word formatida (maksimal 5MB)
{t('PDF yoki Word formatida (maksimal 5MB)')}
</FormDescription>
<FormMessage />
</FormItem>
@@ -260,10 +266,14 @@ export function PartnershipForm() {
<Button
type="submit"
size="lg"
className="w-full"
disabled={isSubmitting}
className="w-full cursor-pointer"
disabled={isPending}
>
{isSubmitting ? 'Yuborilmoqda...' : "So'rov yuborish"}
{isPending ? (
<Loader2 className="animate-spin" />
) : (
t("So'rov yuborish")
)}
</Button>
</form>
</Form>