import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/appointments_view_model.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import 'package:table_calendar/table_calendar.dart'; class CustomCalenderAppointmentWidget extends StatefulWidget { final List customTimeDateSlotList; final CustomTimeDateSlotModel? selectedCustomTimeDateSlotModel; final Function(int) onDateSelected; const CustomCalenderAppointmentWidget({ super.key, required this.customTimeDateSlotList, required this.selectedCustomTimeDateSlotModel, required this.onDateSelected, }); @override State createState() => _CustomCalenderAppointmentWidgetState(); } class _CustomCalenderAppointmentWidgetState extends State { List allDates = []; List allMonths = []; List datesInSelectedMonth = []; final CalendarFormat _calendarFormat = CalendarFormat.month; late int selectedMonth; late int selectedYear; DateTime? _selectedDay; DateTime _focusedDay = DateTime.now(); @override void initState() { super.initState(); populateDateList(); } populateDateList() { for (var value in widget.customTimeDateSlotList) { DateTime dt = DateFormat('dd MMMM, yyyy').parse(value.date!.date.trim()); DropValue dv = DropValue(dt.month, "${dt.month.getMonthNameByNumber()}, ${dt.year}", "${dt.year}"); allDates.add(dt); if (!ifMonthAlreadyThere(dv)) { allMonths.add(dv); } } selectedMonth = allDates.first.month; selectedYear = allDates.first.year; if (widget.selectedCustomTimeDateSlotModel != null) { DateTime alreadySelectedDate = DateFormat('dd MMMM, yyyy').parse(widget.selectedCustomTimeDateSlotModel!.date!.date); _selectedDay = alreadySelectedDate; _focusedDay = alreadySelectedDate; selectedMonth = alreadySelectedDate.month; selectedYear = alreadySelectedDate.year; } datesInSelectedMonth = allDates.where((element) => element.month == selectedMonth).toList(); if (widget.selectedCustomTimeDateSlotModel == null) { _focusedDay = datesInSelectedMonth.first; } } bool ifMonthAlreadyThere(DropValue monthDate) { int index = allMonths.indexWhere((element) => element.id == monthDate.id && element.subValue == monthDate.subValue); if (index == -1) { return false; } return true; } bool ifDateAlreadyThere(DateTime dt) { int index = allDates.indexWhere((element) => dt.month == element.month && dt.year == element.year); if (index == -1) { return false; } return true; } @override Widget build(BuildContext context) { return Consumer( builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Builder(builder: (context) { return DropdownField( (DropValue value) { setState(() { selectedYear = int.parse(value.value.split(',')[1]); selectedMonth = value.value.split(',')[0].getMonthNumberByName(); datesInSelectedMonth = allDates.where((element) => element.month == selectedMonth).toList(); _focusedDay = datesInSelectedMonth.first; }); }, list: allMonths, dropdownValue: DropValue(selectedMonth, "${selectedMonth.getMonthNameByNumber()}, ${selectedYear}", "${selectedYear}"), hint: "${selectedMonth.getMonthNameByNumber()}, $selectedYear", errorValue: "", showAppointmentPickerVariant: true, ); }), ), Spacer(), Icon( Icons.calendar_today, color: Colors.black, size: 18, ).paddingOnly(right: 10) ], ).paddingOnly(left: 6, right: 0), TableCalendar( headerVisible: false, firstDay: datesInSelectedMonth.first, lastDay: datesInSelectedMonth.last, focusedDay: _focusedDay, calendarFormat: _calendarFormat, weekendDays: [DateTime.friday, DateTime.saturday], daysOfWeekHeight: 30, availableGestures: AvailableGestures.none, daysOfWeekStyle: DaysOfWeekStyle( weekdayStyle: TextStyle(fontSize: 14, color: MyColors.black), weekendStyle: TextStyle(fontSize: 14, color: MyColors.black.withOpacity(0.5)), ), calendarBuilders: CalendarBuilders( selectedBuilder: (BuildContext context, DateTime dateTime1, DateTime dateTime2) { return Container( height: 50, width: 50, margin: EdgeInsets.all(5), decoration: BoxDecoration( shape: BoxShape.circle, color: MyColors.darkIconColor, ), alignment: Alignment.center, child: Text( dateTime2.day.toString(), style: TextStyle(color: MyColors.white), ), ); }, defaultBuilder: (BuildContext context, DateTime dateTime1, DateTime dateTime2) { int index = datesInSelectedMonth.indexWhere((element) => isSameDay(dateTime1, element)); if (index == -1) { return Container( height: 50, width: 50, margin: EdgeInsets.all(5), decoration: BoxDecoration( border: Border.all(color: Colors.grey), shape: BoxShape.circle, ), alignment: Alignment.center, child: Text( dateTime1.day.toString(), ), ); } return Container( height: 50, width: 50, margin: EdgeInsets.all(5), decoration: BoxDecoration( border: Border.all(color: Colors.orange, width: 2), shape: BoxShape.circle, ), alignment: Alignment.center, child: Text( dateTime1.day.toString(), ), ); }, disabledBuilder: (BuildContext context, DateTime dateTime1, DateTime selectedDt) { return Container( height: 50, width: 50, margin: EdgeInsets.all(5), decoration: BoxDecoration( border: Border.all(color: Colors.grey), shape: BoxShape.circle, ), alignment: Alignment.center, child: Text( dateTime1.day.toString(), ), ); }, ), headerStyle: HeaderStyle(formatButtonVisible: false), selectedDayPredicate: (day) { // Use `selectedDayPredicate` to determine which day is currently selected. // If this returns true, then `day` will be marked as selected. // Using `isSameDay` is recommended to disregard // the time-part of compared DateTime objects. return isSameDay(_selectedDay, day); }, onDaySelected: (selectedDay, focusedDay) { int index = datesInSelectedMonth.indexWhere((element) => isSameDay(selectedDay, element)); if (index == -1) { return; } if (!isSameDay(_selectedDay, selectedDay)) { setState(() { _selectedDay = selectedDay; _focusedDay = focusedDay; }); int dateIndex = widget.customTimeDateSlotList.indexWhere((element) { DateTime dateFromList = DateFormat('dd MMMM, yyyy').parse(element.date!.date); if (isSameDay(dateFromList, selectedDay)) { return true; } return false; }); if (dateIndex != -1) { widget.onDateSelected(dateIndex); } } }, ), ], ); }, ); } }