Skip to content

Commit a851ee9

Browse files
Merge pull request #77 from kunalverma2512/feature/health-information-hub
Add Comprehensive Healthcare Information Hub
2 parents 370091c + 28bb3b6 commit a851ee9

File tree

17 files changed

+3433
-309
lines changed

17 files changed

+3433
-309
lines changed

client/package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"lucide-react": "^0.540.0",
1717
"react": "^19.1.1",
1818
"react-dom": "^19.1.1",
19+
"react-icons": "^5.5.0",
1920
"react-markdown": "^10.1.0",
2021
"react-router-dom": "^7.8.1",
2122
"react-toastify": "^11.0.5",

client/src/App.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import WellnessHub from './pages/WellnessHub'
1212
import HumanBodyExplorer from './pages/HumanBodyExplorer'
1313
import AirQualityForecaster from './pages/AirQualityForecaster'
1414
import ClinicalTrialFinder from './pages/ClinicalTrialFinder'
15+
import Hub from './pages/Hub'
1516

1617

1718
const App = () => {
@@ -29,6 +30,9 @@ const App = () => {
2930
<Route path="/human-body-explorer" element={<HumanBodyExplorer />} />
3031
<Route path="/air-quality-forecaster" element={<AirQualityForecaster />} />
3132
<Route path="/clinical-trial-finder" element={<ClinicalTrialFinder />} />
33+
34+
<Route path="/hub" element={<Hub />} />
35+
3236
<Route path="*" element={<NotFoundPage/>} />
3337
</Route>
3438
</Routes>
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
import React, { useRef, useState, useEffect } from 'react';
2+
import { motion, useInView, AnimatePresence } from 'framer-motion';
3+
4+
const featuredContent = [
5+
{
6+
id: 1,
7+
title: 'AI-Enhanced Health Education',
8+
description: 'Interactive health learning experiences with personalized medical education content, symptom checkers, and evidence-based health guidance.',
9+
image: '🧠',
10+
category: 'Health Education',
11+
metrics: 'Interactive Learning',
12+
color: 'from-purple-500 to-indigo-600'
13+
},
14+
{
15+
id: 2,
16+
title: 'Comprehensive Medicine Guide',
17+
description: 'Detailed medication information, drug interactions, dosage guidelines, and safe medication management practices.',
18+
image: '💊',
19+
category: 'Medication Safety',
20+
metrics: 'Safe Usage',
21+
color: 'from-blue-500 to-cyan-600'
22+
},
23+
{
24+
id: 3,
25+
title: 'Global Health Insights',
26+
description: 'Worldwide health trends, disease prevention strategies, and public health information from trusted medical sources.',
27+
image: '🌍',
28+
category: 'Public Health',
29+
metrics: 'Global Coverage',
30+
color: 'from-emerald-500 to-teal-600'
31+
},
32+
{
33+
id: 4,
34+
title: 'Environmental Wellness',
35+
description: 'Environmental health factors, air quality awareness, water safety, and creating healthier living environments.',
36+
image: '🌿',
37+
category: 'Environmental Health',
38+
metrics: 'Clean Living',
39+
color: 'from-green-500 to-emerald-600'
40+
},
41+
{
42+
id: 5,
43+
title: 'Medical Research Updates',
44+
description: 'Latest medical breakthroughs, research findings, clinical studies, and evidence-based health recommendations.',
45+
image: '🔬',
46+
category: 'Medical Research',
47+
metrics: 'Latest Studies',
48+
color: 'from-orange-500 to-red-600'
49+
}
50+
];
51+
52+
const FeaturedCarousel = () => {
53+
const [currentIndex, setCurrentIndex] = useState(0);
54+
const [isAutoPlaying, setIsAutoPlaying] = useState(true);
55+
const [isMobile, setIsMobile] = useState(false);
56+
const ref = useRef(null);
57+
const isInView = useInView(ref, { once: true, threshold: 0.3 });
58+
59+
// Handle mobile detection
60+
useEffect(() => {
61+
const checkMobile = () => {
62+
setIsMobile(window.innerWidth < 768);
63+
};
64+
65+
checkMobile();
66+
window.addEventListener('resize', checkMobile);
67+
68+
return () => window.removeEventListener('resize', checkMobile);
69+
}, []);
70+
71+
// Auto-advance carousel
72+
useEffect(() => {
73+
if (!isAutoPlaying || !isInView) return;
74+
75+
const interval = setInterval(() => {
76+
setCurrentIndex((prev) => (prev + 1) % featuredContent.length);
77+
}, 5000);
78+
79+
return () => clearInterval(interval);
80+
}, [isAutoPlaying, isInView]);
81+
82+
const goToSlide = (index) => {
83+
setCurrentIndex(index);
84+
setIsAutoPlaying(false);
85+
setTimeout(() => setIsAutoPlaying(true), 10000);
86+
};
87+
88+
const nextSlide = () => {
89+
setCurrentIndex((prev) => (prev + 1) % featuredContent.length);
90+
setIsAutoPlaying(false);
91+
setTimeout(() => setIsAutoPlaying(true), 10000);
92+
};
93+
94+
const prevSlide = () => {
95+
setCurrentIndex((prev) => (prev - 1 + featuredContent.length) % featuredContent.length);
96+
setIsAutoPlaying(false);
97+
setTimeout(() => setIsAutoPlaying(true), 10000);
98+
};
99+
100+
return (
101+
<div className="max-w-7xl mx-auto px-4 sm:px-6">
102+
<motion.div
103+
ref={ref}
104+
initial={{ opacity: 0, y: 30 }}
105+
animate={isInView ? { opacity: 1, y: 0 } : {}}
106+
transition={{ duration: 0.8 }}
107+
className="text-center mb-12 sm:mb-16"
108+
>
109+
<div className="inline-flex items-center gap-2 px-3 sm:px-4 py-2 bg-indigo-100 rounded-full mb-4 sm:mb-6">
110+
<div className="w-2 h-2 bg-indigo-500 rounded-full animate-pulse"></div>
111+
<span className="text-xs sm:text-sm font-medium text-indigo-700">Featured Health Resources</span>
112+
</div>
113+
114+
<h2 className="text-3xl sm:text-4xl lg:text-5xl font-bold mb-4 sm:mb-6 text-slate-800">
115+
Advanced Health
116+
<br />
117+
<span className="bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">
118+
Knowledge Platform
119+
</span>
120+
</h2>
121+
122+
<p className="text-base sm:text-xl text-slate-600 max-w-3xl mx-auto px-4">
123+
Discover comprehensive health resources powered by medical expertise and evidence-based information
124+
</p>
125+
</motion.div>
126+
127+
{/* Main Carousel */}
128+
<div className="relative">
129+
{/* Carousel Container - Mobile optimized height */}
130+
<div className="relative h-[500px] sm:h-[400px] md:h-96 lg:h-[32rem] overflow-hidden rounded-2xl sm:rounded-3xl bg-white/50 backdrop-blur-sm border border-white/60 shadow-2xl">
131+
<AnimatePresence mode="wait">
132+
<motion.div
133+
key={currentIndex}
134+
initial={{ opacity: 0, x: isMobile ? 200 : 300 }}
135+
animate={{ opacity: 1, x: 0 }}
136+
exit={{ opacity: 0, x: isMobile ? -200 : -300 }}
137+
transition={{ duration: 0.5, ease: [0.25, 0.46, 0.45, 0.94] }}
138+
className="absolute inset-0"
139+
>
140+
{/* Mobile Layout (Stacked) */}
141+
<div className="md:hidden flex flex-col items-center justify-center w-full h-full p-6 text-center">
142+
{/* Visual Section - Top on mobile */}
143+
<div className="flex items-center justify-center mb-6">
144+
<div className={`relative w-32 h-32 bg-gradient-to-br ${featuredContent[currentIndex].color} rounded-2xl flex items-center justify-center shadow-xl`}>
145+
<div className="text-4xl">
146+
{featuredContent[currentIndex].image}
147+
</div>
148+
149+
{/* Floating Elements */}
150+
<motion.div
151+
animate={{
152+
y: [0, -8, 0],
153+
rotate: [0, 5, 0]
154+
}}
155+
transition={{
156+
duration: 3,
157+
repeat: Infinity,
158+
ease: "easeInOut"
159+
}}
160+
className="absolute -top-2 -right-2 w-8 h-8 bg-white/20 backdrop-blur-sm rounded-lg border border-white/30"
161+
></motion.div>
162+
</div>
163+
</div>
164+
165+
{/* Content Section - Bottom on mobile */}
166+
<div className="flex-1 w-full max-w-sm">
167+
<div className="inline-flex items-center gap-2 px-3 py-1 bg-white/80 rounded-full mb-3">
168+
<span className="text-xs font-medium text-slate-600">
169+
{featuredContent[currentIndex].category}
170+
</span>
171+
</div>
172+
173+
<h3 className="text-xl font-bold text-slate-800 mb-3 leading-tight">
174+
{featuredContent[currentIndex].title}
175+
</h3>
176+
177+
<p className="text-sm text-slate-600 mb-4 leading-relaxed">
178+
{featuredContent[currentIndex].description}
179+
</p>
180+
181+
<div className="flex flex-col gap-3">
182+
<div className="flex items-center justify-center gap-3">
183+
<div className={`w-10 h-10 bg-gradient-to-r ${featuredContent[currentIndex].color} rounded-lg flex items-center justify-center text-white font-bold text-sm shadow-lg`}>
184+
185+
</div>
186+
<span className="text-sm text-slate-600 font-medium">
187+
{featuredContent[currentIndex].metrics}
188+
</span>
189+
</div>
190+
191+
<button className={`w-full px-6 py-3 bg-gradient-to-r ${featuredContent[currentIndex].color} text-white rounded-xl font-semibold text-sm hover:shadow-lg transition-all duration-300 hover:scale-105`}>
192+
Learn More
193+
</button>
194+
</div>
195+
</div>
196+
</div>
197+
198+
{/* Desktop/Tablet Layout (Side by side) */}
199+
<div className="hidden md:flex items-center justify-between w-full h-full p-8 lg:p-16">
200+
{/* Content Side */}
201+
<div className="flex-1 lg:pr-12 text-left">
202+
<div className="inline-flex items-center gap-2 px-3 py-1 bg-white/80 rounded-full mb-4">
203+
<span className="text-sm font-medium text-slate-600">
204+
{featuredContent[currentIndex].category}
205+
</span>
206+
</div>
207+
208+
<h3 className="text-2xl lg:text-4xl font-bold text-slate-800 mb-4 leading-tight">
209+
{featuredContent[currentIndex].title}
210+
</h3>
211+
212+
<p className="text-base lg:text-lg text-slate-600 mb-6 leading-relaxed max-w-lg">
213+
{featuredContent[currentIndex].description}
214+
</p>
215+
216+
<div className="flex flex-col sm:flex-row gap-4">
217+
<div className="flex items-center gap-3">
218+
<div className={`w-12 h-12 bg-gradient-to-r ${featuredContent[currentIndex].color} rounded-xl flex items-center justify-center text-white font-bold text-sm shadow-lg`}>
219+
220+
</div>
221+
<span className="text-sm text-slate-600 font-medium">
222+
{featuredContent[currentIndex].metrics}
223+
</span>
224+
</div>
225+
226+
<button className={`px-6 py-3 bg-gradient-to-r ${featuredContent[currentIndex].color} text-white rounded-xl font-semibold hover:shadow-lg transition-all duration-300 hover:scale-105`}>
227+
Learn More
228+
</button>
229+
</div>
230+
</div>
231+
232+
{/* Visual Side */}
233+
<div className="flex-1 flex items-center justify-center lg:justify-end">
234+
<div className={`relative w-64 lg:w-80 h-64 lg:h-80 bg-gradient-to-br ${featuredContent[currentIndex].color} rounded-3xl flex items-center justify-center shadow-2xl`}>
235+
<div className="text-7xl lg:text-9xl">
236+
{featuredContent[currentIndex].image}
237+
</div>
238+
239+
{/* Floating Elements */}
240+
<motion.div
241+
animate={{
242+
y: [0, -10, 0],
243+
rotate: [0, 5, 0]
244+
}}
245+
transition={{
246+
duration: 3,
247+
repeat: Infinity,
248+
ease: "easeInOut"
249+
}}
250+
className="absolute -top-4 -right-4 w-16 h-16 bg-white/20 backdrop-blur-sm rounded-2xl border border-white/30"
251+
></motion.div>
252+
253+
<motion.div
254+
animate={{
255+
y: [0, 15, 0],
256+
rotate: [0, -5, 0]
257+
}}
258+
transition={{
259+
duration: 4,
260+
repeat: Infinity,
261+
ease: "easeInOut",
262+
delay: 1
263+
}}
264+
className="absolute -bottom-6 -left-6 w-12 h-12 bg-white/20 backdrop-blur-sm rounded-xl border border-white/30"
265+
></motion.div>
266+
</div>
267+
</div>
268+
</div>
269+
</motion.div>
270+
</AnimatePresence>
271+
272+
{/* Navigation Arrows */}
273+
<button
274+
onClick={prevSlide}
275+
className="absolute left-2 sm:left-4 top-1/2 -translate-y-1/2 w-10 sm:w-12 h-10 sm:h-12 bg-white/80 backdrop-blur-sm rounded-full flex items-center justify-center shadow-lg hover:bg-white transition-all duration-300 hover:scale-110 z-10"
276+
>
277+
<svg className="w-5 sm:w-6 h-5 sm:h-6 text-slate-700" fill="none" viewBox="0 0 24 24" stroke="currentColor">
278+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
279+
</svg>
280+
</button>
281+
282+
<button
283+
onClick={nextSlide}
284+
className="absolute right-2 sm:right-4 top-1/2 -translate-y-1/2 w-10 sm:w-12 h-10 sm:h-12 bg-white/80 backdrop-blur-sm rounded-full flex items-center justify-center shadow-lg hover:bg-white transition-all duration-300 hover:scale-110 z-10"
285+
>
286+
<svg className="w-5 sm:w-6 h-5 sm:h-6 text-slate-700" fill="none" viewBox="0 0 24 24" stroke="currentColor">
287+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
288+
</svg>
289+
</button>
290+
</div>
291+
292+
{/* Progress Indicators */}
293+
<div className="flex justify-center mt-6 sm:mt-8 gap-2 sm:gap-3">
294+
{featuredContent.map((_, index) => (
295+
<button
296+
key={index}
297+
onClick={() => goToSlide(index)}
298+
className={`relative overflow-hidden rounded-full transition-all duration-300 ${
299+
index === currentIndex
300+
? 'w-8 sm:w-12 h-2 sm:h-3 bg-gradient-to-r from-indigo-500 to-purple-600'
301+
: 'w-2 sm:w-3 h-2 sm:h-3 bg-slate-300 hover:bg-slate-400'
302+
}`}
303+
>
304+
{index === currentIndex && isAutoPlaying && (
305+
<motion.div
306+
initial={{ width: '0%' }}
307+
animate={{ width: '100%' }}
308+
transition={{ duration: 5, ease: 'linear' }}
309+
className="h-full bg-white/30 rounded-full"
310+
/>
311+
)}
312+
</button>
313+
))}
314+
</div>
315+
</div>
316+
</div>
317+
);
318+
};
319+
320+
export default FeaturedCarousel;

0 commit comments

Comments
 (0)