import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/widgets/circular_step_progress_bar.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:flutter/cupertino.dart'; import 'package:pie_chart/pie_chart.dart'; class MonthlyAttendance extends StatefulWidget { MonthlyAttendance({Key? key}) : super(key: key); @override _MonthlyAttendanceState createState() { return _MonthlyAttendanceState(); } } class _MonthlyAttendanceState extends State { bool isPresent = true; bool isAbsent = true; bool isMissingDays = true; bool isOffDays = true; @override void initState() { super.initState(); } Map dataMap = { "Present": 65, "Absent": 35, }; final List _colorList = [Color(0xff2AB2AB), Color(0xff202529)]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: MyColors.white, leading: IconButton( icon: const Icon( Icons.arrow_back_ios, color: MyColors.backgroundBlackColor, ), onPressed: () => Navigator.pop(context), ), ), backgroundColor: Colors.white, body: ListView( scrollDirection: Axis.vertical, children: [ Column( children: [ 20.height, Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Attendance".toText24(isBold: true, color: MyColors.darkIconColor), Row( children: [ "June 13, 2021".toText16(color: MyColors.greyACColor), const Icon(Icons.keyboard_arrow_down_rounded, color: MyColors.greyACColor), ], ).onPress(() { showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2021), lastDate: DateTime(2025), builder: (context, child) { return Theme( data: ThemeData.dark().copyWith( colorScheme: const ColorScheme.dark( primary: MyColors.lightGreenColor, onPrimary: MyColors.white, surface: MyColors.lightGreenColor, onSurface: MyColors.darkTextColor, ), dialogBackgroundColor: Colors.white, ), child: child!, ); }, ); }) ], ).paddingOnly(left: 21, right: 21), 18.height, AspectRatio(aspectRatio: 333 / 270, child: calenderWidget()).paddingOnly(left: 21, right: 21), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ optionUI("Schedule\nDays", "16"), 6.width, optionUI("Off\nDays", "0"), 6.width, optionUI("Non\nAnalyzed", "0"), 6.width, optionUI("Shortage\nHour", "6"), ], ).paddingOnly(left: 21, right: 21), 35.height, Container( width: double.infinity, height: 227, decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), boxShadow: [ BoxShadow( offset: const Offset(0, 2), blurRadius: 26, color: MyColors.darkColor.withOpacity(0.1), ), ], ), child: Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( children: [ "Attendance".toText12(isBold: true, color: MyColors.grey3AColor), "Stats".toText24(isBold: true, color: MyColors.grey3AColor), ], ).paddingOnly(left: 21, top: 29, bottom: 36), Row( children: [ Container( height: 9, width: 9, decoration: BoxDecoration( color: MyColors.lightGreenColor, borderRadius: BorderRadius.circular(100), ), ), Container( margin: const EdgeInsets.only(left: 5, right: 5), child: "PRESENT 16".toText16(isBold: true, color: MyColors.lightGreenColor), ), ], ).paddingOnly(left: 21, right: 23), 8.height, Row( children: [ Container( height: 9, width: 9, decoration: BoxDecoration( color: MyColors.backgroundBlackColor, borderRadius: BorderRadius.circular(100), ), ), Container( margin: const EdgeInsets.only(left: 5, right: 5), child: "ABSENT 04".toText16( isBold: true, color: MyColors.backgroundBlackColor, ), ) ], ).paddingOnly(left: 21, top: 8), ], ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 169, height: 170, child: PieChart( dataMap: dataMap, animationDuration: const Duration(milliseconds: 800), chartLegendSpacing: 0, chartRadius: MediaQuery.of(context).size.width / 5.2, colorList: _colorList, initialAngleInDegree: 0, chartType: ChartType.ring, ringStrokeWidth: 80, legendOptions: const LegendOptions( showLegendsInRow: false, showLegends: false, ), chartValuesOptions: const ChartValuesOptions( showChartValueBackground: false, showChartValues: true, showChartValuesInPercentage: true, showChartValuesOutside: false, decimalPlaces: 1, chartValueStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: MyColors.white, )), ), ), ], ).paddingOnly(left: 65, top: 27, right: 21, bottom: 28), ], ), ), ], ), ], ), ); } Widget optionUI(String title, String value) { return AspectRatio( aspectRatio: 1 / 1, child: Container( padding: const EdgeInsets.only(top: 10, left: 8, right: 8, bottom: 10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( offset: const Offset(0, 1), blurRadius: 15, color: MyColors.darkColor.withOpacity(0.1), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [title.toText10(color: MyColors.darkTextColor).expanded, value.toText20(color: MyColors.darkTextColor)], ), ), ).expanded; } Widget calenderWidget() { return SfCalendar( view: CalendarView.month, headerHeight: 0, todayHighlightColor: MyColors.grey3AColor, viewHeaderStyle: const ViewHeaderStyle( dayTextStyle: TextStyle(color: MyColors.grey3AColor, fontSize: 13, fontWeight: FontWeight.w600), ), monthCellBuilder: (cxt, build) { int val = build.date.day % 4; isPresent = val == 0; isAbsent = val == 1; isMissingDays = val == 2; isOffDays = val == 3; if (isPresent) { return Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: const LinearGradient( transform: GradientRotation(.46), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [MyColors.gradiantEndColor, MyColors.gradiantStartColor], ), shape: BoxShape.circle, boxShadow: [ BoxShadow( offset: const Offset(0, 2), blurRadius: 26, color: MyColors.blackColor.withOpacity(0.100), ), ], ), alignment: Alignment.center, child: Text( "${build.date.day}", style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: MyColors.white, ), ), ); } else if (isAbsent) { return Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( color: MyColors.backgroundBlackColor, shape: BoxShape.circle, boxShadow: [ BoxShadow( offset: const Offset(0, 2), blurRadius: 26, color: MyColors.blackColor.withOpacity(0.100), ), ], ), alignment: Alignment.center, child: Text( "${build.date.day}", style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: MyColors.white, ), ), ); } else if (isMissingDays) { return Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( border: Border.all(color: MyColors.backgroundBlackColor, width: 2.0, style: BorderStyle.solid), //Border.all shape: BoxShape.circle, boxShadow: [ BoxShadow( offset: const Offset(0, 2), blurRadius: 26, color: MyColors.blackColor.withOpacity(0.100), ), ], ), alignment: Alignment.center, child: Text( "${build.date.day}", style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: Color(0xff1F2428), ), ), ); } else if (isOffDays) { return Container( margin: const EdgeInsets.all(4), decoration: BoxDecoration( color: MyColors.greyACColor.withOpacity(.12), shape: BoxShape.circle, ), alignment: Alignment.center, child: Text( "${build.date.day}", style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: MyColors.greyA5Color, ), ), ); } else { return Container(); } }, monthViewSettings: const MonthViewSettings( dayFormat: 'EEE', showTrailingAndLeadingDates: false, appointmentDisplayMode: MonthAppointmentDisplayMode.appointment, showAgenda: false, navigationDirection: MonthNavigationDirection.horizontal, monthCellStyle: MonthCellStyle( textStyle: TextStyle( fontStyle: FontStyle.normal, fontSize: 13, color: Colors.white, ), ), ), showNavigationArrow: false, showDatePickerButton: false, showCurrentTimeIndicator: false, showWeekNumber: false, cellBorderColor: Colors.white, selectionDecoration: BoxDecoration( border: Border.all(color: MyColors.white, width: 10), borderRadius: const BorderRadius.all(Radius.circular(100)), shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), onTap: calendarTapped, ); } void calendarTapped(CalendarTapDetails details) { showModalBottomSheet( context: context, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)), isScrollControlled: true, backgroundColor: MyColors.backgroundBlackColor, builder: (_) { return DraggableScrollableSheet( maxChildSize: 0.9, expand: false, builder: (_, controller) { return Column( children: [ Container( width: 75, height: 7, margin: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: MyColors.darkGreyColor, ), ), Expanded( child: ListView.builder( controller: controller, itemCount: 1, itemBuilder: (_, i) => Container( decoration: const BoxDecoration( borderRadius: BorderRadius.vertical( top: Radius.circular(35.0), ), color: MyColors.backgroundBlackColor, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column(children: [ "June 13, 2021".toText24(isBold: true, color: Colors.white), LocaleKeys.attendanceDetails.tr().toText16(color: MyColors.lightGreyEFColor), 21.height, ]).paddingOnly(top: 25, left: 21, right: 21, bottom: 10), Center( child: CircularStepProgressBar( totalSteps: 16 * 4, currentStep: 16, width: 210, height: 210, selectedColor: MyColors.gradiantEndColor, unselectedColor: MyColors.grey70Color, child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ "99%".toText44(color: Colors.white, isBold: true), "Completed".tr().toText11(color: MyColors.greyACColor), 19.height, "Shift Time".tr().toText11(color: MyColors.greyACColor), "08:00 - 17:00".toText22(color: Colors.white, isBold: true), ], ), ), ), ), Container( padding: const EdgeInsets.only(top: 20, bottom: 20), ), Stack( children: [ Container( height: 5, padding: const EdgeInsets.only(top: 24, bottom: 24), color: MyColors.backgroundBlackColor, ), Container( width: double.infinity, decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white), padding: const EdgeInsets.only(left: 21, right: 21, top: 28, bottom: 24), child: Column( children: [ Row( children: [ Container( margin: const EdgeInsets.only(right: 30, left: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Actual Check In ".tr().toText11( color: MyColors.grey67Color, ), 8.height, "08:27".toText22(color: Colors.black, isBold: true), ], ), ), 40.width, Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Actual Check Out".tr().toText11( color: MyColors.grey67Color, ), 8.height, "18:20".toText22(color: Colors.black, isBold: true), ], ), ], ), 25.height, const Divider( height: 1, thickness: 1, color: MyColors.whiteColor, ), 25.height, Row( children: [ Container( margin: const EdgeInsets.only(right: 30, left: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Approved Check In".tr().toText11( color: MyColors.grey67Color, ), 8.height, "09:27".toText22(color: MyColors.greenColor, isBold: true), ], ), ), 30.width, Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Approved Check Out".tr().toText11( color: MyColors.grey67Color, ), 8.height, "18:20".toText22(color: MyColors.greenColor, isBold: true), ], ), ], ), 25.height, const Divider( height: 1, thickness: 1, color: MyColors.whiteColor, ), 25.height, Row( children: [ Container( margin: const EdgeInsets.only(right: 30, left: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Late In".tr().toText11( color: MyColors.grey67Color, ), 8.height, "00:27".toText22(color: MyColors.redColor, isBold: true), ], ), ), 80.width, Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Excess".tr().toText11( color: MyColors.grey67Color, ), 8.height, "00:00".toText22(color: Colors.black, isBold: true), ], ), ], ), 25.height, const Divider( height: 1, thickness: 1, color: MyColors.whiteColor, ), 25.height, Row( children: [ Container( margin: const EdgeInsets.only(right: 30, left: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Shortage".tr().toText11( color: MyColors.grey67Color, ), 8.height, "00:00".toText22(color: Colors.black, isBold: true), ], ), ), 80.width, Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Early Out".tr().toText11( color: MyColors.grey67Color, ), 8.height, "00:00".toText22(color: Colors.black, isBold: true), ], ), ], ), ], ), ), ], ), ], ), ), ), ), ], ); }, ); }, ); } List _getDataSource() { final List meetings = []; // _events.forEach((key, value) { // final DateTime startTime = DateTime(key.year, key.month, key.day, 21, 0, 0); // final DateTime endTime = DateTime(key.year, key.month, key.day, 22, 0, 0); // meetings.add(Meeting("", startTime, endTime, MyColors.backgroundBlackColor, false)); // }); return meetings; } } class MeetingDataSource extends CalendarDataSource { MeetingDataSource(List 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; Meeting meetingData; if (meeting is Meeting) { meetingData = meeting; } return meeting; } } class Meeting { Meeting(this.eventName, this.from, this.to, this.background, this.isAllDay); String eventName; DateTime from; DateTime to; Color background; bool isAllDay; }