diff --git a/lib/classes/colors.dart b/lib/classes/colors.dart index c97a784..70e46da 100644 --- a/lib/classes/colors.dart +++ b/lib/classes/colors.dart @@ -26,6 +26,7 @@ class MyColors { static const Color lightGreyE5Color = Color(0xffE5E5E5); static const Color darkWhiteColor = Color(0xffE0E0E0); static const Color redColor = Color(0xffD02127); + static const Color pinkColor = Color(0xffEBA9A9); static const Color yellowColor = Color(0xffF4E31C); static const Color orange = Color(0xFFCC9B14); static const Color yellowFavColor = Color(0xffEAC321); diff --git a/lib/main.dart b/lib/main.dart index 3ccb876..8bc0ecf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,12 +20,20 @@ var logger = Logger( // output: null, // U ); +class MyHttpOverrides extends HttpOverrides { + @override + HttpClient createHttpClient(SecurityContext? context) { + return super.createHttpClient(context)..badCertificateCallback = (X509Certificate cert, String host, int port) => true; + } +} + Future main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); AppState().setPostParamsModel( PostParamsModel(channel: 31, versionID: 5.0, mobileType: Platform.isAndroid ? "android" : "ios"), ); + HttpOverrides.global = MyHttpOverrides(); runApp( EasyLocalization( supportedLocales: const [ diff --git a/lib/ui/leave_balance/leave_balance_screen.dart b/lib/ui/leave_balance/leave_balance_screen.dart index 4306e36..cb33825 100644 --- a/lib/ui/leave_balance/leave_balance_screen.dart +++ b/lib/ui/leave_balance/leave_balance_screen.dart @@ -1,23 +1,16 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; import 'package:mohem_flutter_app/api/leave_balance_api_client.dart'; -import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; -import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.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/models/dashboard/get_accrual_balances_list_model.dart'; import 'package:mohem_flutter_app/models/leave_balance/get_absence_transaction_list_model.dart'; -import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/balances_dashboard_widget.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; -import 'package:pie_chart/pie_chart.dart'; -import 'package:provider/provider.dart'; class LeaveBalance extends StatefulWidget { LeaveBalance({Key? key}) : super(key: key); @@ -31,10 +24,6 @@ class LeaveBalance extends StatefulWidget { class _LeaveBalanceState extends State { List? absenceTransList; - List chartModelList = []; - - GetAccrualBalancesList? leaveBalanceAccrual; - DateTime accrualDateTime = DateTime.now(); @override @@ -61,35 +50,8 @@ class _LeaveBalanceState extends State { } } - void changeAccrualDate() async { - try { - Utils.showLoading(context); - List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime)); - if (accrualList.isNotEmpty) { - leaveBalanceAccrual = accrualList[0]; - chartModelList = [ - PieChartModel("Current Balance", leaveBalanceAccrual?.accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""), - PieChartModel("Used", leaveBalanceAccrual?.accrualUsedEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""), - ]; - } - Utils.hideLoading(context); - setState(() {}); - } catch (ex) { - Utils.hideLoading(context); - Utils.handleException(ex, context, null); - } - } - @override Widget build(BuildContext context) { - if (leaveBalanceAccrual == null) { - leaveBalanceAccrual = Provider.of(context, listen: false).leaveBalanceAccrual; - - chartModelList = [ - PieChartModel("Current Balance", leaveBalanceAccrual?.accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""), - PieChartModel("Used", leaveBalanceAccrual?.accrualUsedEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""), - ]; - } return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget( @@ -100,45 +62,7 @@ class _LeaveBalanceState extends State { physics: const BouncingScrollPhysics(), padding: const EdgeInsets.all(21), children: [ - Column( - children: [ - Row( - children: [ - "Current Leave Balance".toText20().expanded, - Row( - children: [ - const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16), - 5.width, - DateUtil.formatDateToDate(accrualDateTime, AppState().isArabic(context)).toText13(isUnderLine: true), - 8.width - ], - ).onPress(() async { - DateTime selectedDate = await Utils.selectDate(context, accrualDateTime); - if (selectedDate != accrualDateTime) { - accrualDateTime = selectedDate; - changeAccrualDate(); - } - }), - ], - ), - 8.height, - AspectRatio( - aspectRatio: 302 / 122, - child: Row( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - chartLegend(chartModelList[0], isFirst: true), - chartLegend(chartModelList[1]), - ], - ).paddingOnly(top: 8, bottom: 8).expanded, - getChart() - ], - ), - ) - ], - ).paddingOnly(top: 19, bottom: 11, right: 6, left: 14).objectContainerView(disablePadding: true, radius: 10), + const BalancesDashboardWidget("Current Leave Balance", true), 12.height, absenceTransList == null ? const SizedBox() @@ -182,79 +106,4 @@ class _LeaveBalanceState extends State { }), ); } - - Widget getChart() { - List _colorList = chartModelList.map((e) => e.color).toList(); - return PieChart( - dataMap: {for (var e in chartModelList) e.title: e.parsedValue}, - animationDuration: const Duration(milliseconds: 800), - chartRadius: MediaQuery.of(context).size.width / 3.2, - colorList: _colorList, - emptyColor: MyColors.lightGreyEAColor, - initialAngleInDegree: 270, - legendOptions: const LegendOptions( - showLegendsInRow: false, - showLegends: false, - ), - chartValuesOptions: const ChartValuesOptions( - showChartValueBackground: false, - showChartValues: true, - showChartValuesInPercentage: true, - showChartValuesOutside: false, - decimalPlaces: 0, - chartValueStyle: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 10, - letterSpacing: -0.64, - color: MyColors.white, - ), - ), - ); - } - - Widget chartLegend(PieChartModel chartModel, {bool isFirst = false}) { - return Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 12, - height: 12, - decoration: BoxDecoration(color: chartModel.color, shape: BoxShape.circle), - ).paddingOnly(top: 2), - 9.width, - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - RichText( - text: TextSpan( - text: chartModel.title, - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: isFirst ? MyColors.textMixColor : MyColors.backgroundBlackColor), - children: [ - TextSpan( - text: " " + chartModel.titleAppend, - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isFirst ? MyColors.textMixColor : MyColors.backgroundBlackColor), - ), - ], - ), - ), - chartModel.value.toString().toText14(), - ], - ).expanded, - ], - ); - } -} - -class PieChartModel { - String title; - String titleAppend; - double value; - Color color; - - PieChartModel(this.title, this.value, this.color, {this.titleAppend = ""}); - - Map get chartMapValue => {title: value}; - - double get parsedValue => value > 0 ? value : value + 0.1; } diff --git a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart index 8dd78f7..af22703 100644 --- a/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart +++ b/lib/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart @@ -7,6 +7,7 @@ import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/models/get_eit_transaction_list_model.dart'; import 'package:mohem_flutter_app/widgets/app_bar_widget.dart'; +import 'package:mohem_flutter_app/widgets/balances_dashboard_widget.dart'; import 'package:mohem_flutter_app/widgets/item_detail_view_widget.dart'; class DynamicListViewParams { @@ -69,27 +70,35 @@ class _DynamicListViewScreenState extends State { return Scaffold( backgroundColor: Colors.white, appBar: AppBarWidget(context, title: dynamicParams!.title), - body: getEITTransactionList == null - ? const SizedBox() - : (getEITTransactionList!.isEmpty - ? Utils.getNoDataWidget(context) - : ListView.separated( - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.all(21), - itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty - ? const SizedBox() - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - for (int t = 0; t < (getEITTransactionList![parentIndex].collectionTransaction ?? []).length; t++) - if (getEITTransactionList![parentIndex].collectionTransaction![t].dISPLAYFLAG == "Y") - ItemDetailView( - getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTPROMPT!, getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTVALUEDSP ?? ""), - ], - ).objectContainerView(), - separatorBuilder: (cxt, index) => 12.height, - itemCount: getEITTransactionList!.length)), + body: ListView( + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.all(21), + children: [ + // HMG_TKT_NEW_EIT_SS Id used for ticket balance dashboard + if (dynamicParams!.dynamicId == "HMG_TKT_NEW_EIT_SS") ...[const BalancesDashboardWidget("Current Ticket Balance", false), 12.height], + getEITTransactionList == null + ? const SizedBox() + : (getEITTransactionList!.isEmpty + ? Utils.getNoDataWidget(context) + : ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (cxt, int parentIndex) => getEITTransactionList![parentIndex].collectionTransaction!.isEmpty + ? const SizedBox() + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + for (int t = 0; t < (getEITTransactionList![parentIndex].collectionTransaction ?? []).length; t++) + if (getEITTransactionList![parentIndex].collectionTransaction![t].dISPLAYFLAG == "Y") + ItemDetailView(getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTPROMPT!, + getEITTransactionList![parentIndex].collectionTransaction![t].sEGMENTVALUEDSP ?? ""), + ], + ).objectContainerView(), + separatorBuilder: (cxt, index) => 12.height, + itemCount: getEITTransactionList!.length)), + ], + ), floatingActionButton: Container( height: 54, width: 54, diff --git a/lib/widgets/balances_dashboard_widget.dart b/lib/widgets/balances_dashboard_widget.dart new file mode 100644 index 0000000..2fd4b52 --- /dev/null +++ b/lib/widgets/balances_dashboard_widget.dart @@ -0,0 +1,209 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/api/dashboard_api_client.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/classes/colors.dart'; +import 'package:mohem_flutter_app/classes/date_uitl.dart'; +import 'package:mohem_flutter_app/classes/utils.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/models/dashboard/get_accrual_balances_list_model.dart'; +import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart'; +import 'package:pie_chart/pie_chart.dart'; +import 'package:provider/provider.dart'; + +class PieChartModel { + String title; + String titleAppend; + double value; + Color color; + + PieChartModel(this.title, this.value, this.color, {this.titleAppend = ""}); + + Map get chartMapValue => {title: value}; + + double get parsedValue => value > 0 ? value : value + 0.1; +} + +class BalancesDashboardWidget extends StatefulWidget { + final String title; + final List chartModelList; + final bool isLeaveBalance; + + const BalancesDashboardWidget(this.title, this.isLeaveBalance, {Key? key, this.chartModelList = const []}) : super(key: key); + + @override + _BalancesDashboardWidgetState createState() { + return _BalancesDashboardWidgetState(); + } +} + +class _BalancesDashboardWidgetState extends State { + List chartModelList = []; + late DateTime accrualDateTime; + GetAccrualBalancesList? leaveBalanceAccrual; + List? ticketBalanceAccrualList; + + @override + void initState() { + super.initState(); + accrualDateTime = DateTime.now(); + } + + @override + void dispose() { + super.dispose(); + } + + void changeAccrualDate() async { + try { + Utils.showLoading(context); + List accrualList = await DashboardApiClient().getAccrualBalances(DateFormat("MM/dd/yyyy").format(accrualDateTime)); + if (accrualList.isNotEmpty) { + if (widget.isLeaveBalance) { + leaveBalanceAccrual = accrualList[0]; + chartModelList = [ + PieChartModel("Current Balance", leaveBalanceAccrual?.accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""), + PieChartModel("Used", leaveBalanceAccrual?.accrualUsedEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""), + ]; + } else { + chartModelList = [ + PieChartModel("Adult", accrualList[1].accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""), + PieChartModel("Child", accrualList[2].accrualNetEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""), + PieChartModel("infants", accrualList[3].accrualNetEntitlement?.toDouble() ?? 0, MyColors.pinkColor, titleAppend: ""), + ]; + } + } + Utils.hideLoading(context); + setState(() {}); + } catch (ex) { + Utils.hideLoading(context); + Utils.handleException(ex, context, null); + } + } + + @override + Widget build(BuildContext context) { + if (leaveBalanceAccrual == null && widget.isLeaveBalance) { + leaveBalanceAccrual = Provider.of(context, listen: false).leaveBalanceAccrual; + chartModelList = [ + PieChartModel("Current Balance", leaveBalanceAccrual?.accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""), + PieChartModel("Used", leaveBalanceAccrual?.accrualUsedEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""), + ]; + } + + if (ticketBalanceAccrualList == null && !widget.isLeaveBalance) { + ticketBalanceAccrualList = Provider.of(context, listen: false).accrualList ?? []; + if (ticketBalanceAccrualList!.isNotEmpty) { + chartModelList = [ + PieChartModel("Adult", ticketBalanceAccrualList![1].accrualNetEntitlement ?? 0, MyColors.textMixColor, titleAppend: ""), + PieChartModel("Child", ticketBalanceAccrualList![2].accrualNetEntitlement?.toDouble() ?? 0, MyColors.backgroundBlackColor, titleAppend: ""), + PieChartModel("infants", ticketBalanceAccrualList![3].accrualNetEntitlement?.toDouble() ?? 0, MyColors.pinkColor, titleAppend: ""), + ]; + } + } + + return Column( + children: [ + Row( + children: [ + widget.title.toText20().expanded, + Row( + children: [ + const Icon(Icons.calendar_month_rounded, color: MyColors.darkIconColor, size: 16), + 5.width, + DateUtil.formatDateToDate(accrualDateTime, AppState().isArabic(context)).toText13(isUnderLine: true), + 8.width + ], + ).onPress(() async { + DateTime selectedDate = await Utils.selectDate(context, accrualDateTime); + if (selectedDate != accrualDateTime) { + accrualDateTime = selectedDate; + changeAccrualDate(); + } + }), + ], + ), + 8.height, + Row( + children: [ + ListView.separated( + shrinkWrap: true, + padding: const EdgeInsets.only(top: 8, bottom: 8), + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (cxt, index) { + return chartLegend(chartModelList[index], isFirst: index == 0); + }, + separatorBuilder: (cxt, index) => 18.height, + itemCount: chartModelList.length) + .expanded, + getChart(chartModelList) + ], + ) + ], + ).paddingOnly(top: 19, bottom: 11, right: 6, left: 14).objectContainerView(disablePadding: true, radius: 10); + } + + Widget chartLegend(PieChartModel chartModel, {bool isFirst = false}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 12, + height: 12, + decoration: BoxDecoration(color: chartModel.color, shape: BoxShape.circle), + ).paddingOnly(top: 2), + 9.width, + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + RichText( + text: TextSpan( + text: chartModel.title, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: isFirst ? MyColors.textMixColor : MyColors.backgroundBlackColor), + children: [ + TextSpan( + text: " " + chartModel.titleAppend, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: isFirst ? MyColors.textMixColor : MyColors.backgroundBlackColor), + ), + ], + ), + ), + chartModel.value.toString().toText14(), + ], + ).expanded, + ], + ); + } + + Widget getChart(List chartModelList) { + List _colorList = chartModelList.map((e) => e.color).toList(); + return PieChart( + dataMap: {for (var e in chartModelList) e.title: e.parsedValue}, + animationDuration: const Duration(milliseconds: 800), + chartRadius: MediaQuery.of(context).size.width / 3.2, + colorList: _colorList, + emptyColor: MyColors.lightGreyEAColor, + initialAngleInDegree: 270, + legendOptions: const LegendOptions( + showLegendsInRow: false, + showLegends: false, + ), + chartValuesOptions: const ChartValuesOptions( + showChartValueBackground: false, + showChartValues: true, + showChartValuesInPercentage: true, + showChartValuesOutside: false, + decimalPlaces: 0, + chartValueStyle: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 10, + letterSpacing: -0.64, + color: MyColors.white, + ), + ), + ); + } +}