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,321 @@
import 'package:flutter/material.dart';
import 'package:flutter_calendar_carousel/classes/event.dart';
import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../../../ftc_mobile_app.dart';
// class SetMonthAndYearWidget extends StatelessWidget {
// const SetMonthAndYearWidget({
// super.key,
// required this.currentMonthName,
// required this.previousMonthTap,
// required this.nextMonthTap,
// });
//
// final String currentMonthName;
// final VoidCallback previousMonthTap;
// final VoidCallback nextMonthTap;
//
// @override
// Widget build(BuildContext context) {
// return Container(
// padding: const EdgeInsets.only(left: 20.0, right: 20.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// GestureDetector(
// onTap: previousMonthTap,
// child: Transform.rotate(
// angle: 3.1415 * 2.5,
// child: const Icon(Icons.arrow_drop_down),
// ),
// ),
// CustomTextWidget(
// isExpanded: false,
// text: currentMonthName,
// textAlign: TextAlign.center,
// fontColor: CustomAppColors.kBlackColor,
// fontSize: 13,
// fontWeight: FontWeight.bold),
// GestureDetector(
// onTap: nextMonthTap,
// child: Transform.rotate(
// angle: 3.1415 * 3.5,
// child: const Icon(Icons.arrow_drop_down),
// ),
// ),
// ],
// ),
// );
// }
// }
typedef OnRangeSelect = Function(
DateTime rangeStart, DateTime? rangeEnd, List<String> selectedDates);
class CalendarWidget extends StatefulWidget {
static final dateFormat = DateFormat("dd-MM-yyyy");
const CalendarWidget({
super.key,
this.minDate,
this.maxDate,
this.onEventTap,
required this.targetDateTime,
required this.markedDatesMap,
this.onDayTap,
this.rangeStart,
this.rangeEnd,
this.canSelectRange = false,
this.onRangeSelect,
});
final DateTime? minDate;
final DateTime? maxDate;
final DateTime targetDateTime;
final EventList<Event> markedDatesMap;
final ValueChanged<List<Event>>? onEventTap;
final Function(DateTime, List<Event>)? onDayTap;
final bool canSelectRange;
///[selectedDates] will be in format dd-MM-yyyy
final OnRangeSelect? onRangeSelect;
final DateTime? rangeStart;
final DateTime? rangeEnd;
@override
State<CalendarWidget> createState() => _CalendarWidgetState();
///This method checks if [start] and [end] dates are at proper position i.e.,
///[start] date should be before [end] date. If not, this method corrects the two dates and
///return proper [start] [end] dates
static ({DateTime start, DateTime end}) rectifyStartEndDates(
DateTime start, DateTime end) {
final first = start.isBefore(end) ? start : end;
final last = end.isAfter(start) ? end : start;
return (start: first, end: last);
}
static List<String> getDatesFromStartEndRange(DateTime start, DateTime end) {
final List<String> dates = [];
// final first = start.isBefore(end) ? start : end;
// final last = end.isAfter(start) ? end : start;
final record = rectifyStartEndDates(start, end);
for (int i = 0; i <= record.end.difference(record.start).inDays; i++) {
dates.add(dateFormat.format(record.start.add(i.days)));
}
return dates;
}
static Widget shiftIcon(String day) => CircleAvatar(
backgroundColor: CustomAppColors.kSecondaryColor,
child: Text(
day,
style:
const TextStyle(color: CustomAppColors.kWhiteColor, fontSize: 13),
),
);
static Widget underlineIcon() => Container(
alignment: Alignment.center,
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: CustomAppColors.kSecondaryColor,
width: 3.0,
),
),
),
);
}
class _CalendarWidgetState extends State<CalendarWidget> {
//Selected dates will be in format dd-MM-yyyy
final selectedDates = RxList<String>();
DateTime? start, end;
@override
void initState() {
super.initState();
if (widget.canSelectRange &&
widget.rangeStart != null &&
widget.rangeEnd != null) {
start = widget.rangeStart;
end = widget.rangeEnd;
selectedDates.value =
CalendarWidget.getDatesFromStartEndRange(start!, end!);
} else {
selectedDates.value = [
CalendarWidget.dateFormat.format(widget.targetDateTime)
];
}
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
double textScaleFactor = MediaQuery.of(context).textScaleFactor;
double itemHeight = (height * textScaleFactor - kToolbarHeight - 24) / 4;
double calHeight = (height * textScaleFactor) / 2.9;
double itemWidth = width * 0.7;
return Container(
height: calHeight,
margin: const EdgeInsets.only(top: 10, bottom: 3),
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: CalendarCarousel<Event>(
targetDateTime: widget.targetDateTime,
firstDayOfWeek: 0,
dayPadding: 1.0,
minSelectedDate: widget.minDate,
maxSelectedDate: widget.maxDate,
todayTextStyle: const TextStyle(
color: CustomAppColors.kBlackColor,
fontWeight: FontWeight.normal,
fontSize: 13.0,
),
weekdayTextStyle: const TextStyle(
color: CustomAppColors.kBlueColor,
fontWeight: FontWeight.bold,
fontSize: 13.0,
),
weekendTextStyle: const TextStyle(
color: CustomAppColors.kBlackColor,
fontSize: 13.0,
),
customDayBuilder: (bool isSelectable,
int index,
bool isSelectedDay,
bool isToday,
bool isPrevMonthDay,
TextStyle textStyle,
bool isNextMonthDay,
bool isThisMonthDay,
DateTime day) {
if (selectedDates.contains(CalendarWidget.dateFormat.format(day))) {
return Container(
width: double.maxFinite,
height: double.maxFinite,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).primaryColor,
),
child: Center(
child: Text(
day.day.toString(),
style: textStyle.copyWith(color: Colors.white),
),
),
);
}
return null;
},
onDayPressed: (DateTime date, List<Event> events) {
if (widget.onEventTap != null) {
widget.onEventTap!(events);
}
if (widget.onDayTap != null) {
widget.onDayTap!(date, events);
}
if (widget.canSelectRange) {
rangeSelectionHandler(date);
}
},
childAspectRatio: textScaleFactor > 1.5
? ((itemWidth / itemHeight) * 1.1)
: textScaleFactor > 1
? ((itemWidth / itemHeight) * 1.05)
: (itemWidth / itemHeight),
todayButtonColor: Colors.transparent,
todayBorderColor: Colors.transparent,
daysHaveCircularBorder: true,
isScrollable: true,
shouldShowTransform: false,
pageSnapping: true,
// selectedDateTime: DateTime(2024, 5, 25),
thisMonthDayBorderColor: Colors.transparent,
daysTextStyle: const TextStyle(
fontSize: 13.0,
color: CustomAppColors.kBlackColor,
),
weekFormat: false,
showOnlyCurrentMonthDate: true,
width: width,
onHeaderTitlePressed: () {},
customGridViewPhysics: const NeverScrollableScrollPhysics(),
markedDatesMap: widget.markedDatesMap,
//marked up dates
markedDateIconBuilder: (event) => event.icon,
markedDateCustomTextStyle: TextStyle(
fontSize: 13.sp,
color: CustomAppColors.kWhiteColor,
),
markedDateShowIcon: true,
markedDateIconMaxShown: 1,
markedDateMoreShowTotal: null,
showHeader: true,
leftButtonIcon: const Icon(
Icons.arrow_left,
color: Colors.black,
),
rightButtonIcon: const Icon(
Icons.arrow_right,
color: Colors.black,
),
headerTextStyle: const TextStyle(
color: CustomAppColors.kBlackColor,
fontSize: 13,
fontWeight: FontWeight.bold),
onCalendarChanged: (DateTime date) {},
onDayLongPressed: (DateTime date) {},
),
);
}
rangeSelectionHandler(DateTime selectedDay) {
final d = CalendarWidget.dateFormat.format(selectedDay);
if (selectedDates.contains(d)) {
selectedDates.remove(d);
} else {
selectedDates.add(d);
}
//meaning either no range selected or range already been selected
if (start == null || (start != null && end != null)) {
start = selectedDay;
end = null;
selectedDates
..clear()
..add(CalendarWidget.dateFormat.format(selectedDay));
if (widget.onRangeSelect != null) {
widget.onRangeSelect!(start!, null, selectedDates());
}
return;
}
//Already selected start date now selecting range end date
if (end == null) {
final record = CalendarWidget.rectifyStartEndDates(start!, selectedDay);
start = record.start;
end = record.end;
selectedDates.clear();
selectedDates.value =
CalendarWidget.getDatesFromStartEndRange(start!, end!);
}
print("start: ${start.toString()}\nEnd:${end.toString()}");
if (widget.onRangeSelect != null) {
widget.onRangeSelect!(start!, end, selectedDates());
}
}
}

