Compare commits

...

11 Commits

Author SHA1 Message Date
Samandar Turgunboyev
345d8de80a Added a back button to the Product detail page 2026-03-28 16:47:01 +05:00
Samandar Turgunboyev
0c7a5127d0 comment update 2026-03-19 14:41:38 +05:00
Samandar Turgunboyev
1851327f8a error update 2026-03-19 09:31:09 +05:00
Samandar Turgunboyev
48ea82de0f comment lenth katta bolishi kerak 0dan 2026-03-18 22:19:53 +05:00
Samandar Turgunboyev
05c15a4f70 favouuriteProduct added page and page size 2026-03-16 16:11:58 +05:00
Samandar Turgunboyev
3d1d9d4860 favourite list update page 2026-03-16 16:10:25 +05:00
Samandar Turgunboyev
26c933d196 api timeout 5000 2026-03-13 21:21:50 +05:00
Samandar Turgunboyev
a842449e4d product detail fixed 2026-03-12 10:24:34 +05:00
Samandar Turgunboyev
bd346aacf3 added validation order 2026-03-11 20:06:14 +05:00
Samandar Turgunboyev
5d81f857da validation added 2026-03-11 20:01:52 +05:00
Samandar Turgunboyev
2ff4de4912 error 2026-03-11 19:42:19 +05:00
17 changed files with 402 additions and 183 deletions

View File

