diff --git a/src/components/education/EducationTraining.tsx b/src/components/education/EducationTraining.tsx index d173809..3b0853b 100644 --- a/src/components/education/EducationTraining.tsx +++ b/src/components/education/EducationTraining.tsx @@ -1,417 +1,254 @@ -// components/EducationTraining.tsx -'use client'; -import { useState, useEffect } from 'react'; -import Image from 'next/image'; -import Link from 'next/link'; -import { ChevronRight, Clock, Users, Award, Calendar } from 'lucide-react'; -import { educationService, Course } from '../../services/educationService'; -import { upcomingEventsService, UpcomingEvent } from '../../services/upcomingEventsService'; +// services/educationService.ts +export interface ApiCourse { + id: number; + title: string; + description: string; + duration: string; + seats: number; + category: string; + level: string; + instructor: string; + price?: string; + startDate?: string; + imageUrl?: string; + eligibility: string[]; + objectives: string[]; + isActive: boolean; + createdDate?: string; + updatedDate?: string; +} -const EducationTraining: React.FC = () => { - const [mounted, setMounted] = useState(false); - const [courses, setCourses] = useState([]); - const [upcomingEvents, setUpcomingEvents] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [selectedCategory, setSelectedCategory] = useState('All'); - const [searchQuery, setSearchQuery] = useState(''); +export interface Course { + id: string; + title: string; + description: string; + duration: string; + seats: number; + category: string; + level: string; + instructor: string; + price: string; + startDate: string; + image: string; + eligibility: string[]; + objectives: string[]; +} - const categories = ['All', 'Certification', 'Training', 'Workshop', 'Fellowship']; +export interface CourseApplicationData { + courseId: number; + fullName: string; + email: string; + phone: string; + qualification: string; + experience?: string; + coverLetter?: string; + resumeUrl?: string; +} - useEffect(() => { - setMounted(true); - loadData(); - }, []); +class EducationService { + private apiBaseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080'; - const loadData = async () => { - try { - setLoading(true); - setError(null); - - // Load both courses and upcoming events concurrently - const [fetchedCourses, fetchedEvents] = await Promise.all([ - educationService.getActiveCourses(), - upcomingEventsService.getActiveUpcomingEvents() - ]); - - setCourses(fetchedCourses); - setUpcomingEvents(fetchedEvents); - } catch (err) { - setError('Failed to load courses and events. Please try again later.'); - console.error('Error loading data:', err); - } finally { - setLoading(false); - } - }; - - if (!mounted) { - return null; + // Helper method to convert relative URLs to absolute URLs + private getFullImageUrl(imageUrl: string | undefined): string { + if (!imageUrl || imageUrl.trim() === '') { + return this.getRandomDefaultImage(); } - - // Filter courses based on category and search - const filteredCourses = courses.filter(course => { - const matchesCategory = selectedCategory === 'All' || course.category === selectedCategory; - const matchesSearch = !searchQuery.trim() || - course.title.toLowerCase().includes(searchQuery.toLowerCase()) || - course.description.toLowerCase().includes(searchQuery.toLowerCase()) || - course.instructor.toLowerCase().includes(searchQuery.toLowerCase()); - - return matchesCategory && matchesSearch; - }); - - const handleSearchChange = (e: React.ChangeEvent) => { - setSearchQuery(e.target.value); - }; - - if (loading) { - return ( -
-
-
-

Loading courses...

