complated service and service detail page connection to backend
This commit is contained in:
@@ -9,19 +9,34 @@ import {
|
||||
SystemFeature,
|
||||
} from "@/lib/api/demoapi/operationalSystems";
|
||||
import { Breadcrumb } from "@/components/breadCrumb";
|
||||
import { useServiceDetail } from "@/store/useService";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import httpClient from "@/request/api";
|
||||
import { endPoints } from "@/request/links";
|
||||
|
||||
export default function OperationalSystemsPage() {
|
||||
const t = useTranslations("operationalSystems");
|
||||
const [data, setData] = useState<SystemFeature[] | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(false);
|
||||
const serviceId = useServiceDetail((state) => state.serviceId);
|
||||
console.log("service id: ", serviceId);
|
||||
|
||||
const {
|
||||
data,
|
||||
isLoading: loading,
|
||||
isError: error,
|
||||
} = useQuery({
|
||||
queryKey: ["firesafety", serviceId],
|
||||
queryFn: () => httpClient(endPoints.services.detail(serviceId || 0)),
|
||||
select: (data) => data?.data?.data,
|
||||
});
|
||||
|
||||
console.log("service detail: ", data);
|
||||
|
||||
// Demo data - fallback ma'lumotlar
|
||||
const demoData: SystemFeature[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: t("systems.sprinkler.title"),
|
||||
shortDesc:t("systems.sprinkler.short-desc"),
|
||||
shortDesc: t("systems.sprinkler.short-desc"),
|
||||
description: t("systems.sprinkler.description"),
|
||||
features: [
|
||||
t("systems.sprinkler.features.0"),
|
||||
@@ -33,33 +48,6 @@ export default function OperationalSystemsPage() {
|
||||
},
|
||||
];
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(false);
|
||||
|
||||
const result = await getOperationalSystems();
|
||||
|
||||
// Agar backend ma'lumot qaytarsa
|
||||
if (result && result.length > 0) {
|
||||
setData(result);
|
||||
} else {
|
||||
// Backend bo'sh ma'lumot qaytarsa, demo ma'lumotlarni ishlatamiz
|
||||
setData(demoData);
|
||||
}
|
||||
} catch (err) {
|
||||
setError(true);
|
||||
// Xatolik bo'lsa, demo ma'lumotlarni ishlatamiz
|
||||
setData(demoData);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
// Animation variants
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
@@ -128,14 +116,6 @@ export default function OperationalSystemsPage() {
|
||||
>
|
||||
<div className="text-7xl">⚠️</div>
|
||||
<p className="text-white text-xl font-medium">{t("error")}</p>
|
||||
<motion.button
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
onClick={fetchData}
|
||||
className="px-6 py-3 bg-red-500 text-white rounded-lg font-medium hover:bg-red-600 transition-colors"
|
||||
>
|
||||
{t("retry")}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
@@ -143,43 +123,12 @@ export default function OperationalSystemsPage() {
|
||||
|
||||
return (
|
||||
<div className="pt-20 md:pt-30 pb-35 max-w-6xl mx-auto w-full px-4">
|
||||
{/* Header */}
|
||||
{/* <motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
className="flex md:flex-row flex-col items-start justify-between gap-6 md:gap-8 w-full mb-16 md:mb-24"
|
||||
>
|
||||
<motion.div variants={itemVariants} className="space-y-4 md:space-y-8 flex-1">
|
||||
<h1 className="bg-linear-to-br from-white via-white to-gray-400 text-transparent bg-clip-text text-3xl md:text-4xl lg:text-5xl font-semibold font-almarai">
|
||||
{t('title')}
|
||||
</h1>
|
||||
<p className="text-white font-medium font-unbounded text-base sm:text-lg md:text-xl max-w-2xl leading-relaxed">
|
||||
{t('subtitle')}
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
variants={itemVariants}
|
||||
whileHover={{ scale: 1.05, rotate: 3 }}
|
||||
transition={{ type: "spring", stiffness: 300, damping: 20 }}
|
||||
className="shrink-0 relative"
|
||||
>
|
||||
<Image
|
||||
src="/images/home/redShlang.png"
|
||||
alt="Fire hose"
|
||||
fill
|
||||
priority
|
||||
className="w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 lg:w-52 lg:h-52 object-contain"
|
||||
/>
|
||||
</motion.div>
|
||||
</motion.div> */}
|
||||
<div className="mb-5">
|
||||
<Breadcrumb />
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
{!data || data.length === 0 ? (
|
||||
{!data || data.legth === 0 ? (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
@@ -194,85 +143,81 @@ export default function OperationalSystemsPage() {
|
||||
animate="visible"
|
||||
className="space-y-12 md:space-y-20"
|
||||
>
|
||||
{data.map((system, index) => (
|
||||
<motion.div
|
||||
variants={cardVariants}
|
||||
whileHover={{ y: -8 }}
|
||||
className={`flex flex-col gap-8 md:gap-12 items-center`}
|
||||
>
|
||||
{/* Image Section */}
|
||||
<motion.div
|
||||
key={system.id}
|
||||
variants={cardVariants}
|
||||
whileHover={{ y: -8 }}
|
||||
className={`flex flex-col gap-8 md:gap-12 items-center`}
|
||||
whileHover={{ scale: 1.03 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="w-full relative h-64 md:h-80 lg:h-96 rounded-xl overflow-hidden"
|
||||
>
|
||||
{/* Image Section */}
|
||||
<motion.div
|
||||
whileHover={{ scale: 1.03 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="w-full relative h-64 md:h-80 lg:h-96 rounded-xl overflow-hidden"
|
||||
>
|
||||
<Image
|
||||
src={system.image}
|
||||
alt={system.title}
|
||||
fill
|
||||
className="object-cover w-full h-auto"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-linear-to-t from-black/10 to-transparent" />
|
||||
</motion.div>
|
||||
|
||||
{/* Content Section */}
|
||||
<div className="w-full space-y-6">
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-2xl md:text-3xl lg:text-4xl font-bold text-white font-almarai"
|
||||
>
|
||||
{system.title}
|
||||
</motion.h2>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.1 }}
|
||||
className="text-gray-300 text-sm md:text-base leading-relaxed font-unbounded"
|
||||
>
|
||||
{system.shortDesc}
|
||||
</motion.p>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.1 }}
|
||||
className="text-gray-300 text-sm md:text-base leading-relaxed font-unbounded"
|
||||
>
|
||||
{system.description}
|
||||
</motion.p>
|
||||
|
||||
<div className="space-y-4">
|
||||
|
||||
<ul className="space-y-3">
|
||||
{system.features.map((feature, featureIndex) => (
|
||||
<motion.li
|
||||
key={featureIndex}
|
||||
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.3 + featureIndex * 0.1,
|
||||
}}
|
||||
className="flex items-start gap-3 text-gray-300"
|
||||
>
|
||||
<span className="text-sm md:text-base font-unbounded">
|
||||
{feature}
|
||||
</span>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<Image
|
||||
src={data?.detail_image}
|
||||
alt={data.title}
|
||||
fill
|
||||
className="object-cover w-full h-auto"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-linear-to-t from-black/10 to-transparent" />
|
||||
</motion.div>
|
||||
))}
|
||||
|
||||
{/* Content Section */}
|
||||
<div className="w-full space-y-6">
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, x: data?.id % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-2xl md:text-3xl lg:text-4xl font-bold text-white font-almarai"
|
||||
>
|
||||
{data.title}
|
||||
</motion.h2>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, x: data?.id % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.1 }}
|
||||
className="text-gray-300 text-sm md:text-base leading-relaxed font-unbounded"
|
||||
>
|
||||
{data.subtitle}
|
||||
</motion.p>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, x: data?.id % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.1 }}
|
||||
className="text-gray-300 text-sm md:text-base leading-relaxed font-unbounded"
|
||||
>
|
||||
{data?.description}
|
||||
</motion.p>
|
||||
|
||||
{/* <div className="space-y-4">
|
||||
<ul className="space-y-3">
|
||||
{system.features.map((feature, featureIndex) => (
|
||||
<motion.li
|
||||
key={featureIndex}
|
||||
initial={{ opacity: 0, x: index % 2 === 0 ? -20 : 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{
|
||||
duration: 0.5,
|
||||
delay: 0.3 + featureIndex * 0.1,
|
||||
}}
|
||||
className="flex items-start gap-3 text-gray-300"
|
||||
>
|
||||
<span className="text-sm md:text-base font-unbounded">
|
||||
{feature}
|
||||
</span>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
</div> */}
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user