You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
car_common_app/lib/views/appointments/widgets/custom_calender_widget.dart

243 lines
9.3 KiB
Dart

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<CustomTimeDateSlotModel> customTimeDateSlotList;
final CustomTimeDateSlotModel? selectedCustomTimeDateSlotModel;
final Function(int) onDateSelected;
const CustomCalenderAppointmentWidget({
super.key,
required this.customTimeDateSlotList,
required this.selectedCustomTimeDateSlotModel,
required this.onDateSelected,
});
@override
State<CustomCalenderAppointmentWidget> createState() => _CustomCalenderAppointmentWidgetState();
}
class _CustomCalenderAppointmentWidgetState extends State<CustomCalenderAppointmentWidget> {
List<DateTime> allDates = [];
List<DropValue> allMonths = [];
List<DateTime> 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);
}
}
},
),
],
);
},
);
}
}