fist commit ftc staff app clone

This commit is contained in:
2024-08-01 13:46:46 +05:30
commit bf9064a9c9
515 changed files with 42796 additions and 0 deletions

View File

@@ -0,0 +1,255 @@
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/dialogs/widgets/holiday_request_sent_dialog.dart';
import 'package:ftc_mobile_app/dialogs/widgets/holidays_data_dialog.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:ftc_mobile_app/models/staffWorkload/StaffWorkloadResponse.dart';
import 'package:ftc_mobile_app/utilities/extensions/custom_extensions.dart';
import 'package:get/get.dart';
import '../../custom_widgets/label_value_box_widget.dart';
class BookHolidayScreen extends StatefulWidget {
const BookHolidayScreen({Key? key}) : super(key: key);
@override
State<BookHolidayScreen> createState() => _BookHolidayScreenState();
}
class _BookHolidayScreenState extends State<BookHolidayScreen> {
final controller = Get.put(BookHolidayScreenController());
@override
Widget build(BuildContext context) {
return CustomScaffold(
backgroundColor: CustomAppColors.kPrimaryColor,
screenKey: controller.screenKey,
onScreenTap: controller.removeFocus,
showAppBar: true,
appBar: CustomAppBarTitleOnly(
context,
titleText: 'Book a Holiday',
),
body: ListView(
children: [
Obx(() {
return InkWell(
onTap: () => _onTotalHolidaysBoxTap(controller.myWorkLoads()),
child: LabelValueBoxWidget(
label: 'Total Holidays Left',
value:
'${controller.myWorkLoads()?.holidaysRemaining ?? 0} days (${controller.myWorkLoads()?.holidayAlwnNoOfHours ?? 0} hours)',
trailing: const Icon(
Icons.arrow_right_rounded,
color: Colors.black,
),
).addPaddingHorizontal(16),
);
}),
10.verticalSpace,
Obx(
() => CalendarWidget(
markedDatesMap: controller.markedDatesMap(),
minDate: DateTime.now().subtract(10.days),
targetDateTime: controller.targetDateTime.value,
canSelectRange: true,
rangeStart: controller.holidayStartDate(),
rangeEnd: controller.holidayEndDate(),
onRangeSelect: controller.onRangeSelect,
onDayTap: (date, _) => controller.targetDateTime(date),
),
),
10.verticalSpace,
Padding(
padding: REdgeInsets.symmetric(horizontal: 16.0, vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//Start End date boxes
Row(
children: <Widget>[
Expanded(
child: Obx(
() => LabelValueBoxWidget(
label: "Start Date",
value: DateFormatter()
.getHolidayDate(controller.holidayStartDate()),
),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 14.r),
child: Icon(
Icons.arrow_forward,
size: 20.0.sp,
),
),
Expanded(
child: Obx(
() => LabelValueBoxWidget(
label: "End Date",
value: DateFormatter()
.getHolidayDate(controller.holidayEndDate()),
),
),
),
],
),
10.verticalSpace,
SizedBox(
width: double.infinity,
child: Obx(() => LabelValueBoxWidget(
label: "Holiday Request",
value:
"${controller.holidayDays()} Days (${controller.holidayHours()} Hours)",
))),
20.verticalSpace,
AgreeToRulesWidget(
agreeToRules: controller.agreeToRules,
onTapViewBookingRules: () {},
),
25.verticalSpace,
RequestHolidayButton(
onTap: _onRequestHolidayButtonTap,
),
],
),
),
],
),
);
}
_onTotalHolidaysBoxTap(StaffWorkLoads? workLoads) {
DateTime date = DateTime.now();
if (workLoads?.endDate.isNotNullOrEmpty() == true) {
date = DateTime.parse(workLoads!.endDate!);
}
final holidayData = HolidayModel(
carriedOver: "${workLoads?.carriedOverHours ?? 0} hours",
holidayEntitlement:
"${workLoads?.holidayEntitlement?.numberOfWeeks ?? 0} weeks (${workLoads?.holidayEntitlement?.numberOfDays ?? 0} days, ${workLoads?.holidayEntitlement?.numberOfHours ?? 0} hours)",
holidayAllowance:
"${workLoads?.holidayAlwnNoOfDys ?? 0} days (${workLoads?.holidayAlwnNoOfHours ?? 0} hours)",
remainingHolidays:
"${workLoads?.holidaysRemaining ?? 0} days (${workLoads?.holidayAlwnNoOfHours ?? 0} hours)",
timeLeftBeforeYearEnd: "${date.difference(DateTime.now()).inDays} days",
);
showDialog(
context: context,
builder: (BuildContext context) {
return HolidaysDataDialog(holidayModel: holidayData);
});
}
_onRequestHolidayButtonTap() async {
final isSuccess = await controller.requestHoliday();
if (isSuccess) {
Get.dialog(HolidayRequestSentDialog(
holidayStartDate:
DateFormatter().getHolidayDate(controller.holidayStartDate.value),
holidayEndDate:
DateFormatter().getHolidayDate(controller.holidayEndDate.value),
holidayTotalTime:
"${controller.holidayDays()} Days (${controller.holidayHours()} Hours)",
));
}
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
class AgreeToRulesWidget extends StatelessWidget {
final RxBool agreeToRules;
final VoidCallback onTapViewBookingRules;
const AgreeToRulesWidget({
super.key,
required this.agreeToRules,
required this.onTapViewBookingRules,
});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
InkWell(
onTap: agreeToRules.toggle,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Obx(
() => Ink(
width: 24.r,
height: 24.r,
child: Checkbox(
value: agreeToRules.value,
activeColor: CustomAppColors.kSecondaryColor,
onChanged: (value) {
agreeToRules.value = value ?? false;
},
),
),
),
10.horizontalSpace,
CustomTextWidget(
isExpanded: false,
text: 'Agree to the booking rules',
fontColor: Colors.black,
fontSize: 10.0.sp,
fontWeight: FontWeight.w400,
),
],
),
),
// const Spacer(),
// InkWell(
// onTap: () {},
// child: Padding(
// padding: REdgeInsets.only(left: 8.0, top: 4.r, bottom: 4.r),
// child: CustomTextWidget(
// isExpanded: false,
// text: 'View Booking Rules',
// fontColor: CustomAppColors.kBlackColor,
// fontWeight: FontWeight.bold,
// fontSize: 10.sp,
// ),
// ),
// ),
],
);
}
}
class RequestHolidayButton extends StatelessWidget {
final VoidCallback onTap;
const RequestHolidayButton({super.key, required this.onTap});
@override
Widget build(BuildContext context) {
// final BookHolidayScreenController controller =
// Get.put(BookHolidayScreenController());
return GestureDetector(
onTap: onTap,
child: Container(
width: MediaQuery.of(context).size.width,
height: 60.h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: CustomAppColors.kSecondaryColor,
borderRadius: BorderRadius.circular(2.r),
),
child: const CustomTextWidget(
text: "REQUEST HOLIDAY", fontColor: CustomAppColors.kPrimaryColor),
),
);
}
}

