338 lines
12 KiB
TypeScript
338 lines
12 KiB
TypeScript
'use client'
|
||
import React, { useState, useEffect, useRef } from "react";
|
||
|
||
export default function Process() {
|
||
const [activeStep, setActiveStep] = useState(-1);
|
||
const [scrollProgress, setScrollProgress] = useState(0);
|
||
const containerRef = useRef<HTMLDivElement>(null);
|
||
const timelineRef = useRef<HTMLDivElement>(null);
|
||
|
||
useEffect(() => {
|
||
const handleScroll = () => {
|
||
if (!containerRef.current || !timelineRef.current) return;
|
||
|
||
const container = containerRef.current;
|
||
const timeline = timelineRef.current;
|
||
const rect = container.getBoundingClientRect();
|
||
const timelineHeight = timeline.scrollHeight - timeline.clientHeight;
|
||
|
||
// Calculate when section enters viewport
|
||
if (rect.top <= 0 && rect.bottom >= window.innerHeight) {
|
||
// Section is sticky, scroll the timeline
|
||
const progress = Math.abs(rect.top) / (rect.height - window.innerHeight);
|
||
const clampedProgress = Math.max(0, Math.min(1, progress));
|
||
setScrollProgress(clampedProgress);
|
||
timeline.scrollTop = clampedProgress * timelineHeight;
|
||
} else if (rect.top > 0) {
|
||
// Before sticky
|
||
setScrollProgress(0);
|
||
timeline.scrollTop = 0;
|
||
} else {
|
||
// After sticky
|
||
setScrollProgress(1);
|
||
timeline.scrollTop = timelineHeight;
|
||
}
|
||
};
|
||
|
||
window.addEventListener('scroll', handleScroll);
|
||
handleScroll(); // Initial check
|
||
|
||
return () => window.removeEventListener('scroll', handleScroll);
|
||
}, []);
|
||
|
||
const CalendarIcon = (
|
||
<svg
|
||
width={34}
|
||
height={34}
|
||
viewBox="0 0 24 24"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
strokeWidth="2"
|
||
strokeLinecap="round"
|
||
strokeLinejoin="round"
|
||
>
|
||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2" />
|
||
<line x1="16" y1="2" x2="16" y2="6" />
|
||
<line x1="8" y1="2" x2="8" y2="6" />
|
||
<line x1="3" y1="10" x2="21" y2="10" />
|
||
</svg>
|
||
);
|
||
|
||
const steps = [
|
||
{
|
||
number: "1",
|
||
title: "2017",
|
||
description: "Formation of Trauma Services",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "2",
|
||
title: "2020",
|
||
description: "Establishment of the Department of Trauma Surgery under Dr. Sukria Nayak",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "3",
|
||
title: "May 2021",
|
||
description: "Development of Trauma Protocols (MHTP, TROB, TRIP, Airway, Obstetric Trauma)",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "4",
|
||
title: "June 2022",
|
||
description: "Inauguration of CMC Ranipet Campus: Level 1 Trauma Centre",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "5",
|
||
title: "November 2022",
|
||
description: "Formation of T-ReCS (Trauma Registry – CMC – Pilot Study) under TCI-CMC Research Scholar Program",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "6",
|
||
title: "November 2022",
|
||
description: "Integration of Multidisciplinary Trauma Services",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "7",
|
||
title: "November 2022",
|
||
description: "Formation of Neurotrauma Unit",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "8",
|
||
title: "January 2023",
|
||
description: "Accreditation of Trauma Radiology Fellowship",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "9",
|
||
title: "August 2023",
|
||
description: "Inaugural ATLS® Course at CMC Vellore",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "10",
|
||
title: "September 2023",
|
||
description: "First Research Publication from the Department",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "11",
|
||
title: "October 2023",
|
||
description: "ACTraM Conference: Advances in Chest Trauma Management",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "12",
|
||
title: "October 2023",
|
||
description: "CME Cadaveric Workshop",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "13",
|
||
title: "December 2023",
|
||
description: "ICMR Trauma Quality Improvement Programme (TQIP) Initiated at CMC",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "14",
|
||
title: "February 2024",
|
||
description: "HOPE Grant & RCPSG Trauma First Responder Outreach Programme",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "15",
|
||
title: "April 2024",
|
||
description: "Launch of Masters of Trauma Online Lecture Series",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "16",
|
||
title: "April 2024",
|
||
description: "Inaugural ATCN® Course for Nurses",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "17",
|
||
title: "July 2024",
|
||
description: "MOU with GVK EMRI for Strengthening Pre-hospital Trauma Care",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "18",
|
||
title: "July 2024",
|
||
description: "Accreditation for FNB in Trauma and Acute Care Surgery",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "19",
|
||
title: "January 2025",
|
||
description: "Trauma Quality Workshop under ICMR-TQIP at CMC Vellore",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "20",
|
||
title: "March 2025",
|
||
description: "Formation of CMC Trauma Quality Improvement Committee",
|
||
icon: CalendarIcon,
|
||
},
|
||
{
|
||
number: "21",
|
||
title: "July 2025",
|
||
description: "Establishment of Trauma Orthopaedics Unit",
|
||
icon: CalendarIcon,
|
||
},
|
||
];
|
||
|
||
// Calculate extra height needed for scroll effect
|
||
const extraHeight = 2000;
|
||
|
||
return (
|
||
<div
|
||
ref={containerRef}
|
||
className="bg-white py-10 sm:py-10"
|
||
style={{ minHeight: `calc(100vh + ${extraHeight}px)` }}
|
||
>
|
||
<div className="sticky top-0 h-screen flex items-start pt-12 sm:pt-20">
|
||
<div className="max-w-7xl mx-auto px-4 sm:px-6 w-full">
|
||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 items-start">
|
||
{/* Left Column */}
|
||
<div className="flex flex-col justify-start">
|
||
<div>
|
||
<div className="text-xl mb-4" style={{ color: "#e64838" }}>
|
||
Milestones
|
||
</div>
|
||
<h2
|
||
className="text-3xl sm:text-4xl md:text-5xl font-bold leading-tight mb-6"
|
||
style={{ color: "#012068" }}
|
||
>
|
||
Our Journey in Trauma Care
|
||
</h2>
|
||
<p className="text-base sm:text-lg leading-relaxed mb-8" style={{ color: '#333' }}>
|
||
From the formation of Trauma Services in 2017 to establishing a Level-1 Trauma Facility and comprehensive trauma care programs, we continue to expand our emergency care services with dedication and excellence.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Right Column - Auto-scrolling Timeline */}
|
||
<div className="relative h-[600px]">
|
||
<div
|
||
ref={timelineRef}
|
||
className="h-full overflow-y-auto pr-2 pl-2 py-2 [&::-webkit-scrollbar]:hidden pointer-events-none"
|
||
style={{
|
||
scrollbarWidth: 'none',
|
||
msOverflowStyle: 'none'
|
||
}}
|
||
>
|
||
{steps.map((step, index) => (
|
||
<div
|
||
key={index}
|
||
className={`relative group transition-all duration-500 ${
|
||
index !== 0 ? "mt-8 sm:mt-12" : ""
|
||
} ${index === 0 ? "pt-2" : ""}`}
|
||
onMouseEnter={() => setActiveStep(index)}
|
||
onMouseLeave={() => setActiveStep(-1)}
|
||
>
|
||
{/* Connecting Line */}
|
||
{index !== 0 && (
|
||
<div className="absolute left-6 -top-8 sm:-top-12 w-0.5 h-8 sm:h-12 bg-gray-300 overflow-hidden">
|
||
<div
|
||
className={`w-full transition-all duration-700 ease-out origin-bottom ${
|
||
activeStep >= index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "h-full scale-y-100"
|
||
: "h-0 scale-y-0"
|
||
}`}
|
||
style={{ backgroundColor: "#012068" }}
|
||
/>
|
||
</div>
|
||
)}
|
||
|
||
{/* Step Content */}
|
||
<div className="flex items-start gap-4 sm:gap-6">
|
||
{/* Number Circle */}
|
||
<div
|
||
className={`relative z-10 flex-shrink-0 w-12 h-12 rounded-full flex items-center justify-center text-white font-semibold text-lg transition-all duration-500 transform ${
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "scale-110 shadow-lg ring-4"
|
||
: "scale-100 hover:scale-105"
|
||
}`}
|
||
style={{
|
||
backgroundColor:
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "#012068"
|
||
: "#333",
|
||
"--tw-ring-color":
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "#012068" + "33"
|
||
: "transparent",
|
||
} as React.CSSProperties}
|
||
>
|
||
{step.number}
|
||
</div>
|
||
|
||
{/* Step Card */}
|
||
<div
|
||
className={`flex-1 p-4 sm:p-6 rounded-lg border transition-all duration-500 transform ${
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "border-transparent text-white shadow-2xl scale-105 -translate-y-2"
|
||
: "border-gray-300 hover:shadow-lg hover:-translate-y-1"
|
||
}`}
|
||
style={{
|
||
backgroundColor:
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "#012068"
|
||
: "#f4f4f4",
|
||
color:
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "white"
|
||
: "#333",
|
||
}}
|
||
>
|
||
{/* Icon */}
|
||
<div
|
||
className={`mb-4 transition-all duration-500 transform ${
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "text-white"
|
||
: "scale-100 group-hover:scale-105"
|
||
}`}
|
||
style={{
|
||
color:
|
||
activeStep === index ||
|
||
(activeStep === -1 && index === 0)
|
||
? "white"
|
||
: "black",
|
||
}}
|
||
>
|
||
{step.icon}
|
||
</div>
|
||
|
||
{/* Text */}
|
||
<h3 className="text-lg sm:text-xl font-semibold mb-3 transition-all duration-300">
|
||
{step.title}
|
||
</h3>
|
||
<p className="text-sm sm:text-base leading-relaxed transition-all duration-500">
|
||
{step.description}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
} |