bug fixed
This commit is contained in:
@@ -29,16 +29,13 @@ export async function generateMetadata({
|
|||||||
res.data.short_name || `Gastro Market mahsuloti: ${res.data.name}`,
|
res.data.short_name || `Gastro Market mahsuloti: ${res.data.name}`,
|
||||||
type: 'website',
|
type: 'website',
|
||||||
images: [
|
images: [
|
||||||
{
|
res.data.images && res.data.images.length > 0
|
||||||
url:
|
? {
|
||||||
res.data.images && res.data.images.length > 0
|
url: res.data.images[0].image?.includes(BASE_URL)
|
||||||
? res.data.images[0].image.includes(BASE_URL)
|
|
||||||
? res.data.images[0].image
|
? res.data.images[0].image
|
||||||
: BASE_URL + res.data.images[0].image
|
: BASE_URL + res.data.images[0].image,
|
||||||
: '/placeholder.svg',
|
}
|
||||||
width: 800,
|
: { url: '/placeholder.svg' },
|
||||||
height: 600,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
@@ -46,14 +43,15 @@ export async function generateMetadata({
|
|||||||
title: `${res.data.name} - Gastro Market`,
|
title: `${res.data.name} - Gastro Market`,
|
||||||
description:
|
description:
|
||||||
res.data.short_name || `Gastro Market mahsuloti: ${res.data.name}`,
|
res.data.short_name || `Gastro Market mahsuloti: ${res.data.name}`,
|
||||||
images:
|
images: [
|
||||||
res.data.images && res.data.images.length > 0
|
res.data.images && res.data.images.length > 0
|
||||||
? [
|
? {
|
||||||
res.data.images[0].image.includes(BASE_URL)
|
url: res.data.images[0].image?.includes(BASE_URL)
|
||||||
? res.data.images[0].image
|
? res.data.images[0].image
|
||||||
: BASE_URL + res.data.images[0].image,
|
: BASE_URL + res.data.images[0].image,
|
||||||
]
|
}
|
||||||
: ['/placeholder.svg'],
|
: { url: '/placeholder.svg' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -289,11 +289,11 @@ const OrderPage = () => {
|
|||||||
{
|
{
|
||||||
filial_code: 'dodge',
|
filial_code: 'dodge',
|
||||||
delivery_date: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
delivery_date: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
||||||
room_code: '100',
|
room_code: process.env.NEXT_ROOM_CODE!,
|
||||||
deal_time: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
deal_time: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
||||||
robot_code: 'r2',
|
robot_code: process.env.NEXT_ROBOT_CODE!,
|
||||||
status: 'B#N',
|
status: 'B#N',
|
||||||
sales_manager_code: '1',
|
sales_manager_code: process.env.NEXT_SALES_MANAGER_CODE!,
|
||||||
person_code: user?.username,
|
person_code: user?.username,
|
||||||
currency_code: '860',
|
currency_code: '860',
|
||||||
owner_person_code: user?.username,
|
owner_person_code: user?.username,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
import CategoryImage from '@/assets/water-bottle.png';
|
||||||
import { category_api } from '@/shared/config/api/category/api';
|
import { category_api } from '@/shared/config/api/category/api';
|
||||||
import { BASE_URL } from '@/shared/config/api/URLs';
|
import { BASE_URL } from '@/shared/config/api/URLs';
|
||||||
import { Link } from '@/shared/config/i18n/navigation';
|
import { Link } from '@/shared/config/i18n/navigation';
|
||||||
@@ -34,7 +35,11 @@ const Category = () => {
|
|||||||
>
|
>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<Image
|
<Image
|
||||||
src={BASE_URL + category.image}
|
src={
|
||||||
|
category.image === null
|
||||||
|
? CategoryImage
|
||||||
|
: BASE_URL + category.image
|
||||||
|
}
|
||||||
alt={category.name}
|
alt={category.name}
|
||||||
width={70}
|
width={70}
|
||||||
unoptimized
|
unoptimized
|
||||||
|
|||||||
@@ -56,9 +56,11 @@ const ProductDetail = () => {
|
|||||||
select: (res) => res.data.results,
|
select: (res) => res.data.results,
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ---------------- PRICE ---------------- */
|
/* ---------------- DERIVED DATA ---------------- */
|
||||||
const price = Number(data?.prices?.[0]?.price || 0);
|
const price = Number(data?.prices?.[0]?.price || 0);
|
||||||
|
|
||||||
|
const category = 'Ichimliklar'; // default category
|
||||||
|
|
||||||
/* ---------------- SYNC CART QUANTITY ---------------- */
|
/* ---------------- SYNC CART QUANTITY ---------------- */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data || !cartItems) return;
|
if (!data || !cartItems) return;
|
||||||
@@ -103,8 +105,8 @@ const ProductDetail = () => {
|
|||||||
toast.success(t("Mahsulot savatga qo'shildi"), { richColors: true });
|
toast.success(t("Mahsulot savatga qo'shildi"), { richColors: true });
|
||||||
},
|
},
|
||||||
onError: (err: AxiosError) => {
|
onError: (err: AxiosError) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const msg =
|
||||||
const msg = (err.response?.data as any)?.detail || err.message;
|
(err.response?.data as { detail: string })?.detail || err.message;
|
||||||
toast.error(msg, { richColors: true });
|
toast.error(msg, { richColors: true });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -124,6 +126,12 @@ const ProductDetail = () => {
|
|||||||
queryClient.invalidateQueries({ queryKey: ['product_detail'] });
|
queryClient.invalidateQueries({ queryKey: ['product_detail'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['product_list'] });
|
queryClient.invalidateQueries({ queryKey: ['product_list'] });
|
||||||
},
|
},
|
||||||
|
onError: () => {
|
||||||
|
toast.error(t('Tizimga kirilmagan'), {
|
||||||
|
richColors: true,
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ---------------- HANDLERS ---------------- */
|
/* ---------------- HANDLERS ---------------- */
|
||||||
@@ -168,20 +176,20 @@ const ProductDetail = () => {
|
|||||||
unoptimized
|
unoptimized
|
||||||
height={500}
|
height={500}
|
||||||
src={
|
src={
|
||||||
data && data?.images?.length !== 0
|
data?.images?.length
|
||||||
? BASE_URL + data.images[selectedImage]?.image
|
? BASE_URL + data.images[selectedImage]?.image
|
||||||
: data?.images[selectedImage]?.image
|
: '/placeholder.svg'
|
||||||
? BASE_URL + data.images[selectedImage]?.image
|
|
||||||
: '/placeholder.svg'
|
|
||||||
}
|
}
|
||||||
alt={data?.name || 'logo'}
|
alt={data?.name || 'logo'}
|
||||||
className="w-full h-[400px] object-contain"
|
className="w-full h-[400px] object-contain"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Carousel className="mt-4">
|
<Carousel className="mt-4">
|
||||||
<CarouselContent>
|
<CarouselContent>
|
||||||
{data?.images?.map((img, i) => (
|
{(data?.images?.length
|
||||||
<CarouselItem key={img.id} className="basis-1/4">
|
? data.images
|
||||||
|
: [{ id: 0, image: '/placeholder.svg' }]
|
||||||
|
).map((img, i) => (
|
||||||
|
<CarouselItem key={i} className="basis-1/4">
|
||||||
<button
|
<button
|
||||||
onClick={() => setSelectedImage(i)}
|
onClick={() => setSelectedImage(i)}
|
||||||
className={`border rounded-lg p-1 ${
|
className={`border rounded-lg p-1 ${
|
||||||
@@ -191,12 +199,12 @@ const ProductDetail = () => {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={BASE_URL + img.image}
|
src={img.image!}
|
||||||
alt=""
|
alt={data?.name || 'Mahsulot rasmi'}
|
||||||
unoptimized
|
|
||||||
width={120}
|
width={120}
|
||||||
height={120}
|
height={120}
|
||||||
className="object-contain"
|
className="object-contain"
|
||||||
|
unoptimized
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</CarouselItem>
|
</CarouselItem>
|
||||||
@@ -215,7 +223,13 @@ const ProductDetail = () => {
|
|||||||
|
|
||||||
<p className="text-gray-600 mb-6">{data?.short_name}</p>
|
<p className="text-gray-600 mb-6">{data?.short_name}</p>
|
||||||
|
|
||||||
{/* QUANTITY */}
|
<div className="grid grid-cols-2 gap-4 mb-6">
|
||||||
|
<div>
|
||||||
|
<span className="text-gray-500">Kategoriya:</span>
|
||||||
|
<p className="font-semibold">{category}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-4 mb-6">
|
<div className="flex items-center gap-4 mb-6">
|
||||||
<button
|
<button
|
||||||
onClick={() => setQuantity((q) => Math.max(1, q - 1))}
|
onClick={() => setQuantity((q) => Math.max(1, q - 1))}
|
||||||
@@ -246,7 +260,7 @@ const ProductDetail = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ACTIONS */}
|
{/* ACTIONS */}
|
||||||
<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"
|
||||||
@@ -256,7 +270,7 @@ const ProductDetail = () => {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => favouriteMutation.mutate(product)}
|
onClick={() => favouriteMutation.mutate(String(data?.id))}
|
||||||
className={`p-3 rounded-lg border ${
|
className={`p-3 rounded-lg border ${
|
||||||
data?.liked ? 'border-red-500 bg-red-50' : 'border-gray-300'
|
data?.liked ? 'border-red-500 bg-red-50' : 'border-gray-300'
|
||||||
}`}
|
}`}
|
||||||
|
|||||||
@@ -73,14 +73,14 @@ const Profile = () => {
|
|||||||
<Avatar className="w-14 h-14 ring-2 ring-emerald-500 ring-offset-2 flex items-center justify-center">
|
<Avatar className="w-14 h-14 ring-2 ring-emerald-500 ring-offset-2 flex items-center justify-center">
|
||||||
<AvatarImage />
|
<AvatarImage />
|
||||||
<AvatarFallback className="text-muted-foreground font-semibold">
|
<AvatarFallback className="text-muted-foreground font-semibold">
|
||||||
{user?.username.slice(0, 1).toUpperCase()}
|
{user?.first_name.slice(0, 1).toUpperCase()}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-lg text-muted-foreground font-medium">
|
<p className="text-lg text-muted-foreground font-medium">
|
||||||
{user &&
|
{user &&
|
||||||
user.username.charAt(0).toUpperCase() +
|
user.first_name.charAt(0).toUpperCase() +
|
||||||
user.username.slice(1)}
|
user.first_name.slice(1)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,14 +129,14 @@ const Profile = () => {
|
|||||||
<Avatar className="w-10 h-10 md:w-12 md:h-12 ring-2 ring-emerald-500 ring-offset-2">
|
<Avatar className="w-10 h-10 md:w-12 md:h-12 ring-2 ring-emerald-500 ring-offset-2">
|
||||||
<AvatarImage />
|
<AvatarImage />
|
||||||
<AvatarFallback className="text-muted-foreground font-semibold">
|
<AvatarFallback className="text-muted-foreground font-semibold">
|
||||||
{user?.username?.slice(0, 1).toUpperCase()}
|
{user?.first_name?.slice(0, 1).toUpperCase()}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-md md:text-xl text-muted-foreground">
|
<p className="text-md md:text-xl text-muted-foreground">
|
||||||
{user &&
|
{user &&
|
||||||
user.username.charAt(0).toUpperCase() +
|
user.first_name.charAt(0).toUpperCase() +
|
||||||
user.username.slice(1)}
|
user.first_name.slice(1)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ export interface Category {
|
|||||||
export interface CategoryResult {
|
export interface CategoryResult {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
image: string;
|
image: string | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ export interface ProductListResult {
|
|||||||
|
|
||||||
export interface ProductDetail {
|
export interface ProductDetail {
|
||||||
id: number;
|
id: number;
|
||||||
images: { id: number; image: string }[];
|
images: { id: number; image: string | null }[];
|
||||||
liked: boolean;
|
liked: boolean;
|
||||||
meansurement: null | string;
|
meansurement: null | { id: number; name: string };
|
||||||
inventory_id: null | string;
|
inventory_id: null | string;
|
||||||
product_id: string;
|
product_id: string;
|
||||||
code: string;
|
code: string;
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ export function ProductCard({
|
|||||||
<span className="text-lg sm:text-xl font-bold text-green-600">
|
<span className="text-lg sm:text-xl font-bold text-green-600">
|
||||||
{formatPrice(
|
{formatPrice(
|
||||||
Math.max(...product.prices.map((p) => Number(p.price))),
|
Math.max(...product.prices.map((p) => Number(p.price))),
|
||||||
|
true,
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const NavbarMobile = () => {
|
|||||||
isActive && 'text-green-500',
|
isActive && 'text-green-500',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="relative w-full flex justify-center items-center">
|
<div className="relative w-fit flex justify-center items-center ">
|
||||||
<item.icon
|
<item.icon
|
||||||
className={cn(
|
className={cn(
|
||||||
'size-6 transition-colors',
|
'size-6 transition-colors',
|
||||||
@@ -82,7 +82,7 @@ const NavbarMobile = () => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{item.href === '/cart' && (
|
{item.href === '/cart' && (
|
||||||
<Badge className="absolute -top-2 right-2 line-clamp-1 w-5 h-5 flex justify-center items-center">
|
<Badge className="absolute -top-2.5 -right-2.5 line-clamp-1 w-5 h-5 flex justify-center items-center">
|
||||||
{cartQuenty === 9 ? cartQuenty + '+' : cartQuenty}
|
{cartQuenty === 9 ? cartQuenty + '+' : cartQuenty}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { CategoryCarousel } from '@/widgets/categories/ui/category-carousel';
|
|||||||
import { ProductCard } from '@/widgets/categories/ui/product-card';
|
import { ProductCard } from '@/widgets/categories/ui/product-card';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { AlertCircle, ChevronLeft, ChevronRight } from 'lucide-react';
|
import { AlertCircle, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import 'swiper/css';
|
import 'swiper/css';
|
||||||
@@ -32,6 +33,7 @@ const Welcome = () => {
|
|||||||
const [canScrollNext, setCanScrollNext] = useState(false);
|
const [canScrollNext, setCanScrollNext] = useState(false);
|
||||||
const [apiCat, setApiCat] = useState<CarouselApi>();
|
const [apiCat, setApiCat] = useState<CarouselApi>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
const { data, isLoading, isError } = useQuery({
|
const { data, isLoading, isError } = useQuery({
|
||||||
queryKey: ['banner_list'],
|
queryKey: ['banner_list'],
|
||||||
@@ -225,7 +227,7 @@ const Welcome = () => {
|
|||||||
onClick={() => router.push(`/all-product/`)}
|
onClick={() => router.push(`/all-product/`)}
|
||||||
>
|
>
|
||||||
<h2 className="text-2xl font-bold text-slate-800 group-hover:text-blue-600 transition-colors">
|
<h2 className="text-2xl font-bold text-slate-800 group-hover:text-blue-600 transition-colors">
|
||||||
Barcha mahsulotlar
|
{t('Barcha mahsulotlar')}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="p-1.5 bg-slate-100 rounded-full group-hover:bg-blue-100 transition-all">
|
<div className="p-1.5 bg-slate-100 rounded-full group-hover:bg-blue-100 transition-all">
|
||||||
<ChevronRight className="text-slate-600 group-hover:text-blue-600 group-hover:translate-x-0.5 transition-all" />
|
<ChevronRight className="text-slate-600 group-hover:text-blue-600 group-hover:translate-x-0.5 transition-all" />
|
||||||
|
|||||||
Reference in New Issue
Block a user