calendar implementation contd.
parent
73f8baa77e
commit
6f745f3666
@ -0,0 +1,8 @@
|
||||
class TimeSlot {
|
||||
String? isoTime;
|
||||
DateTime? start;
|
||||
DateTime? end;
|
||||
String? vidaDate;
|
||||
|
||||
TimeSlot({required this.isoTime, required this.start, required this.end, this.vidaDate});
|
||||
}
|
||||
@ -0,0 +1,242 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_export.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_state.dart';
|
||||
import 'package:hmg_patient_app_new/core/dependencies.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/book_appointments/models/free_slot.dart';
|
||||
import 'package:hmg_patient_app_new/features/book_appointments/models/timeslots.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:smooth_corner/smooth_corner.dart';
|
||||
import 'package:syncfusion_flutter_calendar/calendar.dart';
|
||||
|
||||
class AppointmentCalendar extends StatefulWidget {
|
||||
const AppointmentCalendar({super.key});
|
||||
|
||||
@override
|
||||
State<AppointmentCalendar> createState() => _AppointmentCalendarState();
|
||||
}
|
||||
|
||||
class _AppointmentCalendarState extends State<AppointmentCalendar> {
|
||||
late CalendarController _calendarController;
|
||||
|
||||
late AppState appState;
|
||||
late BookAppointmentsViewModel bookAppointmentsViewModel;
|
||||
|
||||
var selectedDate = "";
|
||||
var selectedNextDate = "";
|
||||
|
||||
int selectedButtonIndex = 0;
|
||||
int selectedNextDayButtonIndex = -1;
|
||||
|
||||
List<TimeSlot> dayEvents = [];
|
||||
List<TimeSlot> nextDayEvents = [];
|
||||
|
||||
late Map<DateTime, List> _events;
|
||||
|
||||
static String? selectedTime;
|
||||
|
||||
bool isWaitingAppointmentAvailable = false;
|
||||
final _selectedDay = DateTime.now();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
scheduleMicrotask(() {
|
||||
_calendarController = CalendarController();
|
||||
_events = {
|
||||
_selectedDay: ['Event A0']
|
||||
};
|
||||
_onDaySelected(DateUtil.convertStringToDate(bookAppointmentsViewModel.freeSlotsResponse[0]));
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bookAppointmentsViewModel = Provider.of<BookAppointmentsViewModel>(context, listen: false);
|
||||
appState = getIt.get<AppState>();
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 380.h,
|
||||
child: SfCalendar(
|
||||
controller: _calendarController,
|
||||
minDate: DateTime.now(),
|
||||
showNavigationArrow: true,
|
||||
headerHeight: 60.h,
|
||||
headerStyle: CalendarHeaderStyle(
|
||||
backgroundColor: AppColors.scaffoldBgColor,
|
||||
textAlign: TextAlign.start,
|
||||
textStyle: TextStyle(fontSize: 18.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.primaryRedColor, fontFamily: "Poppins"),
|
||||
),
|
||||
viewHeaderStyle: ViewHeaderStyle(
|
||||
backgroundColor: AppColors.scaffoldBgColor,
|
||||
dayTextStyle: TextStyle(fontSize: 14.fSize, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: AppColors.textColor),
|
||||
),
|
||||
view: CalendarView.month,
|
||||
todayHighlightColor: Colors.transparent,
|
||||
todayTextStyle: TextStyle(color: AppColors.textColor),
|
||||
selectionDecoration: ShapeDecoration(
|
||||
color: AppColors.transparent,
|
||||
shape: SmoothRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12 ?? 0),
|
||||
smoothness: 1,
|
||||
side: BorderSide(color: AppColors.primaryRedColor, width: 1.5),
|
||||
),
|
||||
),
|
||||
cellBorderColor: AppColors.transparent,
|
||||
dataSource: MeetingDataSource(_getDataSource()),
|
||||
monthCellBuilder: (context, details) => Padding(
|
||||
padding: EdgeInsets.all(12.h),
|
||||
child: details.date.day.toString().toText14(
|
||||
isCenter: true,
|
||||
color: details.date == _calendarController.selectedDate ? AppColors.primaryRedColor : AppColors.textColor,
|
||||
),
|
||||
),
|
||||
monthViewSettings: MonthViewSettings(
|
||||
dayFormat: "EEE",
|
||||
appointmentDisplayMode: MonthAppointmentDisplayMode.indicator,
|
||||
showTrailingAndLeadingDates: false,
|
||||
appointmentDisplayCount: 1,
|
||||
monthCellStyle: MonthCellStyle(
|
||||
textStyle: TextStyle(fontSize: 19.fSize),
|
||||
),
|
||||
),
|
||||
onTap: (CalendarTapDetails details) {
|
||||
_calendarController.selectedDate = details.date;
|
||||
_onDaySelected(details.date!);
|
||||
},
|
||||
),
|
||||
),
|
||||
//TODO: Add Next Day Span here
|
||||
Container(
|
||||
height: 40,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: dayEvents.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(right: (index == dayEvents.length - 1) ? 16 : 5.0, left: index == 0 ? 16 : 5),
|
||||
child: AppCustomChipWidget(
|
||||
labelText: dayEvents[index].isoTime,
|
||||
backgroundColor: AppColors.whiteColor,
|
||||
),
|
||||
// index == selectedButtonIndex ? getSelectedButton(index) : getNormalButton(index),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
List<Meeting> _getDataSource() {
|
||||
final List<Meeting> meetings = <Meeting>[];
|
||||
for (var slot in bookAppointmentsViewModel.freeSlotsResponse) {
|
||||
final startTime = DateUtil.convertStringToDate(slot);
|
||||
|
||||
final endTime = startTime.add(const Duration(minutes: 15));
|
||||
|
||||
meetings.add(Meeting(
|
||||
"Available", // Or leave empty with ""
|
||||
startTime,
|
||||
endTime,
|
||||
AppColors.primaryRedColor,
|
||||
false,
|
||||
"" // Optional notes
|
||||
));
|
||||
}
|
||||
return meetings;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
openTimeSlotsPickerForDate(DateTime dateStart, List<TimeSlot> freeSlots) {
|
||||
dayEvents.clear();
|
||||
DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0);
|
||||
if (isWaitingAppointmentAvailable && DateUtils.isSameDay(dateStart, DateTime.now())) {
|
||||
dayEvents.add(TimeSlot(isoTime: "Waiting Appointment", start: DateTime.now(), end: DateTime.now(), vidaDate: ""));
|
||||
}
|
||||
freeSlots.forEach((v) {
|
||||
if (v.start == dateStartObj) dayEvents.add(v);
|
||||
});
|
||||
selectedButtonIndex = 0;
|
||||
List<Map<String, dynamic>> timeList = [];
|
||||
for (var i = 0; i < dayEvents.length; i++) {
|
||||
Map<String, dynamic> timeSlot = {"isoTime": dayEvents[i].isoTime, "start": dayEvents[i].start.toString(), "end": dayEvents[i].end.toString(), "vidaDate": dayEvents[i].vidaDate};
|
||||
timeList.add(timeSlot);
|
||||
}
|
||||
selectedTime = dayEvents[selectedButtonIndex].isoTime;
|
||||
}
|
||||
|
||||
void _onDaySelected(DateTime day) {
|
||||
final DateFormat formatter = DateFormat('yyyy-MM-dd');
|
||||
setState(() {
|
||||
selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, "en");
|
||||
selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), "en");
|
||||
_calendarController.selectedDate = day;
|
||||
openTimeSlotsPickerForDate(day, bookAppointmentsViewModel.docFreeSlots);
|
||||
selectedDate = formatter.format(day);
|
||||
selectedNextDayButtonIndex = -1;
|
||||
print(_calendarController.selectedDate);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class MeetingDataSource extends CalendarDataSource {
|
||||
MeetingDataSource(List<Meeting> source) {
|
||||
appointments = source;
|
||||
}
|
||||
|
||||
@override
|
||||
DateTime getStartTime(int index) {
|
||||
return _getMeetingData(index)!.from;
|
||||
}
|
||||
|
||||
@override
|
||||
DateTime getEndTime(int index) {
|
||||
return _getMeetingData(index)!.to;
|
||||
}
|
||||
|
||||
@override
|
||||
String getSubject(int index) {
|
||||
return _getMeetingData(index)!.eventName;
|
||||
}
|
||||
|
||||
@override
|
||||
Color getColor(int index) {
|
||||
return _getMeetingData(index)!.background;
|
||||
}
|
||||
|
||||
@override
|
||||
bool isAllDay(int index) {
|
||||
return _getMeetingData(index)!.isAllDay;
|
||||
}
|
||||
|
||||
Meeting? _getMeetingData(int index) {
|
||||
final dynamic meeting = appointments?[index];
|
||||
Meeting? meetingData;
|
||||
if (meeting is Meeting) {
|
||||
meetingData = meeting;
|
||||
}
|
||||
return meetingData;
|
||||
}
|
||||
}
|
||||
|
||||
class Meeting {
|
||||
Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay, this.notes);
|
||||
|
||||
String eventName;
|
||||
DateTime from;
|
||||
DateTime to;
|
||||
Color background;
|
||||
bool isAllDay;
|
||||
String notes;
|
||||
}
|
||||
Loading…
Reference in New Issue