import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:medora/data/models/consultation_center.dart'; import 'package:medora/data/models/doctor.dart'; import 'package:intl/intl.dart'; import 'package:medora/route/route_names.dart'; class ConsultationTimeScreen extends StatefulWidget { final Doctor doctor; final ConsultationCenter selectedConsultation; const ConsultationTimeScreen({ super.key, required this.doctor, required this.selectedConsultation, }); @override State createState() => _ConsultationTimeScreenState(); } class _ConsultationTimeScreenState extends State { DateTime? selectedDate; String? selectedTime; List getTimeSlotsForDay(String dayName) { try { final schedule = widget.selectedConsultation.weeklySchedule?.firstWhere( (schedule) => schedule.day == dayName, orElse: () => AvailabilitySchedule( day: dayName, timeSlots: [], ), ); return schedule?.timeSlots ?? []; } catch (e) { debugPrint('Error getting time slots: $e'); return []; } } DateTime? parseTimeString(String? timeStr) { if (timeStr == null) return null; try { // Try parsing 12-hour format first return DateFormat('h:mm a').parse(timeStr); } catch (e) { try { // Try parsing 24-hour format return DateFormat('HH:mm').parse(timeStr); } catch (e) { debugPrint('Error parsing time: $timeStr'); return null; } } } String get formattedAddress { final parts = [ widget.selectedConsultation.floorBuilding, widget.selectedConsultation.street, widget.selectedConsultation.city, widget.selectedConsultation.state, widget.selectedConsultation.postalCode ].where((part) => part != null && part.isNotEmpty).toList(); return parts.join(', '); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F7FF), appBar: _buildAppBar(), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildLocationInfo(), const SizedBox(height: 24), _buildDateSelection(), const SizedBox(height: 24), _buildTimeSlots(), ], ), ), ), ); } PreferredSizeWidget _buildAppBar() { return AppBar( backgroundColor: Colors.white, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.black87), onPressed: () => Navigator.pop(context), ), title: Text( 'Select Date & Time', style: GoogleFonts.poppins( color: Colors.black87, fontWeight: FontWeight.w600, fontSize: 20, ), ), centerTitle: true, ); } Widget _buildLocationInfo() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.doctor.firstName ?? '', style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.w600, ), ), Text( widget.doctor.speciality!, style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], ), ), ], ), ), ClipRRect( borderRadius: BorderRadius.circular(12), child: Image.network( widget.doctor.profileImage!, width: 60, height: 60, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Container( width: 60, height: 60, color: Colors.grey[300], child: Icon(Icons.person, size: 30, color: Colors.grey[600]), ); }, ), ), ], ), const Divider(height: 24), Text( 'Selected Location', style: GoogleFonts.poppins( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), Text( widget.selectedConsultation.city ?? '', style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], ), ), const SizedBox(height: 4), Text( 'Average consultation time: ${widget.selectedConsultation.averageDurationMinutes}', style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], ), ), ], ), ); } Widget _buildDateSelection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Select Date', style: GoogleFonts.poppins( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 12), SizedBox( height: 100, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: 20, // Show next 20 days itemBuilder: (context, index) { final date = DateTime.now().add(Duration(days: index)); final isSelected = selectedDate?.day == date.day && selectedDate?.month == date.month && selectedDate?.year == date.year; final isAvailable = _isDateAvailable(date); return GestureDetector( onTap: isAvailable ? () { setState(() { selectedDate = date; selectedTime = null; // Reset time when date changes }); } : null, child: Container( width: 70, margin: const EdgeInsets.only(right: 12), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isSelected ? Colors.blue : isAvailable ? Colors.white : Colors.grey[200], borderRadius: BorderRadius.circular(16), boxShadow: isAvailable ? [ BoxShadow( color: Colors.grey.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 2), ), ] : null, ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( DateFormat('EEE').format(date).toUpperCase(), style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, color: isSelected ? Colors.white : isAvailable ? Colors.grey[600] : Colors.grey[400], ), ), const SizedBox(height: 8), Text( date.day.toString(), style: GoogleFonts.poppins( fontSize: 18, fontWeight: FontWeight.w600, color: isSelected ? Colors.white : isAvailable ? Colors.black87 : Colors.grey[400], ), ), ], ), ), ); }, ), ), ], ); } Widget _buildTimeSlots() { if (selectedDate == null) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white.withOpacity(0.5), borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.grey.withOpacity(0.2)), ), child: Center( child: Text( 'Please select a date to view available time slots', style: GoogleFonts.poppins( fontSize: 14, color: Colors.grey[600], ), ), ), ); } final dayName = DateFormat('EEEE').format(selectedDate!); final timeSlots = getTimeSlotsForDay(dayName); final allTimeSlots = _generateTimeSlots(timeSlots); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Select Time', style: GoogleFonts.poppins( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Wrap( spacing: 12, runSpacing: 12, children: allTimeSlots.map((time) { final isSelected = selectedTime == time; final isAvailable = _isTimeSlotAvailable(time); return GestureDetector( onTap: isAvailable ? () { Navigator.pushNamed( context, RouteNames.consultationBookingScreen, arguments: { 'doctor': widget.doctor, 'selectedConsultation': widget.selectedConsultation, 'selectedDate': selectedDate, 'selectedTime': time }, ); } : null, child: Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), decoration: BoxDecoration( color: isSelected ? Colors.blue : isAvailable ? Colors.white : Colors.grey[200], borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? Colors.blue : isAvailable ? Colors.grey.withOpacity(0.2) : Colors.grey.withOpacity(0.1), ), ), child: Text( time, style: GoogleFonts.poppins( fontSize: 14, fontWeight: FontWeight.w500, color: isSelected ? Colors.white : isAvailable ? Colors.black87 : Colors.grey[400], ), ), ), ); }).toList(), ), ), ], ); } bool _isDateAvailable(DateTime date) { final dayName = DateFormat('EEEE').format(date); return widget.selectedConsultation.weeklySchedule ?.any((schedule) => schedule.day == dayName) ?? false; } List _generateTimeSlots(List timeSlots) { final slots = []; final timeFormat = DateFormat('h:mm a'); for (var slot in timeSlots) { final startTime = parseTimeString(slot.startTime); final endTime = parseTimeString(slot.endTime); if (startTime == null || endTime == null) continue; var currentTime = startTime; while (currentTime.isBefore(endTime)) { slots.add(timeFormat.format(currentTime)); currentTime = currentTime.add(const Duration(minutes: 30)); } } return slots; } bool _isTimeSlotAvailable(String time) { final now = DateTime.now(); if (selectedDate == null) return false; // Parse the time slot final timeSlot = parseTimeString(time); if (timeSlot == null) return false; // Create a DateTime combining selected date and time final slotDateTime = DateTime( selectedDate!.year, selectedDate!.month, selectedDate!.day, timeSlot.hour, timeSlot.minute, ); // Check if the slot is in the past if (slotDateTime.isBefore(now)) return false; // Here you would typically check against your booking database // For now, returning true for future slots return true; } void _handleBooking() { showDialog( context: context, builder: (context) => AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), title: Text( 'Confirm Booking', style: GoogleFonts.poppins( fontWeight: FontWeight.w600, ), ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildConfirmationDetail( 'Doctor', widget.doctor.firstName!, ), const SizedBox(height: 8), _buildConfirmationDetail( 'Location', widget.selectedConsultation.city!, ), const SizedBox(height: 8), _buildConfirmationDetail( 'Date', DateFormat('EEEE, MMMM d').format(selectedDate!), ), const SizedBox(height: 8), _buildConfirmationDetail( 'Time', selectedTime!, ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text( 'Cancel', style: GoogleFonts.poppins( color: Colors.grey[600], ), ), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text( 'Confirm', style: GoogleFonts.poppins( color: Colors.white, ), ), ), ], ), ); } Widget _buildConfirmationDetail(String label, String value) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 80, child: Text( '$label:', style: GoogleFonts.poppins( fontWeight: FontWeight.w500, color: Colors.grey[600], ), ), ), Expanded( child: Text( value, style: GoogleFonts.poppins( fontWeight: FontWeight.w500, ), ), ), ], ); } }