add catalog filter card
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import Catalog from "@/components/pages/home/blog/catalog";
|
||||
import { ProductBanner } from "@/components/pages/products";
|
||||
import { MainSubCategory } from "@/components/pages/subCategory";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="bg-[#1e1d1c] pb-30">
|
||||
<ProductBanner />
|
||||
<div className="max-w-300 mx-auto w-full pt-20">
|
||||
<Catalog />
|
||||
<MainSubCategory />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { ProductBanner, Products } from "@/components/pages/products";
|
||||
import FilterCatalog from "@/components/pages/products/filter/catalog/filterCatalog";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="bg-[#1e1d1c] pb-30">
|
||||
<ProductBanner />
|
||||
{/* <FilterCatalog /> */}
|
||||
<Products />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useTranslations } from "next-intl";
|
||||
export function ProductBanner() {
|
||||
const t = useTranslations();
|
||||
return (
|
||||
<section className="relative w-full h-[60vh] min-h-100 overflow-hidden pt-10">
|
||||
<section className="relative w-full min-[400px]:h-[60vh] h-[75vh] min-h-100 overflow-hidden pt-10">
|
||||
{/* Background Image */}
|
||||
<div
|
||||
className="absolute inset-0 z-0"
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function CatalogCard({
|
||||
};
|
||||
|
||||
const navigateLink = have_sub_category
|
||||
? `/${locale}/subCategory?category=${id}`
|
||||
? `/${locale}/catalog_page?category=${id}`
|
||||
: `/${locale}/products?category=${id}`;
|
||||
|
||||
return (
|
||||
|
||||
96
components/pages/products/filter/catalog/filterCatalog.tsx
Normal file
96
components/pages/products/filter/catalog/filterCatalog.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
"use client";
|
||||
import EmptyData from "@/components/EmptyData";
|
||||
import { CategoryType } from "@/lib/types";
|
||||
import httpClient from "@/request/api";
|
||||
import { getRouteLang } from "@/request/getLang";
|
||||
import { endPoints } from "@/request/links";
|
||||
import { useCategory } from "@/store/useCategory";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useEffect } from "react";
|
||||
import CatalogCardSkeletonSmall from "./loading";
|
||||
import Image from "next/image";
|
||||
import { ArrowUpRight } from "lucide-react";
|
||||
|
||||
export default function FilterCatalog() {
|
||||
const language = getRouteLang();
|
||||
const setCategory = useCategory((state) => state.setCategory);
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ["category", language],
|
||||
queryFn: () => httpClient(endPoints.category.all),
|
||||
select: (data): CategoryType[] => data?.data?.results,
|
||||
});
|
||||
useEffect(() => {
|
||||
console.log("product catalog data: ", data);
|
||||
}, [data]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{[...Array(3)].map((_, index) => (
|
||||
<CatalogCardSkeletonSmall key={index} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Ma'lumot yo'q holati
|
||||
if (!data || data.length === 0) {
|
||||
return (
|
||||
<EmptyData
|
||||
title="Katalog topilmadi"
|
||||
description="Hozircha kategoriyalar mavjud emas. Keyinroq qaytib keling."
|
||||
icon="shopping"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-200 w-full mx-auto space-x-5 px-5 flex items-center justify-around my-10 -mt-30 pb-5 relative z-20 sm:overflow-x-hidden overflow-x-scroll">
|
||||
{data?.map((item) => (
|
||||
<div
|
||||
onClick={() => setCategory(item)}
|
||||
className="shrink-0 group relative w-55 h-60 overflow-hidden rounded-2xl bg-[#17161679] border border-white/10 transition-all duration-500 hover:-translate-y-1 hover:border-red-700 cursor-pointer"
|
||||
>
|
||||
{/* Background glow effect */}
|
||||
<div className="absolute inset-0 bg-linear-to-t from-red-600/20 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
|
||||
{/* Decorative corner accent */}
|
||||
<div className="absolute top-0 right-0 w-16 h-16 bg-linear-to-br from-red-500/20 to-transparent rounded-bl-full opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
|
||||
{/* Content container */}
|
||||
<div className="relative h-full flex flex-col p-4">
|
||||
{/* Title section */}
|
||||
<div className="mb-3">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<h3 className="text-lg font-unbounded font-bold text-white leading-tight transition-colors duration-300">
|
||||
{item.name}
|
||||
</h3>
|
||||
|
||||
<div className="shrink-0 w-6 h-6 rounded-full bg-white/10 flex items-center justify-center group-hover:bg-red-500 transition-all duration-300 group-hover:scale-110">
|
||||
<ArrowUpRight
|
||||
className="w-3.5 h-3.5 text-white"
|
||||
strokeWidth={2.5}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image container */}
|
||||
<div className="relative flex-1 rounded-xl overflow-hidden bg-linear-to-br from-[#444242] to-gray-900/50 border border-white/5 group-hover:border-white/20 transition-all duration-500">
|
||||
<div className="absolute inset-0 bg-linear-to-t from-black/60 via-transparent to-transparent z-10" />
|
||||
|
||||
<div className="relative w-full h-full">
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={item.name}
|
||||
fill
|
||||
className="object-contain p-3 transition-transform duration-700 group-hover:scale-105"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
23
components/pages/products/filter/catalog/loading.tsx
Normal file
23
components/pages/products/filter/catalog/loading.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
// components/CatalogCardSkeletonSmall.tsx
|
||||
export default function CatalogCardSkeletonSmall() {
|
||||
return (
|
||||
<div className="relative w-50 h-87.5 overflow-hidden rounded-2xl bg-[#17161679] border border-white/10 animate-pulse">
|
||||
<div className="flex flex-col h-full p-4 gap-3">
|
||||
|
||||
{/* Title skeleton */}
|
||||
<div className="space-y-2">
|
||||
<div className="h-5 bg-white/10 rounded-md w-3/4" />
|
||||
<div className="h-5 bg-white/10 rounded-md w-1/2" />
|
||||
</div>
|
||||
|
||||
{/* Image skeleton */}
|
||||
<div className="flex-1 rounded-xl bg-linear-to-br from-[#444242] to-gray-900/50 border border-white/5 flex items-center justify-center">
|
||||
<div className="w-20 h-20 bg-white/5 rounded-lg" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Shimmer */}
|
||||
<div className="absolute inset-0 -translate-x-full animate-shimmer bg-linear-to-r from-transparent via-white/5 to-transparent" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -67,26 +67,22 @@ export default function Filter() {
|
||||
const visibleSectionNumber = numberExpanded
|
||||
? sizeData
|
||||
: sizeData.slice(0, 10);
|
||||
|
||||
console.log("have suncategory: ", category.have_sub_category);
|
||||
if (category.have_sub_category || subCategory.id !== 0) {
|
||||
return null;
|
||||
}
|
||||
console.log("filter: ",filter);
|
||||
console.log("filter: ", filter);
|
||||
|
||||
return (
|
||||
<div className="space-y-3 max-w-70 w-full text-white">
|
||||
<div className="space-y-3 lg:max-w-70 lg:px-0 px-3 w-full text-white">
|
||||
{/* Bo'lim filtri */}
|
||||
<div className="bg-gray-500 rounded-lg">
|
||||
{visibleSectionData && (
|
||||
<div className="bg-gray-500 rounded-lg w-full">
|
||||
<p className="bg-red-500 text-white p-2 font-semibold font-almarai text-lg rounded-t-lg">
|
||||
Bo'lim
|
||||
</p>
|
||||
<div className="space-y-3 p-2">
|
||||
<div className="lg:space-y-3 space-x-6 lg:p-2 p-5 flex lg:flex-col overflow-x-auto lg:overflow-x-hidden items-start justify-start w-full">
|
||||
{visibleSectionData.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
onClick={() => toggleFilter(item)}
|
||||
className="hover:cursor-pointer flex items-center gap-2"
|
||||
className="hover:cursor-pointer flex items-center gap-2 w-auto shrink-0"
|
||||
>
|
||||
<span
|
||||
className={`flex h-5 w-5 items-center justify-center rounded border-2 transition ${
|
||||
@@ -100,29 +96,31 @@ export default function Filter() {
|
||||
<Check className="h-3 w-3 text-white" strokeWidth={3} />
|
||||
)}
|
||||
</span>
|
||||
<p>{item.name}</p>
|
||||
<p className="whitespace-nowrap">{item.name}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<button
|
||||
className="p-2 text-lg underline hover:text-red-300 transition"
|
||||
className="lg:flex hidden p-2 text-lg underline hover:text-red-300 transition"
|
||||
onClick={() => setDataExpanded(!dataExpanded)}
|
||||
>
|
||||
{dataExpanded ? "Yashirish" : "Ko'proq ko'rish"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* O'lcham filtri */}
|
||||
{visibleSectionNumber && (
|
||||
<div className="bg-gray-500 rounded-lg">
|
||||
<p className="bg-red-500 text-white p-2 font-semibold font-almarai text-lg rounded-t-lg">
|
||||
O'lcham
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-3 p-2">
|
||||
<div className="lg:space-y-3 space-x-6 lg:p-2 p-5 flex lg:flex-col overflow-x-auto lg:overflow-x-hidden items-start justify-start w-full">
|
||||
{visibleSectionNumber.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
onClick={() => toggleFilter(item)}
|
||||
className="hover:cursor-pointer flex items-center gap-2"
|
||||
className="hover:cursor-pointer flex items-center gap-2 w-auto shrink-0"
|
||||
>
|
||||
<span
|
||||
className={`flex h-5 w-5 items-center justify-center rounded border-2 transition ${
|
||||
@@ -142,11 +140,12 @@ export default function Filter() {
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setNumberExpanded(!numberExpanded)}
|
||||
className="p-2 text-lg underline hover:text-red-300 transition"
|
||||
className="lg:flex hidden p-2 text-lg underline hover:text-red-300 transition"
|
||||
>
|
||||
{numberExpanded ? "Yashirish" : "Ko'proq ko'rish"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import MainProduct from "./mianProduct";
|
||||
|
||||
export function Products() {
|
||||
return (
|
||||
<div className="bg-[#1e1d1c] py-20">
|
||||
<div className="bg-[#1e1d1c] py-10">
|
||||
<div className="max-w-300 mx-auto w-full z-20 relative">
|
||||
<div className="flex items-start gap-5">
|
||||
<div className="flex lg:flex-row flex-col lg:items-start items-center gap-5">
|
||||
{/* filter part */}
|
||||
<Filter />
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function Card({
|
||||
image,
|
||||
category,
|
||||
});
|
||||
router.push(`/${locale}/products/${slug}`);
|
||||
router.push(`/${locale}/products`);
|
||||
};
|
||||
return (
|
||||
<Link href="#" onClick={handleClick}>
|
||||
|
||||
Reference in New Issue
Block a user