import 'package:flutter/material.dart'; import 'package:ftc_mobile_app/dialogs/app_dialogs.dart'; import 'package:ftc_mobile_app/models/profileData/user_data.dart'; import 'package:get/get.dart'; import 'package:grouped_list/grouped_list.dart'; import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart'; import '../../../ftc_mobile_app.dart'; import '../../../models/appointmentsListResponse/AppointmentsListResponse.dart'; import '../../custom_widgets/my_circle_image.dart'; class AppointmentScreen extends StatefulWidget { final UserData userData; const AppointmentScreen({Key? key, required this.userData}) : super(key: key); @override State createState() => _AppointmentScreenState(); } class _AppointmentScreenState extends State { final controller = Get.put(AppointmentScreenController()); @override void initState() { controller.serviceUserId = widget.userData.id ?? ""; super.initState(); } @override Widget build(BuildContext context) { return CustomScaffold( backgroundColor: CustomAppColors.kPrimaryColor, screenKey: controller.screenKey, onScreenTap: controller.removeFocus, showAppBar: true, appBar: CustomAppBarTitleOnly( context, titleText: 'Appointments', ), body: Column( children: [ 16.verticalSpace, MyCircleImage( imageSize: 80.r, url: "${WebUrls.baseUrl}${widget.userData.profilePictureUrl}", errorWidget: CustomImageWidget( imagePath: AssetsManager.kPersonMainIcon, height: 80.r, width: 80.r, ), ), 16.verticalSpace, CustomTextWidget( text: widget.userData.displayName, fontSize: 14.sp, fontWeight: FontWeight.w600), 16.verticalSpace, Expanded(child: _appointmentsList()), ], ), ); } Widget _appointmentsList() { return ObxValue((RxList appointments) { return SmartRefresher( key: const ValueKey("refreshListAppointments"), controller: controller.listRC, scrollController: controller.listSC, enablePullUp: false, header: FrequentFunctions.waterDropHeader, onRefresh: controller.onRefresh, child: (appointments.isEmpty) ? FrequentFunctions.centerText(text: "No appointments yet") : GroupedListView( elements: appointments(), groupBy: (d) { return DateTime.fromMillisecondsSinceEpoch(d.appointmentDate!) .toLocal() .isAfter(DateTime.now()) ? 0 : 1; }, groupSeparatorBuilder: (int groupByValue) { final label = groupByValue == 0 ? "Upcoming Appointments" : "Previous Appointments"; return _buildGroupSeparatorWidget(label); }, itemBuilder: (context, element) => _buildItemWidget(appointments.indexOf(element), element), separator: 8.verticalSpace, groupComparator: (item1, item2) { return item1.compareTo(item2); }, ), ); }, controller.appointments); } Widget _buildGroupSeparatorWidget(String susTag) { return Container( padding: EdgeInsets.only(left: 20.w), child: CustomTextWidget( alignment: Alignment.centerLeft, isExpanded: false, text: susTag, fontSize: 16.sp, fontWeight: FontWeight.w700), ); } Widget _buildItemWidget(int index, AppointmentsListResponseData data) { return AppointmentWidget(data: data); } @override void dispose() { controller.dispose(); super.dispose(); } } class AppointmentWidget extends StatelessWidget { final AppointmentsListResponseData data; const AppointmentWidget({ super.key, required this.data, }); @override Widget build(BuildContext context) { return Container( // height: 150, alignment: Alignment.center, margin: EdgeInsets.only(left: 20.w, bottom: 5.h, right: 10.w, top: 10.h), padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.h), width: MediaQuery.of(context).size.width, decoration: BoxDecoration( color: Colors.white, border: Border( left: BorderSide(color: Get.theme.primaryColor, width: 6), top: BorderSide(color: Get.theme.primaryColor, width: 1), right: BorderSide(color: Get.theme.primaryColor, width: 1), bottom: BorderSide(color: Get.theme.primaryColor, width: 1), ), borderRadius: BorderRadius.all( Radius.circular(2.0.r), ), ), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CustomTextWidget( text: data.staff?.name ?? "", fontWeight: FontWeight.bold, isExpanded: false), CustomTextWidget( text: data.appointmentStartTime ?? "", fontSize: 10.sp, fontWeight: FontWeight.w500, fontColor: CustomAppColors.kLightTextColor, isExpanded: false), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: CustomTextWidget( text: data.appointmentDetails ?? "", fontSize: 12.sp, isExpanded: false, maxLines: 2, textAlign: TextAlign.left, ), ), 10.horizontalSpace, CustomTextWidget( text: DateFormatter().getAppointmentTime( DateTime.fromMillisecondsSinceEpoch(data.appointmentDate!)), fontSize: 14.sp, isExpanded: false, fontWeight: FontWeight.w600, ), ], ), 10.verticalSpace, SizedBox( height: 32.r, child: CustomAppButton( onTap: () { AppDialog.showAppointmentDetailDialog(data: data); }, buttonText: "View Appointment", buttonColor: CustomAppColors.kSecondaryColor, textColor: CustomAppColors.kPrimaryColor, ), ), // SizedBox( // height: 5.h, // ), // const ViewAppointmentButtonWidget( // text: "+Add Note", // textColor: CustomAppColors.kSecondaryColor, // buttonColor: CustomAppColors.kPrimaryColor, // borderColor: CustomAppColors.kSecondaryColor, // ), ], ), ); } } class ViewAppointmentButtonWidget extends StatelessWidget { const ViewAppointmentButtonWidget({ super.key, required this.text, required this.textColor, required this.buttonColor, this.borderColor, }); final String text; final Color textColor; final Color buttonColor; final Color? borderColor; @override Widget build(BuildContext context) { return InkWell( onTap: () {}, child: Container( width: MediaQuery.of(context).size.width, alignment: Alignment.center, padding: EdgeInsets.symmetric(vertical: 5.h), margin: EdgeInsets.symmetric(horizontal: 2.w), decoration: BoxDecoration( border: borderColor != null ? Border.all(color: borderColor!) : null, color: buttonColor, borderRadius: BorderRadius.circular(2.r), ), child: CustomTextWidget( text: text, fontColor: textColor, fontSize: 14.sp, fontWeight: FontWeight.w700, ), ), ); } }