Files
ignum/app/[locale]/services/detail/page.tsx
2026-02-16 15:57:19 +05:00

281 lines
8.8 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import Image from "next/image";
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import { useTranslations } from "next-intl";
import {
getOperationalSystems,
SystemFeature,
} from "@/lib/api/demoapi/operationalSystems";
import { Breadcrumb } from "@/components/breadCrumb";
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);
// Demo data - fallback ma'lumotlar
const demoData: SystemFeature[] = [
{
id: "1",
title: t("systems.sprinkler.title"),
shortDesc:t("systems.sprinkler.short-desc"),
description: t("systems.sprinkler.description"),
features: [
t("systems.sprinkler.features.0"),
t("systems.sprinkler.features.1"),
t("systems.sprinkler.features.2"),
t("systems.sprinkler.features.3"),
],
image: "/images/services/sprinkler.jpg",
},
];
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 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.15,
},
},
};
const itemVariants = {
hidden: { opacity: 0, y: 30 },
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.6,
ease: [0.22, 1, 0.36, 1] as const,
},
},
};
const cardVariants = {
hidden: { opacity: 0, scale: 0.95 },
visible: {
opacity: 1,
scale: 1,
transition: {
duration: 0.5,
ease: [0.22, 1, 0.36, 1] as const,
},
},
};
// Loading state
if (loading) {
return (
<div className="min-h-screen flex items-center justify-center bg-black">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="text-center space-y-6"
>
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
className="w-16 h-16 border-4 border-red-500 border-t-transparent rounded-full mx-auto"
/>
<p className="text-white text-xl font-medium font-unbounded">
{t("loading")}
</p>
</motion.div>
</div>
);
}
// Error state with retry
if (error && !data) {
return (
<div className="min-h-screen flex items-center justify-center bg-black px-4">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center space-y-6 max-w-md"
>
<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>
);
}
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 ? (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="text-center py-20"
>
<p className="text-gray-400 text-xl font-unbounded">{t("noData")}</p>
</motion.div>
) : (
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="space-y-12 md:space-y-20"
>
{data.map((system, index) => (
<motion.div
key={system.id}
variants={cardVariants}
whileHover={{ y: -8 }}
className={`flex flex-col gap-8 md:gap-12 items-center`}
>
{/* 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>
</motion.div>
))}
</motion.div>
)}
</div>
);
}