Aggiunge visite specialistiche e aggiorna sezione servizi

This commit is contained in:
2026-05-23 11:43:28 +02:00
parent 35de87511d
commit f8e6daa084
4 changed files with 203 additions and 36 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,31 +1,57 @@
/*
* DESIGN: "Clinical Warmth"
* Sezione servizi con 6 card principali allineate al menu della clinica.
* Layout: immagine in alto, bordo superiore colorato, hover lift.
* Sezione servizi con due livelli:
* - Servizi Clinici
* - Visite Specialistiche
*/
import { motion, useInView } from "framer-motion";
import { useRef } from "react";
import { Activity, ArrowRight, FlaskConical, Scan, Stethoscope, Video } from "lucide-react";
import {
Activity,
Apple,
ArrowRight,
Bone,
Eye,
FlaskConical,
Scan,
Sparkles,
Stethoscope,
Video,
} from "lucide-react";
import { toast } from "sonner";
const services = [
type ServiceItem = {
id: string;
title: string;
subtitle: string;
description: string;
image: string;
imageClassName?: string;
imageHoverClassName?: string;
icon: React.ComponentType<{ size?: number; className?: string }>;
color: string;
features: string[];
tone?: "default" | "specialist";
};
const clinicalServices: ServiceItem[] = [
{
id: "visite-cliniche",
title: "Visite Cliniche",
subtitle: "Medicina preventiva",
description:
"Percorsi di prevenzione e visite cliniche complete per monitorare lo stato di salute di cani e gatti in ogni fase della vita. Un approccio attento, continuativo e personalizzato.",
"Percorsi di prevenzione e visite cliniche complete per monitorare lo stato di salute di cani e gatti in ogni fase della vita.",
image: "https://images.unsplash.com/photo-1628009368231-7bb7cfcb0def?w=900&q=85",
icon: Stethoscope,
color: "#1B4F72",
features: ["Check-up periodici", "Vaccinazioni", "Profilassi antiparassitaria", "Piani prevenzione senior"],
features: ["Check-up periodici", "Vaccinazioni", "Profilassi antiparassitaria", "Controlli senior"],
},
{
id: "ecografia",
title: "Ecografia",
subtitle: "Diagnostica non invasiva",
description:
"Indagini ecografiche per approfondire in modo rapido e non invasivo organi addominali, apparato urinario, apparato riproduttivo e principali sospetti clinici.",
"Indagini ecografiche rapide per approfondire apparato addominale, urinario e riproduttivo con maggiore precisione clinica.",
image: "https://images.unsplash.com/photo-1579684385127-1ef15d508118?w=900&q=85",
icon: Activity,
color: "#4ECDC4",
@@ -36,7 +62,7 @@ const services = [
title: "Radiologia",
subtitle: "Diagnostica per immagini",
description:
"Radiografie digitali e diagnostica per immagini a supporto della visita clinica, utili per valutare apparato scheletrico, torace, addome e urgenze.",
"Radiografie digitali e diagnostica per immagini per apparato scheletrico, torace, addome e approfondimenti d'urgenza.",
image: "https://d2xsxph8kpxj0f.cloudfront.net/310519663483796440/DLUbzKbSnCG3dLeob4sLeC/radiology_39785f88.jpg",
icon: Scan,
color: "#2E86AB",
@@ -47,7 +73,7 @@ const services = [
title: "Laboratorio",
subtitle: "Analisi interne",
description:
"Laboratorio interno per esami rapidi e mirati, fondamentale per supportare diagnosi tempestive, monitoraggi terapeutici e controlli pre-operatori.",
"Laboratorio interno per esami rapidi e mirati, utile per diagnosi tempestive, monitoraggi terapeutici e controlli pre-operatori.",
image: "https://d2xsxph8kpxj0f.cloudfront.net/310519663483796440/DLUbzKbSnCG3dLeob4sLeC/laboratory_5a1c4119.jpg",
icon: FlaskConical,
color: "#1B4F72",
@@ -58,7 +84,7 @@ const services = [
title: "Endoscopia",
subtitle: "Esplorazione mini-invasiva",
description:
"Tecniche endoscopiche per esplorare apparato digerente e vie respiratorie, riducendo invasivita e tempi di recupero quando il quadro clinico lo consente.",
"Tecniche endoscopiche per esplorare apparato digerente e vie respiratorie riducendo invasivita e tempi di recupero.",
image: "https://images.unsplash.com/photo-1530026405186-ed1f139313f8?w=900&q=85",
icon: Video,
color: "#4ECDC4",
@@ -69,7 +95,7 @@ const services = [
title: "Laparoscopia",
subtitle: "Chirurgia mini-invasiva",
description:
"Procedure mini-invasive che permettono interventi piu delicati, incisioni ridotte e recuperi piu confortevoli rispetto alla chirurgia tradizionale.",
"Procedure mini-invasive con incisioni ridotte, recuperi piu confortevoli e maggiore delicatezza nei passaggi operatori.",
image: "https://d2xsxph8kpxj0f.cloudfront.net/310519663483796440/DLUbzKbSnCG3dLeob4sLeC/surgery_e92904ed.jpg",
icon: Activity,
color: "#2E86AB",
@@ -77,25 +103,103 @@ const services = [
},
];
function ServiceCard({ service, index }: { service: typeof services[0]; index: number }) {
const specialistVisits: ServiceItem[] = [
{
id: "oncologia",
title: "Oncologia",
subtitle: "Percorsi dedicati",
description:
"Valutazioni specialistiche per definire iter diagnostici e strategie terapeutiche personalizzate nei casi oncologici.",
image: "https://images.unsplash.com/photo-1511174511562-5f97f4f4a759?w=900&q=85",
icon: Stethoscope,
color: "#A95F3A",
features: ["Inquadramento clinico", "Piani terapeutici", "Monitoraggi periodici"],
tone: "specialist",
},
{
id: "dermatologia",
title: "Dermatologia",
subtitle: "Cute e mantello",
description:
"Approfondimenti per prurito, alopecie, otiti ricorrenti e alterazioni cutanee che richiedono un percorso mirato.",
image: "https://images.unsplash.com/photo-1516734212186-a967f81ad0d7?w=900&q=85",
icon: Sparkles,
color: "#B76E79",
features: ["Allergie", "Citologie cutanee", "Otiti croniche"],
tone: "specialist",
},
{
id: "oculistica",
title: "Oculistica",
subtitle: "Vista e benessere oculare",
description:
"Controlli specialistici per disturbi oculari, lacrimazione, arrossamenti e valutazioni funzionali della vista.",
image: "https://images.unsplash.com/photo-1517849845537-4d257902454a?w=900&q=85",
icon: Eye,
color: "#4C7A9F",
features: ["Esame del segmento anteriore", "Pressione oculare", "Follow-up oculari"],
tone: "specialist",
},
{
id: "nutrizione",
title: "Nutrizione",
subtitle: "Equilibrio alimentare",
description:
"Consulenze per impostare piani nutrizionali su misura in base a eta, patologie, stile di vita e obiettivi clinici.",
image: "https://images.unsplash.com/photo-1548199973-03cce0bbc87b?w=900&q=85",
icon: Apple,
color: "#7EA55A",
features: ["Diete personalizzate", "Gestione del peso", "Supporto nutrizionale"],
tone: "specialist",
},
{
id: "ortopedia",
title: "Ortopedia",
subtitle: "Movimento e postura",
description:
"Valutazioni specialistiche per zoppie, dolore articolare, traumi e impostazione del corretto iter ortopedico.",
image: "/images/ortovet.webp",
imageClassName: "scale-[0.5]",
imageHoverClassName: "group-hover:scale-[0.7]",
icon: Bone,
color: "#6D7B8C",
features: ["Valutazioni zoppia", "Controlli articolari", "Percorsi post-trauma"],
tone: "specialist",
},
];
function ServiceCard({
service,
index,
className = "",
}: {
service: ServiceItem;
index: number;
className?: string;
}) {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-50px" });
const specialist = service.tone === "specialist";
return (
<motion.div
ref={ref}
initial={{ opacity: 0, y: 40 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: index * 0.12 }}
className="group bg-white rounded-2xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-400 hover:-translate-y-1"
transition={{ duration: 0.6, delay: index * 0.1 }}
className={`group overflow-hidden rounded-2xl transition-all duration-400 hover:-translate-y-1 ${className} ${
specialist
? "border border-[#D7C1A8] bg-gradient-to-b from-[#fffaf2] to-white shadow-[0_18px_45px_rgba(169,95,58,0.12)] hover:shadow-[0_22px_50px_rgba(169,95,58,0.18)]"
: "bg-white shadow-md hover:shadow-xl"
}`}
>
<div className="h-1" style={{ backgroundColor: service.color }} />
<div className="h-1.5" style={{ backgroundColor: service.color }} />
<div className="relative h-52 overflow-hidden">
<img
src={service.image}
alt={service.title}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
className={`h-full w-full object-cover transition-transform duration-700 ${service.imageHoverClassName ?? "group-hover:scale-105"} ${service.imageClassName ?? ""}`}
/>
<div
className="absolute top-4 right-4 w-12 h-12 rounded-full flex items-center justify-center shadow-lg"
@@ -103,37 +207,42 @@ function ServiceCard({ service, index }: { service: typeof services[0]; index: n
>
<service.icon size={22} className="text-white" />
</div>
{specialist && (
<div className="absolute left-4 top-4 rounded-full bg-white/90 px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-[#7d5233] shadow-sm">
Alta specializzazione
</div>
)}
</div>
<div className="p-6">
<div className="text-xs uppercase tracking-widest font-semibold mb-1" style={{ color: service.color }}>
<div className="mb-1 text-xs font-semibold uppercase tracking-widest" style={{ color: service.color }}>
{service.subtitle}
</div>
<h3
className="text-[#1B4F72] mb-3"
className="mb-3 text-[#1B4F72]"
style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "1.75rem", fontWeight: 600 }}
>
{service.title}
</h3>
<p className="text-gray-600 text-sm leading-relaxed mb-4">{service.description}</p>
<p className="mb-4 text-sm leading-relaxed text-gray-600">{service.description}</p>
<ul className="space-y-1.5 mb-5">
<ul className="mb-5 space-y-1.5">
{service.features.map((feat) => (
<li key={feat} className="flex items-center gap-2 text-sm text-gray-600">
<span className="w-1.5 h-1.5 rounded-full flex-shrink-0" style={{ backgroundColor: service.color }} />
<span className="h-1.5 w-1.5 flex-shrink-0 rounded-full" style={{ backgroundColor: service.color }} />
{feat}
</li>
))}
</ul>
<button
className="flex items-center gap-1.5 text-sm font-semibold transition-all duration-200 group/btn"
className="group/btn flex items-center gap-1.5 text-sm font-semibold transition-all duration-200"
style={{ color: service.color }}
onClick={() => {
toast("Sezione in arrivo", { description: `La pagina dedicata a ${service.title} sara disponibile a breve.` });
}}
>
Scopri di piu
Approfondisci
<ArrowRight size={15} className="transition-transform duration-200 group-hover/btn:translate-x-1" />
</button>
</div>
@@ -143,7 +252,9 @@ function ServiceCard({ service, index }: { service: typeof services[0]; index: n
export default function ServicesSection() {
const ref = useRef(null);
const specialistRef = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-80px" });
const specialistInView = useInView(specialistRef, { once: true, margin: "-80px" });
return (
<section id="servizi" className="py-20 md:py-28" style={{ backgroundColor: "#F5F0E8" }}>
@@ -155,38 +266,74 @@ export default function ServicesSection() {
transition={{ duration: 0.7 }}
className="mb-14"
>
<div className="flex items-center gap-3 mb-4">
<div className="w-12 h-0.5 bg-[#4ECDC4]" />
<span className="text-[#4ECDC4] text-sm font-semibold uppercase tracking-widest">
<div className="mb-4 flex items-center gap-3">
<div className="h-0.5 w-12 bg-[#4ECDC4]" />
<span className="text-sm font-semibold uppercase tracking-widest text-[#4ECDC4]">
Specializzazioni
</span>
</div>
<h2
className="text-[#1B4F72] mb-4"
className="mb-4 text-[#1B4F72]"
style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "clamp(2rem, 4vw, 3rem)", fontWeight: 600 }}
>
Servizi Specialistici
Servizi Clinici
</h2>
<p className="text-gray-600 max-w-xl text-base leading-relaxed">
<p className="max-w-xl text-base leading-relaxed text-gray-600">
Sei aree di eccellenza clinica per accompagnare prevenzione, diagnosi e trattamento
dei tuoi animali domestici, con tecnologie avanzate e professionisti esperti.
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-8">
{services.map((service, index) => (
<div className="grid grid-cols-1 gap-8 md:grid-cols-2 xl:grid-cols-3">
{clinicalServices.map((service, index) => (
<ServiceCard key={service.id} service={service} index={index} />
))}
</div>
<motion.div
ref={specialistRef}
initial={{ opacity: 0, y: 30 }}
animate={specialistInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.7, delay: 0.2 }}
className="mt-20"
>
<div className="mb-4 flex items-center gap-3">
<div className="h-0.5 w-12 bg-[#A95F3A]" />
<span className="text-sm font-semibold uppercase tracking-widest text-[#A95F3A]">
Alta specializzazione
</span>
</div>
<h3
className="mb-4 text-[#1B4F72]"
style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "clamp(1.9rem, 3.7vw, 2.8rem)", fontWeight: 600 }}
>
Visite Specialistiche
</h3>
<p className="max-w-2xl text-base leading-relaxed text-gray-600">
Un secondo livello di consulenza clinica per casi che richiedono competenze dedicate,
approfondimenti mirati e percorsi di valutazione ad alto valore aggiunto.
</p>
</motion.div>
<div className="mt-10 grid grid-cols-1 gap-8 md:grid-cols-2 xl:grid-cols-6">
{specialistVisits.map((service, index) => (
<ServiceCard
key={service.id}
service={service}
index={index}
className={index < 3 ? "xl:col-span-2" : "xl:col-span-3"}
/>
))}
</div>
<motion.div
initial={{ opacity: 0 }}
animate={isInView ? { opacity: 1 } : {}}
animate={specialistInView ? { opacity: 1 } : {}}
transition={{ duration: 0.7, delay: 0.6 }}
className="text-center mt-12"
className="mt-12 text-center"
>
<button
className="inline-flex items-center gap-2 text-[#1B4F72] font-semibold border-2 border-[#1B4F72] px-8 py-3 rounded-full hover:bg-[#1B4F72] hover:text-white transition-all duration-300"
className="inline-flex items-center gap-2 rounded-full border-2 border-[#1B4F72] px-8 py-3 font-semibold text-[#1B4F72] transition-all duration-300 hover:bg-[#1B4F72] hover:text-white"
onClick={() => {
toast("Tutti i servizi", { description: "La pagina completa dei servizi sara disponibile a breve." });
}}