parsaaghayi-front/src/app/(routes)/(website)/components/services/services.tsx

116 lines
3.8 KiB
TypeScript

"use client";
import { Service } from "@/app/types/types";
import { getCookie } from "cookies-next";
import { useEffect, useState } from "react";
import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";
import { motion } from "framer-motion";
import Image from "next/image";
interface ServicesProps {
dict: {
website: {
homePage: {
services: {
title: string;
description: string;
};
};
};
};
}
export default function Services({ dict }: ServicesProps) {
const [services, setServices] = useState<Service[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchServices = async () => {
setLoading(true);
const response = await fetch(
`/api/website/services/${getCookie("selectedLocale") !== undefined ? getCookie("selectedLocale") : getCookie("defaultLocale")}`,
).then((res) => res.json());
setServices(response);
setLoading(false);
};
fetchServices();
}, [getCookie("selectedLocale")]);
const renderServiceCard = (service?: Service, index?: number) => (
<motion.div
key={service?.id || index}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: (index || 0) * 0.1 }}
viewport={{ once: true }}
whileHover={{ y: -10 }}
className="group flex h-full w-full flex-col items-start rounded-3xl glass-panel p-8 transition-all duration-300 hover:border-primary/50"
>
<div className="mb-6 relative overflow-hidden rounded-2xl w-20 h-20 bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-colors">
{loading ? (
<Skeleton containerClassName="w-12 h-12" />
) : (
<img
src={service!.imageSrc}
alt={service!.altText}
className="w-12 h-12 object-contain transition-transform duration-300 group-hover:scale-110 dark:brightness-0 dark:invert dark-invert-target"
/>
)}
</div>
<h3 className="mb-4 text-2xl font-bold text-foreground group-hover:text-primary transition-colors">
{loading ? (
<Skeleton containerClassName="w-full" height={32} />
) : (
service!.title
)}
</h3>
<p className="text-muted-foreground leading-relaxed text-sm md:text-base">
{loading ? (
<Skeleton containerClassName="w-full" height={60} />
) : (
service!.description
)}
</p>
</motion.div>
);
return (
<section
className="relative flex w-full max-w-[1200px] flex-col items-center py-20"
id="services"
>
<div className="text-center mb-16 space-y-4">
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
className="text-4xl md:text-5xl font-bold text-foreground tracking-tight"
>
{dict.website.homePage.services.title}
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
viewport={{ once: true }}
className="text-lg text-muted-foreground max-w-2xl mx-auto text-balance"
>
{dict.website.homePage.services.description}
</motion.p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-5xl mx-auto w-full">
{loading
? Array.from({ length: 3 }).map((_, index) =>
renderServiceCard(undefined, index),
)
: services.map((service, index) => renderServiceCard(service, index))}
</div>
</section>
);
}