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

BIN
assets/ortovet.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,31 +1,57 @@
/* /*
* DESIGN: "Clinical Warmth" * DESIGN: "Clinical Warmth"
* Sezione servizi con 6 card principali allineate al menu della clinica. * Sezione servizi con due livelli:
* Layout: immagine in alto, bordo superiore colorato, hover lift. * - Servizi Clinici
* - Visite Specialistiche
*/ */
import { motion, useInView } from "framer-motion"; import { motion, useInView } from "framer-motion";
import { useRef } from "react"; 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"; 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", id: "visite-cliniche",
title: "Visite Cliniche", title: "Visite Cliniche",
subtitle: "Medicina preventiva", subtitle: "Medicina preventiva",
description: 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", image: "https://images.unsplash.com/photo-1628009368231-7bb7cfcb0def?w=900&q=85",
icon: Stethoscope, icon: Stethoscope,
color: "#1B4F72", color: "#1B4F72",
features: ["Check-up periodici", "Vaccinazioni", "Profilassi antiparassitaria", "Piani prevenzione senior"], features: ["Check-up periodici", "Vaccinazioni", "Profilassi antiparassitaria", "Controlli senior"],
}, },
{ {
id: "ecografia", id: "ecografia",
title: "Ecografia", title: "Ecografia",
subtitle: "Diagnostica non invasiva", subtitle: "Diagnostica non invasiva",
description: 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", image: "https://images.unsplash.com/photo-1579684385127-1ef15d508118?w=900&q=85",
icon: Activity, icon: Activity,
color: "#4ECDC4", color: "#4ECDC4",
@@ -36,7 +62,7 @@ const services = [
title: "Radiologia", title: "Radiologia",
subtitle: "Diagnostica per immagini", subtitle: "Diagnostica per immagini",
description: 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", image: "https://d2xsxph8kpxj0f.cloudfront.net/310519663483796440/DLUbzKbSnCG3dLeob4sLeC/radiology_39785f88.jpg",
icon: Scan, icon: Scan,
color: "#2E86AB", color: "#2E86AB",
@@ -47,7 +73,7 @@ const services = [
title: "Laboratorio", title: "Laboratorio",
subtitle: "Analisi interne", subtitle: "Analisi interne",
description: 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", image: "https://d2xsxph8kpxj0f.cloudfront.net/310519663483796440/DLUbzKbSnCG3dLeob4sLeC/laboratory_5a1c4119.jpg",
icon: FlaskConical, icon: FlaskConical,
color: "#1B4F72", color: "#1B4F72",
@@ -58,7 +84,7 @@ const services = [
title: "Endoscopia", title: "Endoscopia",
subtitle: "Esplorazione mini-invasiva", subtitle: "Esplorazione mini-invasiva",
description: 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", image: "https://images.unsplash.com/photo-1530026405186-ed1f139313f8?w=900&q=85",
icon: Video, icon: Video,
color: "#4ECDC4", color: "#4ECDC4",
@@ -69,7 +95,7 @@ const services = [
title: "Laparoscopia", title: "Laparoscopia",
subtitle: "Chirurgia mini-invasiva", subtitle: "Chirurgia mini-invasiva",
description: 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", image: "https://d2xsxph8kpxj0f.cloudfront.net/310519663483796440/DLUbzKbSnCG3dLeob4sLeC/surgery_e92904ed.jpg",
icon: Activity, icon: Activity,
color: "#2E86AB", 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 ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-50px" }); const isInView = useInView(ref, { once: true, margin: "-50px" });
const specialist = service.tone === "specialist";
return ( return (
<motion.div <motion.div
ref={ref} ref={ref}
initial={{ opacity: 0, y: 40 }} initial={{ opacity: 0, y: 40 }}
animate={isInView ? { opacity: 1, y: 0 } : {}} animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, delay: index * 0.12 }} transition={{ duration: 0.6, delay: index * 0.1 }}
className="group bg-white rounded-2xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-400 hover:-translate-y-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"> <div className="relative h-52 overflow-hidden">
<img <img
src={service.image} src={service.image}
alt={service.title} 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 <div
className="absolute top-4 right-4 w-12 h-12 rounded-full flex items-center justify-center shadow-lg" 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" /> <service.icon size={22} className="text-white" />
</div> </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>
<div className="p-6"> <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} {service.subtitle}
</div> </div>
<h3 <h3
className="text-[#1B4F72] mb-3" className="mb-3 text-[#1B4F72]"
style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "1.75rem", fontWeight: 600 }} style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "1.75rem", fontWeight: 600 }}
> >
{service.title} {service.title}
</h3> </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) => ( {service.features.map((feat) => (
<li key={feat} className="flex items-center gap-2 text-sm text-gray-600"> <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} {feat}
</li> </li>
))} ))}
</ul> </ul>
<button <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 }} style={{ color: service.color }}
onClick={() => { onClick={() => {
toast("Sezione in arrivo", { description: `La pagina dedicata a ${service.title} sara disponibile a breve.` }); 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" /> <ArrowRight size={15} className="transition-transform duration-200 group-hover/btn:translate-x-1" />
</button> </button>
</div> </div>
@@ -143,7 +252,9 @@ function ServiceCard({ service, index }: { service: typeof services[0]; index: n
export default function ServicesSection() { export default function ServicesSection() {
const ref = useRef(null); const ref = useRef(null);
const specialistRef = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-80px" }); const isInView = useInView(ref, { once: true, margin: "-80px" });
const specialistInView = useInView(specialistRef, { once: true, margin: "-80px" });
return ( return (
<section id="servizi" className="py-20 md:py-28" style={{ backgroundColor: "#F5F0E8" }}> <section id="servizi" className="py-20 md:py-28" style={{ backgroundColor: "#F5F0E8" }}>
@@ -155,38 +266,74 @@ export default function ServicesSection() {
transition={{ duration: 0.7 }} transition={{ duration: 0.7 }}
className="mb-14" className="mb-14"
> >
<div className="flex items-center gap-3 mb-4"> <div className="mb-4 flex items-center gap-3">
<div className="w-12 h-0.5 bg-[#4ECDC4]" /> <div className="h-0.5 w-12 bg-[#4ECDC4]" />
<span className="text-[#4ECDC4] text-sm font-semibold uppercase tracking-widest"> <span className="text-sm font-semibold uppercase tracking-widest text-[#4ECDC4]">
Specializzazioni Specializzazioni
</span> </span>
</div> </div>
<h2 <h2
className="text-[#1B4F72] mb-4" className="mb-4 text-[#1B4F72]"
style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "clamp(2rem, 4vw, 3rem)", fontWeight: 600 }} style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: "clamp(2rem, 4vw, 3rem)", fontWeight: 600 }}
> >
Servizi Specialistici Servizi Clinici
</h2> </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 Sei aree di eccellenza clinica per accompagnare prevenzione, diagnosi e trattamento
dei tuoi animali domestici, con tecnologie avanzate e professionisti esperti. dei tuoi animali domestici, con tecnologie avanzate e professionisti esperti.
</p> </p>
</motion.div> </motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-8"> <div className="grid grid-cols-1 gap-8 md:grid-cols-2 xl:grid-cols-3">
{services.map((service, index) => ( {clinicalServices.map((service, index) => (
<ServiceCard key={service.id} service={service} index={index} /> <ServiceCard key={service.id} service={service} index={index} />
))} ))}
</div> </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 <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={isInView ? { opacity: 1 } : {}} animate={specialistInView ? { opacity: 1 } : {}}
transition={{ duration: 0.7, delay: 0.6 }} transition={{ duration: 0.7, delay: 0.6 }}
className="text-center mt-12" className="mt-12 text-center"
> >
<button <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={() => { onClick={() => {
toast("Tutti i servizi", { description: "La pagina completa dei servizi sara disponibile a breve." }); toast("Tutti i servizi", { description: "La pagina completa dei servizi sara disponibile a breve." });
}} }}

View File

@@ -11,13 +11,33 @@
- endoscopia - endoscopia
- laparoscopia - laparoscopia
- viite specialistiche - visite specialistiche
- oncologia - oncologia
- dermatologia - dermatologia
- oculistica - oculistica
- nutrizione - nutrizione
- ortopedia - ortopedia
- team medico - Team medico
Dott. Paolo Parmeggiani
Dott.ssa Irene Paganelli
Dott. Simone Tinti
Dott.ssa Michela Sghedoni
Dott. Luca Pietri
-Collaborazioni
Dott. Andrea Arrigoni
Dott. Alessandro Poli
Dott.ssa Elena Venturelli
Dott.ssa Cinzia Pellegrini
-Team Tecnici Veterinari
Alessia Succi
Francesca Polato
Cristina Vecchi