-
-
- ); + + // If it's already a full URL, return as-is + if (imageUrl.startsWith('http://') || imageUrl.startsWith('https://')) { + return imageUrl; } + + // If it's a relative URL, prepend the backend API URL + const cleanUrl = imageUrl.startsWith('/') ? imageUrl.substring(1) : imageUrl; + return `${this.apiBaseUrl}/${cleanUrl}`; + } - return ( -
- {/* Header Section */} -
-
- {/* Breadcrumb */} - + async getActiveCourses(): Promise { + try { + const response = await fetch(`${this.apiBaseUrl}/api/courses/active`, { + cache: 'no-store' + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const apiCourses: ApiCourse[] = await response.json(); + return this.transformApiCoursesToCourses(apiCourses); + } catch (error) { + console.error('Error fetching courses:', error); + return this.getFallbackCourses(); + } + } - {/* Page Header */} -
-

- Education & Training -

-

- Advance your trauma care expertise with structured training programs for doctors, nurses, students, and community partners. -

-
-
-
+ async getCourseById(id: number): Promise { + try { + const token = typeof window !== 'undefined' ? localStorage.getItem('authToken') : null; + const response = await fetch(`${this.apiBaseUrl}/api/courses/${id}`, { + headers: { + 'Content-Type': 'application/json', + ...(token ? { Authorization: `Bearer ${token}` } : {}), + }, + cache: 'no-store' + }); - {/* Error Message */} - {error && ( -
-
-

{error}

- -
-
- )} + if (!response.ok) { + if (response.status === 404) return null; + throw new Error(`HTTP error! status: ${response.status}`); + } - {/* Upcoming Training Section with Dynamic Cards */} -
-
-

- Upcoming Training Programs -

-
- {upcomingEvents.length > 0 ? ( - upcomingEvents.map((event) => ( -
-
-
-

- {event.title} -

-
- - {event.schedule} -
-
-
-

- {event.description} -

-
- )) - ) : ( - // Fallback to static cards if no events are loaded - <> -
-
-
-

- Simulation-based Team Drills -

-
- - Q3 2025 -
-
-
-

- Hands-on simulation training designed to improve team coordination and emergency response in high-pressure trauma situations. -

-
+ const apiCourse: ApiCourse = await response.json(); + return this.transformApiCourseToCourse(apiCourse); + } catch (error) { + console.error(`Error fetching course ${id}:`, error); + return null; + } + } -
-
-
-

- Online Webinar Series -

-
- - Monthly Sessions -
-
-
-

- Monthly online sessions covering trauma ethics, young doctor support, and professional development in emergency medicine. -

-
+ async submitApplication(applicationData: CourseApplicationData): Promise { + try { + const response = await fetch(`${this.apiBaseUrl}/api/course-applications`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(applicationData), + }); + + return response.ok; + } catch (error) { + console.error('Error submitting application:', error); + return false; + } + } -
-
-
-

- Community Education -

-
- - Ongoing -
-
-
-

- Road safety fairs and school education sessions to promote trauma prevention and basic first aid awareness in the community. -

-
- - )} -
-
-
+ private transformApiCoursesToCourses(apiCourses: ApiCourse[]): Course[] { + return apiCourses.map(apiCourse => this.transformApiCourseToCourse(apiCourse)); + } - {/* Filter & Search */} -
-
-
- {/* Category Filter */} -
- {categories.map((category) => ( - - ))} -
+ private transformApiCourseToCourse(apiCourse: ApiCourse): Course { + return { + id: apiCourse.id.toString(), + title: apiCourse.title, + description: apiCourse.description, + duration: apiCourse.duration, + seats: apiCourse.seats, + category: apiCourse.category, + level: apiCourse.level, + instructor: apiCourse.instructor, + price: apiCourse.price || 'N/A', + startDate: apiCourse.startDate || '', + image: this.getFullImageUrl(apiCourse.imageUrl), + eligibility: apiCourse.eligibility || [], + objectives: apiCourse.objectives || [] + }; + } - {/* Search */} -
- - -
-
+ private getRandomDefaultImage(): string { + const defaultImages = [ + "https://images.unsplash.com/photo-1576091160550-2173dba999ef?w=400&h=200&fit=crop&crop=center", + "https://images.unsplash.com/photo-1559757175-0eb30cd8c063?w=400&h=300&fit=crop&crop=center", + "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=400&h=300&fit=crop&crop=center", + "https://images.unsplash.com/photo-1582750433449-648ed127bb54?w=400&h=300&fit=crop&crop=center", + "https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=400&h=300&fit=crop&crop=center", + "https://images.unsplash.com/photo-1559757148-5c350d0d3c56?w=400&h=300&fit=crop&crop=center" + ]; + return defaultImages[Math.floor(Math.random() * defaultImages.length)]; + } - {/* Results Info */} - {(selectedCategory !== 'All' || searchQuery.trim()) && ( -
-

- {filteredCourses.length === 0 - ? 'No courses found matching your criteria.' - : `Showing ${filteredCourses.length} of ${courses.length} course${courses.length !== 1 ? 's' : ''}` - } -

-
- )} -
-
+ private getFallbackCourses(): Course[] { + return [ + { + id: '1', + title: "ATLS® (Advanced Trauma Life Support)", + description: "Eligibility: MBBS + internship complete. Last Course: Aug 31 – Sep 2, 2023 (60 doctors certified). Next Schedule: [#Incomplete – Date TBD]", + duration: "3 Days", + seats: 60, + category: "Certification", + level: "Professional", + image: "https://images.unsplash.com/photo-1576091160550-2173dba999ef?w=400&h=200&fit=crop&crop=center", + instructor: "Trauma Faculty Team", + price: "N/A", + startDate: "2023-08-31", + eligibility: ["MBBS + internship complete"], + objectives: ["Advanced trauma life support skills", "Emergency trauma management"] + }, + { + id: '2', + title: "ATCN® (Advanced Trauma Care for Nurses)", + description: "First Course: Apr 11-13, 2024 (manikin-based training). Participants: 40 critical care nurses from CMC and partner hospitals. Next Batch: [#Incomplete – Date TBD]", + duration: "3 Days", + seats: 40, + category: "Training", + level: "Professional", + image: "https://images.unsplash.com/photo-1559757175-0eb30cd8c063?w=400&h=300&fit=crop&crop=center", + instructor: "Nursing Faculty Team", + price: "N/A", + startDate: "2024-04-11", + eligibility: ["Registered Nurse", "Critical care experience preferred"], + objectives: ["Advanced trauma nursing skills", "Manikin-based training proficiency"] + }, + { + id: '3', + title: "Trauma First Responder Program", + description: "Partners: RCPSG Hope Foundation, local colleges. Locations: Walajapet, Auxilium College—250 students trained. Curriculum: CPR, airway support, bleeding control, scene assessment.", + duration: "Varies", + seats: 250, + category: "Workshop", + level: "Beginner", + image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=400&h=300&fit=crop&crop=center", + instructor: "Community Trainers", + price: "N/A", + startDate: "2023-01-01", + eligibility: ["Students", "Community members"], + objectives: ["CPR proficiency", "Basic trauma response", "Scene safety assessment"] + }, + { + id: '4', + title: "FNB in Trauma Surgery", + description: "3-year structured training program in acute surgery, ICU management, and research. Open to MS-qualified surgeons seeking specialized trauma surgery expertise.", + duration: "3 Years", + seats: 8, + category: "Certification", + level: "Advanced", + image: "https://images.unsplash.com/photo-1582750433449-648ed127bb54?w=400&h=300&fit=crop&crop=center", + instructor: "Senior Trauma Surgeons", + price: "N/A", + startDate: "2025-07-01", + eligibility: ["MS qualification in Surgery", "Valid medical license"], + objectives: ["Advanced trauma surgery skills", "ICU management", "Research methodology"] + }, + { + id: '5', + title: "Observerships & Electives", + description: "4-8 week clinical blocks for national and international residents. Includes ATLS® course access and hands-on trauma experience. Application by email required.", + duration: "4-8 Weeks", + seats: 20, + category: "Training", + level: "Intermediate", + image: "https://images.unsplash.com/photo-1551601651-2a8555f1a136?w=400&h=300&fit=crop&crop=center", + instructor: "Clinical Faculty", + price: "N/A", + startDate: "2025-01-15", + eligibility: ["Medical residency status", "Valid medical credentials"], + objectives: ["Clinical observation skills", "Hands-on trauma experience", "ATLS certification"] + }, + { + id: '6', + title: "Nursing Skills Lab", + description: "Trauma-focused skills laboratory sessions open quarterly (Q2, Q4). Includes chest tube insertion, airway management drills, and EFAST simulation training.", + duration: "2 Days", + seats: 30, + category: "Workshop", + level: "Intermediate", + image: "https://images.unsplash.com/photo-1559757148-5c350d0d3c56?w=400&h=300&fit=crop&crop=center", + instructor: "Nursing Skills Faculty", + price: "N/A", + startDate: "2025-04-01", + eligibility: ["Licensed nurse", "Basic trauma knowledge"], + objectives: ["Chest tube insertion", "Airway management", "EFAST simulation"] + } + ]; + } +} - {/* Courses Grid */} -
-
- {filteredCourses.length === 0 && !error ? ( -
-

- {searchQuery.trim() || selectedCategory !== 'All' - ? 'No courses match your search criteria.' - : 'No courses available at the moment.' - } -

- {(searchQuery.trim() || selectedCategory !== 'All') && ( - - )} -
- ) : ( -
- {filteredCourses.map((course) => ( - - {/* Image */} -
- {course.title} -
- - {/* Content */} -
-
-

- {course.title} -

-

- {course.description} -

-
- - {course.category} - -
-
- -
-
- - {course.instructor} - -
-
-
- - {course.duration} -
-
- - {course.seats} -
-
-
-
- {course.startDate ? `Starts: ${new Date(course.startDate).toLocaleDateString()}` : 'Contact for dates'} -
-
-
-
- - ))} -
- )} -
-
- - {/* CTA */} -
-
- -

- Ready to Advance Your Trauma Care Expertise? -

-

- Join our structured training programs designed to empower healthcare professionals, nurses, and community responders with critical trauma care skills. -

-
- - Contact Admissions - - - Download Brochure - -
-
-
-
- ); -}; - -export default EducationTraining; \ No newline at end of file +export const educationService = new EducationService(); \ No newline at end of file