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.
243 lines
9.3 KiB
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);
|
|
}
|
|
}
|
|
},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|