View File

@@ -0,0 +1,3 @@
export 'custom_calendar_widget.dart';
export "package:ftc_mobile_app/dialogs/widgets/shift_dialog.dart";
export 'rota_list_item.dart';

View File

@@ -0,0 +1,130 @@
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/models/rota/WeekArrayData.dart';
import 'package:ftc_mobile_app/utilities/extensions/custom_extensions.dart';
import '../../../ftc_mobile_app.dart';
class RotaWidget extends StatelessWidget {
const RotaWidget(
{super.key, required this.data, required this.onViewShiftTap});
final DaysArrayData data;
final Function() onViewShiftTap;
@override
Widget build(BuildContext context) {
return Container(
// height: 150,
alignment: Alignment.center,
padding: EdgeInsets.all(10.sp),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
border: Border(
left: BorderSide(
width: 6.r,
color: CustomAppColors.kSecondaryColor,
),
top: const BorderSide(
color: CustomAppColors.kSecondaryColor,
),
right: const BorderSide(
color: CustomAppColors.kSecondaryColor,
),
bottom: const BorderSide(
color: CustomAppColors.kSecondaryColor,
),
),
borderRadius: BorderRadius.all(Radius.circular(2.0.r)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text.rich(
TextSpan(
text: data.locationId?.shiftLocationName ?? "",
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w400,
),
children: [
const TextSpan(text: ' ('),
TextSpan(
text: ((data.serviceUserId?.displayName ??
"Unassigned"))
.trim(),
style: TextStyle(
color: data.serviceUserId?.displayName
.isNotNullOrEmpty() ==
true
? Colors.black
: Colors.red)),
const TextSpan(text: ')'),
],
),
),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
CustomTextWidget(
fontWeight: FontWeight.w500,
fontSize: 10.sp,
text: DateFormatter().getRotaNewDate(
shiftDate: data.shiftDate ?? 0,
startShiftTime: data.shiftStartTime ?? '0',
endShiftTime: data.shiftEndTime ?? '0',
),
isExpanded: false),
6.verticalSpace,
CustomTextWidget(
text: '${int.parse(data.workHrs?.toString() ?? "0")}hrs',
fontSize: 14.sp,
fontWeight: FontWeight.w600,
isExpanded: false,
),
],
),
],
),
10.verticalSpace,
ShiftButtonWidget(onTap: onViewShiftTap)
],
),
);
}
}
class ShiftButtonWidget extends StatelessWidget {
final VoidCallback onTap;
const ShiftButtonWidget({
super.key,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Container(
width: MediaQuery.of(context).size.width,
height: 26.h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: CustomAppColors.kSecondaryColor,
borderRadius: BorderRadius.circular(2.r),
),
child: const Text(
"View Shift",
style: TextStyle(color: CustomAppColors.kPrimaryColor),
),
),
);
}
}