diff --git a/assets/images/bad.svg b/assets/images/bad.svg new file mode 100644 index 0000000..1a71742 --- /dev/null +++ b/assets/images/bad.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/good.svg b/assets/images/good.svg new file mode 100644 index 0000000..690d4d0 --- /dev/null +++ b/assets/images/good.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/normal.svg b/assets/images/normal.svg new file mode 100644 index 0000000..1885ab6 --- /dev/null +++ b/assets/images/normal.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/poor.svg b/assets/images/poor.svg new file mode 100644 index 0000000..95ce430 --- /dev/null +++ b/assets/images/poor.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/xcellent.svg b/assets/images/xcellent.svg new file mode 100644 index 0000000..eab98b3 --- /dev/null +++ b/assets/images/xcellent.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index b4f7eb6..8dea962 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -402,6 +402,10 @@ "itemCreation": "أنشاء عنصر", "stamp": "ختم", "addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله", + "feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم", + "rateUI": ".1 كيف تريد تقييم التطبيق", + "submitSurvey":"ارسال الاستبيان", + "typeHere": "اكتب هنا", "profile": { "reset_password": { "label": "Reset Password", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 7e0d3f7..c365621 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -402,6 +402,10 @@ "itemCreation": "Item Creation", "stamp": "Stamp", "addFavoriteList": "Do you want to add {name} in your favorite list", + "feedbackUserExperience": "This is to get the feedback about the user experience", + "rateUI": "1. How would you rate this UI?", + "submitSurvey":"Submit Survey", + "typeHere": "Type here", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/config/routes.dart b/lib/config/routes.dart index ffafbc7..099342b 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -4,6 +4,7 @@ import 'package:mohem_flutter_app/ui/attendance/monthly_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/attendance/vacation_rule_screen.dart'; import 'package:mohem_flutter_app/ui/bottom_sheets/attendence_details_bottom_sheet.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; +import 'package:mohem_flutter_app/ui/landing/survey_screen.dart'; import 'package:mohem_flutter_app/ui/landing/today_attendance_screen.dart'; import 'package:mohem_flutter_app/ui/leave_balance/add_leave_balance_screen.dart'; import 'package:mohem_flutter_app/ui/leave_balance/leave_balance_screen.dart'; @@ -76,6 +77,7 @@ class AppRoutes { static const String subMenuScreen = "/submenuScreen"; static const String addEitScreen = "/addeitScreen"; static const String initialRoute = login; + static const String survey = "/survey"; //Work List static const String workList = "/workList"; @@ -165,6 +167,7 @@ class AppRoutes { verifyLogin: (context) => VerifyLoginScreen(), verifyLastLogin: (context) => VerifyLastLoginScreen(), dashboard: (context) => DashboardScreen(), + survey: (context) => SurveyScreen(), subMenuScreen: (context) => SubMenuScreen(), newPassword: (context) => NewPasswordScreen(), diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 556d011..5fa9f8b 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -78,6 +78,11 @@ extension EmailValidator on String { style: TextStyle(fontSize: 18, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -1.08), ); + Widget toText19({Color? color, bool isBold = false}) => Text( + this, + style: TextStyle(fontSize: 19, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -1.14), + ); + Widget toText20({Color? color, bool isBold = false}) => Text( this, style: TextStyle(fontSize: 20, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4), diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index dc3bdb7..fb39dd7 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -55,7 +55,7 @@ extension WidgetExtensions on Widget { offset: const Offset(0, -3), ), ], - ), + ),alignment: Alignment.center, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, @@ -69,7 +69,7 @@ extension WidgetExtensions on Widget { ); } - Widget objectContainerBorderView({String title = "", String note = "", bool disablePadding = false, double radius = 15, Color? color, Color borderColor = MyColors.lightGreyEFColor}) { + Widget objectContainerBorderView({String title = "", String note = "", bool disablePadding = false, double radius = 15, Color? color, Color borderColor = MyColors.lightGreyEFColor,bool disableWidth = false,bool isAlignment = false }) { return Container( padding: disablePadding ? EdgeInsets.zero : const EdgeInsets.only(top: 15, bottom: 15, left: 14, right: 14), decoration: BoxDecoration( @@ -77,9 +77,10 @@ extension WidgetExtensions on Widget { color: color, border: Border.all( color: borderColor, - width: 1, + width: disableWidth ? 2 : 1, ), ), + alignment: isAlignment? Alignment.center : null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index c4e2891..f48e420 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -418,6 +418,10 @@ class CodegenLoader extends AssetLoader{ "itemCreation": "أنشاء عنصر", "stamp": "ختم", "addFavoriteList": "هل تريد اضافة {name} لقائمة المفضله", + "feedbackUserExperience": "هذا للحصول على تعليقات حول تجربة المستخدم", + "rateUI": ".1 كيف تريد تقييم التطبيق", + "Submit Survey": "ارسال الاستبيان", + "typeHere": "اكتب هنا", "profile": { "reset_password": { "label": "Reset Password", @@ -856,6 +860,10 @@ static const Map en_US = { "itemCreation": "Item Creation", "stamp": "Stamp", "addFavoriteList": "Do you want to add {name} in your favorite list", + "feedbackUserExperience": "This is to get the feedback about the user experience", + "rateUI": "1. How would you rate this UI?", + "Submit Survey": "Submit Survey", + "typeHere": "Type here", "profile": { "reset_password": { "label": "Reset Password", diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 16ceab4..1bbf8b2 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -403,6 +403,10 @@ abstract class LocaleKeys { static const itemCreation = 'itemCreation'; static const stamp = 'stamp'; static const addFavoriteList = 'addFavoriteList'; + static const feedbackUserExperience = 'feedbackUserExperience'; + static const rateUI = 'rateUI'; + static const submitSurvey = 'submitSurvey'; + static const typeHere = 'typeHere'; static const profile_reset_password_label = 'profile.reset_password.label'; static const profile_reset_password_username = 'profile.reset_password.username'; static const profile_reset_password_password = 'profile.reset_password.password'; diff --git a/lib/ui/landing/survey_screen.dart b/lib/ui/landing/survey_screen.dart new file mode 100644 index 0000000..16e6cec --- /dev/null +++ b/lib/ui/landing/survey_screen.dart @@ -0,0 +1,111 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/config/routes.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/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/widgets/button/default_button.dart'; +import 'package:flutter_rating_bar/flutter_rating_bar.dart'; +import 'package:mohem_flutter_app/widgets/dynamic_forms/dynamic_textfield_widget.dart'; + +class SurveyScreen extends StatefulWidget { + const SurveyScreen({Key? key}) : super(key: key); + + @override + _SurveyScreenState createState() => _SurveyScreenState(); +} + +class _SurveyScreenState extends State { + String reviewText = ""; + int _selectedIndex = -1; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.backgroundColor, + body: Column( + children: [ + Expanded( + child: ListView( + scrollDirection: Axis.vertical, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 124.height, + LocaleKeys.feedbackUserExperience.tr().toText19(), + 27.height, + LocaleKeys.rateUI.tr().toText16(), + 22.height, + Row( + children: [ + RatingBar.builder( + initialRating: 3, + minRating: 1, + direction: Axis.horizontal, + allowHalfRating: true, + itemCount: 5, + itemPadding: EdgeInsets.symmetric(horizontal: 12), + itemBuilder: (context, _) => Icon( + Icons.star, + color: Colors.amber, + ), + onRatingUpdate: (rating) {}, + ) + ], + ).paddingOnly(left: 22, right: 22, top: 12, bottom: 12).objectContainerView(disablePadding: true), + 39.height, + LocaleKeys.rateUI.tr().toText16(), + 10.height, + GridView( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5, crossAxisSpacing: 7, mainAxisSpacing: 7), + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 0), + shrinkWrap: true, + children: [ + optionUI("poor.svg", 0), + optionUI("bad.svg", 1), + optionUI("normal.svg", 2), + optionUI("good.svg", 3), + optionUI("xcellent.svg", 4), + ], + ), + 27.height, + DynamicTextFieldWidget( + LocaleKeys.description.tr(), + LocaleKeys.typeHere.tr(), + lines: 3, + ), + 150.height + ], + ).paddingOnly(left: 21, right: 21), + ], + )), + DefaultButton(LocaleKeys.submitSurvey.tr(), () async {}).insideContainer, + ], + )); + } + + Widget optionUI(String icon, int index) { + return (_selectedIndex == index + ? SvgPicture.asset( + 'assets/images/' + icon, + height: 32, + width: 32, + ).objectContainerBorderView(disablePadding: true, borderColor: MyColors.textMixColor, disableWidth: true, isAlignment: true) + : SvgPicture.asset( + 'assets/images/' + icon, + height: 32, + width: 32, + ).objectContainerView( + disablePadding: true, + )) + .onPress(() { + _selectedIndex = index; + setState(() {}); + }); + } +} diff --git a/lib/ui/landing/widget/app_drawer.dart b/lib/ui/landing/widget/app_drawer.dart index b86fc4e..ebe3f7b 100644 --- a/lib/ui/landing/widget/app_drawer.dart +++ b/lib/ui/landing/widget/app_drawer.dart @@ -87,6 +87,7 @@ class _AppDrawerState extends State { menuItem("assets/images/drawer/employee_id.svg", LocaleKeys.employeeDigitalID.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: EmployeeDigitialIdDialog())), menuItem("assets/images/drawer/view_business_card.svg", LocaleKeys.viewBusinessCard.tr(), "", closeDrawer: false, onPress: () => showMDialog(context, child: BusinessCardDialog())), menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: performLogout), + // menuItem("assets/images/drawer/logout.svg", LocaleKeys.logout.tr(), "", color: MyColors.redA3Color, closeDrawer: false, onPress: () {Navigator.pushNamed(context, AppRoutes.survey,); ], ).expanded, const Divider( diff --git a/lib/ui/my_team/view_attendance.dart b/lib/ui/my_team/view_attendance.dart index 7d8a6e0..b3f123e 100644 --- a/lib/ui/my_team/view_attendance.dart +++ b/lib/ui/my_team/view_attendance.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/monthly_attendance_api_client.dart'; import 'package:mohem_flutter_app/api/my_team/my_team_api_client.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; @@ -9,9 +10,11 @@ import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_model.dart'; import 'package:mohem_flutter_app/models/get_day_hours_type_details_list_model.dart'; +import 'package:mohem_flutter_app/models/get_schedule_shifts_details_list_model.dart'; import 'package:mohem_flutter_app/models/get_time_card_summary_list_model.dart'; import 'package:mohem_flutter_app/models/my_team/get_employee_subordinates_list.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/circular_step_progress_bar.dart'; import 'package:month_picker_dialog/month_picker_dialog.dart'; import 'package:pie_chart/pie_chart.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; @@ -44,6 +47,7 @@ class _ViewAttendanceState extends State { GetTimeCardSummaryList? getTimeCardSummaryList; GetAttendanceTracking? attendanceTracking; GetEmployeeSubordinatesList? getEmployeeSubordinates; + GetScheduleShiftsDetailsList? getScheduleShiftsDetailsList; @override void initState() { @@ -68,6 +72,18 @@ class _ViewAttendanceState extends State { } } + Future getScheduleShiftsDetails(index, pRTPID) async { + try { + Utils.showLoading(context); + getScheduleShiftsDetailsList = await MonthlyAttendanceApiClient().getScheduleShiftsDetails(pRTPID); + Utils.hideLoading(context); + //setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + final CalendarController _calendarController = CalendarController(); final List _colorList = [Color(0xff2AB2AB), Color(0xff202529)]; @@ -269,6 +285,7 @@ class _ViewAttendanceState extends State { shape: BoxShape.circle, ), dataSource: MeetingDataSource(_getDataSource()), + onTap: calendarTapped, monthViewSettings: const MonthViewSettings( dayFormat: 'EEE', showTrailingAndLeadingDates: false, @@ -388,6 +405,229 @@ class _ViewAttendanceState extends State { ); } + + void calendarTapped(CalendarTapDetails details) async { + dynamic index = details.date?.day; + if (index != null) { + index = index - 1; + } + pRTPID = getDayHoursTypeDetailsList[index].rTPID; + await getScheduleShiftsDetails(index, pRTPID); + dynamic value = getScheduleShiftsDetailsList!.pERCENTAGE; + dynamic percentage; + if (value!.indexOf('%') == 3) { + percentage = int.parse(value!.substring(0, 3)); + } else if (value!.indexOf('%') == 2) { + percentage = int.parse(value!.substring(0, 2)); + } else if (value!.indexOf('%') == 1 && value!.indexOf('%') != 0 && value!.indexOf('%') != "") { + percentage = int.parse(value!.substring(0, 1)); + } else if (value!.indexOf('%') == 0 || value!.indexOf('%') == "") { + percentage = 0; + } + showModalBottomSheet( + context: context, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)), + isScrollControlled: true, + backgroundColor: MyColors.backgroundBlackColor, + builder: (_) { + return DraggableScrollableSheet( + maxChildSize: 0.9, + expand: false, + builder: (_, controller) { + dynamic dmyString = getScheduleShiftsDetailsList!.sCHEDULEDATE; + DateTime dateTime1 = DateFormat("MM/dd/yyyy hh:mm:ss a").parse(dmyString); + return Column( + children: [ + Container( + width: 49, + height: 7, + margin: const EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25), + color: MyColors.darkGreyColor, + ), + ), + Expanded( + child: ListView.builder( + controller: controller, + itemCount: 1, + itemBuilder: (_, i) => Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.vertical( + top: Radius.circular(25.0), + ), + color: MyColors.backgroundBlackColor, + ), + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "${DateFormat("MMMM-dd-yyyy").format(dateTime1).replaceAll('-', " ")}".toText24(isBold: true, color: Colors.white), + LocaleKeys.attendanceDetails.tr().toText16(color: MyColors.greyACColor), + 12.height, + CircularStepProgressBar( + totalSteps: 16 * 4, + currentStep: percentage, + width: 224, + height: 236, + selectedColor: MyColors.gradiantEndColor, + unselectedColor: MyColors.grey70Color, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + "${getScheduleShiftsDetailsList!.pERCENTAGE}".toText44(color: Colors.white, isBold: true), + LocaleKeys.completed.tr().toText11(color: MyColors.greyACColor), + 28.height, + LocaleKeys.shiftTime.tr().toText11(color: MyColors.greyACColor), + "${getScheduleShiftsDetailsList!.sHTNAME}".toText22(color: Colors.white, isBold: true), + ], + ).center, + ).center, + ], + ).paddingOnly(left: 21, right: 21, top: 27, bottom: 37), + Stack( + children: [ + 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: 31, right: 31, top: 30, bottom: 29), + child: Column( + children: [ + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.actualCheckIn.tr().toText11( + color: MyColors.grey67Color, + ), + "${getScheduleShiftsDetailsList!.sHTACTUALSTARTTIME}" != "" + ? "${getScheduleShiftsDetailsList!.sHTACTUALSTARTTIME}".toText22(color: Colors.black, isBold: true) + : "__".toText22(color: Colors.black, isBold: true), + ], + ).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.actualCheckOut.tr().toText11( + color: MyColors.grey67Color, + ), + "${getScheduleShiftsDetailsList!.sHTACTUALENDTIME}" != "" + ? "${getScheduleShiftsDetailsList!.sHTACTUALENDTIME}".toText22(color: Colors.black, isBold: true) + : "__".toText22(color: Colors.black, isBold: true), + ], + ).expanded, + ], + ), + 25.height, + const Divider( + height: 1, + thickness: 1, + color: MyColors.lightGreyEFColor, + ), + 25.height, + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.approvedCheckIn.tr().toText11( + color: MyColors.grey67Color, + ), + "${getScheduleShiftsDetailsList!.aPPROVEDSTARTTIME}" != "" + ? "${getScheduleShiftsDetailsList!.aPPROVEDSTARTTIME}".toText22(color: MyColors.greenColor, isBold: true) + : "__".toText22(color: MyColors.greenColor, isBold: true), + ], + ).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.approvedCheckOut.tr().toText11( + color: MyColors.grey67Color, + ), + "${getScheduleShiftsDetailsList!.aPPROVEDENDTIME}" != "" + ? "${getScheduleShiftsDetailsList!.aPPROVEDENDTIME}".toText22(color: MyColors.greenColor, isBold: true) + : "__".toText22(color: MyColors.greenColor, isBold: true), + ], + ).expanded, + ], + ), + 25.height, + const Divider( + height: 1, + thickness: 1, + color: MyColors.lightGreyEFColor, + ), + 25.height, + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.lateIn.tr().toText11( + color: MyColors.grey67Color, + ), + "${getDayHoursTypeDetailsList[index].lATEINHRS}".toText22(color: MyColors.redColor, isBold: true), + ], + ).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.excess.tr().toText11( + color: MyColors.grey67Color, + ), + "${getDayHoursTypeDetailsList[index].eXCESSHRS}".toText22(color: MyColors.backgroundBlackColor, isBold: true), + ], + ).expanded, + ], + ), + 25.height, + const Divider( + height: 1, + thickness: 1, + color: MyColors.lightGreyEFColor, + ), + 25.height, + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.shortage.tr().toText11( + color: MyColors.grey67Color, + ), + "${getDayHoursTypeDetailsList[index].sHORTAGEHRS}".toText22(color: MyColors.backgroundBlackColor, isBold: true), + ], + ).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.earlyOut.tr().toText11( + color: MyColors.grey67Color, + ), + "${getDayHoursTypeDetailsList[index].eARLYOUTHRS}".toText22(color: Colors.black, isBold: true), + ], + ).expanded, + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + ); + }, + ); + }, + ); + } List _getDataSource() { List meetings = []; return meetings; diff --git a/pubspec.yaml b/pubspec.yaml index ee15638..e4f6dfc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -73,6 +73,7 @@ dependencies: qr_flutter: ^4.0.0 url_launcher: ^6.0.15 share: 2.0.4 + flutter_rating_bar: ^4.0.1 dev_dependencies: flutter_test: