260 lines
8.2 KiB
Dart
260 lines
8.2 KiB
Dart
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<AppointmentScreen> createState() => _AppointmentScreenState();
|
|
}
|
|
|
|
class _AppointmentScreenState extends State<AppointmentScreen> {
|
|
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<AppointmentsListResponseData> 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<AppointmentsListResponseData, int>(
|
|
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,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|