@@ -18,7 +18,7 @@ export async function generateMetadata({
}: PageProps): Promise<Metadata> { }: PageProps): Promise<Metadata> {
const { locale } = await params; const { locale } = await params;
try { try {
const res = await product_api.favouuriteProduct(); const res = await product_api.favouuriteProduct({ page: 1, page_size: 1 });
const total = res.data.total; const total = res.data.total;
if (locale === 'ru') { if (locale === 'ru') {

View File

@@ -58,7 +58,7 @@ export interface OrderCreateBody {
person_code: string; person_code: string;
currency_code: string; currency_code: string;
owner_person_code: string; owner_person_code: string;
note: string; note?: string;
order_products: { order_products: {
inventory_kind: string; inventory_kind: string;
product_code: string; product_code: string;

View File

@@ -3,6 +3,9 @@ import { z } from 'zod';
export const orderForm = z.object({ export const orderForm = z.object({
long: z.string().min(1, { message: 'Majburiy maydon' }), long: z.string().min(1, { message: 'Majburiy maydon' }),
lat: z.string().min(1, { message: 'Majburiy maydon' }), lat: z.string().min(1, { message: 'Majburiy maydon' }),
comment: z.string().max(300, 'Izoh 300 ta belgidan oshmasligi kerak'), comment: z
.string()
// .min(1, "Eng kamida 1ta belgi bo'lishi kerak")
.max(300, 'Izoh 300 ta belgidan oshmasligi kerak'),
city: z.string().optional(), city: z.string().optional(),
}); });

View File

@@ -112,7 +112,7 @@ const CartPage = () => {
const isGram = item.product.meansurement?.name?.toLowerCase() === 'gr'; const isGram = item.product.meansurement?.name?.toLowerCase() === 'gr';
const STEP = isGram ? 100 : 1; const STEP = isGram ? 100 : 1;
const MIN_QTY = isGram ? 100 : 0.5; const MIN_QTY = isGram ? 100 : 1;
let updatedQty: number; let updatedQty: number;
if (newValue !== undefined) { if (newValue !== undefined) {
@@ -329,23 +329,6 @@ const CartPage = () => {
} }
}, 500); }, 500);
}} }}
onBlur={() => {
// Blur bo'lganda noto'g'ri qiymatlarni tuzatish
const isGram =
item.product.meansurement?.name?.toLowerCase() ===
'gr';
const MIN_QTY = isGram ? 100 : 0.5;
let value = quantities[item.id] ?? item.quantity;
if (!value || isNaN(value) || value < MIN_QTY)
value = MIN_QTY;
setInputValues((prev) => ({
...prev,
[item.id]: String(value),
}));
handleQuantityChange(item.id, 0, value);
}}
type="text" type="text"
inputMode="decimal" inputMode="decimal"
className="w-16 text-center border-none p-0" className="w-16 text-center border-none p-0"

View File

@@ -37,6 +37,7 @@ import {
ZoomControl, ZoomControl,
} from '@pbe/react-yandex-maps'; } from '@pbe/react-yandex-maps';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { format } from 'date-fns'; import { format } from 'date-fns';
import { uz } from 'date-fns/locale'; import { uz } from 'date-fns/locale';
import { import {
@@ -63,6 +64,15 @@ interface CoordsData {
polygon: [number, number][][]; polygon: [number, number][][];
} }
type DRFError = {
[key: string]: Array<
| string
| {
[key: string]: string[];
}
>;
};
// Yetkazib berish vaqt oraliqlar // Yetkazib berish vaqt oraliqlar
const deliveryTimeSlots = [ const deliveryTimeSlots = [
{ id: 1, label: '10:00 - 12:00', start: '10:00', end: '12:00' }, { id: 1, label: '10:00 - 12:00', start: '10:00', end: '12:00' },
@@ -106,7 +116,7 @@ const OrderPage = () => {
queryClinet.refetchQueries({ queryKey: ['cart_items'] }); queryClinet.refetchQueries({ queryKey: ['cart_items'] });
} else if (message.errors && message.errors.length > 0) { } else if (message.errors && message.errors.length > 0) {
// Xatolik bo'lsa chiqarish // Xatolik bo'lsa chiqarish
toast.error(t('Xatolik yuz berdi: ') + message.errors[0].message, { toast.error(t('Xatolik yuz berdi') + message.errors[0].message, {
richColors: true, richColors: true,
position: 'top-center', position: 'top-center',
}); });
@@ -118,8 +128,38 @@ const OrderPage = () => {
}); });
} }
}, },
onError: () => { onError: (error: AxiosError<DRFError>) => {
toast.error(t('Xatolik yuz berdi: Mahsulot omborxoda yetarli emas'), { const data = error.response?.data;
let message = t('Xatolik yuz berdi');
if (data) {
// 🔥 DRF validation error parsing
if (typeof data === 'object') {
const firstKey = Object.keys(data)[0]; // "order"
const firstValue = data[firstKey];
if (Array.isArray(firstValue)) {
const firstErrorObj = firstValue[0]; // { note: [...] }
if (typeof firstErrorObj === 'object') {
const innerKey = Object.keys(firstErrorObj)[0]; // "note"
const innerValue = firstErrorObj[innerKey];
if (Array.isArray(innerValue)) {
message = innerValue[0]; // "This field may not be blank."
}
}
}
}
}
// fallback
if (!error.response) {
message = error.message;
}
toast.error(message, {
richColors: true, richColors: true,
position: 'top-center', position: 'top-center',
}); });
@@ -221,6 +261,7 @@ const OrderPage = () => {
}; };
const cityValue = form.watch('city'); const cityValue = form.watch('city');
const comment = form.watch('comment');
useEffect(() => { useEffect(() => {
if (!cityValue || cityValue.length < 3) return; if (!cityValue || cityValue.length < 3) return;
@@ -254,6 +295,14 @@ const OrderPage = () => {
return; return;
} }
if (value.comment.length > 300) {
toast.error(t('Izoh 300ta belgidan oshib ketdi'), {
richColors: true,
position: 'top-center',
});
return;
}
// Yetkazib berish vaqtini tekshirish // Yetkazib berish vaqtini tekshirish
if (!deliveryDate) { if (!deliveryDate) {
toast.error(t('Yetkazib berish sanasini tanlang'), { toast.error(t('Yetkazib berish sanasini tanlang'), {
@@ -290,7 +339,7 @@ const OrderPage = () => {
})); }));
if (user) { if (user) {
const dealTime = formatDate.format(deliveryDate, 'DD.MM.YYYY'); const dealTime = formatDate.format(deliveryDate, 'DD.MM.YYYY');
const note = value.comment.trim() ? value.comment : undefined;
mutate({ mutate({
order: [ order: [
{ {
@@ -304,13 +353,13 @@ const OrderPage = () => {
person_code: user?.username, person_code: user?.username,
currency_code: '860', currency_code: '860',
owner_person_code: user?.username, owner_person_code: user?.username,
note: value.comment,
order_products: order_products, order_products: order_products,
note: note,
}, },
], ],
}); });
} else { } else {
toast.error(t('Xatolik yuz berdi'), { toast.error(t('Xatolik yuz berdi: Foydalanuvchi topilmadi'), {
richColors: true, richColors: true,
position: 'top-center', position: 'top-center',
}); });
@@ -360,7 +409,7 @@ const OrderPage = () => {
<p className="text-gray-600">{t("Ma'lumotlaringizni to'ldiring")}</p> <p className="text-gray-600">{t("Ma'lumotlaringizni to'ldiring")}</p>
</div> </div>
<Form {...form}> <Form {...form}>
<div onSubmit={form.handleSubmit(onSubmit)} className="contents"> <form onSubmit={form.handleSubmit(onSubmit)} className="contents">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2 space-y-6"> <div className="lg:col-span-2 space-y-6">
{/* Contact Information */} {/* Contact Information */}
@@ -368,25 +417,47 @@ const OrderPage = () => {
<FormField <FormField
control={form.control} control={form.control}
name="comment" name="comment"
render={({ field }) => ( render={({ field }) => {
<FormItem> const length = field.value?.length || 0;
<Label className="block mt-3 text-sm font-medium text-gray-700">
{t('Izoh')} return (
</Label> <FormItem>
<FormControl> <Label className="block mt-3 text-sm font-medium text-gray-700">
<Textarea {t('Izoh')}
{...field} </Label>
maxLength={300}
className="w-full min-h-42 max-h-64 border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:border-blue-500" <FormControl>
placeholder={t('Izoh')} <Textarea
/> {...field}
</FormControl> className={cn(
<div className="text-right text-xs text-gray-500"> 'w-full min-h-42 max-h-64 border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:border-blue-500',
{field.value?.length || 0}/300 length > 300 &&
</div> 'border-red-500 focus-visible:border-red-500 focus-visible:ring-none focus-visible:outline-0',
<FormMessage /> )}
</FormItem> placeholder={t(
)} 'Izoh 300 ta belgidan oshmasligi kerak',
)}
/>
</FormControl>
<div
className={cn(
'text-right text-xs',
comment.length > 300
? 'text-red-500'
: 'text-gray-500',
)}
>
{comment.length}/300
</div>
{comment.length > 300 && (
<p className="text-red-500 text-md">
{t('Izoh 300 ta belgidan oshmasligi kerak')}
</p>
)}
</FormItem>
);
}}
/> />
</div> </div>
@@ -649,7 +720,6 @@ const OrderPage = () => {
<button <button
type="submit" type="submit"
disabled={isPending} disabled={isPending}
onClick={form.handleSubmit(onSubmit)}
className="w-full bg-blue-600 text-white py-4 rounded-lg font-semibold hover:bg-blue-700 transition disabled:bg-gray-400 disabled:cursor-not-allowed" className="w-full bg-blue-600 text-white py-4 rounded-lg font-semibold hover:bg-blue-700 transition disabled:bg-gray-400 disabled:cursor-not-allowed"
> >
{isPending ? ( {isPending ? (
@@ -663,7 +733,7 @@ const OrderPage = () => {
</div> </div>
</div> </div>
</div> </div>
</div> </form>
</Form> </Form>
</div> </div>
</div> </div>

View File

@@ -3,25 +3,54 @@
import { product_api } from '@/shared/config/api/product/api'; import { product_api } from '@/shared/config/api/product/api';
import { useRouter } from '@/shared/config/i18n/navigation'; import { useRouter } from '@/shared/config/i18n/navigation';
import { Button } from '@/shared/ui/button'; import { Button } from '@/shared/ui/button';
import { Card } from '@/shared/ui/card';
import { Skeleton } from '@/shared/ui/skeleton'; import { Skeleton } from '@/shared/ui/skeleton';
import { ProductCard } from '@/widgets/categories/ui/product-card'; import { ProductCard } from '@/widgets/categories/ui/product-card';
import { useQuery } from '@tanstack/react-query'; import { useInfiniteQuery } from '@tanstack/react-query';
import { Heart } from 'lucide-react'; import { Heart, Loader2 } from 'lucide-react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { useEffect, useRef } from 'react';
export default function Favourite() { export default function Favourite() {
const router = useRouter(); const router = useRouter();
const t = useTranslations(); const t = useTranslations();
const { data: favourite, isLoading } = useQuery({ const loadMoreRef = useRef<HTMLDivElement>(null);
queryKey: ['favourite_product'],
queryFn: () => product_api.favouuriteProduct(),
select(data) {
return data.data;
},
});
if (favourite && favourite.results.length === 0) { const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
useInfiniteQuery({
queryKey: ['favourite_product'],
initialPageParam: 1,
queryFn: ({ pageParam }) =>
product_api.favouuriteProduct({ page: pageParam, page_size: 30 }),
getNextPageParam: (lastPage) => {
if (lastPage.data.has_next) return lastPage.data.page + 1;
return undefined;
},
select(data) {
return data.pages.flatMap((page) => page.data.results);
},
});
// Intersection Observer — loadMoreRef ko'ringanda keyingi sahifani yuklaydi
useEffect(() => {
const el = loadMoreRef.current;
if (!el) return;
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) {
fetchNextPage();
}
},
{ threshold: 0.1 },
);
observer.observe(el);
return () => observer.disconnect();
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
const favourite = data ?? [];
if (!isLoading && favourite.length === 0) {
return ( return (
<div className="min-h-screen py-12"> <div className="min-h-screen py-12">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">
@@ -54,8 +83,6 @@ export default function Favourite() {
<Skeleton className="h-8 w-64 mb-2" /> <Skeleton className="h-8 w-64 mb-2" />
<Skeleton className="h-4 w-32" /> <Skeleton className="h-4 w-32" />
</div> </div>
{/* Grid */}
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4">
{Array.from({ length: 10 }).map((_, i) => ( {Array.from({ length: 10 }).map((_, i) => (
<div key={i} className="rounded-xl border p-3 space-y-3"> <div key={i} className="rounded-xl border p-3 space-y-3">
@@ -71,37 +98,32 @@ export default function Favourite() {
return ( return (
<div className="custom-container"> <div className="custom-container">
<> <div className="mb-8">
<div className="mb-8"> <h1 className="text-3xl font-bold text-slate-800 mb-2">
<div> {t('Sevimli mahsulotlar')}
<h1 className="text-3xl font-bold text-slate-800 mb-2"> </h1>
{t('Sevimli mahsulotlar')} <p className="text-slate-500">
</h1> {favourite.length} {t('ta mahsulot')}
<p className="text-slate-500"> </p>
{favourite && favourite.total} {t('ta mahsulot')} </div>
</p>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4 mb-30"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 xl:grid-cols-6 gap-4 mb-8">
{isLoading && {favourite
Array.from({ length: 6 }).map((_, index) => ( .filter((product) => product.state === 'A')
<Card className="p-3 space-y-3 rounded-xl" key={index}> .map((product) => (
<Skeleton className="h-40 sm:h-48 md:h-56 w-full rounded-lg" /> <ProductCard key={product.id} product={product} />
<Skeleton className="h-4 w-3/4" /> ))}
<Skeleton className="h-4 w-1/2" /> </div>
<Skeleton className="h-10 w-full rounded-lg" />
</Card> {/* Sentinel element — screen pastiga yetganda trigger bo'ladi */}
))} <div ref={loadMoreRef} className="h-10" />
{favourite &&
!isLoading && {/* Yuklash indikatori */}
favourite?.results {isFetchingNextPage && (
.filter((product) => product.state === 'A') <div className="flex justify-center py-6">
.map((product) => ( <Loader2 className="w-6 h-6 animate-spin text-blue-600" />
<ProductCard key={product.id} product={product} />
))}
</div> </div>
</> )}
</div> </div>
); );
} }

View File

@@ -5,14 +5,24 @@ import { product_api } from '@/shared/config/api/product/api';
import { BASE_URL } from '@/shared/config/api/URLs'; import { BASE_URL } from '@/shared/config/api/URLs';
import { useRouter } from '@/shared/config/i18n/navigation'; import { useRouter } from '@/shared/config/i18n/navigation';
import { useCartId } from '@/shared/hooks/cartId'; import { useCartId } from '@/shared/hooks/cartId';
import formatDate from '@/shared/lib/formatDate';
import formatPrice from '@/shared/lib/formatPrice'; import formatPrice from '@/shared/lib/formatPrice';
import { cn } from '@/shared/lib/utils'; import { cn } from '@/shared/lib/utils';
import { Button } from '@/shared/ui/button';
import { Input } from '@/shared/ui/input'; import { Input } from '@/shared/ui/input';
import { Skeleton } from '@/shared/ui/skeleton'; import { Skeleton } from '@/shared/ui/skeleton';
import { userStore } from '@/widgets/welcome/lib/hook'; import { userStore } from '@/widgets/welcome/lib/hook';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { Heart, Minus, Plus, Shield, ShoppingCart, Truck } from 'lucide-react'; import {
ChevronLeft,
Heart,
Minus,
Plus,
Shield,
ShoppingCart,
Truck,
} from 'lucide-react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Image from 'next/image'; import Image from 'next/image';
import { useParams } from 'next/navigation'; import { useParams } from 'next/navigation';
@@ -26,6 +36,9 @@ const ProductDetail = () => {
const { cart_id } = useCartId(); const { cart_id } = useCartId();
const { user } = userStore(); const { user } = userStore();
const router = useRouter(); const router = useRouter();
// const [api, setApi] = useState<CarouselApi>();
// const [canScrollPrev, setCanScrollPrev] = useState(false);
// const [canScrollNext, setCanScrollNext] = useState(false);
const [quantity, setQuantity] = useState<number | string>(1); const [quantity, setQuantity] = useState<number | string>(1);
@@ -50,6 +63,12 @@ const ProductDetail = () => {
enabled: !!cart_id, enabled: !!cart_id,
}); });
// const { data: recomendation, isLoading: recLoad } = useQuery({
// queryKey: ['product_list', data?.group.id],
// queryFn: () => product_api.list({ page: 1, page_size: 12 }),
// select: (res) => res.data.results,
// });
const favouriteMutation = useMutation({ const favouriteMutation = useMutation({
mutationFn: (productId: string) => product_api.favourite(productId), mutationFn: (productId: string) => product_api.favourite(productId),
@@ -67,6 +86,27 @@ const ProductDetail = () => {
}, },
}); });
// useEffect(() => {
// if (!api) return;
// const updateButtons = () => {
// setCanScrollPrev(api.canScrollPrev());
// setCanScrollNext(api.canScrollNext());
// };
// updateButtons();
// api.on('select', updateButtons);
// api.on('reInit', updateButtons);
// return () => {
// api.off('select', updateButtons);
// api.off('reInit', updateButtons);
// };
// }, [api]);
// const scrollPrev = () => api?.scrollPrev();
// const scrollNext = () => api?.scrollNext();
const measurement = data?.meansurement?.name?.toLowerCase() || ''; const measurement = data?.meansurement?.name?.toLowerCase() || '';
const isGram = measurement === 'gr'; const isGram = measurement === 'gr';
@@ -264,6 +304,16 @@ const ProductDetail = () => {
return ( return (
<div className="custom-container pb-8"> <div className="custom-container pb-8">
<div className="mb-5">
<Button
variant={'outline'}
className="w-fit"
onClick={() => router.back()}
>
<ChevronLeft />
{t('Orqaga')}
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 bg-white p-6 rounded-lg shadow"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8 bg-white p-6 rounded-lg shadow">
<div> <div>
<Image <Image
@@ -338,7 +388,7 @@ const ProductDetail = () => {
{t('Jami')}: {formatPrice(Number(subtotal) * numericQty, true)} {t('Jami')}: {formatPrice(Number(subtotal) * numericQty, true)}
</div> </div>
<div className="flex gap-3"> <div className="flex gap-3 mb-6">
<button <button
onClick={handleAddToCart} onClick={handleAddToCart}
className="flex-1 bg-green-600 hover:bg-green-700 text-white py-3 rounded-lg flex justify-center items-center gap-2" className="flex-1 bg-green-600 hover:bg-green-700 text-white py-3 rounded-lg flex justify-center items-center gap-2"
@@ -368,6 +418,15 @@ const ProductDetail = () => {
</button> </button>
</div> </div>
{data?.updated_at && data.payment_type === 'cash' && (
<div className="bg-yellow-50 border border-yellow-400 text-yellow-800 p-3 mb-4 rounded-md">
<p className="text-xs font-medium">
{t("Narxi o'zgargan bo'lishi mumkin")} {t('Yangilangan')}:{' '}
{formatDate.format(data.updated_at, 'DD-MM-YYYY')}
</p>
</div>
)}
<div className="grid grid-cols-2 gap-4 mt-6 border-t pt-4"> <div className="grid grid-cols-2 gap-4 mt-6 border-t pt-4">
<div className="text-center"> <div className="text-center">
<Truck className="mx-auto mb-1" /> <Truck className="mx-auto mb-1" />
@@ -380,6 +439,55 @@ const ProductDetail = () => {
</div> </div>
</div> </div>
</div> </div>
{/* <div className="mt-10 bg-white p-6 rounded-lg shadow relative">
<Button
onClick={scrollPrev}
disabled={!canScrollPrev}
className="absolute top-1/2 left-0 -translate-x-1/2 z-20 rounded-full"
size={'icon'}
variant={'outline'}
>
<ChevronLeft size={32} />
</Button>
<h2 className="text-2xl font-bold mb-4">{t("O'xshash mahsulotlar")}</h2>
<Carousel setApi={setApi}>
<CarouselContent>
{recLoad &&
Array.from({ length: 6 }).map((_, i) => (
<CarouselItem
key={i}
className="basis-1/1 sm:basis-1/3 md:basis-1/4 lg:basis-1/5 xl:basis-1/6 pb-2"
>
<Skeleton className="h-60 w-full" />
</CarouselItem>
))}
{recomendation
?.filter((p) => p.state === 'A')
.map((p) => (
<CarouselItem
key={p.id}
className="basis-1/2 sm:basis-1/3 md:basis-1/4 lg:basis-1/5 xl:basis-1/6 pb-2"
>
<ProductCard product={p} />
</CarouselItem>
))}
</CarouselContent>
</Carousel>
<Button
onClick={scrollNext}
disabled={!canScrollNext}
className="absolute top-1/2 -translate-x-1/2 z-20 -right-10 rounded-full"
size={'icon'}
variant={'outline'}
>
<ChevronRight size={32} />
</Button>
</div> */}
</div> </div>
); );
}; };

View File

@@ -36,6 +36,7 @@ import {
ZoomControl, ZoomControl,
} from '@pbe/react-yandex-maps'; } from '@pbe/react-yandex-maps';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { import {
Calendar as CalIcon, Calendar as CalIcon,
CheckCircle2, CheckCircle2,
@@ -72,6 +73,15 @@ interface CoordsData {
polygon: [number, number][][]; polygon: [number, number][][];
} }
type DRFError = {
[key: string]: Array<
| string
| {
[key: string]: string[];
}
>;
};
const RefreshOrder = () => { const RefreshOrder = () => {
const [deliveryDate, setDeliveryDate] = useState<Date>(); const [deliveryDate, setDeliveryDate] = useState<Date>();
const [selectedTimeSlot, setSelectedTimeSlot] = useState<string>(''); const [selectedTimeSlot, setSelectedTimeSlot] = useState<string>('');
@@ -126,13 +136,57 @@ const RefreshOrder = () => {
const { mutate, isPending } = useMutation({ const { mutate, isPending } = useMutation({
mutationFn: (body: OrderCreateBody) => cart_api.createOrder(body), mutationFn: (body: OrderCreateBody) => cart_api.createOrder(body),
onSuccess: () => { onSuccess: (res) => {
setOrderSuccess(true); const message = JSON.parse(res.data.response);
queryClient.refetchQueries({ queryKey: ['cart_items'] });
queryClient.refetchQueries({ queryKey: ['order_list'] }); if (message.successes && message.successes.length > 0) {
setOrderSuccess(true);
queryClient.refetchQueries({ queryKey: ['cart_items'] });
queryClient.refetchQueries({ queryKey: ['order_list'] });
} else if (message.errors && message.errors.length > 0) {
toast.error(t('Xatolik yuz berdi') + message.errors[0].message, {
richColors: true,
position: 'top-center',
});
} else {
toast.error(t('Xatolik yuz berdi'), {
richColors: true,
position: 'top-center',
});
}
}, },
onError: () => { onError: (error: AxiosError<DRFError>) => {
toast.error(t('Xatolik yuz berdi'), { const data = error.response?.data;
let message = t('Xatolik yuz berdi');
if (data) {
// 🔥 DRF validation error parsing
if (typeof data === 'object') {
const firstKey = Object.keys(data)[0]; // "order"
const firstValue = data[firstKey];
if (Array.isArray(firstValue)) {
const firstErrorObj = firstValue[0]; // { note: [...] }
if (typeof firstErrorObj === 'object') {
const innerKey = Object.keys(firstErrorObj)[0]; // "note"
const innerValue = firstErrorObj[innerKey];
if (Array.isArray(innerValue)) {
message = innerValue[0]; // "This field may not be blank."
}
}
}
}
}
// fallback
if (!error.response) {
message = error.message;
}
toast.error(message, {
richColors: true, richColors: true,
position: 'top-center', position: 'top-center',
}); });
@@ -321,7 +375,7 @@ const RefreshOrder = () => {
})); }));
if (user) { if (user) {
const dealTime = formatDate.format(deliveryDate, 'DD.MM.YYYY'); const dealTime = formatDate.format(deliveryDate, 'DD.MM.YYYY');
const note = value.comment.trim() ? value.comment : undefined;
mutate({ mutate({
order: [ order: [
{ {
@@ -335,7 +389,7 @@ const RefreshOrder = () => {
person_code: user?.username, person_code: user?.username,
currency_code: '860', currency_code: '860',
owner_person_code: user?.username, owner_person_code: user?.username,
note: value.comment, note: note,
order_products: order_products, order_products: order_products,
}, },
], ],
@@ -354,6 +408,7 @@ const RefreshOrder = () => {
); );
const totalItems = orderItems.reduce((sum, item) => sum + item.quantity, 0); const totalItems = orderItems.reduce((sum, item) => sum + item.quantity, 0);
const comment = form.watch('comment');
if (isLoading) { if (isLoading) {
return ( return (
@@ -373,7 +428,7 @@ const RefreshOrder = () => {
<p className="text-gray-500 mb-6"> <p className="text-gray-500 mb-6">
{t("Ushbu buyurtma mavjud emas yoki o'chirilgan")} {t("Ushbu buyurtma mavjud emas yoki o'chirilgan")}
</p> </p>
<Button onClick={() => (window.location.href = '/profile/history')}> <Button onClick={() => (window.location.href = '/profile')}>
{t('Buyurtmalar tarixiga qaytish')} {t('Buyurtmalar tarixiga qaytish')}
</Button> </Button>
</div> </div>
@@ -442,15 +497,31 @@ const RefreshOrder = () => {
<FormControl> <FormControl>
<Textarea <Textarea
{...field} {...field}
maxLength={300} className={cn(
className="w-full min-h-42 max-h-64 border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:border-blue-500" 'w-full min-h-42 max-h-64 border border-gray-300 rounded-lg px-4 py-3 focus:outline-none focus:border-blue-500',
placeholder={t('Izoh')} comment.length > 300 &&
'border-red-500 focus-visible:border-red-500 focus-visible:ring-none focus-visible:outline-0',
)}
placeholder={t(
'Izoh 300 ta belgidan oshmasligi kerak',
)}
/> />
</FormControl> </FormControl>
<div className="text-right text-xs text-gray-500"> <div
{field.value?.length || 0}/300 className={cn(
'text-right text-xs',
comment.length > 300
? 'text-red-500'
: 'text-gray-500',
)}
>
{comment.length}/300
</div> </div>
<FormMessage /> {comment.length > 300 && (
<p className="text-red-500 text-md">
{t('Izoh 300 ta belgidan oshmasligi kerak')}
</p>
)}
</FormItem> </FormItem>
)} )}
/> />

View File

@@ -14,7 +14,7 @@ import { BASE_URL } from './URLs';
const httpClient = axios.create({ const httpClient = axios.create({
baseURL: BASE_URL, baseURL: BASE_URL,
timeout: 10000, timeout: 50000,
}); });
httpClient.interceptors.request.use( httpClient.interceptors.request.use(
@@ -45,10 +45,6 @@ httpClient.interceptors.response.use(
if ((error as AxiosError)?.status === 403) { if ((error as AxiosError)?.status === 403) {
try { try {
const refToken = getRefToken(); const refToken = getRefToken();
if (!refToken) {
removeToken();
removeRefToken();
}
const { data } = await axios.post( const { data } = await axios.post(
`${BASE_URL}api/v1/accounts/refresh/token/`, `${BASE_URL}api/v1/accounts/refresh/token/`,
{ refresh: refToken }, { refresh: refToken },
@@ -62,10 +58,6 @@ httpClient.interceptors.response.use(
} else if ((error as AxiosError)?.status === 401) { } else if ((error as AxiosError)?.status === 401) {
try { try {
const refToken = getRefToken(); const refToken = getRefToken();
if (!refToken) {
removeToken();
removeRefToken();
}
const { data } = await axios.post( const { data } = await axios.post(
`${BASE_URL}api/v1/accounts/refresh/token/`, `${BASE_URL}api/v1/accounts/refresh/token/`,
{ refresh: refToken }, { refresh: refToken },

View File

@@ -55,8 +55,11 @@ export const product_api = {
return res; return res;
}, },
async favouuriteProduct(): Promise<AxiosResponse<FavouriteProduct>> { async favouuriteProduct(params: {
const res = await httpClient.get(API_URLS.FavouriteProduct); page: number;
page_size: number;
}): Promise<AxiosResponse<FavouriteProduct>> {
const res = await httpClient.get(API_URLS.FavouriteProduct, { params });
return res; return res;
}, },
}; };

View File

@@ -61,7 +61,7 @@ export interface ProductDetail {
litr: null | string; litr: null | string;
box_type_code: null | string; box_type_code: null | string;
box_quant: null | string; box_quant: null | string;
groups: { id: number; name: string }[]; group: { id: number; name: string };
state: 'A' | 'P'; state: 'A' | 'P';
barcodes: string; barcodes: string;
article_code: null | string; article_code: null | string;

View File

@@ -40,12 +40,10 @@
"To'g'ri email manzilini kiriting": "Введите правильный адрес электронной почты", "To'g'ri email manzilini kiriting": "Введите правильный адрес электронной почты",
"To'g'ri telefon raqamini kiriting": "Введите правильный номер телефона", "To'g'ri telefon raqamini kiriting": "Введите правильный номер телефона",
"File yuklash majburiy": "Загрузка файла обязательна", "File yuklash majburiy": "Загрузка файла обязательна",
"Maxfiylik Siyosati": "Политика конфиденциальности", "Maxfiylik Siyosati": "Политика конфиденциальности",
"Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market серьезно относится к безопасности ваших данных", "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market серьезно относится к безопасности ваших данных",
"Oxirgi yangilanish: 16 Dekabr 2025": "Последнее обновление: 16 декабря 2025", "Oxirgi yangilanish: 16 Dekabr 2025": "Последнее обновление: 16 декабря 2025",
"Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Эта Политика конфиденциальности объясняет, как Gastro Market собирает, использует и защищает персональные данные, предоставленные вами в онлайн-магазине. Используя наши услуги, вы соглашаетесь с описанными практиками.", "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Эта Политика конфиденциальности объясняет, как Gastro Market собирает, использует и защищает персональные данные, предоставленные вами в онлайн-магазине. Используя наши услуги, вы соглашаетесь с описанными практиками.",
"Biz To'playdigan Ma'lumotlar": "1. Сбор информации", "Biz To'playdigan Ma'lumotlar": "1. Сбор информации",
"Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Имя, адрес электронной почты, номер телефона", "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Имя, адрес электронной почты, номер телефона",
"Kompaniya nomi, website, hamkorlik so'rovlari": "Название компании, веб-сайт, запросы на сотрудничество", "Kompaniya nomi, website, hamkorlik so'rovlari": "Название компании, веб-сайт, запросы на сотрудничество",
@@ -55,7 +53,6 @@
"Kompaniya Ma'lumotlari": "Информация о компании", "Kompaniya Ma'lumotlari": "Информация о компании",
"Fayllar:": "Файлы:", "Fayllar:": "Файлы:",
"Texnik Ma'lumotlar": "Технические данные", "Texnik Ma'lumotlar": "Технические данные",
"Ma'lumotlardan Foydalanish": "2. Использование данных", "Ma'lumotlardan Foydalanish": "2. Использование данных",
"To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "Мы будем использовать собранные вами данные для следующих целей:", "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "Мы будем использовать собранные вами данные для следующих целей:",
"Hamkorlik so'rovlarini qayta ishlash va javob berish": "Обработка и ответ на запросы на сотрудничество", "Hamkorlik so'rovlarini qayta ishlash va javob berish": "Обработка и ответ на запросы на сотрудничество",
@@ -63,27 +60,23 @@
"Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Обеспечение безопасности сайта и предотвращение мошенничества", "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Обеспечение безопасности сайта и предотвращение мошенничества",
"Foydalanuvchi tajribasini tahlil qilish va yaxshilash": "Анализ и улучшение пользовательского опыта", "Foydalanuvchi tajribasini tahlil qilish va yaxshilash": "Анализ и улучшение пользовательского опыта",
"Qonuniy talablarni bajarish": "Соблюдение законных требований", "Qonuniy talablarni bajarish": "Соблюдение законных требований",
"Ma'lumotlar Xavfsizligi": "3. Безопасность данных", "Ma'lumotlar Xavfsizligi": "3. Безопасность данных",
"Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Мы применяем современные меры безопасности для защиты ваших персональных данных:", "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Мы применяем современные меры безопасности для защиты ваших персональных данных:",
"SSL/TLS shifrlash orqali ma'lumotlar uzatish": "Передача данных с шифрованием SSL/TLS", "SSL/TLS shifrlash orqali ma'lumotlar uzatish": "Передача данных с шифрованием SSL/TLS",
"Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Хранение на безопасных серверах и в базе данных", "Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Хранение на безопасных серверах и в базе данных",
"Cheklangan kirish huquqlari va autentifikatsiya": "Ограниченный доступ и аутентификация", "Cheklangan kirish huquqlari va autentifikatsiya": "Ограниченный доступ и аутентификация",
"Doimiy xavfsizlik monitoringi va yangilanishlar": "Постоянный мониторинг безопасности и обновления", "Doimiy xavfsizlik monitoringi va yangilanishlar": "Постоянный мониторинг безопасности и обновления",
"Ma'lumotlarni Ulashish": "4. Раскрытие данных", "Ma'lumotlarni Ulashish": "4. Раскрытие данных",
"Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Мы не будем продавать ваши персональные данные третьим лицам.", "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Мы не будем продавать ваши персональные данные третьим лицам.",
"Sizning roziligingiz bilan": "С вашего согласия", "Sizning roziligingiz bilan": "С вашего согласия",
"Qonuniy talablar bo'yicha": "В соответствии с законом", "Qonuniy talablar bo'yicha": "В соответствии с законом",
"Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "С надежными партнерами (соглашения о конфиденциальности)", "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "С надежными партнерами (соглашения о конфиденциальности)",
"Kompaniya birlashuvi yoki sotilishi holatida": "В случае слияния или продажи компании", "Kompaniya birlashuvi yoki sotilishi holatida": "В случае слияния или продажи компании",
"Biz Bilan Bog'lanish": "Связь с нами", "Biz Bilan Bog'lanish": "Связь с нами",
"Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Если у вас есть вопросы по данной Политике конфиденциальности или вашим данным, свяжитесь с нами:", "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Если у вас есть вопросы по данной Политике конфиденциальности или вашим данным, свяжитесь с нами:",
"Telefon": "Телефон", "Telefon": "Телефон",
"Toshkent, O'zbekiston": "Ташкент, Узбекистан", "Toshkent, O'zbekiston": "Ташкент, Узбекистан",
"Manzil": "Адрес", "Manzil": "Адрес",
"Miqdor": "Количество", "Miqdor": "Количество",
"Jami": "Итого", "Jami": "Итого",
"Bepul yetkazib berish": "Бесплатная доставка", "Bepul yetkazib berish": "Бесплатная доставка",
@@ -94,25 +87,21 @@
"Ishlab chiqaruvchi": "Производитель", "Ishlab chiqaruvchi": "Производитель",
"Hajmi": "Объем", "Hajmi": "Объем",
"O'xshash mahsulotlar": "Похожие товары", "O'xshash mahsulotlar": "Похожие товары",
"Hech narsa topilmadi": "Не найдено", "Hech narsa topilmadi": "Не найдено",
"Qidiruv natijalari": "Результаты поиска", "Qidiruv natijalari": "Результаты поиска",
"Tavsiya etiladi": "Рекомендуется", "Tavsiya etiladi": "Рекомендуется",
"Yuklanmoqda": "Загрузка...", "Yuklanmoqda": "Загрузка...",
"Natija topilmadi": "Нет результатов", "Natija topilmadi": "Нет результатов",
"Asosiy": "Основная", "Asosiy": "Основная",
"Katalog": "Каталог", "Katalog": "Каталог",
"Sevimli": "Избранное", "Sevimli": "Избранное",
"Savatda": "В корзине", "Savatda": "В корзине",
"Profil": "Профиль", "Profil": "Профиль",
"Username yoki parol xato kiritildi": "Неверное имя пользователя или пароль", "Username yoki parol xato kiritildi": "Неверное имя пользователя или пароль",
"Tizimga kirish": "Войти в систему", "Tizimga kirish": "Войти в систему",
"Username": "Имя пользователя", "Username": "Имя пользователя",
"Parol": "Пароль", "Parol": "Пароль",
"Kirish": "Вход", "Kirish": "Вход",
"Savatingiz bo'sh": "Ваша корзина пуста", "Savatingiz bo'sh": "Ваша корзина пуста",
"Mahsulotlar qo'shish uchun katalogga o'ting": "Перейти в каталог, чтобы добавить товары", "Mahsulotlar qo'shish uchun katalogga o'ting": "Перейти в каталог, чтобы добавить товары",
"Xarid qilishni boshlash": "Начать покупку", "Xarid qilishni boshlash": "Начать покупку",
@@ -153,31 +142,25 @@
"Manzilni qidirish": "Поиск адреса", "Manzilni qidirish": "Поиск адреса",
"Toshkent": "Ташкент", "Toshkent": "Ташкент",
"Mening joylashuvim": "Моё местоположение", "Mening joylashuvim": "Моё местоположение",
"Yetkazib berish usuli": "Способ доставки", "Yetkazib berish usuli": "Способ доставки",
"Standart yetkazib berish": "Стандартная доставка", "Standart yetkazib berish": "Стандартная доставка",
"2-3 kun ichida": "В течение 23 дней", "2-3 kun ichida": "В течение 23 дней",
"Tez yetkazib berish": "Экспресс-доставка", "Tez yetkazib berish": "Экспресс-доставка",
"1 kun ichida": "В течение 1 дня", "1 kun ichida": "В течение 1 дня",
"To'lov usuli": "Способ оплаты", "To'lov usuli": "Способ оплаты",
"Naqd pul": "Наличные", "Naqd pul": "Наличные",
"Yetkazib berishda to'lash": "Оплата при доставке", "Yetkazib berishda to'lash": "Оплата при доставке",
"Plastik karta": "Банковская карта", "Plastik karta": "Банковская карта",
"Online to'lov": "Онлайн-оплата", "Online to'lov": "Онлайн-оплата",
"Mahsulotlar": "Товары", "Mahsulotlar": "Товары",
"Buyurtmani tasdiqlash": "Подтвердить заказ", "Buyurtmani tasdiqlash": "Подтвердить заказ",
"Majburiy maydon": "Обязательное поле", "Majburiy maydon": "Обязательное поле",
"Xato raqam kiritildi": "Введен неверный номер", "Xato raqam kiritildi": "Введен неверный номер",
"Orqaga": "Назад", "Orqaga": "Назад",
"Sevimlilar bo'sh": "Избранное пусто", "Sevimlilar bo'sh": "Избранное пусто",
"Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Вы пока не добавили ни одного товара в избранное. Перейдите в каталог и сохраните понравившиеся товары.", "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Вы пока не добавили ни одного товара в избранное. Перейдите в каталог и сохраните понравившиеся товары.",
"Sevimli mahsulotlar": "Избранные товары", "Sevimli mahsulotlar": "Избранные товары",
"Ism email manzil telefon raqami": "Имя, адрес электронной почты, номер телефона", "Ism email manzil telefon raqami": "Имя, адрес электронной почты, номер телефона",
"Faol buyurtmalar": "Активные заказы", "Faol buyurtmalar": "Активные заказы",
"Barchasi": "Все", "Barchasi": "Все",
"Buyurtmalar tarixi": "История заказов", "Buyurtmalar tarixi": "История заказов",
@@ -186,7 +169,6 @@
"Umumiy": "Общее", "Umumiy": "Общее",
"Buyurtmalar": "Заказы", "Buyurtmalar": "Заказы",
"Tarix": "История", "Tarix": "История",
"Faol": "Активно", "Faol": "Активно",
"Tugadi": "Заканчивается", "Tugadi": "Заканчивается",
"Yetkazish": "Доставка", "Yetkazish": "Доставка",
@@ -200,17 +182,14 @@
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Если у вас нет логина и пароля для входа, пожалуйста, свяжитесь с нами", "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Если у вас нет логина и пароля для входа, пожалуйста, свяжитесь с нами",
"Murojat qilish": "Заявление", "Murojat qilish": "Заявление",
"So'rov yuborildi!": "Запрос успешно отправлен!", "So'rov yuborildi!": "Запрос успешно отправлен!",
"Tez-tez So'raladigan Savollar": "Часто задаваемые вопросы", "Tez-tez So'raladigan Savollar": "Часто задаваемые вопросы",
"Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Ответы на самые часто задаваемые вопросы о Gastro Market", "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Ответы на самые часто задаваемые вопросы о Gastro Market",
"Barcha mahsulotlar": "Все товары", "Barcha mahsulotlar": "Все товары",
"Xatolik yuz berdi: Mahsulot omborxonada yetarli emas": "Произошла ошибка: недостаточно товаров на складе", "Xatolik yuz berdi: Mahsulot omborxonada yetarli emas": "Произошла ошибка: недостаточно товаров на складе",
"Bu kategoriyada hozircha mahsulot yoq": "В этой категории пока нет товаров", "Bu kategoriyada hozircha mahsulot yoq": "В этой категории пока нет товаров",
"Tez orada qoshiladi": "Скоро будет добавлено", "Tez orada qoshiladi": "Скоро будет добавлено",
"Hozirchali bu kategoriyada mahsulot yo'q": "Пока нет товаров в этой категории", "Hozirchali bu kategoriyada mahsulot yo'q": "Пока нет товаров в этой категории",
"Kataloglar": "Каталог", "Kataloglar": "Каталог",
"Naqd bilan olinadi": "Получено наличными", "Naqd bilan olinadi": "Получено наличными",
"Pul o'tkazish yo'li bilan olinadi": "Получено путём перевода денег", "Pul o'tkazish yo'li bilan olinadi": "Получено путём перевода денег",
"Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin": "Внимание! Цена продукта может измениться", "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin": "Внимание! Цена продукта может измениться",
@@ -225,5 +204,9 @@
"Qayta buyurtma": "Заказать заново", "Qayta buyurtma": "Заказать заново",
"Yangilangan": "Обновлено", "Yangilangan": "Обновлено",
"Narxi o'zgargan bo'lishi mumkin": "Цена может быть изменена", "Narxi o'zgargan bo'lishi mumkin": "Цена может быть изменена",
"ga yangilandi": "обновлено" "ga yangilandi": "обновлено",
} "Izoh 300 ta belgidan oshmasligi kerak": "Комментарий не должен превышать 300 символов",
"Xatolik yuz berdi: Foydalanuvchi topilmadi": "Ошибка: Пользователь не найден",
"Izoh 300ta belgidan oshib ketdi": "Комментарий превышает 300 символов",
"Izoh kamida 1ta belgi bo'lishi kerak": "Должно быть как минимум 1 символ"
}

View File

@@ -43,12 +43,10 @@ declare const messages: {
"To'g'ri email manzilini kiriting": "To'g'ri email manzilini kiriting"; "To'g'ri email manzilini kiriting": "To'g'ri email manzilini kiriting";
"To'g'ri telefon raqamini kiriting": "To'g'ri telefon raqamini kiriting"; "To'g'ri telefon raqamini kiriting": "To'g'ri telefon raqamini kiriting";
'File yuklash majburiy': 'File yuklash majburiy'; 'File yuklash majburiy': 'File yuklash majburiy';
'Maxfiylik Siyosati': 'Maxfiylik Siyosati'; 'Maxfiylik Siyosati': 'Maxfiylik Siyosati';
"Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi"; "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi";
'Oxirgi yangilanish: 16 Dekabr 2025': 'Oxirgi yangilanish: 16 Dekabr 2025'; 'Oxirgi yangilanish: 16 Dekabr 2025': 'Oxirgi yangilanish: 16 Dekabr 2025';
"Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz, ishlatamiz va himoya qilishimizni tushuntiradi. Xizmatlarimizdan foydalanish orqali siz ushbu siyosatda tasvirlangan amaliyotlarga rozilik bildirasiz."; "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz, ishlatamiz va himoya qilishimizni tushuntiradi. Xizmatlarimizdan foydalanish orqali siz ushbu siyosatda tasvirlangan amaliyotlarga rozilik bildirasiz.";
"Biz To'playdigan Ma'lumotlar": "1. Biz To'playdigan Ma'lumotlar"; "Biz To'playdigan Ma'lumotlar": "1. Biz To'playdigan Ma'lumotlar";
"Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz:"; "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz:";
'Ism email manzil telefon raqami': 'Ism, email manzil, telefon raqami'; 'Ism email manzil telefon raqami': 'Ism, email manzil, telefon raqami';
@@ -59,7 +57,6 @@ declare const messages: {
"Kompaniya Ma'lumotlari": "Kompaniya Ma'lumotlari"; "Kompaniya Ma'lumotlari": "Kompaniya Ma'lumotlari";
'Fayllar:': 'Fayllar:'; 'Fayllar:': 'Fayllar:';
"Texnik Ma'lumotlar": "Texnik Ma'lumotlar"; "Texnik Ma'lumotlar": "Texnik Ma'lumotlar";
"Ma'lumotlardan Foydalanish": "2. Ma'lumotlardan Foydalanish"; "Ma'lumotlardan Foydalanish": "2. Ma'lumotlardan Foydalanish";
"To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:"; "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:";
"Hamkorlik so'rovlarini qayta ishlash va javob berish": "Hamkorlik so'rovlarini qayta ishlash va javob berish"; "Hamkorlik so'rovlarini qayta ishlash va javob berish": "Hamkorlik so'rovlarini qayta ishlash va javob berish";
@@ -67,27 +64,23 @@ declare const messages: {
"Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish"; "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish";
'Foydalanuvchi tajribasini tahlil qilish va yaxshilash': 'Foydalanuvchi tajribasini tahlil qilish va yaxshilash'; 'Foydalanuvchi tajribasini tahlil qilish va yaxshilash': 'Foydalanuvchi tajribasini tahlil qilish va yaxshilash';
'Qonuniy talablarni bajarish': 'Qonuniy talablarni bajarish'; 'Qonuniy talablarni bajarish': 'Qonuniy talablarni bajarish';
"Ma'lumotlar Xavfsizligi": "3. Ma'lumotlar Xavfsizligi"; "Ma'lumotlar Xavfsizligi": "3. Ma'lumotlar Xavfsizligi";
"Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:"; "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:";
"SSL/TLS shifrlash orqali ma'lumotlar uzatish": "SSL/TLS shifrlash orqali ma'lumotlar uzatish"; "SSL/TLS shifrlash orqali ma'lumotlar uzatish": "SSL/TLS shifrlash orqali ma'lumotlar uzatish";
"Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Xavfsiz serverlar va ma'lumotlar bazasida saqlash"; "Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Xavfsiz serverlar va ma'lumotlar bazasida saqlash";
'Cheklangan kirish huquqlari va autentifikatsiya': 'Cheklangan kirish huquqlari va autentifikatsiya'; 'Cheklangan kirish huquqlari va autentifikatsiya': 'Cheklangan kirish huquqlari va autentifikatsiya';
'Doimiy xavfsizlik monitoringi va yangilanishlar': 'Doimiy xavfsizlik monitoringi va yangilanishlar'; 'Doimiy xavfsizlik monitoringi va yangilanishlar': 'Doimiy xavfsizlik monitoringi va yangilanishlar';
"Ma'lumotlarni Ulashish": "4. Ma'lumotlarni Ulashish"; "Ma'lumotlarni Ulashish": "4. Ma'lumotlarni Ulashish";
"Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz"; "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz";
'Sizning roziligingiz bilan': 'Sizning roziligingiz bilan'; 'Sizning roziligingiz bilan': 'Sizning roziligingiz bilan';
"Qonuniy talablar bo'yicha": "Qonuniy talablar bo'yicha"; "Qonuniy talablar bo'yicha": "Qonuniy talablar bo'yicha";
"Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)"; "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)";
'Kompaniya birlashuvi yoki sotilishi holatida': 'Kompaniya birlashuvi yoki sotilishi holatida'; 'Kompaniya birlashuvi yoki sotilishi holatida': 'Kompaniya birlashuvi yoki sotilishi holatida';
"Biz Bilan Bog'lanish": "Biz Bilan Bog'lanish"; "Biz Bilan Bog'lanish": "Biz Bilan Bog'lanish";
"Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:"; "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:";
Telefon: 'Telefon'; Telefon: 'Telefon';
"Toshkent, O'zbekiston": "Toshkent, O'zbekiston"; "Toshkent, O'zbekiston": "Toshkent, O'zbekiston";
Manzil: 'Manzil'; Manzil: 'Manzil';
Miqdor: 'Miqdor'; Miqdor: 'Miqdor';
Jami: 'Jami'; Jami: 'Jami';
'Bepul yetkazib berish': 'Bepul yetkazib berish'; 'Bepul yetkazib berish': 'Bepul yetkazib berish';
@@ -98,25 +91,21 @@ declare const messages: {
'Ishlab chiqaruvchi': 'Ishlab chiqaruvchi'; 'Ishlab chiqaruvchi': 'Ishlab chiqaruvchi';
Hajmi: 'Hajmi'; Hajmi: 'Hajmi';
"O'xshash mahsulotlar": "O'xshash mahsulotlar"; "O'xshash mahsulotlar": "O'xshash mahsulotlar";
'Hech narsa topilmadi': 'Hech narsa topilmadi'; 'Hech narsa topilmadi': 'Hech narsa topilmadi';
'Qidiruv natijalari': 'Qidiruv natijalari'; 'Qidiruv natijalari': 'Qidiruv natijalari';
'Tavsiya etiladi': 'Tavsiya etiladi'; 'Tavsiya etiladi': 'Tavsiya etiladi';
Yuklanmoqda: 'Yuklanmoqda....'; Yuklanmoqda: 'Yuklanmoqda....';
'Natija topilmadi': 'Natija topilmadi'; 'Natija topilmadi': 'Natija topilmadi';
Asosiy: 'Asosiy'; Asosiy: 'Asosiy';
Katalog: 'Katalog'; Katalog: 'Katalog';
Sevimli: 'Sevimli'; Sevimli: 'Sevimli';
Savatda: 'Savatda'; Savatda: 'Savatda';
Profil: 'Profil'; Profil: 'Profil';
'Username yoki parol xato kiritildi': 'Username yoki parol xato kiritildi'; 'Username yoki parol xato kiritildi': 'Username yoki parol xato kiritildi';
'Tizimga kirish': 'Tizimga kirish'; 'Tizimga kirish': 'Tizimga kirish';
Username: 'Username'; Username: 'Username';
Parol: 'Parol'; Parol: 'Parol';
Kirish: 'Kirish'; Kirish: 'Kirish';
"Savatingiz bo'sh": "Savatingiz bo'sh"; "Savatingiz bo'sh": "Savatingiz bo'sh";
"Mahsulotlar qo'shish uchun katalogga o'ting": "Mahsulotlar qo'shish uchun katalogga o'ting"; "Mahsulotlar qo'shish uchun katalogga o'ting": "Mahsulotlar qo'shish uchun katalogga o'ting";
'Xarid qilishni boshlash': 'Xarid qilishni boshlash'; 'Xarid qilishni boshlash': 'Xarid qilishni boshlash';
@@ -131,7 +120,6 @@ declare const messages: {
'Xaridni davom ettirish': 'Xaridni davom ettirish'; 'Xaridni davom ettirish': 'Xaridni davom ettirish';
'Tez yetkazib berish 1-2 kun ichida': 'Tez yetkazib berish 1-2 kun ichida'; 'Tez yetkazib berish 1-2 kun ichida': 'Tez yetkazib berish 1-2 kun ichida';
"Xavfsiz to'lov usullari": "Xavfsiz to'lov usullari"; "Xavfsiz to'lov usullari": "Xavfsiz to'lov usullari";
'Buyurtma qabul qilindi!': 'Buyurtma qabul qilindi!'; 'Buyurtma qabul qilindi!': 'Buyurtma qabul qilindi!';
'Buyurtma raqami': 'Buyurtma raqami'; 'Buyurtma raqami': 'Buyurtma raqami';
'Buyurtmangiz muvaffaqiyatli qabul qilindi': 'Buyurtmangiz muvaffaqiyatli qabul qilindi.'; 'Buyurtmangiz muvaffaqiyatli qabul qilindi': 'Buyurtmangiz muvaffaqiyatli qabul qilindi.';
@@ -176,7 +164,6 @@ declare const messages: {
"Sevimlilar bo'sh": "Sevimlilar bo'sh"; "Sevimlilar bo'sh": "Sevimlilar bo'sh";
"Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz. Mahsulotlar ro'yxatiga o'ting va yoqqan mahsulotlaringizni saqlang."; "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz. Mahsulotlar ro'yxatiga o'ting va yoqqan mahsulotlaringizni saqlang.";
'Sevimli mahsulotlar': 'Sevimli mahsulotlar'; 'Sevimli mahsulotlar': 'Sevimli mahsulotlar';
'Faol buyurtmalar': 'Faol buyurtmalar'; 'Faol buyurtmalar': 'Faol buyurtmalar';
Barchasi: 'Barchasi'; Barchasi: 'Barchasi';
'Buyurtmalar tarixi': 'Buyurtmalar tarixi'; 'Buyurtmalar tarixi': 'Buyurtmalar tarixi';
@@ -185,7 +172,6 @@ declare const messages: {
Umumiy: 'Umumiy'; Umumiy: 'Umumiy';
Buyurtmalar: 'Buyurtmalar'; Buyurtmalar: 'Buyurtmalar';
Tarix: 'Tarix'; Tarix: 'Tarix';
Faol: 'Faol'; Faol: 'Faol';
Tugadi: 'Tugadi'; Tugadi: 'Tugadi';
Yetkazish: 'Yetkazish'; Yetkazish: 'Yetkazish';
@@ -199,10 +185,8 @@ declare const messages: {
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling"; "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling";
'Murojat qilish': 'Murojat qilish'; 'Murojat qilish': 'Murojat qilish';
"So'rov yuborildi!": "So'rov yuborildi!"; "So'rov yuborildi!": "So'rov yuborildi!";
"Tez-tez So'raladigan Savollar": "Tez-tez So'raladigan Savollar"; "Tez-tez So'raladigan Savollar": "Tez-tez So'raladigan Savollar";
"Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar"; "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar";
'Barcha mahsulotlar': 'Barcha mahsulotlar'; 'Barcha mahsulotlar': 'Barcha mahsulotlar';
'Xatolik yuz berdi: Mahsulot omborxonada yetarli emas': 'Xatolik yuz berdi: Mahsulot omborxonada yetarli emas'; 'Xatolik yuz berdi: Mahsulot omborxonada yetarli emas': 'Xatolik yuz berdi: Mahsulot omborxonada yetarli emas';
'Bu kategoriyada hozircha mahsulot yoq': 'Bu kategoriyada hozircha mahsulot yoq'; 'Bu kategoriyada hozircha mahsulot yoq': 'Bu kategoriyada hozircha mahsulot yoq';
@@ -211,7 +195,6 @@ declare const messages: {
Kataloglar: 'Kataloglar'; Kataloglar: 'Kataloglar';
'Naqd bilan olinadi': 'Naqd bilan olinadi'; 'Naqd bilan olinadi': 'Naqd bilan olinadi';
"Pul o'tkazish yo'li bilan olinadi": "Pul o'tkazish yo'li bilan olinadi"; "Pul o'tkazish yo'li bilan olinadi": "Pul o'tkazish yo'li bilan olinadi";
"Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin": "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin"; "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin": "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin";
"So'nggi yangilanish:": "So'nggi yangilanish"; "So'nggi yangilanish:": "So'nggi yangilanish";
only_available: 'Faqat {maxBalance} dona mavjud'; only_available: 'Faqat {maxBalance} dona mavjud';
@@ -225,5 +208,9 @@ declare const messages: {
Yangilangan: 'Yangilangan'; Yangilangan: 'Yangilangan';
"Narxi o'zgargan bo'lishi mumkin": "Narxi o'zgargan bo'lishi mumkin"; "Narxi o'zgargan bo'lishi mumkin": "Narxi o'zgargan bo'lishi mumkin";
'ga yangilandi': 'ga yangilandi'; 'ga yangilandi': 'ga yangilandi';
'Izoh 300 ta belgidan oshmasligi kerak': 'Izoh 300 ta belgidan oshmasligi kerak';
'Xatolik yuz berdi: Foydalanuvchi topilmadi': 'Xatolik yuz berdi: Foydalanuvchi topilmadi';
'Izoh 300ta belgidan oshib ketdi': 'Izoh 300ta belgidan oshib ketdi';
"Izoh kamida 1ta belgi bo'lishi kerak": "Izoh kamida 1ta belgi bo'lishi kerak";
}; };
export default messages; export default messages;

View File

@@ -40,12 +40,10 @@
"To'g'ri email manzilini kiriting": "To'g'ri email manzilini kiriting", "To'g'ri email manzilini kiriting": "To'g'ri email manzilini kiriting",
"To'g'ri telefon raqamini kiriting": "To'g'ri telefon raqamini kiriting", "To'g'ri telefon raqamini kiriting": "To'g'ri telefon raqamini kiriting",
"File yuklash majburiy": "File yuklash majburiy", "File yuklash majburiy": "File yuklash majburiy",
"Maxfiylik Siyosati": "Maxfiylik Siyosati", "Maxfiylik Siyosati": "Maxfiylik Siyosati",
"Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi", "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi": "Gastro Market sizning ma'lumotlaringiz xavfsizligini jiddiy qabul qiladi",
"Oxirgi yangilanish: 16 Dekabr 2025": "Oxirgi yangilanish: 16 Dekabr 2025", "Oxirgi yangilanish: 16 Dekabr 2025": "Oxirgi yangilanish: 16 Dekabr 2025",
"Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz, ishlatamiz va himoya qilishimizni tushuntiradi. Xizmatlarimizdan foydalanish orqali siz ushbu siyosatda tasvirlangan amaliyotlarga rozilik bildirasiz.", "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz": "Ushbu Maxfiylik Siyosati Gastro Market online magazinida siz tomonidan taqdim etilgan shaxsiy ma'lumotlarni qanday to'playmiz, ishlatamiz va himoya qilishimizni tushuntiradi. Xizmatlarimizdan foydalanish orqali siz ushbu siyosatda tasvirlangan amaliyotlarga rozilik bildirasiz.",
"Biz To'playdigan Ma'lumotlar": "1. Biz To'playdigan Ma'lumotlar", "Biz To'playdigan Ma'lumotlar": "1. Biz To'playdigan Ma'lumotlar",
"Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz:", "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz": "Sizning tajribangizni yaxshilash uchun biz quyidagi ma'lumotlarni to'playmiz:",
"Ism email manzil telefon raqami": "Ism, email manzil, telefon raqami", "Ism email manzil telefon raqami": "Ism, email manzil, telefon raqami",
@@ -56,7 +54,6 @@
"Kompaniya Ma'lumotlari": "Kompaniya Ma'lumotlari", "Kompaniya Ma'lumotlari": "Kompaniya Ma'lumotlari",
"Fayllar:": "Fayllar:", "Fayllar:": "Fayllar:",
"Texnik Ma'lumotlar": "Texnik Ma'lumotlar", "Texnik Ma'lumotlar": "Texnik Ma'lumotlar",
"Ma'lumotlardan Foydalanish": "2. Ma'lumotlardan Foydalanish", "Ma'lumotlardan Foydalanish": "2. Ma'lumotlardan Foydalanish",
"To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:", "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:": "To'plangan ma'lumotlaringizdan quyidagi maqsadlarda foydalanamiz:",
"Hamkorlik so'rovlarini qayta ishlash va javob berish": "Hamkorlik so'rovlarini qayta ishlash va javob berish", "Hamkorlik so'rovlarini qayta ishlash va javob berish": "Hamkorlik so'rovlarini qayta ishlash va javob berish",
@@ -64,27 +61,23 @@
"Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish", "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish": "Sayt xavfsizligini ta'minlash va firibgarlikka qarshi kurashish",
"Foydalanuvchi tajribasini tahlil qilish va yaxshilash": "Foydalanuvchi tajribasini tahlil qilish va yaxshilash", "Foydalanuvchi tajribasini tahlil qilish va yaxshilash": "Foydalanuvchi tajribasini tahlil qilish va yaxshilash",
"Qonuniy talablarni bajarish": "Qonuniy talablarni bajarish", "Qonuniy talablarni bajarish": "Qonuniy talablarni bajarish",
"Ma'lumotlar Xavfsizligi": "3. Ma'lumotlar Xavfsizligi", "Ma'lumotlar Xavfsizligi": "3. Ma'lumotlar Xavfsizligi",
"Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:", "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:": "Biz sizning shaxsiy ma'lumotlaringizni himoya qilish uchun zamonaviy xavfsizlik choralarini qo'llaymiz:",
"SSL/TLS shifrlash orqali ma'lumotlar uzatish": "SSL/TLS shifrlash orqali ma'lumotlar uzatish", "SSL/TLS shifrlash orqali ma'lumotlar uzatish": "SSL/TLS shifrlash orqali ma'lumotlar uzatish",
"Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Xavfsiz serverlar va ma'lumotlar bazasida saqlash", "Xavfsiz serverlar va ma'lumotlar bazasida saqlash": "Xavfsiz serverlar va ma'lumotlar bazasida saqlash",
"Cheklangan kirish huquqlari va autentifikatsiya": "Cheklangan kirish huquqlari va autentifikatsiya", "Cheklangan kirish huquqlari va autentifikatsiya": "Cheklangan kirish huquqlari va autentifikatsiya",
"Doimiy xavfsizlik monitoringi va yangilanishlar": "Doimiy xavfsizlik monitoringi va yangilanishlar", "Doimiy xavfsizlik monitoringi va yangilanishlar": "Doimiy xavfsizlik monitoringi va yangilanishlar",
"Ma'lumotlarni Ulashish": "4. Ma'lumotlarni Ulashish", "Ma'lumotlarni Ulashish": "4. Ma'lumotlarni Ulashish",
"Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz", "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz": "Biz sizning shaxsiy ma'lumotlaringizni uchinchi shaxslarga sotmaymiz",
"Sizning roziligingiz bilan": "Sizning roziligingiz bilan", "Sizning roziligingiz bilan": "Sizning roziligingiz bilan",
"Qonuniy talablar bo'yicha": "Qonuniy talablar bo'yicha", "Qonuniy talablar bo'yicha": "Qonuniy talablar bo'yicha",
"Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)", "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)": "Xizmat ko'rsatuvchi ishonchli hamkorlar bilan (maxfiylik shartnomalari ostida)",
"Kompaniya birlashuvi yoki sotilishi holatida": "Kompaniya birlashuvi yoki sotilishi holatida", "Kompaniya birlashuvi yoki sotilishi holatida": "Kompaniya birlashuvi yoki sotilishi holatida",
"Biz Bilan Bog'lanish": "Biz Bilan Bog'lanish", "Biz Bilan Bog'lanish": "Biz Bilan Bog'lanish",
"Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:", "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:": "Ushbu Maxfiylik Siyosati yoki shaxsiy ma'lumotlaringiz haqida savollaringiz bo'lsa, biz bilan bog'laning:",
"Telefon": "Telefon", "Telefon": "Telefon",
"Toshkent, O'zbekiston": "Toshkent, O'zbekiston", "Toshkent, O'zbekiston": "Toshkent, O'zbekiston",
"Manzil": "Manzil", "Manzil": "Manzil",
"Miqdor": "Miqdor", "Miqdor": "Miqdor",
"Jami": "Jami", "Jami": "Jami",
"Bepul yetkazib berish": "Bepul yetkazib berish", "Bepul yetkazib berish": "Bepul yetkazib berish",
@@ -95,25 +88,21 @@
"Ishlab chiqaruvchi": "Ishlab chiqaruvchi", "Ishlab chiqaruvchi": "Ishlab chiqaruvchi",
"Hajmi": "Hajmi", "Hajmi": "Hajmi",
"O'xshash mahsulotlar": "O'xshash mahsulotlar", "O'xshash mahsulotlar": "O'xshash mahsulotlar",
"Hech narsa topilmadi": "Hech narsa topilmadi", "Hech narsa topilmadi": "Hech narsa topilmadi",
"Qidiruv natijalari": "Qidiruv natijalari", "Qidiruv natijalari": "Qidiruv natijalari",
"Tavsiya etiladi": "Tavsiya etiladi", "Tavsiya etiladi": "Tavsiya etiladi",
"Yuklanmoqda": "Yuklanmoqda....", "Yuklanmoqda": "Yuklanmoqda....",
"Natija topilmadi": "Natija topilmadi", "Natija topilmadi": "Natija topilmadi",
"Asosiy": "Asosiy", "Asosiy": "Asosiy",
"Katalog": "Katalog", "Katalog": "Katalog",
"Sevimli": "Sevimli", "Sevimli": "Sevimli",
"Savatda": "Savatda", "Savatda": "Savatda",
"Profil": "Profil", "Profil": "Profil",
"Username yoki parol xato kiritildi": "Username yoki parol xato kiritildi", "Username yoki parol xato kiritildi": "Username yoki parol xato kiritildi",
"Tizimga kirish": "Tizimga kirish", "Tizimga kirish": "Tizimga kirish",
"Username": "Username", "Username": "Username",
"Parol": "Parol", "Parol": "Parol",
"Kirish": "Kirish", "Kirish": "Kirish",
"Savatingiz bo'sh": "Savatingiz bo'sh", "Savatingiz bo'sh": "Savatingiz bo'sh",
"Mahsulotlar qo'shish uchun katalogga o'ting": "Mahsulotlar qo'shish uchun katalogga o'ting", "Mahsulotlar qo'shish uchun katalogga o'ting": "Mahsulotlar qo'shish uchun katalogga o'ting",
"Xarid qilishni boshlash": "Xarid qilishni boshlash", "Xarid qilishni boshlash": "Xarid qilishni boshlash",
@@ -128,7 +117,6 @@
"Xaridni davom ettirish": "Xaridni davom ettirish", "Xaridni davom ettirish": "Xaridni davom ettirish",
"Tez yetkazib berish 1-2 kun ichida": "Tez yetkazib berish 1-2 kun ichida", "Tez yetkazib berish 1-2 kun ichida": "Tez yetkazib berish 1-2 kun ichida",
"Xavfsiz to'lov usullari": "Xavfsiz to'lov usullari", "Xavfsiz to'lov usullari": "Xavfsiz to'lov usullari",
"Buyurtma qabul qilindi!": "Buyurtma qabul qilindi!", "Buyurtma qabul qilindi!": "Buyurtma qabul qilindi!",
"Buyurtma raqami": "Buyurtma raqami", "Buyurtma raqami": "Buyurtma raqami",
"Buyurtmangiz muvaffaqiyatli qabul qilindi": "Buyurtmangiz muvaffaqiyatli qabul qilindi.", "Buyurtmangiz muvaffaqiyatli qabul qilindi": "Buyurtmangiz muvaffaqiyatli qabul qilindi.",
@@ -173,7 +161,6 @@
"Sevimlilar bo'sh": "Sevimlilar bo'sh", "Sevimlilar bo'sh": "Sevimlilar bo'sh",
"Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz. Mahsulotlar ro'yxatiga o'ting va yoqqan mahsulotlaringizni saqlang.", "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz": "Hali hech qanday mahsulotni sevimlilarga qo'shmadingiz. Mahsulotlar ro'yxatiga o'ting va yoqqan mahsulotlaringizni saqlang.",
"Sevimli mahsulotlar": "Sevimli mahsulotlar", "Sevimli mahsulotlar": "Sevimli mahsulotlar",
"Faol buyurtmalar": "Faol buyurtmalar", "Faol buyurtmalar": "Faol buyurtmalar",
"Barchasi": "Barchasi", "Barchasi": "Barchasi",
"Buyurtmalar tarixi": "Buyurtmalar tarixi", "Buyurtmalar tarixi": "Buyurtmalar tarixi",
@@ -182,7 +169,6 @@
"Umumiy": "Umumiy", "Umumiy": "Umumiy",
"Buyurtmalar": "Buyurtmalar", "Buyurtmalar": "Buyurtmalar",
"Tarix": "Tarix", "Tarix": "Tarix",
"Faol": "Faol", "Faol": "Faol",
"Tugadi": "Tugadi", "Tugadi": "Tugadi",
"Yetkazish": "Yetkazish", "Yetkazish": "Yetkazish",
@@ -196,10 +182,8 @@
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling", "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling": "Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling",
"Murojat qilish": "Murojat qilish", "Murojat qilish": "Murojat qilish",
"So'rov yuborildi!": "So'rov yuborildi!", "So'rov yuborildi!": "So'rov yuborildi!",
"Tez-tez So'raladigan Savollar": "Tez-tez So'raladigan Savollar", "Tez-tez So'raladigan Savollar": "Tez-tez So'raladigan Savollar",
"Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar", "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar": "Gastro Market haqida eng ko'p so'raladigan savollarga javoblar",
"Barcha mahsulotlar": "Barcha mahsulotlar", "Barcha mahsulotlar": "Barcha mahsulotlar",
"Xatolik yuz berdi: Mahsulot omborxonada yetarli emas": "Xatolik yuz berdi: Mahsulot omborxonada yetarli emas", "Xatolik yuz berdi: Mahsulot omborxonada yetarli emas": "Xatolik yuz berdi: Mahsulot omborxonada yetarli emas",
"Bu kategoriyada hozircha mahsulot yoq": "Bu kategoriyada hozircha mahsulot yoq", "Bu kategoriyada hozircha mahsulot yoq": "Bu kategoriyada hozircha mahsulot yoq",
@@ -208,7 +192,6 @@
"Kataloglar": "Kataloglar", "Kataloglar": "Kataloglar",
"Naqd bilan olinadi": "Naqd bilan olinadi", "Naqd bilan olinadi": "Naqd bilan olinadi",
"Pul o'tkazish yo'li bilan olinadi": "Pul o'tkazish yo'li bilan olinadi", "Pul o'tkazish yo'li bilan olinadi": "Pul o'tkazish yo'li bilan olinadi",
"Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin": "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin", "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin": "Diqqat! Mahsulot narxi o'zgargan bo'lishi mumkin",
"So'nggi yangilanish:": "So'nggi yangilanish", "So'nggi yangilanish:": "So'nggi yangilanish",
"only_available": "Faqat {maxBalance} dona mavjud", "only_available": "Faqat {maxBalance} dona mavjud",
@@ -221,5 +204,9 @@
"Qayta buyurtma": "Qayta buyurtma", "Qayta buyurtma": "Qayta buyurtma",
"Yangilangan": "Yangilangan", "Yangilangan": "Yangilangan",
"Narxi o'zgargan bo'lishi mumkin": "Narxi o'zgargan bo'lishi mumkin", "Narxi o'zgargan bo'lishi mumkin": "Narxi o'zgargan bo'lishi mumkin",
"ga yangilandi": "ga yangilandi" "ga yangilandi": "ga yangilandi",
} "Izoh 300 ta belgidan oshmasligi kerak": "Izoh 300 ta belgidan oshmasligi kerak",
"Xatolik yuz berdi: Foydalanuvchi topilmadi": "Xatolik yuz berdi: Foydalanuvchi topilmadi",
"Izoh 300ta belgidan oshib ketdi": "Izoh 300ta belgidan oshib ketdi",
"Izoh kamida 1ta belgi bo'lishi kerak": "Izoh kamida 1ta belgi bo'lishi kerak"
}

View File

@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
<textarea <textarea
data-slot="textarea" data-slot="textarea"
className={cn( className={cn(
'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', 'border-input placeholder:text-muted-foreground aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
className, className,
)} )}
{...props} {...props}

View File

@@ -173,7 +173,8 @@ export function ProductCard({
mutationFn: (productId: string) => product_api.favourite(productId), mutationFn: (productId: string) => product_api.favourite(productId),
onSuccess: () => { onSuccess: () => {
queryClient.refetchQueries({ queryKey: ['product_list'] }); queryClient.refetchQueries({ queryKey: ['list'] });
queryClient.refetchQueries({ queryKey: ['all_products'] });
queryClient.refetchQueries({ queryKey: ['favourite_product'] }); queryClient.refetchQueries({ queryKey: ['favourite_product'] });
}, },

View File

@@ -10,7 +10,12 @@ import {
} from '@/shared/ui/dropdown-menu'; } from '@/shared/ui/dropdown-menu';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import Image from 'next/image'; import Image from 'next/image';
import { useParams, usePathname, useRouter } from 'next/navigation'; import {
useParams,
usePathname,
useRouter,
useSearchParams,
} from 'next/navigation';
import { languages } from '../lib/data'; import { languages } from '../lib/data';
export function ChangeLang() { export function ChangeLang() {
@@ -18,12 +23,16 @@ export function ChangeLang() {
const pathname = usePathname(); const pathname = usePathname();
const router = useRouter(); const router = useRouter();
const t = useTranslations(); const t = useTranslations();
const searchParams = useSearchParams();
const changeLocale = (locale: LanguageRoutes) => { const changeLocale = (locale: LanguageRoutes) => {
const segments = pathname.split('/'); const segments = pathname.split('/');
segments[1] = locale; segments[1] = locale;
const newPath = segments.join('/'); const newPath = segments.join('/');
router.push(newPath); const query = searchParams.toString();
router.push(query ? `${newPath}?${query}` : newPath);
}; };
return ( return (