From d63aaf8901a20802d3ad0a2327ad512f81a165dc Mon Sep 17 00:00:00 2001 From: mukeshs Date: Thu, 6 Nov 2025 10:29:44 +0530 Subject: [PATCH] Hero image and service admin upload updated --- src/components/about/StatisticsTiles.tsx | 123 +++++++++++++----- src/components/home/HeroSection.tsx | 151 ++++++++++++++++++++--- 2 files changed, 225 insertions(+), 49 deletions(-) diff --git a/src/components/about/StatisticsTiles.tsx b/src/components/about/StatisticsTiles.tsx index 56f9adf..af2f6fe 100644 --- a/src/components/about/StatisticsTiles.tsx +++ b/src/components/about/StatisticsTiles.tsx @@ -1,30 +1,80 @@ -import React from 'react'; -import { ShieldPlus, UserCheck, Hospital, BookOpen } from 'lucide-react'; +'use client'; + +import React, { useState, useEffect } from 'react'; + +interface ServiceTile { + id: number; + title: string; + description: string; + isActive: boolean; + displayOrder: number; + createdDate: string; + lastModified: string; +} const StatisticsTiles = () => { - const tiles = [ + const [tiles, setTiles] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + + // Default fallback data + const defaultTiles = [ { - icon: , title: "Primary Trauma Care", description: "Specialized care for Priority One trauma patients in close coordination with the Emergency Department team." }, { - icon: , - title: "24×7 Trauma Surgeon", + title: "24x7 Trauma Surgeon", description: "Round-the-clock availability of trauma surgeons ensures immediate surgical intervention when needed." }, { - icon: , title: "Trauma Intensive & Ward Care", description: "Comprehensive trauma intensive care and dedicated trauma ward services for critical and recovering patients." }, { - icon: , title: "Trauma Education", description: "Focused education and counseling for patients and families to enhance recovery and awareness." }, ]; + useEffect(() => { + const fetchServiceTiles = async () => { + try { + const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080'; + const response = await fetch(`${apiUrl}/service-tiles/active`); + + if (response.ok) { + const data: ServiceTile[] = await response.json(); + // Filter active tiles and sort by display order + const activeTiles = data + .filter(tile => tile.isActive) + .sort((a, b) => a.displayOrder - b.displayOrder); + + if (activeTiles.length > 0) { + setTiles(activeTiles); + setError(false); + } else { + // No active tiles, use defaults + setError(true); + } + } else { + // API error, use defaults + setError(true); + } + } catch (err) { + console.error('Error fetching service tiles:', err); + setError(true); + } finally { + setLoading(false); + } + }; + + fetchServiceTiles(); + }, []); + + // Use fetched tiles or fall back to default + const displayTiles = error || tiles.length === 0 ? defaultTiles : tiles; + return (
@@ -34,37 +84,44 @@ const StatisticsTiles = () => { > Our Trauma Care Services -
- {tiles.map((tile, index) => ( -
-
-
-
- {tile.icon} + + {loading ? ( + // Loading state +
+
+
+ ) : ( + // Display tiles +
+ {displayTiles.map((tile, index) => ( +
+
+
+

+ {tile.title} +

-

- {tile.title} -

+ {tile.description} +

-

- {tile.description} -

-
- ))} -
+ ))} +
+ )}
); }; -export default StatisticsTiles; +export default StatisticsTiles; \ No newline at end of file diff --git a/src/components/home/HeroSection.tsx b/src/components/home/HeroSection.tsx index 4a27bd4..9555e9c 100644 --- a/src/components/home/HeroSection.tsx +++ b/src/components/home/HeroSection.tsx @@ -1,16 +1,121 @@ -import React from 'react'; +'use client'; + +import React, { useState, useEffect } from 'react'; import Image from 'next/image'; +interface HeroImage { + id: number; + title: string; + subtitle: string; + description: string; + imageUrl: string; + imageFilename: string; + isActive: boolean; + uploadDate: string; + lastModified: string; +} + const HeroSection = () => { + const [heroData, setHeroData] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + + // Default fallback data + const defaultHeroData = { + title: 'This year, we celebrate', + subtitle: '125 years of CMC Vellore', + description: '1900 - 2025', + imageUrl: '/images/heronew.png', + }; + + useEffect(() => { + const fetchHeroImage = async () => { + try { + const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080'; + console.log('Fetching from:', `${apiUrl}/hero/active`); // Debug log + + const response = await fetch(`${apiUrl}/hero/active`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + cache: 'no-store', // Disable caching to always get fresh data + }); + + if (response.ok) { + const data: HeroImage = await response.json(); + console.log('Hero image data:', data); // Debug log + setHeroData(data); + setError(false); + } else { + console.error('Failed to fetch hero image:', response.status); + setError(true); + } + } catch (err) { + console.error('Error fetching hero image:', err); + setError(true); + } finally { + setLoading(false); + } + }; + + fetchHeroImage(); + }, []); + + // Use fetched data or fall back to default + const displayData = heroData || defaultHeroData; + + // ✅ FIX: Construct full image URL with API base URL + const getImageUrl = () => { + if (!heroData) { + return defaultHeroData.imageUrl; // Local fallback image + } + + const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080'; + + // If imageUrl already contains the full URL (starts with http), use it directly + if (heroData.imageUrl.startsWith('http')) { + return heroData.imageUrl; + } + + // Otherwise, construct the full URL + // Remove leading slash from imageUrl if present to avoid double slashes + const imagePath = heroData.imageUrl.startsWith('/') + ? heroData.imageUrl.slice(1) + : heroData.imageUrl; + + return `${apiUrl}/${imagePath}`; + }; + + const imageUrl = getImageUrl(); + + console.log('Final image URL:', imageUrl); // Debug log + return (
{/* Background Image */} - CMC Vellore 125 years celebration + {heroData ? ( + // For API images - use full URL with API base + {displayData.title} { + console.error('Image failed to load:', imageUrl); + // Fallback to default image on error + e.currentTarget.src = defaultHeroData.imageUrl; + }} + /> + ) : ( + // For local images (fallback) + {displayData.title} + )} {/* Main Content */}
@@ -19,15 +124,15 @@ const HeroSection = () => {
{/* Main Heading */}

-
- This year, we celebrate 125 years -
-
- of CMC Vellore -
-
- 1900 - 2025 -
+
+ This year, we celebrate 125 years +
+
+ of CMC Vellore +
+
+ 1900 - 2025 +

{/* CTA Button */} @@ -46,6 +151,20 @@ const HeroSection = () => {
+ + {/* Loading indicator */} + {loading && ( +
+
+
+ )} + + {/* Error indicator (for debugging) */} + {error && process.env.NODE_ENV === 'development' && ( +
+ Failed to load hero image +
+ )} ); };