View File

@@ -0,0 +1,82 @@
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:get/get.dart';
class CalendarScreen extends StatefulWidget {
const CalendarScreen({Key? key}) : super(key: key);
@override
State<CalendarScreen> createState() => _CalendarScreenState();
}
class _CalendarScreenState extends State<CalendarScreen> {
final CalendarViewScreenController controller =
Get.find<CalendarViewScreenController>();
@override
Widget build(BuildContext context) {
return CustomScaffold(
backgroundColor: CustomAppColors.kPrimaryColor,
screenKey: controller.scaffoldKey,
onScreenTap: controller.removeFocus,
body: Obx(
() => controller.isLoading.value
? const Center(
child: CircularProgressIndicator(),
)
: Column(
children: [
// Obx(
// () => SetMonthAndYearWidget(
// currentMonthName: controller.currentMonthName.value,
// nextMonthTap: controller.onNextMonthTap,
// previousMonthTap: controller.onPreviousMonthTap),
// ),
Obx(
() => CalendarWidget(
markedDatesMap: controller.events(),
targetDateTime: controller.targetDateTime.value,
onEventTap: (events) {
if (events.isNotEmpty) {
controller.selectedDate.value =
MarkDatesModel.addDate(
date: events.first.date,
title: events.first.title ?? "");
controller.datesToShowList.value = [
RotaShift(
name: "",
staffRequired: "",
workerType: "",
location: "",
startTime: controller.selectedDate.value.date
.toIso8601String(),
endTime: "",
breakTime: "",
notes: "")
];
}
}),
),
10.verticalSpace,
Expanded(
child: Obx(
() => ListView.builder(
itemCount: controller.datesToShowList.length,
itemBuilder: (BuildContext context, int index) {
Rx<RotaShift> dateModel =
controller.datesToShowList[index].obs;
//Todo: RotaWidget need to reconfigure here
return SizedBox.shrink();
// return RotaWidget(
// startDateTime: dateModel.value.shiftStartTime,
// endDateTime: dateModel.value.shiftEndTime);
},
),
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,5 @@
export 'calendar_view_screen.dart';
export 'rota_dashboard_screen.dart';
export 'book_holiday_screen.dart';
export 'pick_up_shifts_screen.dart';
export 'your_rota_screen.dart';

View File

@@ -0,0 +1,69 @@
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/models/rota/WeekArrayData.dart';
class NewRotaListWidget extends StatelessWidget {
final List<DaysArrayData> shifts;
final Function(int index, DaysArrayData data)? onClaimShiftTap;
final Function(int index, DaysArrayData data)? onCancelShiftTap;
final ScrollPhysics? physics;
const NewRotaListWidget({
super.key,
required this.shifts,
this.onClaimShiftTap,
this.onCancelShiftTap,
this.physics,
});
@override
Widget build(BuildContext context) {
return (shifts.isEmpty)
? FrequentFunctions.centerText(text: "No shifts found")
: ListView.separated(
shrinkWrap: true,
itemCount: shifts.length,
physics: physics,
padding: REdgeInsets.symmetric(horizontal: 20),
separatorBuilder: (_, index) => 10.verticalSpace,
itemBuilder: (_, index) {
return RotaWidget(
data: shifts[index],
onViewShiftTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return ShowRotaAlertDialog(
data: shifts[index],
onClaimShiftTap: () {
if (onClaimShiftTap != null) {
onClaimShiftTap!.call(index, shifts[index]);
}
},
onCancelShiftTap: () {
if (onCancelShiftTap != null) {
onCancelShiftTap!.call(index, shifts[index]);
}
},
);
});
// onViewShiftTap(index, shifts[index])
},
);
},
);
}
// Container _upperTextWidget({required String text}) {
// return Container(
// padding: const EdgeInsets.only(left: 20),
// child: Text(
// text,
// style: const TextStyle(
// color: CustomAppColors.kLightTextColor, fontSize: 12),
// ),
// );
// }
}

View File

@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:get/get.dart';
import 'new_rota_list_widget.dart';
class PickUpShiftsScreen extends StatefulWidget {
const PickUpShiftsScreen({Key? key}) : super(key: key);
@override
State<PickUpShiftsScreen> createState() => _PickUpShiftsScreenState();
}
class _PickUpShiftsScreenState extends State<PickUpShiftsScreen> {
final _controller = Get.put(PickUpShiftsScreenController());
@override
Widget build(BuildContext context) {
return CustomScaffold(
screenKey: _controller.screenKey,
onScreenTap: _controller.removeFocus,
showAppBar: true,
appBar: CustomAppBarTitleOnly(context, titleText: "Available Shifts"),
body: _getBody(),
);
}
Widget _getBody() {
return Obx(
() => _controller.loadingShifts()
? const Center(child: CircularProgressIndicator())
: NewRotaListWidget(
shifts: _controller.myShiftsList(),
onClaimShiftTap: _controller.claimShifts,
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}

View File

@@ -0,0 +1,206 @@
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:ftc_mobile_app/models/rota/WeekArrayData.dart';
import 'package:get/get.dart';
import 'new_rota_list_widget.dart';
class RotaDashboardScreen extends StatefulWidget {
const RotaDashboardScreen({Key? key}) : super(key: key);
@override
State<RotaDashboardScreen> createState() => _RotaDashboardScreenState();
}
class _RotaDashboardScreenState extends State<RotaDashboardScreen> {
final _controller = Get.put(RotaDashboardScreenController());
@override
Widget build(BuildContext context) {
return CustomScaffold(
screenKey: _controller.screenKey,
onScreenTap: _controller.removeFocus,
showAppBar: true,
appBar: CustomAppBarTitleOnly(context, titleText: 'Rota'),
body: _tabWidget(),
);
}
Widget _tabWidget() {
return Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: 18.0.w,
),
child: Row(
children: [
Expanded(
child: _buttons(
onTap: () {
Navigator.pushNamed(
context,
CustomRouteNames.kPickUpShiftsScreenRoute,
);
},
text: "Pick up Shifts")),
24.horizontalSpace,
Expanded(
child: _buttons(
onTap: () {
Navigator.pushNamed(
context,
CustomRouteNames.kBookHolidayScreenRoute,
);
},
text: "Book a Holiday")),
],
),
),
Container(
width: Get.width,
alignment: Alignment.center,
child: TabBar(
controller: _controller.tabController,
unselectedLabelColor: CustomAppColors.kLightGreyColor,
labelColor: CustomAppColors.kSecondaryColor,
labelPadding: const EdgeInsets.all(0),
indicatorSize: TabBarIndicatorSize.tab,
indicatorColor: CustomAppColors.kSecondaryColor,
tabs: const [
Tab(
child: Text(
"List",
textAlign: TextAlign.center,
maxLines: 2,
),
),
Tab(
child: Text(
"Calendar",
textAlign: TextAlign.center,
maxLines: 2,
),
),
],
//Change
),
),
Expanded(
child: TabBarView(
controller: _controller.tabController,
children: [_yourRotaListTabView, _calandarTabView()],
),
),
],
);
}
Widget _calandarTabView() {
return Column(
children: [
Flexible(
child: Obx(
() {
return CalendarWidget(
key: UniqueKey(),
markedDatesMap: _controller.markedDatesMap(),
minDate: DateTime.now().subtract(40.days),
targetDateTime: _controller.targetDateTime(),
canSelectRange: false,
onDayTap: _controller.onDateSelect,
);
},
),
),
Expanded(
child: Obx(
() => NewRotaListWidget(
shifts: _controller.dateFilteredShiftsList(),
onCancelShiftTap: (int index, DaysArrayData data) {},
),
),
),
],
);
}
Widget get _yourRotaListTabView {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_yourRotaHeader(),
Expanded(
child: Obx(
() => _controller.loadingShifts()
? const Center(child: CircularProgressIndicator())
: NewRotaListWidget(
shifts: _controller.myShiftsList(),
onCancelShiftTap: (int index, DaysArrayData data) {},
),
),
),
],
);
}
Widget _yourRotaHeader() {
return InkWell(
onTap: () {
Navigator.pushNamed(context, CustomRouteNames.kYourRotaScreenRoute);
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomTextWidget(
text: "Your Rota",
fontSize: 16.sp,
fontWeight: FontWeight.w700,
isExpanded: false,
),
const CustomImageWidget(
imagePath: AssetsManager.kArrowNextIcon,
),
],
),
),
);
}
Widget _buttons({required VoidCallback onTap, required String text}) {
return InkWell(
onTap: onTap,
child: Container(
height: 42.r,
width: double.maxFinite,
padding: REdgeInsets.all(10).copyWith(right: 2.r),
decoration: BoxDecoration(
border: Border.all(
color: CustomAppColors.kSecondaryColor,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomTextWidget(
text: text,
isExpanded: false,
fontWeight: FontWeight.w600,
fontSize: 14.sp),
Icon(
Icons.keyboard_arrow_right,
size: 20.r,
),
],
),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}

View File

@@ -0,0 +1,92 @@
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:ftc_mobile_app/models/rota/WeekArrayData.dart';
import 'package:get/get.dart';
import 'new_rota_list_widget.dart';
class YourRotaScreen extends StatefulWidget {
const YourRotaScreen({Key? key}) : super(key: key);
@override
State<YourRotaScreen> createState() => _YourRotaScreenState();
}
class _YourRotaScreenState extends State<YourRotaScreen> {
final controller = Get.put(YourRotaScreenController());
@override
Widget build(BuildContext context) {
return CustomScaffold(
backgroundColor: CustomAppColors.kPrimaryColor,
screenKey: controller.screenKey,
onScreenTap: controller.removeFocus,
showAppBar: true,
appBar: CustomAppBar(
showBoxShadow: false,
leadingButton: Container(),
titleWidget: Row(
children: [
InkWell(
onTap: () {
Navigator.pop(context);
},
child: CustomImageWidget(
imagePath: AssetsManager.kBackIcon,
height: 11.53.h,
width: 8.66.w,
),
),
SizedBox(
width: 15.w,
),
CustomTextWidget(
text: "Your Rota",
isExpanded: false,
fontSize: 16.sp,
fontWeight: FontWeight.w700),
],
),
),
body: _getBody(),
);
}
Widget _getBody() {
return Obx(
() => controller.loadingShifts()
? const Center(child: CircularProgressIndicator())
: NewRotaListWidget(
shifts: controller.myShiftsList(),
onCancelShiftTap: (int index, DaysArrayData data) {},
),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
// class UpperTextWidget extends StatelessWidget {
// const UpperTextWidget({
// super.key,
// required this.text,
// });
//
// final String text;
//
// @override
// Widget build(BuildContext context) {
// return Container(
// padding: const EdgeInsets.only(left: 20),
// child: Text(
// text,
// style: const TextStyle(
// color: CustomAppColors.kLightTextColor, fontSize: 12),
// ),
// );
// }
// }