Changes on 19-11-2025

This commit is contained in:
2025-11-19 15:01:00 +05:30
parent f55a506ea5
commit 4db6f5d132
8 changed files with 579 additions and 277 deletions

View File

@ -7,18 +7,24 @@ import { usePathname } from "next/navigation";
const Header = () => { const Header = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isServicesOpen, setIsServicesOpen] = useState(false);
const [isMobileServicesOpen, setIsMobileServicesOpen] = useState(false);
const pathname = usePathname(); const pathname = usePathname();
const closeAllMenus = () => { const closeAllMenus = () => {
setIsMenuOpen(false); setIsMenuOpen(false);
setIsServicesOpen(false);
setIsMobileServicesOpen(false);
}; };
const menuItems = [ const menuItems = [
{ href: "/", label: "Home" }, { href: "/", label: "Home" },
{ href: "/about", label: "About" }, { href: "/about", label: "About" },
{ href: "/teamMember", label: "Our Team" }, { href: "/teamMember", label: "Our Team" },
{ href: "/education-training", label: "Academics & Research" }, { href: "/education-training", label: "Academics & Research" },
{ href: "/services", label: "Services" }, { href: "/services", label: "Services", hasDropdown: true },
{ href: "/events", label: "Events" }, { href: "/events", label: "Events" },
{ href: "/blogs", label: "Blogs" }, { href: "/blogs", label: "Blogs" },
{ href: "/career", label: "Career" }, { href: "/career", label: "Career" },
@ -77,6 +83,50 @@ const Header = () => {
{menuItems.map((item, idx) => { {menuItems.map((item, idx) => {
const isActive = pathname === item.href || const isActive = pathname === item.href ||
(item.href !== "/" && pathname.startsWith(item.href)); (item.href !== "/" && pathname.startsWith(item.href));
if (item.hasDropdown) {
return (
<div
key={idx}
className="relative flex-1"
onMouseEnter={() => setIsServicesOpen(true)}
onMouseLeave={() => setIsServicesOpen(false)}
>
<Link
href="/services"
className={`font-medium text-sm xl:text-[15px] whitespace-nowrap px-4 xl:px-5 py-3.5 transition-colors w-full ${
isActive
? "text-white bg-red-600"
: "text-white hover:bg-red-600"
} flex items-center justify-center gap-1`}
>
{item.label}
<svg
className={`w-4 h-4 transition-transform ${isServicesOpen ? "rotate-180" : ""}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</Link>
{/* Services Dropdown */}
{isServicesOpen && (
<div className="absolute top-full left-0 mt-0 w-64 bg-white shadow-lg border border-gray-200 rounded-b-md z-50">
<Link
href="/services/acute-care-surgery"
className="block px-4 py-3 text-sm font-medium text-blue-900 hover:bg-gray-100 hover:text-red-600 transition-colors"
onClick={closeAllMenus}
>
Acute Care Surgery Services
</Link>
</div>
)}
</div>
);
}
return ( return (
<Link <Link
key={idx} key={idx}
@ -95,7 +145,7 @@ const Header = () => {
</div> </div>
</nav> </nav>
{/* Mobile menu button - More visible */} {/* Mobile menu button */}
<button <button
className="lg:hidden p-3 text-white hover:bg-red-600 transition-colors w-full flex items-center justify-between" className="lg:hidden p-3 text-white hover:bg-red-600 transition-colors w-full flex items-center justify-between"
onClick={() => setIsMenuOpen(!isMenuOpen)} onClick={() => setIsMenuOpen(!isMenuOpen)}
@ -136,6 +186,47 @@ const Header = () => {
{menuItems.map((item, idx) => { {menuItems.map((item, idx) => {
const isActive = pathname === item.href || const isActive = pathname === item.href ||
(item.href !== "/" && pathname.startsWith(item.href)); (item.href !== "/" && pathname.startsWith(item.href));
if (item.hasDropdown) {
return (
<li key={idx}>
<button
className={`w-full text-left font-medium py-3 px-4 transition-colors rounded text-sm sm:text-base flex items-center justify-between ${
isActive
? "bg-red-600 text-white"
: "text-blue-900 hover:bg-gray-100 hover:text-red-600"
}`}
onClick={() => setIsMobileServicesOpen(!isMobileServicesOpen)}
>
{item.label}
<svg
className={`w-4 h-4 transition-transform ${isMobileServicesOpen ? "rotate-180" : ""}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>
{/* Mobile Services Submenu */}
{isMobileServicesOpen && (
<ul className="ml-4 mt-1 space-y-1">
<li>
<Link
href="/services/acute-care-surgery"
className="block py-2.5 px-4 text-sm font-medium text-gray-700 hover:bg-gray-100 hover:text-red-600 rounded transition-colors"
onClick={closeAllMenus}
>
Acute Care Surgery Services
</Link>
</li>
</ul>
)}
</li>
);
}
return ( return (
<li key={idx}> <li key={idx}>
<Link <Link

View File

@ -64,10 +64,10 @@ const StatisticsTiles = () => {
}; };
return ( return (
<section className="py-8 sm:py-12" style={{ backgroundColor: '#f4f4f4' }}> <section className="py-12 sm:py-16" style={{ backgroundColor: '#f4f4f4' }}>
<div className="max-w-7xl mx-auto px-4"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h2 <h2
className="text-2xl sm:text-3xl font-semibold text-center mb-8 sm:mb-12" className="text-3xl sm:text-4xl font-bold text-center mb-12 sm:mb-16"
style={{ color: '#012068' }} style={{ color: '#012068' }}
> >
Our Trauma Care Services Our Trauma Care Services
@ -86,33 +86,31 @@ const StatisticsTiles = () => {
</p> </p>
</div> </div>
) : ( ) : (
// Display tiles // Display services one after another
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 lg:gap-6"> <div className="space-y-8">
{tiles.map((tile, index) => ( {tiles.map((tile, index) => (
<div <div key={tile.id} className="text-left">
key={tile.id} <h3
className="border border-gray-300 rounded-lg p-5 h-full hover:shadow-lg transition-shadow duration-300" className="text-xl sm:text-2xl font-bold mb-4 pb-2 border-b-2 inline-block"
style={{ backgroundColor: '#ffffff' }} style={{ color: '#012068', borderColor: '#012068' }}
> >
<div className="flex flex-col h-full"> {tile.title}
<h3 </h3>
className="text-base sm:text-lg font-semibold mb-3 text-left" <ul className="space-y-2.5 mt-4">
style={{ color: '#012068' }} {parseDescription(tile.description).map((point, idx) => (
> <li
{tile.title} key={idx}
</h3> className="text-sm sm:text-base leading-relaxed flex items-start"
<ul className="list-disc pl-5 space-y-2 flex-grow text-left"> style={{ color: '#333' }}
{parseDescription(tile.description).map((point, idx) => ( >
<li <span
key={idx} className="inline-block w-1.5 h-1.5 rounded-full mt-2 mr-3 flex-shrink-0"
className="text-sm sm:text-base leading-relaxed text-left" style={{ backgroundColor: '#012068' }}
style={{ color: '#333' }} ></span>
> <span>{point}</span>
{point} </li>
</li> ))}
))} </ul>
</ul>
</div>
</div> </div>
))} ))}
</div> </div>

View File

@ -116,20 +116,6 @@ const BlogDetail: React.FC = () => {
target.src = '/images/default-blog-image.jpg'; target.src = '/images/default-blog-image.jpg';
}; };
const getAuthorName = (blog: Blog) => {
if (blog.professors && blog.professors.length > 0) {
return blog.professors.map(prof => prof.firstName || prof.name).join(', ');
}
return 'Medical Team';
};
const getAuthorBio = (blog: Blog) => {
if (blog.professors && blog.professors.length > 0) {
return `Medical professional${blog.professors.length > 1 ? 's' : ''} specializing in trauma care and mental health support.`;
}
return 'Our medical team consists of experienced professionals dedicated to trauma care and mental health support.';
};
if (!mounted) { if (!mounted) {
return null; return null;
} }
@ -286,23 +272,6 @@ const BlogDetail: React.FC = () => {
<span>{blogData.readTime}</span> <span>{blogData.readTime}</span>
</div> </div>
</div> </div>
{/* Author Info */}
<div className="flex items-start space-x-4 mt-6 p-4 rounded-lg" style={{ backgroundColor: '#f4f4f4' }}>
<div className="w-15 h-15 bg-gray-300 rounded-full flex items-center justify-center flex-shrink-0">
<span className="text-2xl font-medium" style={{ color: '#012068' }}>
{getAuthorName(blogData).charAt(0)}
</span>
</div>
<div>
<h3 className="font-medium" style={{ color: '#012068' }}>
{getAuthorName(blogData)}
</h3>
<p className="text-sm mt-1" style={{ color: '#666' }}>
{getAuthorBio(blogData)}
</p>
</div>
</div>
</header> </header>
{/* Share Buttons */} {/* Share Buttons */}

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Calendar, MapPin, Clock, Users, Star, Share2, ArrowLeft, ChevronRight } from 'lucide-react'; import { Calendar, MapPin, Clock, Users, Star, Share2, ArrowLeft, ChevronRight, ExternalLink } from 'lucide-react';
import { useRouter, useParams } from 'next/navigation'; import { useRouter, useParams } from 'next/navigation';
import Link from "next/link"; import Link from "next/link";
import { eventAPI, Event } from '../../lib/api'; // Adjust path as needed import { eventAPI, Event } from '../../lib/api'; // Adjust path as needed
@ -75,7 +75,7 @@ const EventDetail = () => {
} }
}; };
// NEW FUNCTION: Handle book seat click - redirects to admin-provided link // Handle book seat click - redirects to admin-provided link
const handleBookSeat = () => { const handleBookSeat = () => {
if (!eventData) return; if (!eventData) return;
@ -100,6 +100,28 @@ const EventDetail = () => {
} }
}; };
// Handle learn more click - redirects to admin-provided learn more link
const handleLearnMore = () => {
if (!eventData) return;
// Check if admin has provided a custom learn more link
if (eventData.learnMoreLink && eventData.learnMoreLink.trim() !== '') {
// Validate if it's a proper URL
try {
// If the URL doesn't start with http:// or https://, add https://
let url = eventData.learnMoreLink;
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'https://' + url;
}
// Open in new tab
window.open(url, '_blank', 'noopener,noreferrer');
} catch (error) {
console.error('Invalid learn more link:', error);
alert('Invalid information link. Please contact the organizers.');
}
}
};
const handleShare = async () => { const handleShare = async () => {
if (!eventData || typeof window === 'undefined') return; if (!eventData || typeof window === 'undefined') return;
@ -348,9 +370,20 @@ const EventDetail = () => {
<div className="text-xs font-medium mb-2" style={{ color: '#e64838' }}> <div className="text-xs font-medium mb-2" style={{ color: '#e64838' }}>
{eventData.date} {eventData.date}
</div> </div>
<h1 className="text-2xl md:text-3xl font-medium leading-tight" style={{ color: '#012068' }}> <h1 className="text-2xl md:text-3xl font-medium leading-tight mb-3" style={{ color: '#012068' }}>
{eventData.title} {eventData.title}
</h1> </h1>
{/* Learn More Button - THIS IS THE NEW ADDITION */}
{eventData.learnMoreLink && eventData.learnMoreLink.trim() !== '' && (
<button
onClick={handleLearnMore}
className="inline-flex items-center text-xs hover:underline transition-all duration-200"
style={{ color: '#012068', opacity: 0.7 }}
>
<ExternalLink className="w-3 h-3 mr-1" />
Learn More
</button>
)}
</div> </div>
<div className="text-left sm:text-right w-full sm:w-auto"> <div className="text-left sm:text-right w-full sm:w-auto">
<div className="text-xs mb-1" style={{ color: '#012068', opacity: 0.8 }}>From</div> <div className="text-xs mb-1" style={{ color: '#012068', opacity: 0.8 }}>From</div>

View File

@ -3,68 +3,130 @@ import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { ChevronRight } from 'lucide-react'; import { ChevronRight } from 'lucide-react';
import Link from "next/link"; import Link from "next/link";
import { eventAPI, Event } from '../../lib/api'; // Adjust path as needed import { eventAPI, Event } from '../../lib/api';
import { educationService, Course } from '../../services/educationService';
// Combined type for events and training programs
type DisplayItem =
| (Event & { type: 'event'; itemDate: Date })
| (Course & {
type: 'training';
itemDate: Date;
mainImage: string;
date: string; // Add this field
detail: string;
galleryImages?: string[];
venue?: any[]
});
const MedicalEventsComponent = () => { const MedicalEventsComponent = () => {
const [selectedPeriod, setSelectedPeriod] = useState('Upcoming Events'); const [selectedPeriod, setSelectedPeriod] = useState('Upcoming Events');
const [activeTab, setActiveTab] = useState('Upcoming Events'); const [activeTab, setActiveTab] = useState('Upcoming Events');
const [upcomingEvents, setUpcomingEvents] = useState<Event[]>([]); const [upcomingItems, setUpcomingItems] = useState<DisplayItem[]>([]);
const [pastEvents, setPastEvents] = useState<Event[]>([]); const [pastItems, setPastItems] = useState<DisplayItem[]>([]);
const [nextEvent, setNextEvent] = useState<Event | null>(null); const [nextItem, setNextItem] = useState<DisplayItem | null>(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
loadEvents(); loadData();
}, []); }, []);
const loadEvents = async () => { const loadData = async () => {
try { try {
setLoading(true); setLoading(true);
const [upcoming, past] = await Promise.all([ const [events, trainingPrograms] = await Promise.all([
eventAPI.getUpcomingEvents(), eventAPI.getAllEvents(), // Get all events (both upcoming and past)
eventAPI.getPastEvents() educationService.getActiveCourses() // Get all training programs
]); ]);
setUpcomingEvents(upcoming); const currentDate = new Date();
setPastEvents(past); currentDate.setHours(0, 0, 0, 0); // Set to start of day for accurate comparison
// Set the next event (first upcoming event) // Transform events with type
const eventsWithType: DisplayItem[] = events.map(event => {
const eventDate = new Date(event.date);
return {
...event,
type: 'event' as const,
itemDate: eventDate
};
});
// Transform training programs (courses) with type
const trainingWithType: DisplayItem[] = trainingPrograms.map(course => {
const courseDate = course.startDate ? new Date(course.startDate) : new Date();
return {
...course,
type: 'training' as const,
itemDate: courseDate,
mainImage: course.image,
detail: `${course.duration} | ${course.seats} seats available | Led by ${course.instructor}`,
galleryImages: [], // Training programs don't have gallery images
date: course.startDate || 'Date TBD'
};
});
// Combine all items (events + training programs)
const allItems = [...eventsWithType, ...trainingWithType];
// Separate into upcoming and past based on date
const upcoming = allItems
.filter(item => item.itemDate >= currentDate)
.sort((a, b) => a.itemDate.getTime() - b.itemDate.getTime());
const past = allItems
.filter(item => item.itemDate < currentDate)
.sort((a, b) => b.itemDate.getTime() - a.itemDate.getTime()); // Most recent first
setUpcomingItems(upcoming);
setPastItems(past);
// Set the next item (first upcoming item)
if (upcoming.length > 0) { if (upcoming.length > 0) {
setNextEvent(upcoming[0]); setNextItem(upcoming[0]);
} }
} catch (error) { } catch (error) {
console.error('Error loading events:', error); console.error('Error loading data:', error);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
// Filter events based on search term // Filter items based on search term and active tab
const filteredEvents = () => { const filteredItems = () => {
const events = activeTab === 'Upcoming Events' ? upcomingEvents : pastEvents; const items = activeTab === 'Upcoming Events' ? upcomingItems : pastItems;
if (!searchTerm) return events; if (!searchTerm) return items;
return events.filter(event => return items.filter(item =>
event.title.toLowerCase().includes(searchTerm.toLowerCase()) || item.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
event.description.toLowerCase().includes(searchTerm.toLowerCase()) || item.description.toLowerCase().includes(searchTerm.toLowerCase())
event.subject.toLowerCase().includes(searchTerm.toLowerCase())
); );
}; };
// Navigation function for App Router // Navigation function
const navigateToEventDetail = (eventId: string | number) => { const navigateToDetail = (item: DisplayItem) => {
router.push(`/event-detail/${eventId}`); if (item.type === 'event') {
router.push(`/event-detail/${item.id}`);
} else {
// For training programs, navigate to course detail
router.push(`/education-training/course-detail?id=${item.id}`);
}
}; };
// Format price display from fees // Format price display
const formatPrice = (event: Event) => { const formatPrice = (item: DisplayItem) => {
if (event.fee && event.fee.length > 0) { if (item.type === 'event') {
return `${event.fee[0].cost} per seat`; if (item.fee && item.fee.length > 0) {
return `${item.fee[0].cost} per seat`;
}
return '₹1,800 per seat';
} else {
// Training program
return item.price !== 'N/A' ? item.price : 'Contact for pricing';
} }
return '₹1,800 per seat'; // fallback price
}; };
// Get safe image URL with fallback // Get safe image URL with fallback
@ -72,8 +134,8 @@ const MedicalEventsComponent = () => {
return imageUrl && imageUrl.trim() !== '' ? imageUrl : fallback; return imageUrl && imageUrl.trim() !== '' ? imageUrl : fallback;
}; };
// Get gallery images with fallbacks // Get gallery images with fallbacks - only for events, not training programs
const getGalleryImages = (galleryImages: string[] | undefined) => { const getGalleryImages = (item: DisplayItem) => {
const fallbackImages = [ const fallbackImages = [
'https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=200&h=100&fit=crop', 'https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=200&h=100&fit=crop',
'https://images.unsplash.com/photo-1582750433449-648ed127bb54?w=200&h=100&fit=crop', 'https://images.unsplash.com/photo-1582750433449-648ed127bb54?w=200&h=100&fit=crop',
@ -81,6 +143,13 @@ const MedicalEventsComponent = () => {
'https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=200&h=100&fit=crop' 'https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=200&h=100&fit=crop'
]; ];
if (item.type === 'training') {
// Training programs don't have gallery images
return [];
}
const galleryImages = item.galleryImages;
if (!galleryImages || galleryImages.length === 0) { if (!galleryImages || galleryImages.length === 0) {
return fallbackImages; return fallbackImages;
} }
@ -97,7 +166,7 @@ const MedicalEventsComponent = () => {
if (loading) { if (loading) {
return ( return (
<div className="min-h-screen flex items-center justify-center"> <div className="min-h-screen flex items-center justify-center">
<div className="text-lg" style={{ color: '#012068' }}>Loading events...</div> <div className="text-lg" style={{ color: '#012068' }}>Loading events and training programs...</div>
</div> </div>
); );
} }
@ -129,7 +198,7 @@ const MedicalEventsComponent = () => {
</h1> </h1>
</div> </div>
<p className="text-sm md:text-base max-w-2xl leading-relaxed" style={{ color: '#333' }}> <p className="text-sm md:text-base max-w-2xl leading-relaxed" style={{ color: '#333' }}>
Discover upcoming medical conferences, workshops, and professional development events Discover upcoming medical conferences, workshops, training programs and professional development events
</p> </p>
</div> </div>
</div> </div>
@ -164,7 +233,7 @@ const MedicalEventsComponent = () => {
<div className="relative w-full sm:w-64"> <div className="relative w-full sm:w-64">
<input <input
type="text" type="text"
placeholder="Search an event..." placeholder="Search events or training programs..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
className="border rounded-lg px-4 py-2 pl-4 pr-10 text-sm focus:outline-none w-full" className="border rounded-lg px-4 py-2 pl-4 pr-10 text-sm focus:outline-none w-full"
@ -184,20 +253,34 @@ const MedicalEventsComponent = () => {
</div> </div>
</div> </div>
{/* Next Event Hero Section */} {/* Next Item Hero Section */}
{nextEvent && ( {nextItem && (
<div className="mb-8"> <div className="mb-8">
<h2 className="text-lg font-medium mb-4" style={{ color: '#012068' }}>Next Event</h2> <h2 className="text-lg font-medium mb-4" style={{ color: '#012068' }}>
Next {nextItem.type === 'training' ? 'Training Program' : 'Event'}
</h2>
<div <div
className="bg-white border border-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow" className="bg-white border border-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow"
onClick={() => navigateToEventDetail(nextEvent.id)} onClick={() => navigateToDetail(nextItem)}
> >
<div className="relative h-48 md:h-64"> <div className="relative h-48 md:h-64">
<img <img
src={getSafeImageUrl(nextEvent.mainImage, "https://images.unsplash.com/photo-1576091160550-2173dba999ef?w=800&h=300&fit=crop")} src={getSafeImageUrl(nextItem.mainImage, "https://images.unsplash.com/photo-1576091160550-2173dba999ef?w=800&h=300&fit=crop")}
alt={nextEvent.title} alt={nextItem.title}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
{/* Type Badge */}
<div className="absolute top-4 right-4">
<span
className="px-3 py-1 rounded text-xs font-medium"
style={{
backgroundColor: nextItem.type === 'event' ? '#e64838' : '#012068',
color: 'white'
}}
>
{nextItem.type === 'event' ? 'Event' : 'Training Program'}
</span>
</div>
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2"> <div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2">
<div className="w-2 h-2 bg-white rounded-full shadow"></div> <div className="w-2 h-2 bg-white rounded-full shadow"></div>
<div className="w-2 h-2 bg-gray-400 rounded-full"></div> <div className="w-2 h-2 bg-gray-400 rounded-full"></div>
@ -207,26 +290,30 @@ const MedicalEventsComponent = () => {
<div className="p-4 md:p-6"> <div className="p-4 md:p-6">
<div className="flex flex-col lg:flex-row lg:justify-between gap-4"> <div className="flex flex-col lg:flex-row lg:justify-between gap-4">
<div className="flex-1"> <div className="flex-1">
<div className="text-xs font-medium mb-3" style={{ color: '#e64838' }}>{nextEvent.date}</div> <div className="text-xs font-medium mb-3" style={{ color: '#e64838' }}>
{nextItem.type === 'event' ? nextItem.date : (nextItem.date || 'Date TBD')}
</div>
<div className="text-lg md:text-xl font-medium mb-2" style={{ color: '#012068' }}> <div className="text-lg md:text-xl font-medium mb-2" style={{ color: '#012068' }}>
{nextEvent.title} {nextItem.title}
</div> </div>
<div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}> <div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}>
{nextEvent.description} {nextItem.description}
</div> </div>
<div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}> <div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}>
{nextEvent.detail} {nextItem.detail || (nextItem.type === 'event' ? nextItem.detail : '')}
</div> </div>
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4"> <div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
<div <div
className="text-xs cursor-pointer hover:underline" className="text-xs cursor-pointer hover:underline"
style={{ color: '#012068' }} style={{ color: '#012068' }}
> >
Share Event Share {nextItem.type === 'training' ? 'Training Program' : 'Event'}
</div>
<div className="text-xs" style={{ color: '#012068' }}>
📍 {nextEvent.venue?.[0]?.address || 'Convention Center, Medical District'}
</div> </div>
{nextItem.type === 'event' && (
<div className="text-xs" style={{ color: '#012068' }}>
📍 {nextItem.venue?.[0]?.address || 'Convention Center, Medical District'}
</div>
)}
</div> </div>
</div> </div>
<div className="text-left lg:text-right"> <div className="text-left lg:text-right">
@ -238,15 +325,17 @@ const MedicalEventsComponent = () => {
}} }}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
console.log('Book seat clicked'); navigateToDetail(nextItem);
}} }}
> >
Book Your Seat {nextItem.type === 'training' ? 'Register Now' : 'Book Your Seat'}
</button> </button>
<div className="text-sm font-medium" style={{ color: '#e64838' }}>{formatPrice(nextEvent)}</div> <div className="text-sm font-medium" style={{ color: '#e64838' }}>{formatPrice(nextItem)}</div>
<div className="text-xs mt-1" style={{ color: '#333' }}> {nextItem.type === 'event' && (
Early bird discount available <div className="text-xs mt-1" style={{ color: '#333' }}>
</div> Early bird discount available
</div>
)}
</div> </div>
</div> </div>
</div> </div>
@ -272,7 +361,7 @@ const MedicalEventsComponent = () => {
color: activeTab === 'Upcoming Events' ? '#012068' : '#012068' color: activeTab === 'Upcoming Events' ? '#012068' : '#012068'
}} }}
> >
Upcoming Events ({upcomingEvents.length}) Upcoming Events ({upcomingItems.length})
</button> </button>
<button <button
onClick={() => setActiveTab('Past Events')} onClick={() => setActiveTab('Past Events')}
@ -286,84 +375,103 @@ const MedicalEventsComponent = () => {
color: activeTab === 'Past Events' ? '#012068' : '#012068' color: activeTab === 'Past Events' ? '#012068' : '#012068'
}} }}
> >
Past Events ({pastEvents.length}) Past Events ({pastItems.length})
</button> </button>
</div> </div>
</div> </div>
{/* Event Rows */} {/* Item Rows */}
<div className="space-y-6"> <div className="space-y-6">
{filteredEvents().length === 0 ? ( {filteredItems().length === 0 ? (
<div className="text-center py-8"> <div className="text-center py-8">
<p className="text-gray-500">No events found.</p> <p className="text-gray-500">No items found.</p>
</div> </div>
) : ( ) : (
filteredEvents().map((event) => ( filteredItems().map((item) => {
<div const galleryImages = getGalleryImages(item);
key={event.id} const showGallery = item.type === 'event' && galleryImages.length > 0;
className="bg-white border border-gray-100 rounded-lg p-4 md:p-6 cursor-pointer hover:shadow-lg transition-shadow"
onClick={() => navigateToEventDetail(event.id)} return (
> <div
<div className="flex flex-col md:flex-row gap-4"> key={`${item.type}-${item.id}`}
{/* Images Section */} className="bg-white border border-gray-100 rounded-lg p-4 md:p-6 cursor-pointer hover:shadow-lg transition-shadow"
<div className="flex flex-col sm:flex-row gap-1 md:w-auto"> onClick={() => navigateToDetail(item)}
{/* Main image */} >
<div className="w-full sm:w-48 h-32 md:h-30 flex-shrink-0 rounded-xs overflow-hidden"> <div className="flex flex-col md:flex-row gap-4">
<img {/* Images Section */}
src={getSafeImageUrl(event.mainImage, "https://images.unsplash.com/photo-1559757148-5c350d0d3c56?w=400&h=200&fit=crop")} <div className="flex flex-col sm:flex-row gap-1 md:w-auto">
alt={event.title} {/* Main image */}
className="w-full h-full object-cover" <div className="w-full sm:w-48 h-32 md:h-30 flex-shrink-0 rounded-xs overflow-hidden relative">
/> <img
src={getSafeImageUrl(item.mainImage, "https://images.unsplash.com/photo-1559757148-5c350d0d3c56?w=400&h=200&fit=crop")}
alt={item.title}
className="w-full h-full object-cover"
/>
{/* Type Badge */}
<div className="absolute top-2 right-2">
<span
className="px-2 py-1 rounded text-xs font-medium"
style={{
backgroundColor: item.type === 'event' ? '#e64838' : '#012068',
color: 'white'
}}
>
{item.type === 'event' ? 'Event' : 'Training'}
</span>
</div>
</div>
{/* Gallery grid - only for events */}
{showGallery && (
<div className="grid grid-cols-2 gap-1 w-full sm:w-60 h-32 md:h-30">
{galleryImages.map((img, index) => (
<div key={index} className="rounded-xs overflow-hidden">
<img
src={img}
alt={`${item.title} gallery ${index + 1}`}
className="w-full h-full object-cover"
/>
</div>
))}
</div>
)}
</div> </div>
{/* Gallery grid */} {/* Item details */}
<div className="grid grid-cols-2 gap-1 w-full sm:w-60 h-32 md:h-30"> <div className="flex-1 text-sm">
{getGalleryImages(event.galleryImages).map((img, index) => ( <div className="mb-1 font-medium text-xs" style={{ color: '#e64838' }}>
<div key={index} className="rounded-xs overflow-hidden"> {item.type === 'event' ? item.date : item.date}
<img </div>
src={img} <div className="font-medium mb-2 text-lg md:text-xl" style={{ color: '#012068' }}>
alt={`${event.title} gallery ${index + 1}`} {item.title}
className="w-full h-full object-cover" </div>
/> <div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}>
</div> {item.description}
))} </div>
</div> <div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}>
</div> {item.type === 'event' ? item.detail : item.detail}
</div>
{/* Event details */} <div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
<div className="flex-1 text-sm"> <button
<div className="mb-1 font-medium text-xs" style={{ color: '#e64838' }}> className="text-xs hover:underline text-left"
{event.date} style={{ color: '#012068' }}
</div> onClick={(e) => {
<div className="font-medium mb-2 text-lg md:text-xl" style={{ color: '#012068' }}> e.stopPropagation();
{event.title} navigateToDetail(item);
</div> }}
<div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}> >
{event.description} View Details
</div> </button>
<div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}> <span className="text-gray-400 hidden sm:inline">|</span>
{event.detail} <span className="text-xs font-medium" style={{ color: '#e64838' }}>
</div> {formatPrice(item)}
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4"> </span>
<button </div>
className="text-xs hover:underline text-left"
style={{ color: '#012068' }}
onClick={(e) => {
e.stopPropagation();
navigateToEventDetail(event.id);
}}
>
View Details
</button>
<span className="text-gray-400 hidden sm:inline">|</span>
<span className="text-xs font-medium" style={{ color: '#e64838' }}>
{formatPrice(event)}
</span>
</div> </div>
</div> </div>
</div> </div>
</div> );
)) })
)} )}
</div> </div>
</div> </div>
@ -374,35 +482,38 @@ const MedicalEventsComponent = () => {
Recent Past Events Recent Past Events
</h3> </h3>
<div className="grid sm:grid-cols-2 lg:grid-cols-1 gap-6"> <div className="grid sm:grid-cols-2 lg:grid-cols-1 gap-6">
{pastEvents.slice(0, 2).map((event) => ( {pastItems.filter(item => item.type === 'event').slice(0, 2).map((item) => {
<div const event = item as Event & { type: 'event'; itemDate: Date };
key={event.id} return (
className="cursor-pointer hover:bg-gray-50 p-2 rounded-lg transition-colors" <div
onClick={() => navigateToEventDetail(event.id)} key={event.id}
> className="cursor-pointer hover:bg-gray-50 p-2 rounded-lg transition-colors"
<div className="w-full h-32 lg:h-28 mb-3 overflow-hidden rounded-xs"> onClick={() => router.push(`/event-detail/${event.id}`)}
<img >
src={getSafeImageUrl(event.mainImage, "https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=300&h=200&fit=crop")} <div className="w-full h-32 lg:h-28 mb-3 overflow-hidden rounded-xs">
alt={event.title} <img
className="w-full h-full object-cover" src={getSafeImageUrl(event.mainImage, "https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=300&h=200&fit=crop")}
/> alt={event.title}
</div> className="w-full h-full object-cover"
<div className="text-sm"> />
<div className="mb-1 font-medium text-xs" style={{ color: '#e64838' }}>
{event.date}
</div> </div>
<div className="font-medium mb-1" style={{ color: '#012068' }}> <div className="text-sm">
{event.title} <div className="mb-1 font-medium text-xs" style={{ color: '#e64838' }}>
</div> {event.date}
<div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}> </div>
{event.description} <div className="font-medium mb-1" style={{ color: '#012068' }}>
</div> {event.title}
<div className="text-xs leading-relaxed" style={{ color: '#333' }}> </div>
{event.detail} <div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}>
{event.description}
</div>
<div className="text-xs leading-relaxed" style={{ color: '#333' }}>
{event.detail}
</div>
</div> </div>
</div> </div>
</div> );
))} })}
</div> </div>
</div> </div>
</div> </div>

View File

@ -249,7 +249,7 @@ const TeamListing: React.FC<TeamListingProps> = ({
<div className="max-w-7xl mx-auto px-4"> <div className="max-w-7xl mx-auto px-4">
<div className="mb-8"> <div className="mb-8">
<h2 className="text-2xl font-bold mb-4" style={{ color: '#012068' }}> <h2 className="text-2xl font-bold mb-4" style={{ color: '#012068' }}>
Retired Staff FACULTY ALUMNI
</h2> </h2>
<p className="text-sm mb-2" style={{ color: '#666' }}> <p className="text-sm mb-2" style={{ color: '#666' }}>
Honoring our retired faculty and staff members for their dedicated service Honoring our retired faculty and staff members for their dedicated service

View File

@ -2,60 +2,113 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { eventAPI, Event } from '../../lib/api'; import { eventAPI, Event } from '../../lib/api';
import { educationService, Course } from '../../services/educationService';
// Combined type for events and courses
type EventOrCourse = (Event & { type: 'event' }) | (Course & { type: 'course', date: string, mainImage: string });
const EventsSection = () => { const EventsSection = () => {
const router = useRouter(); const router = useRouter();
const [upcomingEvents, setUpcomingEvents] = useState<Event[]>([]); const [upcomingEvents, setUpcomingEvents] = useState<Event[]>([]);
const [pastEvents, setPastEvents] = useState<Event[]>([]); const [pastEvents, setPastEvents] = useState<Event[]>([]);
const [courses, setCourses] = useState<Course[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [combinedUpcoming, setCombinedUpcoming] = useState<EventOrCourse[]>([]);
useEffect(() => { useEffect(() => {
loadEvents(); loadData();
}, []); }, []);
const loadEvents = async () => { const loadData = async () => {
try { try {
setLoading(true); setLoading(true);
const [upcoming, past] = await Promise.all([ const [upcoming, past, activeCourses] = await Promise.all([
eventAPI.getUpcomingEvents(), eventAPI.getUpcomingEvents(),
eventAPI.getPastEvents() eventAPI.getPastEvents(),
educationService.getActiveCourses()
]); ]);
setUpcomingEvents(upcoming); setUpcomingEvents(upcoming);
setPastEvents(past); setPastEvents(past);
setCourses(activeCourses);
// Combine events and courses for display
const eventsWithType: EventOrCourse[] = upcoming.map(event => ({
...event,
type: 'event' as const
}));
const coursesWithType: EventOrCourse[] = activeCourses.map(course => ({
...course,
type: 'course' as const,
date: course.startDate || 'Date TBD',
mainImage: course.image
}));
// Combine and sort by date
const combined = [...eventsWithType, ...coursesWithType].sort((a, b) => {
const dateA = new Date(a.date);
const dateB = new Date(b.date);
return dateA.getTime() - dateB.getTime();
});
setCombinedUpcoming(combined);
} catch (error) { } catch (error) {
console.error('Error loading events:', error); console.error('Error loading data:', error);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
// Navigation function for App Router // Navigation functions
const navigateToEventDetail = (eventId: string | number) => { const navigateToDetail = (item: EventOrCourse) => {
router.push(`/event-detail/${eventId}`); if (item.type === 'event') {
router.push(`/event-detail/${item.id}`);
} else {
router.push(`/education-training/course-detail?id=${item.id}`);
}
}; };
const navigateToAllEvents = () => { const navigateToAllEvents = () => {
router.push('/events'); router.push('/events');
}; };
// Format price display from fees // Format price display
const formatPrice = (event: Event) => { const formatPrice = (item: EventOrCourse) => {
if (event.fee && event.fee.length > 0) { if (item.type === 'event') {
return `${event.fee[0].cost} per ticket`; if (item.fee && item.fee.length > 0) {
return `${item.fee[0].cost} per ticket`;
}
return '₹1,800 per ticket';
} else {
return item.price !== 'N/A' ? item.price : 'Contact for pricing';
} }
return '₹1,800 per ticket';
}; };
// Top section events (first 4 events for the grid) // Get title for the item
const topEvents = upcomingEvents.slice(0, 4); const getTitle = (item: EventOrCourse) => {
return item.title;
};
// Get description for the item
const getDescription = (item: EventOrCourse) => {
if (item.type === 'event') {
return item.description;
} else {
return item.description;
}
};
// Top section items (first 4 for the grid)
const topItems = combinedUpcoming.slice(0, 4);
// Featured event (first event) // Featured item (first item)
const featuredEvent = upcomingEvents.length > 0 ? upcomingEvents[0] : null; const featuredItem = combinedUpcoming.length > 0 ? combinedUpcoming[0] : null;
if (loading) { if (loading) {
return ( return (
<div className="py-12 px-6 sm:px-8 md:px-6 lg:px-6 xl:px-6 bg-white max-w-7xl mx-auto"> <div className="py-12 px-6 sm:px-8 md:px-6 lg:px-6 xl:px-6 bg-white max-w-7xl mx-auto">
<div className="text-center" style={{ color: '#012068' }}>Loading events...</div> <div className="text-center" style={{ color: '#012068' }}>Loading events and courses...</div>
</div> </div>
); );
} }
@ -65,7 +118,7 @@ const EventsSection = () => {
{/* Section Header */} {/* Section Header */}
<div className="flex justify-between items-center mb-8"> <div className="flex justify-between items-center mb-8">
<h2 className="text-2xl md:text-3xl font-bold" style={{ color: '#012068' }}> <h2 className="text-2xl md:text-3xl font-bold" style={{ color: '#012068' }}>
Our Events Our Events & Courses
</h2> </h2>
<button <button
className="text-sm font-medium hover:opacity-70 transition-opacity duration-200" className="text-sm font-medium hover:opacity-70 transition-opacity duration-200"
@ -76,39 +129,52 @@ const EventsSection = () => {
</button> </button>
</div> </div>
{/* Events Grid - Top Section with Event Details */} {/* Events/Courses Grid - Top Section with Details */}
{topEvents.length === 0 ? ( {topItems.length === 0 ? (
<div className="text-center py-8 mb-12"> <div className="text-center py-8 mb-12">
<p className="text-gray-500">No upcoming events.</p> <p className="text-gray-500">No upcoming events or courses.</p>
</div> </div>
) : ( ) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
{topEvents.map((event, index) => ( {topItems.map((item, index) => (
<div <div
key={event.id} key={`${item.type}-${item.id}`}
className={`relative rounded-lg h-48 overflow-hidden cursor-pointer hover:shadow-lg transition-shadow ${ className={`relative rounded-lg h-48 overflow-hidden cursor-pointer hover:shadow-lg transition-shadow ${
index === 2 ? 'lg:hidden xl:block' : '' index === 2 ? 'lg:hidden xl:block' : ''
} ${index === 3 ? 'md:col-span-2 lg:col-span-1' : ''}`} } ${index === 3 ? 'md:col-span-2 lg:col-span-1' : ''}`}
onClick={() => navigateToEventDetail(event.id)} onClick={() => navigateToDetail(item)}
> >
<img <img
src={event.mainImage} src={item.mainImage}
alt={event.title} alt={getTitle(item)}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
{/* Gradient overlay for better text readability */} {/* Gradient overlay for better text readability */}
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent"></div> <div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent"></div>
{/* Event details overlay */} {/* Item type badge */}
<div className="absolute top-3 right-3">
<span
className="text-xs font-medium px-2 py-1 rounded"
style={{
backgroundColor: item.type === 'event' ? '#e64838' : '#012068',
color: 'white'
}}
>
{item.type === 'event' ? 'Event' : 'Course'}
</span>
</div>
{/* Item details overlay */}
<div className="absolute bottom-0 left-0 right-0 p-4 text-white"> <div className="absolute bottom-0 left-0 right-0 p-4 text-white">
<div className="text-xs font-medium mb-1" style={{ color: '#e64838' }}> <div className="text-xs font-medium mb-1" style={{ color: '#e64838' }}>
{event.date} {item.date}
</div> </div>
<h4 className="font-medium mb-2 text-sm leading-tight"> <h4 className="font-medium mb-2 text-sm leading-tight line-clamp-2">
{event.title} {getTitle(item)}
</h4> </h4>
<div className="text-xs font-medium"> <div className="text-xs font-medium">
{formatPrice(event)} {formatPrice(item)}
</div> </div>
</div> </div>
</div> </div>
@ -116,26 +182,40 @@ const EventsSection = () => {
</div> </div>
)} )}
{/* Featured Events Section */} {/* Featured Section */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Left - Large Featured Event */} {/* Left - Large Featured Item */}
<div className="lg:col-span-2 px-4 py-4 rounded-lg" style={{ backgroundColor: '#f4f4f4' }}> <div className="lg:col-span-2 px-4 py-4 rounded-lg" style={{ backgroundColor: '#f4f4f4' }}>
<h3 className="text-xl font-semibold mb-4" style={{ color: '#012068' }}>Upcoming Events</h3> <h3 className="text-xl font-semibold mb-4" style={{ color: '#012068' }}>
{!featuredEvent ? ( Featured {featuredItem?.type === 'course' ? 'Course' : 'Event'}
</h3>
{!featuredItem ? (
<div className="text-center py-8"> <div className="text-center py-8">
<p className="text-gray-500">No upcoming events.</p> <p className="text-gray-500">No upcoming events or courses.</p>
</div> </div>
) : ( ) : (
<div <div
className="bg-white border border-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow" className="bg-white border border-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow"
onClick={() => navigateToEventDetail(featuredEvent.id)} onClick={() => navigateToDetail(featuredItem)}
> >
<div className="relative h-48 md:h-64"> <div className="relative h-48 md:h-64">
<img <img
src={featuredEvent.mainImage} src={featuredItem.mainImage}
alt={featuredEvent.title} alt={getTitle(featuredItem)}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
{/* Item type badge */}
<div className="absolute top-4 right-4">
<span
className="text-xs font-medium px-3 py-1 rounded"
style={{
backgroundColor: featuredItem.type === 'event' ? '#e64838' : '#012068',
color: 'white'
}}
>
{featuredItem.type === 'event' ? 'Event' : 'Course'}
</span>
</div>
{/* Pagination dots */} {/* Pagination dots */}
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2"> <div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex space-x-2">
<div className="w-2 h-2 bg-white rounded-full shadow"></div> <div className="w-2 h-2 bg-white rounded-full shadow"></div>
@ -147,27 +227,47 @@ const EventsSection = () => {
<div className="flex flex-col lg:flex-row lg:justify-between gap-4"> <div className="flex flex-col lg:flex-row lg:justify-between gap-4">
<div className="flex-1"> <div className="flex-1">
<div className="text-xs font-medium mb-3" style={{ color: '#e64838' }}> <div className="text-xs font-medium mb-3" style={{ color: '#e64838' }}>
{featuredEvent.date} {featuredItem.date}
</div> </div>
<h4 className="text-lg md:text-xl font-medium mb-2" style={{ color: '#012068' }}> <h4 className="text-lg md:text-xl font-medium mb-2" style={{ color: '#012068' }}>
{featuredEvent.title} {getTitle(featuredItem)}
</h4> </h4>
<div className="text-xs leading-relaxed mb-1" style={{ color: '#333' }}>
{featuredEvent.description}
</div>
<div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}> <div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}>
{featuredEvent.detail} {getDescription(featuredItem)}
</div> </div>
{featuredItem.type === 'event' && (
<div className="text-xs leading-relaxed mb-4" style={{ color: '#333' }}>
{featuredItem.detail}
</div>
)}
{featuredItem.type === 'course' && (
<div className="flex items-center gap-4 mb-4 text-xs" style={{ color: '#012068' }}>
<div className="flex items-center">
<span className="mr-1"></span>
<span>{featuredItem.duration}</span>
</div>
<div className="flex items-center">
<span className="mr-1">👥</span>
<span>{featuredItem.seats} seats</span>
</div>
<div className="flex items-center">
<span className="mr-1">👨🏫</span>
<span>{featuredItem.instructor}</span>
</div>
</div>
)}
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4"> <div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
<div <div
className="text-xs cursor-pointer hover:underline" className="text-xs cursor-pointer hover:underline"
style={{ color: '#012068' }} style={{ color: '#012068' }}
> >
Share Event Share {featuredItem.type === 'course' ? 'Course' : 'Event'}
</div>
<div className="text-xs" style={{ color: '#012068' }}>
📍 {featuredEvent.venue?.[0]?.address || 'Convention Center, Medical District'}
</div> </div>
{featuredItem.type === 'event' && (
<div className="text-xs" style={{ color: '#012068' }}>
📍 {featuredItem.venue?.[0]?.address || 'Convention Center, Medical District'}
</div>
)}
</div> </div>
</div> </div>
<div className="text-left lg:text-right"> <div className="text-left lg:text-right">
@ -179,17 +279,19 @@ const EventsSection = () => {
}} }}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
console.log('Book seat clicked'); navigateToDetail(featuredItem);
}} }}
> >
Book Your Seat {featuredItem.type === 'course' ? 'Apply Now' : 'Book Your Seat'}
</button> </button>
<div className="text-sm font-medium" style={{ color: '#e64838' }}> <div className="text-sm font-medium" style={{ color: '#e64838' }}>
{formatPrice(featuredEvent)} {formatPrice(featuredItem)}
</div>
<div className="text-xs mt-1" style={{ color: '#012068', opacity: 0.8 }}>
Early bird discount available
</div> </div>
{featuredItem.type === 'event' && (
<div className="text-xs mt-1" style={{ color: '#012068', opacity: 0.8 }}>
Early bird discount available
</div>
)}
</div> </div>
</div> </div>
</div> </div>
@ -197,7 +299,7 @@ const EventsSection = () => {
)} )}
</div> </div>
{/* Right - Event List with Scroller */} {/* Right - Past Events List with Scroller */}
<div className="lg:col-span-1"> <div className="lg:col-span-1">
<h3 className="text-xl font-semibold mb-4" style={{ color: '#012068' }}>Past Events</h3> <h3 className="text-xl font-semibold mb-4" style={{ color: '#012068' }}>Past Events</h3>
{pastEvents.length === 0 ? ( {pastEvents.length === 0 ? (
@ -210,7 +312,7 @@ const EventsSection = () => {
<div <div
key={event.id} key={event.id}
className="bg-white border border-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow flex-shrink-0" className="bg-white border border-gray-100 rounded-lg overflow-hidden cursor-pointer hover:shadow-lg transition-shadow flex-shrink-0"
onClick={() => navigateToEventDetail(event.id)} onClick={() => router.push(`/event-detail/${event.id}`)}
> >
<div className="h-24"> <div className="h-24">
<img <img
@ -226,7 +328,7 @@ const EventsSection = () => {
<h4 className="font-medium mb-1 text-sm" style={{ color: '#012068' }}> <h4 className="font-medium mb-1 text-sm" style={{ color: '#012068' }}>
{event.title} {event.title}
</h4> </h4>
<p className="text-xs leading-relaxed" style={{ color: '#333' }}> <p className="text-xs leading-relaxed line-clamp-2" style={{ color: '#333' }}>
{event.description} {event.description}
</p> </p>
<div className="mt-2 flex justify-between items-center"> <div className="mt-2 flex justify-between items-center">
@ -235,14 +337,11 @@ const EventsSection = () => {
style={{ color: '#012068' }} style={{ color: '#012068' }}
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
navigateToEventDetail(event.id); router.push(`/event-detail/${event.id}`);
}} }}
> >
View Details View Details
</button> </button>
{/* <span className="text-xs font-medium" style={{ color: '#e64838' }}>
{formatPrice(event)}
</span> */}
</div> </div>
</div> </div>
</div> </div>

View File

@ -18,7 +18,8 @@ export interface Event {
phone: string; phone: string;
email: string; email: string;
isActive: boolean; isActive: boolean;
bookSeatLink?: string; // NEW FIELD bookSeatLink?: string; // Registration/booking link
learnMoreLink?: string; // Additional information link
professors?: Professor[]; professors?: Professor[];
} }