connected to backend

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-02-04 10:01:25 +05:00
parent 1d0698573f
commit e7b838e3fe
21 changed files with 571 additions and 395 deletions

View File

@@ -3,45 +3,85 @@
import { useCarDetail } from "@/components/lib_components/carDetailProvider";
import Text from "@/components/lib_components/text";
import Image from "next/image";
import React, { useState } from "react";
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 { logoImg } from "@/assets";
const baseUrl = "https://api.spes-texnika.uz/api/v1/products/";
export default function CarDetailPage() {
const { detail } = useCarDetail();
const [modalOpen, setModalOpen] = useState<boolean>(false);
const { t } = useTranslation();
if (!detail) {
return (
<div className="my-20 text-center text-gray-500">
<Text txt="Mahsulot topilmadi yoki hali tanlanmagan." />
</div>
);
// tools of request
const initialCar = useCarType((state) => state.initialCar);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const pathname = usePathname();
const lang = pathname.split("/")[1];
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) {
setLoading(false);
return;
}
const fetchProducts = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(`${baseUrl}${initialCar.id}/`, {
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);
}
};
fetchProducts();
}, [lang]); // initialCar.id ham dependency ga qo'shildi
const firstData = cars ? cars[0] : undefined;
if (!firstData) {
return <>Maluot topilmadi</>;
}
const {t} = useTranslation();
const techSpecs: Record<string, string | number | undefined> = {
[t("weight_kg")]: detail.weight_kg && `${detail.weight_kg.toLocaleString("uz-UZ")} kg`,
[t("maxLength_m")]: detail.maxLength_m && `${detail.maxLength_m} m`,
[t("maxHeight_m")]: detail.maxHeight_m && `${detail.maxHeight_m} m`,
[t("capacity_tons")]: detail.capacity_tons && `${detail.capacity_tons} t`,
[t("capacity_kg")]: detail.capacity_kg && `${detail.capacity_kg} kg`,
[t("fuelType")]: detail.fuelType,
[t("tankVolume_m3")]: detail.tankVolume_m3 && `${detail.tankVolume_m3}`,
[t("maxSpeed_kmh")]: detail.maxSpeed_kmh && `${detail.maxSpeed_kmh} km/soat`,
[t("intercooler")]: detail.intercooler,
[t("enginePower_hp")]: detail.enginePower_hp,
[t("transmission")]: detail.transmission,
[t("bom")]: detail.bom && `${detail.bom} m`,
[t("qazish")]: detail.qazish && `${detail.qazish} m`,
[t("pichoq")]: detail.pichoq && `${detail.pichoq} m`,
[t("zichlash")]: detail.zichlash && `${detail.zichlash} m`,
[t("siqish")]: detail.siqish && `${detail.siqish} bar`,
[t("havo")]: detail.havo && `${detail.havo} l`,
[t("kompressor_sig")]: detail.kompressor_sig && `${detail.kompressor_sig} l`
};
return (
<div
dir="ltr"
@@ -49,7 +89,7 @@ export default function CarDetailPage() {
>
{/* 1⃣ Mashina nomi */}
<div className="text-2xl font-bold w-full text-center text-secondary mb-10">
<Text txt={detail.name} />
<Text txt={""} />
</div>
{/* 2⃣ Rasmi + asosiy narx malumotlari */}
@@ -57,8 +97,8 @@ export default function CarDetailPage() {
{/* Mashina rasmi */}
<div className="max-w-[600px] w-full h-auto">
<Image
src={detail.image}
alt={detail.name}
src={firstData?.image ? firstData?.image : logoImg}
alt={firstData?.name ? firstData?.name : "image"}
width={600}
height={200}
className="rounded-lg object-cover border border-gray-200 w-full"
@@ -70,24 +110,17 @@ export default function CarDetailPage() {
<div className="text-lg font-semibold flex gap-2">
<Text txt="hour-price" />
<span className="font-medium flex gap-2 text-gray-500">
{detail.price?.toLocaleString("uz-UZ")}
{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">
{detail.min_order_time}
{firstData.minimal_order}
<Text txt="time" />
</span>
</div>
<div className="text-lg font-semibold flex gap-2">
<Text txt="day-price" />
<span className="font-medium flex gap-2 text-gray-500">
{detail.price && (detail.price * 8).toLocaleString("uz-UZ")}
<Text txt="wallet" />
</span>
</div>
{/* Izoh */}
<div className="space-y-2 text-gray-500 text-lg">
@@ -110,25 +143,25 @@ export default function CarDetailPage() {
{/* 3⃣ Texnik xususiyatlar (faqat mavjudlari) */}
<div className="w-full border-t border-gray-300 pt-6">
<h2 className="text-xl font-semibold mb-4 text-secondary">Texnik xususiyatlari</h2>
<h2 className="text-xl font-semibold mb-4 text-secondary">
Texnik xususiyatlari
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 text-gray-700">
{Object.entries(techSpecs)
.filter(([_, value]) => value !== undefined)
.map(([key, value]) => (
<div
key={key}
className="p-3 rounded-md bg-gray-50 border border-gray-200 hover:bg-gray-100 transition"
>
<p className="font-medium">{key}:</p>
<p className="text-gray-600">{value}</p>
</div>
))}
{firstData?.features.map((item: any) => (
<div
key={item.id}
className="p-3 rounded-md bg-gray-50 border border-gray-200 hover:bg-gray-100 transition"
>
<p className="font-medium">{item?.name}:</p>
<p className="text-gray-600">{item?.value}</p>
</div>
))}
</div>
</div>
{/* 4⃣ Ijara modal */}
<CarRentalModal
car={detail}
car={firstData}
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
/>

View File

@@ -1,194 +1,100 @@
"use client";
import InnerProductcard from "@/components/cards/innerProductcard";
import { EmptyState } from "@/components/emptyState";
import Text from "@/components/lib_components/text";
import Title from "@/components/lib_components/title";
import {
asfalt,
assenizator,
avtogreyderlar,
avtokran,
avtolift,
avtovishka,
betonNasoslar,
buldozerlar,
cement_trucks,
dumb_trucks,
eks_yuklagichlar,
evakuatorDemo,
forkliftlar,
gildirakli_eks,
katkalar,
manipulyator,
mini_eks,
mini_loaders,
minora,
old_yuklagichlar,
paletli_eks,
shalandaTraller,
teleskop_yuklagichlar,
trailers,
vodovoz,
} from "@/data";
import { useParams } from "next/navigation";
import { LoadingSkeleton } from "@/components/loadingProduct";
import { useCarType } from "@/store/carType";
import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
const baseUrl = "https://api.spes-texnika.uz/api/v1/subcategory/";
export default function CartType() {
const router = useParams();
const carType = router.carType;
const initialCar = useCarType((state) => state.initialCar);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const pathname = usePathname();
const lang = pathname.split("/")[1];
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) {
setLoading(false);
return;
}
const fetchProducts = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(`${baseUrl}${initialCar.id}/`, {
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);
}
};
fetchProducts();
}, [lang]); // initialCar.id ham dependency ga qo'shildi
return (
<div dir="ltr" className="my-20">
<Title text="tex-rent" />
{/* Error message */}
{error && (
<div className="mb-4 p-4 bg-red-50 border border-red-200 rounded-lg">
<p className="text-red-600 text-center">
<Text txt="downloadError" />: {error}
</p>
</div>
)}
{/* car type groups */}
<div className="mt-10 grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-5 max-w-[1200px] w-full mx-auto">
{/* Avtosementavoz */}
{carType === "cement-truck" &&
cement_trucks.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Samasvallar */}
{carType === "dumb-truck" &&
dumb_trucks.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Traylerlar */}
{carType === "trailers" &&
trailers.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Avtoliftlar */}
{carType === "Avtolift" &&
avtolift.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Avtovishka */}
{carType === "Avtovishka" &&
avtovishka.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Avtokran */}
{carType === "avtocranes" &&
avtokran.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Minora kranlar */}
{carType === "tower-cranes" &&
minora.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Minora kranlar */}
{carType === "mini-loaders" &&
mini_loaders.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* old yuklagichlar */}
{carType === "front-loaders" &&
old_yuklagichlar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Teleskopik yuklagichlar */}
{carType === "tele-loaders" &&
teleskop_yuklagichlar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* forkliftlar */}
{carType === "forklift-trucks" &&
forkliftlar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Paletli ekskavatorlar */}
{carType === "crawler-excavators" &&
paletli_eks.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* G'ildirakli ekskavatorlar */}
{carType === "wheel-excavators" &&
gildirakli_eks.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Mini-ekskavatorlar */}
{carType === "mini-excavators" &&
mini_eks.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* ekskavator yuklagichlar */}
{carType === "excavator-loaders" &&
eks_yuklagichlar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* avtogreyderlar */}
{carType === "avtograders" &&
avtogreyderlar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Buldozerlar */}
{carType === "buldozers" &&
buldozerlar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Katkalar */}
{carType === "katkas" &&
katkalar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* Evakuatorlar */}
{carType === "evakuator" &&
evakuatorDemo.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* shalanda */}
{carType === "shalanda_traller" &&
shalandaTraller.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* asfalt yotqizuvchi */}
{carType === "asfalt_frez" &&
asfalt.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* asfalt ko'chiruvchi */}
{carType === "beton_nasos" &&
betonNasoslar.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* manipulyator */}
{carType === "manipulyator" &&
manipulyator.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* vodovoz */}
{carType === "vodovoz" &&
vodovoz.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
{/* assertizator */}
{carType === "assenizator" &&
assenizator.map((item) => {
return <InnerProductcard data={item} key={item.id} />;
})}
<div className="mt-10 grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-5 max-w-[1200px] w-full mx-auto px-4">
{loading ? (
<LoadingSkeleton />
) : cars.length > 0 ? (
// MUHIM: Array ustidan map qilish kerak!
cars.map((car, index) => (
<InnerProductcard key={car.id || index} data={car} />
))
) : (
<EmptyState />
)}
</div>
</div>
);

View File

@@ -1,4 +1,4 @@
import Products from "@/components/pageParts/products";
import Products from "@/components/pageParts/products/products";
import Texnika from "@/components/pageParts/texnika";
import Offer from "@/components/pageParts/offer";
import Faq from "@/components/pageParts/faq";
@@ -27,4 +27,3 @@ export default function Home() {
</div>
);
}