Files
ignum/components/pages/products/product/mianProduct.tsx
nabijonovdavronbek619@gmail.com d03a340afb updated compoennt file structure
2026-03-09 13:03:17 +05:00

136 lines
4.6 KiB
TypeScript

"use client";
import httpClient from "@/request/api";
import { endPoints } from "@/request/links";
import { useQuery } from "@tanstack/react-query";
import ProductCard from "./productCard";
import { useCategory } from "@/zustand/useCategory";
import { useFilter } from "@/lib/filter-zustand";
import { useMemo, useState, useEffect } from "react";
import { useProductPageInfo } from "@/zustand/useProduct";
import { useSubCategory } from "@/zustand/useSubCategory";
import { useTranslations } from "next-intl";
import PaginationLite from "@/components/paginationUI";
import { useCatalog } from "@/zustand/useCatalog";
export default function MainProduct() {
const t = useTranslations();
const category = useCategory((s) => s.category);
const subCategory = useSubCategory((s) => s.subCategory);
const filter = useFilter((s) => s.filter);
const getFiltersByType = useFilter((s) => s.getFiltersByType);
const setProduct = useProductPageInfo((s) => s.setProducts);
const parentID = useCatalog((state) => state.parentID);
const [currentPage, setCurrentPage] = useState(1);
useEffect(() => {
setCurrentPage(1);
}, [parentID]);
// ── Filter params ────────────────────────────────────────────────────────
const queryParams = useMemo(() => {
const catalog = getFiltersByType("catalog");
const size = getFiltersByType("size");
const catalogParams = catalog.map((i) => `catalog=${i.id}`).join("&");
const sizeParams = size.map((i) => `size=${i.id}`).join("&");
const allParams = [catalogParams, sizeParams].filter(Boolean).join("&");
setCurrentPage(1);
return allParams ? `&${allParams}` : "";
}, [filter]);
// ── Request URL ──────────────────────────────────────────────────────────
const requestLink = useMemo(() => {
const baseLink = category.have_sub_category
? endPoints.product.bySubCategory({ id: subCategory.id, currentPage })
: parentID
? endPoints.product.byCatalogSection({ id: parentID, currentPage })
: endPoints.product.byCategory({ id: category.id, currentPage });
return `${baseLink}${queryParams}`;
}, [
category.id,
category.have_sub_category,
subCategory.id,
currentPage,
parentID,
queryParams,
]);
// ── Query ────────────────────────────────────────────────────────────────
const { data, isLoading, error } = useQuery({
queryKey: [
"products",
category.id,
category.have_sub_category,
subCategory.id,
parentID,
queryParams,
currentPage,
],
queryFn: () => httpClient(requestLink),
placeholderData: (prev) => prev, // no flicker on pagination
select: (res) => ({
results: res?.data?.data?.results ?? [],
totalPages: res?.data?.data?.total_pages ?? 1,
}),
});
const results = data?.results ?? [];
const totalPages = data?.totalPages ?? 1;
// ── Render states ────────────────────────────────────────────────────────
if (isLoading && !data) {
return (
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-5">
{[1, 2, 3].map((i) => (
<div key={i} className="h-96 bg-gray-800 animate-pulse rounded-2xl" />
))}
</div>
);
}
if (error) {
return (
<div className="text-center text-red-500 py-10">{t("loadingError")}</div>
);
}
if (!results.length) {
return (
<div className="text-center text-gray-400 py-10">
{t("productsNotFound")}
</div>
);
}
return (
<div className="space-y-4">
<div
className={`grid lg:grid-cols-4 sm:grid-cols-2 grid-cols-1 gap-5 transition-opacity ${
isLoading ? "opacity-50 pointer-events-none" : "opacity-100"
}`}
>
{results.map((item: any) => (
<ProductCard
key={item.id}
getProduct={() => setProduct(item)}
title={item.name}
image={item?.images?.[0]?.image || ""}
slug="special_product"
/>
))}
</div>
{totalPages > 1 && (
<PaginationLite
currentPage={currentPage}
totalPages={totalPages}
onChange={(p) => setCurrentPage(p)}
/>
)}
</div>
);
}