classify web

This commit is contained in:
Husanjonazamov
2026-02-24 12:52:49 +05:00
commit 64af77101f
310 changed files with 45449 additions and 0 deletions

View File

@@ -0,0 +1,264 @@
"use client";
import { useEffect, useState } from "react";
import { allItemApi, getMyItemsApi, setItemTotalClickApi } from "@/utils/api";
import ProductFeature from "./ProductFeature";
import ProductDescription from "./ProductDescription";
import ProductDetailCard from "./ProductDetailCard";
import SellerDetailCard from "./SellerDetailCard";
import ProductLocation from "./ProductLocation";
import AdsReportCard from "./AdsReportCard";
import SimilarProducts from "./SimilarProducts";
import MyAdsListingDetailCard from "./MyAdsListingDetailCard";
import AdsStatusChangeCards from "./AdsStatusChangeCards";
import { usePathname, useSearchParams } from "next/navigation";
import Layout from "@/components/Layout/Layout";
import ProductGallery from "./ProductGallery";
import {
getFilteredCustomFields,
getYouTubeVideoId,
t,
truncate,
} from "@/utils";
import PageLoader from "@/components/Common/PageLoader";
import OpenInAppDrawer from "@/components/Common/OpenInAppDrawer";
import { useDispatch, useSelector } from "react-redux";
import { CurrentLanguageData } from "@/redux/reducer/languageSlice";
import BreadCrumb from "@/components/BreadCrumb/BreadCrumb";
import { setBreadcrumbPath } from "@/redux/reducer/breadCrumbSlice";
import MakeFeaturedAd from "./MakeFeaturedAd";
import RenewAd from "./RenewAd";
import AdEditedByAdmin from "./AdEditedByAdmin";
import NoData from "@/components/EmptyStates/NoData";
const ProductDetails = ({ slug }) => {
const CurrentLanguage = useSelector(CurrentLanguageData);
const dispatch = useDispatch();
const pathName = usePathname();
const searchParams = useSearchParams();
const isShare = searchParams.get("share") == "true" ? true : false;
const isMyListing = pathName?.startsWith("/my-listing") ? true : false;
const [productDetails, setProductDetails] = useState(null);
const [galleryImages, setGalleryImages] = useState([]);
const [status, setStatus] = useState("");
const [videoData, setVideoData] = useState({
url: "",
thumbnail: "",
});
const [isLoading, setIsLoading] = useState(false);
const [isOpenInApp, setIsOpenInApp] = useState(false);
const IsShowFeaturedAd =
isMyListing &&
!productDetails?.is_feature &&
productDetails?.status === "approved";
const isMyAdExpired = isMyListing && productDetails?.status === "expired";
const isEditedByAdmin =
isMyListing && productDetails?.is_edited_by_admin === 1;
useEffect(() => {
fetchProductDetails();
}, [CurrentLanguage?.id]);
useEffect(() => {
if (window.innerWidth <= 768 && !isMyListing && isShare) {
setIsOpenInApp(true);
}
}, []);
const fetchMyListingDetails = async (slug) => {
const response = await getMyItemsApi.getMyItems({ slug });
const product = response?.data?.data?.data?.[0];
if (!product) throw new Error("My listing product not found");
setProductDetails(product);
const videoLink = product?.video_link;
if (videoLink) {
const videoId = getYouTubeVideoId(videoLink);
const thumbnail = videoId
? `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`
: "";
setVideoData((prev) => ({ ...prev, url: videoLink, thumbnail }));
}
const galleryImages =
product?.gallery_images?.map((image) => image?.image) || [];
setGalleryImages([product?.image, ...galleryImages]);
setStatus(product?.status);
dispatch(
setBreadcrumbPath([
{
name: t("myAds"),
slug: "/my-ads",
},
{
name: truncate(product?.translated_item?.name || product?.name, 80),
},
])
);
};
const incrementViews = async (item_id) => {
try {
if (!item_id) {
console.error("Invalid item_id for incrementViews");
return;
}
const res = await setItemTotalClickApi.setItemTotalClick({ item_id });
} catch (error) {
console.error("Error incrementing views:", error);
}
};
const fetchPublicListingDetails = async (slug) => {
const response = await allItemApi.getItems({ slug });
const product = response?.data?.data?.data?.[0];
if (!product) throw new Error("Public listing product not found");
setProductDetails(product);
const videoLink = product?.video_link;
if (videoLink) {
setVideoData((prev) => ({ ...prev, url: videoLink }));
const videoId = getYouTubeVideoId(videoLink);
const thumbnail = videoId
? `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`
: "";
setVideoData((prev) => ({ ...prev, thumbnail }));
}
const galleryImages =
product?.gallery_images?.map((image) => image?.image) || [];
setGalleryImages([product?.image, ...galleryImages]);
await incrementViews(product?.id);
};
const fetchProductDetails = async () => {
try {
setIsLoading(true);
if (isMyListing) {
await fetchMyListingDetails(slug);
} else {
await fetchPublicListingDetails(slug);
}
} catch (error) {
console.error("Failed to fetch product details:", error);
// You can also show a toast or error message here
} finally {
setIsLoading(false);
}
};
const filteredFields = getFilteredCustomFields(
productDetails?.all_translated_custom_fields,
CurrentLanguage?.id
);
return (
<Layout>
{isLoading ? (
<PageLoader />
) : productDetails ? (
<>
{isMyListing ? (
<BreadCrumb />
) : (
<BreadCrumb
title2={truncate(
productDetails?.translated_item?.name || productDetails?.name,
80
)}
/>
)}
<div className="container mt-8">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-7 mt-6">
<div className="col-span-1 lg:col-span-8">
<div className="flex flex-col gap-7">
<ProductGallery
galleryImages={galleryImages}
videoData={videoData}
/>
{IsShowFeaturedAd && (
<MakeFeaturedAd
item_id={productDetails?.id}
setProductDetails={setProductDetails}
/>
)}
{filteredFields.length > 0 && (
<ProductFeature filteredFields={filteredFields} />
)}
<ProductDescription productDetails={productDetails} />
</div>
</div>
<div className="flex flex-col col-span-1 lg:col-span-4 gap-7">
{isMyListing ? (
<MyAdsListingDetailCard productDetails={productDetails} />
) : (
<ProductDetailCard
productDetails={productDetails}
setProductDetails={setProductDetails}
/>
)}
{!isMyListing && (
<SellerDetailCard
productDetails={productDetails}
setProductDetails={setProductDetails}
/>
)}
{isMyListing && (
<AdsStatusChangeCards
productDetails={productDetails}
setProductDetails={setProductDetails}
status={status}
setStatus={setStatus}
/>
)}
{isEditedByAdmin && (
<AdEditedByAdmin
admin_edit_reason={productDetails?.admin_edit_reason}
/>
)}
{isMyAdExpired && (
<RenewAd
item_id={productDetails?.id}
setProductDetails={setProductDetails}
currentLanguageId={CurrentLanguage?.id}
setStatus={setStatus}
/>
)}
<ProductLocation productDetails={productDetails} />
{!isMyListing && !productDetails?.is_already_reported && (
<AdsReportCard
productDetails={productDetails}
setProductDetails={setProductDetails}
/>
)}
</div>
</div>
{!isMyListing && (
<SimilarProducts
productDetails={productDetails}
key={`similar-products-${CurrentLanguage?.id}`}
/>
)}
<OpenInAppDrawer
isOpenInApp={isOpenInApp}
setIsOpenInApp={setIsOpenInApp}
/>
</div>
</>
) : (
<div className="container mt-8">
<NoData name={t("oneAdvertisement")} />
</div>
)}
</Layout>
);
};
export default ProductDetails;