complated order
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import Product from '@/features/category/ui/Product';
|
import SubCategory from '@/features/category/ui/SubCategory';
|
||||||
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 { Metadata } from 'next';
|
import { Metadata } from 'next';
|
||||||
@@ -13,7 +13,7 @@ interface Params {
|
|||||||
const fetchCategory = async (categoryId: string) => {
|
const fetchCategory = async (categoryId: string) => {
|
||||||
try {
|
try {
|
||||||
const res = await category_api.getCategory({ page: 1, page_size: 99 });
|
const res = await category_api.getCategory({ page: 1, page_size: 99 });
|
||||||
return res.data.results.find((c) => c.id.toString() === categoryId);
|
return res.data.find((c) => c.id.toString() === categoryId);
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ export async function generateMetadata({ params }: Params): Promise<Metadata> {
|
|||||||
const Page = () => {
|
const Page = () => {
|
||||||
return (
|
return (
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<Product />
|
<SubCategory />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Suspense } from 'react';
|
|||||||
const fetchCategoryData = async () => {
|
const fetchCategoryData = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await category_api.getCategory({ page: 1, page_size: 99 });
|
const res = await category_api.getCategory({ page: 1, page_size: 99 });
|
||||||
return res.data.results;
|
return res.data;
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,9 @@ const CartPage = () => {
|
|||||||
<Image
|
<Image
|
||||||
src={
|
src={
|
||||||
item.product.images.length > 0
|
item.product.images.length > 0
|
||||||
? BASE_URL + item.product.images[0].image
|
? item.product.images[0].image.includes(BASE_URL)
|
||||||
|
? item.product.images[0].image
|
||||||
|
: BASE_URL + item.product.images[0].image
|
||||||
: ProductBanner
|
: ProductBanner
|
||||||
}
|
}
|
||||||
alt={item.product.name}
|
alt={item.product.name}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ 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 {
|
||||||
@@ -106,20 +105,17 @@ const OrderPage = () => {
|
|||||||
|
|
||||||
queryClinet.refetchQueries({ queryKey: ['cart_items'] });
|
queryClinet.refetchQueries({ queryKey: ['cart_items'] });
|
||||||
} else {
|
} else {
|
||||||
toast.error(t('Xatolik yuz berdi'), {
|
toast.error(t('Xatolik yuz berdi: Mahsulot omborxonada yetarli emas'), {
|
||||||
richColors: true,
|
richColors: true,
|
||||||
position: 'top-center',
|
position: 'top-center',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (error: AxiosError) => {
|
onError: () => {
|
||||||
(
|
toast.error(t('Xatolik yuz berdi: Mahsulot omborxoda yetarli emas'), {
|
||||||
error.response?.data as { items: { non_field_errors: string[] }[] }
|
richColors: true,
|
||||||
).items
|
position: 'top-center',
|
||||||
?.flatMap((i) => i.non_field_errors || [])
|
});
|
||||||
.forEach((msg: string) =>
|
|
||||||
toast.error(msg, { richColors: true, position: 'top-center' }),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -281,19 +277,19 @@ const OrderPage = () => {
|
|||||||
order_quant: item.quantity,
|
order_quant: item.quantity,
|
||||||
price_type_code: item.product.prices![0].price_type.code,
|
price_type_code: item.product.prices![0].price_type.code,
|
||||||
product_price: item.product.prices![0].price,
|
product_price: item.product.prices![0].price,
|
||||||
warehouse_code: 'wh1',
|
warehouse_code: process.env.NEXT_PUBLIC_WARHOUSES_CODE!,
|
||||||
}));
|
}));
|
||||||
if (user) {
|
if (user) {
|
||||||
mutate({
|
mutate({
|
||||||
order: [
|
order: [
|
||||||
{
|
{
|
||||||
filial_code: process.env.NEXT_FILIAL_CODE!,
|
filial_code: process.env.NEXT_PUBLIC_FILIAL_CODE!,
|
||||||
delivery_date: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
delivery_date: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
||||||
room_code: process.env.NEXT_ROOM_CODE!,
|
room_code: process.env.NEXT_PUBLIC_ROOM_CODE!,
|
||||||
deal_time: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
deal_time: formatDate.format(deliveryDate, 'DD.MM.YYYY'),
|
||||||
robot_code: process.env.NEXT_ROBOT_CODE!,
|
robot_code: process.env.NEXT_PUBLIC_ROBOT_CODE!,
|
||||||
status: 'B#N',
|
status: 'B#N',
|
||||||
sales_manager_code: process.env.NEXT_SALES_MANAGER_CODE!,
|
sales_manager_code: process.env.NEXT_PUBLIC_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,
|
||||||
@@ -565,7 +561,9 @@ const OrderPage = () => {
|
|||||||
unoptimized
|
unoptimized
|
||||||
src={
|
src={
|
||||||
item.product.images.length !== 0
|
item.product.images.length !== 0
|
||||||
? BASE_URL + item.product.images[0].image
|
? item.product.images[0].image.includes(BASE_URL)
|
||||||
|
? item.product.images[0].image
|
||||||
|
: BASE_URL + item.product.images[0].image
|
||||||
: LogosProduct
|
: LogosProduct
|
||||||
}
|
}
|
||||||
alt={item.product.name}
|
alt={item.product.name}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const Category = () => {
|
|||||||
queryKey: ['category_list'],
|
queryKey: ['category_list'],
|
||||||
queryFn: () => category_api.getCategory({ page: 1, page_size: 99 }),
|
queryFn: () => category_api.getCategory({ page: 1, page_size: 99 }),
|
||||||
select(data) {
|
select(data) {
|
||||||
return data.data.results;
|
return data.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { useEffect, useState } from 'react';
|
|||||||
const PAGE_SIZE = 36;
|
const PAGE_SIZE = 36;
|
||||||
|
|
||||||
const Product = () => {
|
const Product = () => {
|
||||||
const { categoryId } = useParams();
|
const { subId } = useParams();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
@@ -32,18 +33,19 @@ const Product = () => {
|
|||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ['product_list', categoryId, page],
|
queryKey: ['product_list', subId, page],
|
||||||
queryFn: () => {
|
queryFn: () => {
|
||||||
if (!categoryId) throw new Error('Category ID is required');
|
if (!subId) throw new Error('Category ID is required');
|
||||||
return product_api.listGetCategoryId({
|
return product_api.list({
|
||||||
category_id: categoryId.toString(),
|
page,
|
||||||
params: { page, page_size: PAGE_SIZE },
|
page_size: PAGE_SIZE,
|
||||||
|
product_type_id: Number(subId),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
select(data) {
|
select(data) {
|
||||||
return data.data;
|
return data.data;
|
||||||
},
|
},
|
||||||
enabled: !!categoryId,
|
enabled: !!subId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
|
|||||||
@@ -1,30 +1,43 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { category_api } from '@/shared/config/api/category/api';
|
||||||
import { useRouter } from '@/shared/config/i18n/navigation';
|
import { useRouter } from '@/shared/config/i18n/navigation';
|
||||||
import { categoryList } from '@/widgets/welcome/lib/data';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { ChevronRight } from 'lucide-react';
|
import { ChevronRight } from 'lucide-react';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
|
|
||||||
const SubCategory = () => {
|
const SubCategory = () => {
|
||||||
const { categoryId } = useParams();
|
const { categoryId } = useParams();
|
||||||
|
|
||||||
const router = useRouter();
|
const { data: category } = useQuery({
|
||||||
const category =
|
queryKey: ['category_list'],
|
||||||
categoryList.find((cat) => cat.name === categoryId) || categoryList[0];
|
queryFn: () => category_api.getCategory({ page: 1, page_size: 99 }),
|
||||||
|
select(data) {
|
||||||
|
return data.data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const handleSubCategoryClick = (subCategory: { name: string }) => {
|
const router = useRouter();
|
||||||
router.push(`/category/${categoryId}/${subCategory.name}`);
|
const categorys = category?.find((cat) => cat.id === Number(categoryId));
|
||||||
|
|
||||||
|
const handleSubCategoryClick = (subCategory: {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
}) => {
|
||||||
|
router.push(`/category/${categoryId}/${subCategory.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(categorys);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="custom-container">
|
<div className="custom-container">
|
||||||
<>
|
<>
|
||||||
<h1 className="text-2xl font-semibold text-gray-900 mb-6">
|
<h1 className="text-2xl font-semibold text-gray-900 mb-6">
|
||||||
{category.name}
|
{categorys?.name}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||||
{category.subCategories.map((subCategory, index) => (
|
{categorys?.product_types.map((subCategory, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => handleSubCategoryClick(subCategory)}
|
onClick={() => handleSubCategoryClick(subCategory)}
|
||||||
|
|||||||
@@ -175,7 +175,9 @@ const ProductDetail = () => {
|
|||||||
height={500}
|
height={500}
|
||||||
src={
|
src={
|
||||||
data?.images?.length
|
data?.images?.length
|
||||||
? BASE_URL + data.images[selectedImage]?.image
|
? data.images[selectedImage]?.image?.includes(BASE_URL)
|
||||||
|
? data.images[selectedImage]?.image
|
||||||
|
: BASE_URL + data.images[selectedImage]?.image
|
||||||
: '/placeholder.svg'
|
: '/placeholder.svg'
|
||||||
}
|
}
|
||||||
alt={data?.name || 'logo'}
|
alt={data?.name || 'logo'}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
import httpClient from '../httpClient';
|
import httpClient from '../httpClient';
|
||||||
import { API_URLS } from '../URLs';
|
import { API_URLS } from '../URLs';
|
||||||
import { Category } from './type';
|
import { CategoryResult } from './type';
|
||||||
|
|
||||||
export const category_api = {
|
export const category_api = {
|
||||||
async getCategory(params: {
|
async getCategory(params: {
|
||||||
page: number;
|
page: number;
|
||||||
page_size: number;
|
page_size: number;
|
||||||
}): Promise<AxiosResponse<Category>> {
|
}): Promise<AxiosResponse<CategoryResult[]>> {
|
||||||
const res = await httpClient.get(API_URLS.Category, { params });
|
const res = await httpClient.get(API_URLS.Category, { params });
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ export interface Category {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CategoryResult {
|
export interface CategoryResult {
|
||||||
id: string;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
image: string | null;
|
image: string | null;
|
||||||
|
product_types: ProductTypes[];
|
||||||
|
}
|
||||||
|
export interface ProductTypes {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ export const product_api = {
|
|||||||
async list(params: {
|
async list(params: {
|
||||||
page: number;
|
page: number;
|
||||||
page_size: number;
|
page_size: number;
|
||||||
|
product_type_id?: number;
|
||||||
|
category_id?: number;
|
||||||
}): Promise<AxiosResponse<ProductList>> {
|
}): Promise<AxiosResponse<ProductList>> {
|
||||||
const res = await httpClient.get(`${API_URLS.Product}list/`, { params });
|
const res = await httpClient.get(`${API_URLS.Product}list/`, { params });
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -204,5 +204,8 @@
|
|||||||
"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": "Произошла ошибка: недостаточно товаров на складе",
|
||||||
|
"Bu kategoriyada hozircha mahsulot yo‘q": "В этой категории пока нет товаров",
|
||||||
|
"Tez orada qo‘shiladi": "Скоро будет добавлено"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,5 +204,8 @@ declare const messages: {
|
|||||||
"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';
|
||||||
|
'Bu kategoriyada hozircha mahsulot yo‘q': 'Bu kategoriyada hozircha mahsulot yo‘q';
|
||||||
|
'Tez orada qo‘shiladi': 'Tez orada qo‘shiladi';
|
||||||
};
|
};
|
||||||
export default messages;
|
export default messages;
|
||||||
|
|||||||
@@ -200,5 +200,8 @@
|
|||||||
"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",
|
||||||
|
"Bu kategoriyada hozircha mahsulot yo‘q": "Bu kategoriyada hozircha mahsulot yo‘q",
|
||||||
|
"Tez orada qo‘shiladi": "Tez orada qo‘shiladi"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { CategoryResult } from '@/shared/config/api/category/type';
|
import { ProductTypes } from '@/shared/config/api/category/type';
|
||||||
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 { cn } from '@/shared/lib/utils';
|
import { cn } from '@/shared/lib/utils';
|
||||||
@@ -18,7 +18,7 @@ import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { ProductCard } from './product-card';
|
import { ProductCard } from './product-card';
|
||||||
|
|
||||||
export function CategoryCarousel({ category }: { category: CategoryResult }) {
|
export function CategoryCarousel({ category }: { category: ProductTypes }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [api, setApi] = useState<CarouselApi>();
|
const [api, setApi] = useState<CarouselApi>();
|
||||||
const [canScrollPrev, setCanScrollPrev] = useState(false);
|
const [canScrollPrev, setCanScrollPrev] = useState(false);
|
||||||
@@ -57,9 +57,10 @@ export function CategoryCarousel({ category }: { category: CategoryResult }) {
|
|||||||
const { data: product, isLoading } = useQuery({
|
const { data: product, isLoading } = useQuery({
|
||||||
queryKey: ['product_list', category],
|
queryKey: ['product_list', category],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
product_api.listGetCategoryId({
|
product_api.list({
|
||||||
category_id: category.id,
|
page: 1,
|
||||||
params: { page: 1, page_size: 16 },
|
page_size: 16,
|
||||||
|
product_type_id: category.id,
|
||||||
}),
|
}),
|
||||||
select(data) {
|
select(data) {
|
||||||
return data.data;
|
return data.data;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const Footer = () => {
|
|||||||
queryKey: ['category_list'],
|
queryKey: ['category_list'],
|
||||||
queryFn: () => category_api.getCategory({ page: 1, page_size: 12 }),
|
queryFn: () => category_api.getCategory({ page: 1, page_size: 12 }),
|
||||||
select(data) {
|
select(data) {
|
||||||
return data.data.results;
|
return data.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { CategoryType } from '@/widgets/welcome/lib/data';
|
import { CategoryResult } from '@/shared/config/api/category/type';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
type Category = {
|
type Category = {
|
||||||
active: CategoryType | null;
|
active: CategoryResult | null;
|
||||||
openToolbar: boolean;
|
openToolbar: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Actions = {
|
type Actions = {
|
||||||
setActive: (active: CategoryType | null) => void;
|
setActive: (active: CategoryResult | null) => void;
|
||||||
setOpenToolbar: (openToolbar: boolean) => void;
|
setOpenToolbar: (openToolbar: boolean) => void;
|
||||||
setCloseToolbar: (openToolbar: boolean) => void;
|
setCloseToolbar: (openToolbar: boolean) => void;
|
||||||
};
|
};
|
||||||
@@ -15,7 +15,7 @@ type Actions = {
|
|||||||
const useCategoryActive = create<Category & Actions>((set) => ({
|
const useCategoryActive = create<Category & Actions>((set) => ({
|
||||||
active: null,
|
active: null,
|
||||||
openToolbar: false,
|
openToolbar: false,
|
||||||
setActive: (active: CategoryType | null) => set(() => ({ active })),
|
setActive: (active: CategoryResult | null) => set(() => ({ active })),
|
||||||
setOpenToolbar: () => set(() => ({ openToolbar: true })),
|
setOpenToolbar: () => set(() => ({ openToolbar: true })),
|
||||||
setCloseToolbar: () => set(() => ({ openToolbar: false })),
|
setCloseToolbar: () => set(() => ({ openToolbar: false })),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { cart_api } from '@/features/cart/lib/api';
|
import { cart_api } from '@/features/cart/lib/api';
|
||||||
|
import { category_api } from '@/shared/config/api/category/api';
|
||||||
import { Link, useRouter } from '@/shared/config/i18n/navigation';
|
import { Link, useRouter } from '@/shared/config/i18n/navigation';
|
||||||
import { useCartId } from '@/shared/hooks/cartId';
|
import { useCartId } from '@/shared/hooks/cartId';
|
||||||
import formatPhone from '@/shared/lib/formatPhone';
|
import formatPhone from '@/shared/lib/formatPhone';
|
||||||
@@ -18,7 +19,6 @@ import {
|
|||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from '@/shared/ui/sheet';
|
} from '@/shared/ui/sheet';
|
||||||
import { banner_api } from '@/widgets/welcome/lib/api';
|
import { banner_api } from '@/widgets/welcome/lib/api';
|
||||||
import { categoryList } from '@/widgets/welcome/lib/data';
|
|
||||||
import { userStore } from '@/widgets/welcome/lib/hook';
|
import { userStore } from '@/widgets/welcome/lib/hook';
|
||||||
import { PopoverTrigger } from '@radix-ui/react-popover';
|
import { PopoverTrigger } from '@radix-ui/react-popover';
|
||||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
Facebook,
|
Facebook,
|
||||||
Heart,
|
Heart,
|
||||||
Instagram,
|
Instagram,
|
||||||
|
LayoutGrid,
|
||||||
Mail,
|
Mail,
|
||||||
MenuIcon,
|
MenuIcon,
|
||||||
Phone,
|
Phone,
|
||||||
@@ -35,6 +36,7 @@ import {
|
|||||||
ShoppingCart,
|
ShoppingCart,
|
||||||
Twitter,
|
Twitter,
|
||||||
User,
|
User,
|
||||||
|
XIcon,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
@@ -69,6 +71,14 @@ const Navbar = () => {
|
|||||||
queryFn: () => banner_api.getMe(),
|
queryFn: () => banner_api.getMe(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: category } = useQuery({
|
||||||
|
queryKey: ['category_list'],
|
||||||
|
queryFn: () => category_api.getCategory({ page: 1, page_size: 99 }),
|
||||||
|
select(data) {
|
||||||
|
return data.data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (me) {
|
if (me) {
|
||||||
setUser(me.data);
|
setUser(me.data);
|
||||||
@@ -392,7 +402,7 @@ const Navbar = () => {
|
|||||||
</Sheet>
|
</Sheet>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 flex gap-3">
|
<div className="flex-1 flex gap-3">
|
||||||
{/* <Button
|
<Button
|
||||||
variant={'outline'}
|
variant={'outline'}
|
||||||
className="h-10 max-lg:hidden cursor-pointer"
|
className="h-10 max-lg:hidden cursor-pointer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -409,7 +419,7 @@ const Navbar = () => {
|
|||||||
<LayoutGrid className="size-4 text-foreground" />
|
<LayoutGrid className="size-4 text-foreground" />
|
||||||
)}
|
)}
|
||||||
<p className="text-foreground">Kataloglar</p>
|
<p className="text-foreground">Kataloglar</p>
|
||||||
</Button> */}
|
</Button>
|
||||||
|
|
||||||
<div className="relative w-full max-lg:hidden">
|
<div className="relative w-full max-lg:hidden">
|
||||||
<Input
|
<Input
|
||||||
@@ -483,12 +493,13 @@ const Navbar = () => {
|
|||||||
<div />
|
<div />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
className="w-[100vw] !p-0 h-[100vh] rounded-b-xl border-t-2 border-blue-500"
|
className="w-[100vw] !p-0 h-[100vh] rounded-b-xl"
|
||||||
onInteractOutside={() => setOpenToolbar(false)}
|
onInteractOutside={() => setOpenToolbar(false)}
|
||||||
>
|
>
|
||||||
<div className="flex h-[90vh]">
|
<div className="flex h-[90vh]">
|
||||||
<div className="border-r border-slate-200 w-[20%] py-3 flex flex-col gap-2 px-3 overflow-y-auto scrollbar-thin bg-slate-50">
|
<div className="border-r border-slate-200 w-[20%] py-3 flex flex-col gap-2 px-3 overflow-y-auto scrollbar-thin bg-slate-50">
|
||||||
{categoryList.map((e, index) => {
|
{category &&
|
||||||
|
category.map((e, index) => {
|
||||||
const isActive = active?.name === e.name;
|
const isActive = active?.name === e.name;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -503,19 +514,22 @@ const Navbar = () => {
|
|||||||
: 'hover:bg-slate-100 border border-transparent'
|
: 'hover:bg-slate-100 border border-transparent'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="flex gap-3 items-center">
|
<div className="flex gap-3 items-center min-w-0">
|
||||||
<div
|
<div className={`p-1.5 rounded-lg bg-white shrink-0`}>
|
||||||
className={`p-1.5 rounded-lg ${isActive ? 'bg-white' : 'bg-white'}`}
|
|
||||||
>
|
|
||||||
<Image
|
<Image
|
||||||
src={e.image || '/placeholder.svg'}
|
src={e.image || '/placeholder.svg'}
|
||||||
alt={e.name}
|
alt={e.name}
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
unoptimized
|
unoptimized
|
||||||
className="w-5 h-5 object-contain"
|
className="w-5 h-5 object-contain"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
className={`text-sm font-medium ${isActive ? 'text-blue-700' : 'text-slate-700'}`}
|
className={`text-sm font-medium truncate ${
|
||||||
|
isActive ? 'text-blue-700' : 'text-slate-700'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{e.name}
|
{e.name}
|
||||||
</p>
|
</p>
|
||||||
@@ -538,21 +552,30 @@ const Navbar = () => {
|
|||||||
{active?.name}
|
{active?.name}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
{active && active?.product_types?.length > 0 ? (
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="grid grid-cols-3 gap-4">
|
||||||
{active?.subCategories.map((sub, index) => (
|
{active.product_types.map((sub, index) => (
|
||||||
<Button
|
<Button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCloseToolbar(false);
|
setCloseToolbar(false);
|
||||||
router.push(`/category/${active.name}/${sub.name}`);
|
router.push(`/category/${active.id}/${sub.id}`);
|
||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="justify-start h-12 cursor-pointer border border-slate-200 hover:border-blue-400 hover:bg-blue-50 transition-all text-slate-700 hover:text-blue-700 font-medium rounded-xl bg-transparent"
|
className="justify-start h-12 border border-slate-200 hover:border-blue-400 hover:bg-blue-50 transition-all rounded-xl"
|
||||||
>
|
>
|
||||||
{sub.name}
|
{sub.name}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col items-center justify-center h-[50vh] text-slate-400">
|
||||||
|
<p className="text-lg font-medium">
|
||||||
|
{t('Bu kategoriyada hozircha mahsulot yo‘q')}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">{t('Tez orada qo‘shiladi')}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ const Welcome = () => {
|
|||||||
const [apiPro, setApiPro] = useState<CarouselApi>();
|
const [apiPro, setApiPro] = useState<CarouselApi>();
|
||||||
const [canScrollPrev, setCanScrollPrev] = useState(false);
|
const [canScrollPrev, setCanScrollPrev] = useState(false);
|
||||||
const [canScrollNext, setCanScrollNext] = useState(false);
|
const [canScrollNext, setCanScrollNext] = useState(false);
|
||||||
const [apiCat, setApiCat] = useState<CarouselApi>();
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@ const Welcome = () => {
|
|||||||
queryKey: ['category_list'],
|
queryKey: ['category_list'],
|
||||||
queryFn: () => category_api.getCategory({ page: 1, page_size: 99 }),
|
queryFn: () => category_api.getCategory({ page: 1, page_size: 99 }),
|
||||||
select(data) {
|
select(data) {
|
||||||
return data.data.results;
|
return data.data;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -89,10 +88,6 @@ const Welcome = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const scrollPrevCar = () => {
|
|
||||||
apiCat?.scrollPrev();
|
|
||||||
};
|
|
||||||
|
|
||||||
const scrollNext = () => {
|
const scrollNext = () => {
|
||||||
if (api?.canScrollNext()) {
|
if (api?.canScrollNext()) {
|
||||||
api?.scrollNext();
|
api?.scrollNext();
|
||||||
@@ -101,10 +96,6 @@ const Welcome = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const scrollNextCat = () => {
|
|
||||||
apiCat?.scrollNext();
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data: product, isLoading: productLoading } = useQuery({
|
const { data: product, isLoading: productLoading } = useQuery({
|
||||||
queryKey: ['list'],
|
queryKey: ['list'],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
@@ -172,7 +163,7 @@ const Welcome = () => {
|
|||||||
</CarouselContent>
|
</CarouselContent>
|
||||||
</Carousel>
|
</Carousel>
|
||||||
|
|
||||||
<Carousel className="w-full mt-5" setApi={setApiCat}>
|
<Carousel className="w-full mt-5">
|
||||||
<CarouselContent className="py-2 px-1 pr-[12%]">
|
<CarouselContent className="py-2 px-1 pr-[12%]">
|
||||||
{category &&
|
{category &&
|
||||||
category.map((banner, index) => (
|
category.map((banner, index) => (
|
||||||
@@ -200,24 +191,6 @@ const Welcome = () => {
|
|||||||
</CarouselItem>
|
</CarouselItem>
|
||||||
))}
|
))}
|
||||||
</CarouselContent>
|
</CarouselContent>
|
||||||
<Button
|
|
||||||
onClick={scrollNextCat}
|
|
||||||
className="absolute max-lg:w-8 max-lg:h-8 top-1/2 -translate-y-1/2 -right-2 cursor-pointer"
|
|
||||||
variant={'secondary'}
|
|
||||||
size={'icon'}
|
|
||||||
aria-label="next images"
|
|
||||||
>
|
|
||||||
<ChevronRight className="size-6 max-lg:size-6" />
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={scrollPrevCar}
|
|
||||||
className="absolute max-lg:w-8 max-lg:h-8 top-1/2 -translate-y-1/2 -left-2 cursor-pointer"
|
|
||||||
variant={'secondary'}
|
|
||||||
size={'icon'}
|
|
||||||
aria-label="prev images"
|
|
||||||
>
|
|
||||||
<ChevronLeft className="size-6 max-lg:size-6" />
|
|
||||||
</Button>
|
|
||||||
</Carousel>
|
</Carousel>
|
||||||
</div>
|
</div>
|
||||||
<section className="relative custom-container mt-5 justify-center items-center border-b border-slate-200">
|
<section className="relative custom-container mt-5 justify-center items-center border-b border-slate-200">
|
||||||
@@ -300,9 +273,11 @@ const Welcome = () => {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{category &&
|
{category &&
|
||||||
category
|
category.map((e) =>
|
||||||
.slice(0, 6)
|
e.product_types.map((c) => (
|
||||||
.map((e) => <CategoryCarousel category={e} key={e.id} />)}
|
<CategoryCarousel category={c} key={c.id} />
|
||||||
|
)),
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user