detail page updated , add subcategory zustand

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-04-17 11:04:34 +05:00
parent 83bfb6296d
commit ebc08eff8f
7 changed files with 173 additions and 65 deletions

View File

@@ -1,98 +1,134 @@
"use client";
import { useCarDetail } from "@/components/lib_components/carDetailProvider";
import Text from "@/components/lib_components/text";
import Image from "next/image";
import React, { useEffect, useState } from "react";
import CarRentalModal from "@/components/lib_components/carRentalModal";
import { useTranslation } from "react-i18next";
import { useCarType } from "@/store/carType";
import { usePathname } from "next/navigation";
import { usePathname, useParams } from "next/navigation";
import { logoImg } from "@/assets";
import { useSubCategory } from "@/store/subCategory";
import { minimumValues } from "@/data/minimimValues";
import { LoadingSkeleton } from "@/components/loadingProduct";
import { EmptyState } from "@/components/emptyState";
import { ErrorState } from "@/components/errorState";
const baseUrl = "https://api.spes-texnika.uz/api/v1/products/";
type Lang = "uz" | "ru" | "en";
const validLangs: Lang[] = ["uz", "ru", "en"];
function checkCategory(categoryName: string | undefined, lang: string) {
if (!categoryName || !validLangs.includes(lang as Lang)) {
return { isMinimum: false, text: "" };
}
const validLang = lang as Lang;
const matched = minimumValues[validLang].find(
(item: string) => item === categoryName,
);
if (matched)
return { isMinimum: true, text: minimumValues.values[validLang] };
return { isMinimum: false, text: "" };
}
export default function CarDetailPage() {
const [modalOpen, setModalOpen] = useState<boolean>(false);
const { t } = useTranslation();
// tools of request
const initialCar = useCarType((state) => state.initialCar);
const initialSubCategory = useSubCategory(
(state) => state.initialSubCategory,
);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const pathname = usePathname();
const params = useParams();
const lang = pathname.split("/")[1];
const carId = params.carDeatil as string;
const [cars, setCars] = useState<any[]>([]);
console.log("car type id: ", initialCar.id);
console.log("request URL: ", `${baseUrl}${initialCar.id}/`);
useEffect(() => {
// Agar ID bo'lmasa, fetchni ishga tushirma
if (!initialCar.id) {
const fetchProducts = async () => {
if (!carId) {
setLoading(false);
return;
}
const fetchProducts = async () => {
try {
setLoading(true);
setError(null);
try {
setLoading(true);
setError(null);
const response = await fetch(`${baseUrl}${initialCar.id}/`, {
headers: {
"Accept-Language": lang,
},
});
const response = await fetch(`${baseUrl}${carId}/`, {
headers: {
"Accept-Language": lang,
},
});
if (!response.ok) {
throw new Error("Server xatosi");
}
const result = await response.json();
console.log("backend full response: ", result);
console.log("backend Data: ", result?.data);
// Data array ekanligini tekshirish
if (result?.data) {
if (Array.isArray(result.data)) {
setCars(result.data);
} else {
// Agar object bo'lsa, uni array ichiga o'rab qo'yamiz
setCars([result.data]);
}
} else {
setCars([]);
}
} catch (error) {
console.log("Xatolik: ", error);
setError(error instanceof Error ? error.message : "Noma'lum xatolik");
setCars([]);
} finally {
setLoading(false);
if (!response.ok) {
throw new Error("Server xatosi");
}
};
const result = await response.json();
console.log("backend full response: ", result);
console.log("backend Data: ", result?.data);
if (result?.data) {
if (Array.isArray(result.data)) {
setCars(result.data);
} else {
setCars([result.data]);
}
} else {
setCars([]);
}
} catch (err) {
console.log("Xatolik: ", err);
setError(err instanceof Error ? err.message : "Noma'lum xatolik");
setCars([]);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchProducts();
}, [lang]); // initialCar.id ham dependency ga qo'shildi
}, [carId, lang]);
const firstData = cars ? cars[0] : undefined;
if (loading) {
return (
<div className="my-10 max-w-[1200px] w-full mx-auto grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 px-2">
<LoadingSkeleton />
</div>
);
}
if (error) {
return (
<div className="my-10 max-w-[1200px] w-full mx-auto px-2">
<ErrorState message={error} onRetry={fetchProducts} />
</div>
);
}
const firstData = cars[0];
if (!firstData) {
return <>Maluot topilmadi</>;
return (
<div className="my-10 max-w-[1200px] w-full mx-auto px-2">
<EmptyState />
</div>
);
}
const { isMinimum, text } = checkCategory(initialSubCategory.name, lang);
return (
<div
dir="ltr"
className="my-10 max-w-[1200px] w-full mx-auto space-y-8 flex flex-col items-start justify-center px-2"
>
{/* 1 Mashina nomi */}
{/* Mashina nomi */}
<div className="text-2xl font-bold w-full text-center text-secondary mb-10">
<Text txt={""} />
</div>
{/* 2 Rasmi + asosiy narx malumotlari */}
{/* Rasmi + asosiy narx ma'lumotlari */}
<div className="flex flex-col md:flex-row md:items-start items-center gap-6 justify-center w-full">
{/* Mashina rasmi */}
<div className="max-w-[600px] w-full h-auto">
@@ -105,22 +141,24 @@ export default function CarDetailPage() {
/>
</div>
{/* Asosiy malumotlar */}
{/* Asosiy ma'lumotlar */}
<div className="lg:space-y-6 space-y-3 w-full">
<div className="text-lg font-semibold flex gap-2">
<Text txt="hour-price" />
{isMinimum ? <p>{text}</p> : <Text txt="hour-price" />} :
<span className="font-medium flex gap-2 text-gray-500">
{firstData.price?.toLocaleString("uz-UZ")}
<Text txt="wallet" />
</span>
</div>
<div className="text-lg font-semibold flex gap-2">
<Text txt="min-time" />
<span className="font-medium flex gap-2 text-gray-500">
{firstData.minimal_order}
<Text txt="time" />
</span>
</div>
{!isMinimum && (
<div className="text-lg font-semibold flex gap-2">
<Text txt="min-time" />
<span className="font-medium flex gap-2 text-gray-500">
{firstData.minimal_order}
<Text txt="time" />
</span>
</div>
)}
{/* Izoh */}
<div className="space-y-2 text-gray-500 text-lg">
@@ -141,7 +179,7 @@ export default function CarDetailPage() {
</div>
</div>
{/* 3 Texnik xususiyatlar (faqat mavjudlari) */}
{/* Texnik xususiyatlar */}
<div className="w-full border-t border-gray-300 pt-6">
<h2 className="text-xl font-semibold mb-4 text-secondary">
Texnik xususiyatlari
@@ -159,7 +197,7 @@ export default function CarDetailPage() {
</div>
</div>
{/* 4 Ijara modal */}
{/* Ijara modal */}
<CarRentalModal
car={firstData}
isOpen={modalOpen}