From 2d553b56e07990e5a908f577b7c30579b6b310be Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 19 Oct 2023 15:21:06 +0300 Subject: [PATCH 1/7] service request detail ui changed. --- assets/images/comment_send.svg | 3 + flutter_gen.yaml | 2 + lib/extensions/text_extensions.dart | 10 - lib/l10n/app_ar.arb | 3 +- lib/l10n/app_en.arb | 5 +- lib/main.dart | 2 + lib/new_views/app_style/app_text_style.dart | 2 +- .../future_request_service_details.dart | 4 +- .../pages/user/requests/request_details.dart | 548 ------------------ .../requests/service_request_details.dart | 228 ++++++++ .../create_service_report.dart | 0 .../edit_service_report.dart | 0 .../future_service_report.dart | 0 .../work_order/work_orders_list_page.dart | 179 ++++++ .../requests/service_request_list.dart | 4 +- lib/views/widgets/sound/sound_player.dart | 150 +++-- 16 files changed, 496 insertions(+), 644 deletions(-) create mode 100644 assets/images/comment_send.svg create mode 100644 flutter_gen.yaml delete mode 100644 lib/views/pages/user/requests/request_details.dart create mode 100644 lib/views/pages/user/requests/service_request_details.dart rename lib/views/pages/user/requests/{report => work_order}/create_service_report.dart (100%) rename lib/views/pages/user/requests/{report => work_order}/edit_service_report.dart (100%) rename lib/views/pages/user/requests/{report => work_order}/future_service_report.dart (100%) create mode 100644 lib/views/pages/user/requests/work_order/work_orders_list_page.dart diff --git a/assets/images/comment_send.svg b/assets/images/comment_send.svg new file mode 100644 index 00000000..a332cc45 --- /dev/null +++ b/assets/images/comment_send.svg @@ -0,0 +1,3 @@ + + + diff --git a/flutter_gen.yaml b/flutter_gen.yaml new file mode 100644 index 00000000..17c1af22 --- /dev/null +++ b/flutter_gen.yaml @@ -0,0 +1,2 @@ +assets: + - assets/images/ diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index b6767296..7a08a656 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -46,7 +46,6 @@ abstract class AppTextStyles { static final TextStyle heading1 = TextStyle( fontSize: 54.toScreenWidth, fontWeight: FontWeight.w500, - height: 0.89, letterSpacing: -0.81, fontStyle: FontStyle.normal, decoration: TextDecoration.none, @@ -55,7 +54,6 @@ abstract class AppTextStyles { static final TextStyle heading2 = TextStyle( fontSize: 28.toScreenWidth, fontWeight: FontWeight.w700, - height: 1.5, letterSpacing: -0.56, fontStyle: FontStyle.normal, decoration: TextDecoration.none, @@ -64,7 +62,6 @@ abstract class AppTextStyles { static final TextStyle heading3 = TextStyle( fontSize: 24.toScreenWidth, fontWeight: FontWeight.w700, - height: 1.5, letterSpacing: -0.12, fontStyle: FontStyle.normal, decoration: TextDecoration.none, @@ -73,7 +70,6 @@ abstract class AppTextStyles { static final TextStyle heading4 = TextStyle( fontSize: 21.toScreenWidth, fontWeight: FontWeight.w500, - height: 1.48, fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); @@ -81,7 +77,6 @@ abstract class AppTextStyles { static final TextStyle heading5 = TextStyle( fontSize: 19.toScreenWidth, fontWeight: FontWeight.w500, - //height: 1.47, fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); @@ -89,7 +84,6 @@ abstract class AppTextStyles { static final TextStyle heading6 = TextStyle( fontSize: 16.toScreenWidth, fontWeight: FontWeight.w500, - height: 1.5, fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); @@ -97,7 +91,6 @@ abstract class AppTextStyles { static final TextStyle bodyText = TextStyle( fontSize: 14.toScreenWidth, fontWeight: FontWeight.w500, - height: 1.5, fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); @@ -105,7 +98,6 @@ abstract class AppTextStyles { static final TextStyle bodyText2 = TextStyle( fontSize: 12.toScreenWidth, fontWeight: FontWeight.w500, - height: 1.5, fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); @@ -113,7 +105,6 @@ abstract class AppTextStyles { static final TextStyle tinyFont = TextStyle( fontSize: 11.toScreenWidth, fontWeight: FontWeight.w500, - height: 1.45, fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); @@ -121,7 +112,6 @@ abstract class AppTextStyles { static final TextStyle overline = TextStyle( fontSize: 9.toScreenWidth, fontWeight: FontWeight.w500, - height: 1.56, letterSpacing: 0.05, fontStyle: FontStyle.normal, decoration: TextDecoration.none, diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index a07a6771..e3e12807 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -251,5 +251,6 @@ "model" : "الطراز", "serialNumber" : "الرقم التسلسلي", "device" : "الجهاز", - "pickAsset" : "إختر جهاز" + "pickAsset" : "إختر جهاز", + "firstAction" : "First Action" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 57522750..ec5fbcf8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -251,5 +251,8 @@ "model" : "Model", "serialNumber" : "Serial Number", "device" : "Device", - "pickAsset" : "Pick Asset" + "pickAsset" : "Pick Asset", + "firstAction" : "First Action", + "workOrder" : "Work Orders", + "viewWorkOrder" : "View All Work Order" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 110f3295..ddcac114 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -67,6 +67,7 @@ import 'package:test_sa/views/pages/user/report_issues_page.dart'; import 'package:test_sa/views/pages/user/requests/create_request.dart'; import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; import 'package:test_sa/views/pages/user/requests/requests_page.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart'; import 'package:test_sa/views/pages/user/visits/preventive_maintenance_visits_page.dart'; import 'package:test_sa/views/pages/user/visits/regular_visits_page.dart'; import 'package:test_sa/views/widgets/departments/single_department_picker.dart'; @@ -197,6 +198,7 @@ class MyApp extends StatelessWidget { TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), SearchSubWorkOrderPage.id: (_) => const SearchSubWorkOrderPage(), CreateSubWorkOrderPage.id: (_) => const CreateSubWorkOrderPage(), + WorkOrderListPage.id: (_) => WorkOrderListPage(), }, ), ), diff --git a/lib/new_views/app_style/app_text_style.dart b/lib/new_views/app_style/app_text_style.dart index 436ec40d..6ebea2eb 100644 --- a/lib/new_views/app_style/app_text_style.dart +++ b/lib/new_views/app_style/app_text_style.dart @@ -68,7 +68,7 @@ class AppTextStyle { decoration: TextDecoration.none, ); static final TextStyle tiny = TextStyle( - height: 1.5, + //height: 1.5, fontSize: 11.toScreenWidth, letterSpacing: 0, fontFamily: fontFamily, diff --git a/lib/views/pages/user/requests/future_request_service_details.dart b/lib/views/pages/user/requests/future_request_service_details.dart index fc98bda9..27096f9c 100644 --- a/lib/views/pages/user/requests/future_request_service_details.dart +++ b/lib/views/pages/user/requests/future_request_service_details.dart @@ -7,7 +7,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; -import 'package:test_sa/views/pages/user/requests/request_details.dart'; +import 'package:test_sa/views/pages/user/requests/service_request_details.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/failed_loading.dart'; @@ -40,7 +40,7 @@ class _FutureRequestServiceDetailsState extends State(context); - SettingProvider _settingProvider = Provider.of(context); - List workOrders = []; - ServiceRequestsProvider _serviceRequestsProvider = Provider.of(context); - _serviceRequestsProvider.getServiceRequestObjectById(requestId: serviceRequest.id); - - Widget informationCard() { - return Container( - decoration: ShapeDecoration( - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)], - ), - child: Column( - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - StatusLabel( - label: serviceRequest.priority.name, - id: serviceRequest.priority.id, - textColor: AColors.getPriorityStatusTextColor(serviceRequest.priority.id), - backgroundColor: AColors.getPriorityStatusColor(serviceRequest.priority.id)), - 8.width, - StatusLabel( - label: serviceRequest.statusLabel, - textColor: AColors.getRequestStatusTextColor(serviceRequest.statusValue), - backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)), - 1.width.expanded, - Text(serviceRequest.date.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), - ], - ), - 8.height, - Text(serviceRequest.deviceEnName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), - Text( - '${context.translation.assetNumber}: ${serviceRequest.device.assetNumber}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text( - 'Request Type: ${serviceRequest.type.name}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text( - 'Request No: ${serviceRequest.requestCode}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - 8.height, - const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), - 8.height, - Text( - 'Manufacture: ${serviceRequest.device.modelDefinition.manufacturerName}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - Text( - 'Model: ${serviceRequest.device.modelDefinition.modelName}', - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - 8.height, - const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), - 8.height, - if ((serviceRequest.callComments ?? "").isNotEmpty) ...[ - Text( - serviceRequest.callComments, - style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), - ), - 8.height, - const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), - ], - if (serviceRequest.devicePhotos.isNotEmpty) ...[ - FilesList(images: serviceRequest.devicePhotos), - const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), - ], - if (serviceRequest.audio?.isNotEmpty == true) ...[ - 16.height, - ASoundPlayer( - audio: serviceRequest.audio, - ), - 16.height, - const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), - ], - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'View Comments', - style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF4A8DB7)), - ), - 4.width, - const Icon( - Icons.arrow_forward, - color: Color(0xFF4A8DB7), - size: 14, - ) - ], - ), - ], - ).paddingAll(16), - ], - ), - ); - } - - return DefaultTabController( - length: 2, - child: Scaffold( - appBar: DefaultAppBar(title: context.translation.serviceRequest), - backgroundColor: const Color(0xfff8f9fb), - body: SafeArea( - child: FutureBuilder( - future: _serviceRequestsProvider.getServiceRequestObjectById(requestId: serviceRequest.id), - builder: (context, snap) { - if (snap.connectionState == ConnectionState.waiting) { - return const ALoading(); - } else if (snap.hasData) { - serviceRequest = snap.data; - return Column( - children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Row( - children: [ - ABackButton(), - Expanded( - child: Center( - child: Text( - context.translation.details, - style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), - ), - ), - ), - _userProvider.user.type == UsersTypes.normal_user - ? - // AIconButton( - // iconData: Icons.warning_amber_rounded, - // color: AColors.white, - // buttonSize: 42, - // backgroundColor: AColors.deepOrange, - // onPressed: (){ - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) - // ) - // ); - // }, - // ) - const SizedBox( - width: 48, - ) - : AIconButton( - iconData: Icons.edit, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: (serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3) - ? null - : () async { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => CreateRequestPage(serviceRequest: serviceRequest)), - ); - // showModalBottomSheet( - // context: context, - // builder: (context) { - // return ServiceRequestsUpdateDialog( - // request: serviceRequest, - // ); - // }); - // DateTime picked = await showDatePicker( - // context: context, - // initialDate: DateTime.now(), - // firstDate: DateTime.now(), - // lastDate: DateTime.now().add(Duration(days: 182)) - // ); - // if(picked == null){return;} - // showDialog( - // context: context, - // barrierDismissible: false, - // builder: (BuildContext context) { - // return CupertinoAlertDialog( - // title: Text(context.translation.updatingDots), - // content: Center(child: CircularProgressIndicator()), - // ); - // }, - // ); - // int status = await _serviceRequestsProvider.updateDate( - // user: _userProvider.user, - // host: _settingProvider.host, - // request: serviceRequest, - // newDate: picked.toString().split(" ").first - // ); - // Navigator.of(context).pop(); - // Fluttertoast.showToast( - // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation), - // ); - }, - ), - SizedBox( - width: 16, - ) - ], - ), - ), - serviceRequest.devicePhotos.isEmpty - ? const SizedBox.shrink() - : SizedBox( - height: 60 * AppStyle.getScaleFactor(context), - child: FilesList( - images: serviceRequest.devicePhotos, - ), - ).paddingOnly(top: 4, bottom: 4), - TabBar(labelColor: AColors.primaryColor, tabs: [ - Tab( - text: context.translation.general, - ), - Tab( - text: context.translation.serviceRequestInformation, - ), - ]), - SizedBox( - height: 8, - ), - Expanded( - child: TabBarView( - children: [ - Column( - children: [ - ListView( - padding: const EdgeInsets.all(16), - children: [ - informationCard(), - RequestInfoRow( - title: context.translation.callId, - info: serviceRequest.requestCode, - ), - RequestInfoRow( - title: "Asset Number", - info: serviceRequest.deviceNumber, - ), - RequestInfoRow( - title: context.translation.assetName, - info: serviceRequest.deviceEnName, - ), - RequestInfoRow( - title: context.translation.deviceModel, - info: serviceRequest.deviceModel, - ), - RequestInfoRow( - title: context.translation.engineerName, - info: serviceRequest.engineerName, - ), - RequestInfoRow( - title: context.translation.engineerPhone, - info: serviceRequest.engineerMobile, - ), - RequestInfoRow( - title: context.translation.date, - info: serviceRequest.date, - ), - serviceRequest.nextVisitDate == null - ? SizedBox.shrink() - : RequestInfoRow( - title: context.translation.next, - info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), - ), - Row( - children: [ - Expanded( - child: Text( - "${context.translation.status} : ", - style: Theme.of(context).textTheme.subtitle1, - textScaleFactor: AppStyle.getScaleFactor(context), - ), - ), - StatusLabel(label: serviceRequest.statusLabel, backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)), - ], - ), - Divider( - color: Theme.of(context).primaryColor, - ), - RequestInfoRow( - title: context.translation.hospital, - info: serviceRequest.hospitalName, - ), - RequestInfoRow( - title: context.translation.unite, - info: serviceRequest.departmentName, - ), - // RequestInfoRow( - // title: context.translation.deviceArName, - // content: serviceRequest.deviceArName, - // ), - // RequestInfoRow( - // title: context.translation.deviceName, - // content: serviceRequest.deviceEnName, - // ), - RequestInfoRow( - title: context.translation.maintenanceIssue, - content: serviceRequest.callComments, - ), - if (serviceRequest.audio?.isNotEmpty == true) - ASoundPlayer( - audio: serviceRequest.audio, - ), - // - // Center( - // child: Padding( - // padding: EdgeInsets.all(32), - // child: AButton( - // text: context.translation.duplicateRequest, - // onPressed: () async { - // bool result = await showDialog( - // context: context, - // builder: (_) => AAlertDialog( - // title: context.translation.duplicateAlert, - // content: context.translation.duplicateAlertMessage, - // ) - // ); - // if(result == true){ - // showDialog( - // context: context, - // builder: (context){ - // return Center(child: CircularProgressIndicator()); - // } - // ); - // int status = await _serviceRequestsProvider.createDuplicatedReport( - // host: _settingProvider.host, - // user: _userProvider.user, - // request: serviceRequest - // ); - // Navigator.of(context).pop(); - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text( - // HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation) - // ) - // ) - // ); - // } - // }, - // ), - // ), - // ) - ], - ).expanded, - AppFilledButton(label: context.translation.login, maxWidth: true, onPressed: () {}).paddingOnly(start: 16, end: 16, bottom: 24), - ], - ), - // workOrders.isEmpty ? - FutureBuilder( - future: _serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode), - builder: (context, snap) { - workOrders = snap.data as List; - if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); - if (snap.connectionState == ConnectionState.done && (snap.data?.length ?? 0) != 0) { - return SingleChildScrollView( - child: Column( - children: [ - ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.all(21), - itemCount: workOrders.length, - separatorBuilder: (czt, index) => 21.height, - itemBuilder: (context, index) { - Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; - Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; - - return ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), - primary: itemColor.withOpacity(.7), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - ), - ), - //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - onPressed: () { - // onPressed(request); - }, - child: Column( - children: [ - RequestInfoRow( - title: context.translation.callId, - content: serviceRequest.requestCode, - ), - RequestInfoRow( - title: context.translation.orderWorkNumber, - info: workOrders[index].workOrderNo.toString(), - ), - RequestInfoRow( - title: context.translation.visitDate, - info: workOrders[index].visitDate, - ), - RequestInfoRow(title: context.translation.assignedEmployee, info: workOrders[index].assignedEmployee?.name ?? ""), - RequestInfoRow( - title: context.translation.assetSN, - info: workOrders[index].callRequest.asset.assetSerialNo, - ), - RequestInfoRow( - title: context.translation.assetName, - info: workOrders[index].callRequest.asset.modelDefinition.assetName, - ), - RequestInfoRow( - title: context.translation.assetNumber, - info: workOrders[index].callRequest.asset.assetNumber, - ), - RequestInfoRow( - title: context.translation.model, - info: workOrders[index].callRequest.asset.modelDefinition.modelName, - ), - RequestInfoRow( - title: context.translation.site, - info: workOrders[index].callRequest.asset.site.custName, - ), - RequestInfoRow( - title: "Call last Situation", - info: workOrders[index].currentSituation.name ?? '', - ), - _userProvider.user.type == UsersTypes.engineer && workOrders[index].workOrderNo != null - ? Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: context.translation.editServiceReport, - onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 - ? null - : () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FutureServiceReport( - request: serviceRequest, - workOrder: workOrders[index], - )), - ); - }, - ), - ) - : SizedBox.shrink(), - ], - ), - ); - }, - ), - if (_userProvider.user.type == UsersTypes.engineer) - Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: AButton( - text: "Create Work Order", - onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 - ? null - : () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }, - ), - ), - ), - ], - ), - ); - } else { - return Column( - children: [ - Expanded( - child: Center( - child: ASubTitle(context.translation.dataNotFound), - ), - ), - if (_userProvider.user.type == UsersTypes.engineer) - Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: AButton( - text: "Create Work Order", - onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 - ? null - : () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }, - ), - ), - ), - ], - ); - } - }, - ), - ], - ), - ), - ], - ); - } - return const SizedBox(); - }), - ), - ), - ); - } -} diff --git a/lib/views/pages/user/requests/service_request_details.dart b/lib/views/pages/user/requests/service_request_details.dart new file mode 100644 index 00000000..86f83c4f --- /dev/null +++ b/lib/views/pages/user/requests/service_request_details.dart @@ -0,0 +1,228 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/localization/localization.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/enums/translation_keys.dart'; +import 'package:test_sa/models/enums/user_types.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; +import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/requests/create_request.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/future_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart'; +import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; +import 'package:test_sa/views/widgets/buttons/app_button.dart'; +import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; +import 'package:test_sa/views/widgets/images/files_list.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; +import 'package:test_sa/views/widgets/requests/info_row.dart'; +import 'package:test_sa/views/widgets/requests/request_status.dart'; +import 'package:test_sa/views/widgets/sound/sound_player.dart'; +import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import '../../../../models/service_request/search_work_order.dart'; + +class ServiceRequestDetailsPage extends StatelessWidget { + static const String id = "/call-details"; + ServiceRequest serviceRequest; + + ServiceRequestDetailsPage({Key key, this.serviceRequest}) : super(key: key); + + @override + Widget build(BuildContext context) { + UserProvider _userProvider = Provider.of(context); + ServiceRequestsProvider _serviceRequestsProvider = Provider.of(context); + // _serviceRequestsProvider.getServiceRequestObjectById(requestId: serviceRequest.id); + + Widget informationCard() { + return Container( + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + StatusLabel( + label: serviceRequest.priority.name, + id: serviceRequest.priority.id, + textColor: AColors.getPriorityStatusTextColor(serviceRequest.priority.id), + backgroundColor: AColors.getPriorityStatusColor(serviceRequest.priority.id)), + 8.width, + StatusLabel( + label: serviceRequest.statusLabel, + textColor: AColors.getRequestStatusTextColor(serviceRequest.statusValue), + backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)), + 1.width.expanded, + Text(serviceRequest.date.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), + ], + ), + 8.height, + Text(serviceRequest.deviceEnName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), + Text( + '${context.translation.assetNumber}: ${serviceRequest.device.assetNumber}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + Text( + 'Request Type: ${serviceRequest.type.name}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + Text( + 'Request No: ${serviceRequest.requestCode}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + 8.height, + const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), + 8.height, + Text( + 'Manufacture: ${serviceRequest.device.modelDefinition.manufacturerName}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + Text( + 'Model: ${serviceRequest.device.modelDefinition.modelName}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + 8.height, + if ((serviceRequest.callComments ?? "").isNotEmpty) ...[ + const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), + 8.height, + Text( + serviceRequest.callComments, + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + ], + if (serviceRequest.devicePhotos.isNotEmpty) ...[ + 8.height, + const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), + FilesList(images: serviceRequest.devicePhotos), + ], + if (serviceRequest.audio?.isNotEmpty ?? false) ...[ + const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), + 16.height, + ASoundPlayer(audio: serviceRequest.audio), + ], + ], + ).paddingAll(16), + (_userProvider.user.type == UsersTypes.normal_user + ? Container( + height: 50, + padding: const EdgeInsets.only(left: 16, right: 16), + alignment: Alignment.center, + width: double.infinity, + decoration: const ShapeDecoration( + color: Color(0xFFEAF1F4), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20), + bottomRight: Radius.circular(20), + ), + ), + ), + child: Row( + children: [ + Text( + 'Comment here...', + style: AppTextStyles.heading6.copyWith( + color: AppColor.neutral50.withOpacity(.6), + ), + ).expanded, + SvgPicture.asset("assets/images/comment_send.svg", width: 24 * AppStyle.getScaleFactor(context), height: 24 * AppStyle.getScaleFactor(context), color: AppColor.primary70), + ], + ), + ) + : Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'View Comments', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF4A8DB7)), + ), + 4.width, + const Icon( + Icons.arrow_forward, + color: Color(0xFF4A8DB7), + size: 14, + ) + ], + ), + ], + ).paddingOnly(bottom: 16, start: 16, end: 16)) + .onPress(() { + // todo 'sikander' add comment bottom sheet + }), + ], + ), + ); + } + + return Scaffold( + appBar: DefaultAppBar(title: context.translation.serviceRequest), + backgroundColor: const Color(0xfff8f9fb), + body: SafeArea( + child: FutureBuilder( + future: _serviceRequestsProvider.getServiceRequestObjectById(requestId: serviceRequest.id), + builder: (context, snap) { + if (snap.connectionState == ConnectionState.waiting) { + return const ALoading(); + } else if (snap.hasData) { + serviceRequest = snap.data; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: informationCard(), + ).expanded, + if (_userProvider.user.type != UsersTypes.engineer || (serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3)) + (serviceRequest.firstAction == null + ? AppFilledButton( + label: context.translation.firstAction, + maxWidth: true, + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => CreateRequestPage(serviceRequest: serviceRequest)), + ); + }) + : AppFilledButton( + label: context.translation.viewWorkOrder, + maxWidth: true, + onPressed: () { + Navigator.of(context).pushNamed(WorkOrderListPage.id, arguments: serviceRequest); + })) + .paddingOnly(start: 16, end: 16, bottom: 24), + ], + ); + } + return const SizedBox(); + }))); + } +} diff --git a/lib/views/pages/user/requests/report/create_service_report.dart b/lib/views/pages/user/requests/work_order/create_service_report.dart similarity index 100% rename from lib/views/pages/user/requests/report/create_service_report.dart rename to lib/views/pages/user/requests/work_order/create_service_report.dart diff --git a/lib/views/pages/user/requests/report/edit_service_report.dart b/lib/views/pages/user/requests/work_order/edit_service_report.dart similarity index 100% rename from lib/views/pages/user/requests/report/edit_service_report.dart rename to lib/views/pages/user/requests/work_order/edit_service_report.dart diff --git a/lib/views/pages/user/requests/report/future_service_report.dart b/lib/views/pages/user/requests/work_order/future_service_report.dart similarity index 100% rename from lib/views/pages/user/requests/report/future_service_report.dart rename to lib/views/pages/user/requests/work_order/future_service_report.dart diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart new file mode 100644 index 00000000..a2dce886 --- /dev/null +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/models/enums/user_types.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/future_service_report.dart'; +import 'package:test_sa/views/widgets/buttons/app_button.dart'; +import 'package:test_sa/views/widgets/requests/info_row.dart'; +import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + +class WorkOrderListPage extends StatelessWidget { + static const String id = "/work-order-list"; + ServiceRequest serviceRequest; + + WorkOrderListPage({Key key, this.serviceRequest}) : super(key: key); + + @override + Widget build(BuildContext context) { + // UserProvider _userProvider = Provider.of(context); + // SettingProvider _settingProvider = Provider.of(context); + List workOrders = []; + ServiceRequestsProvider serviceRequestsProvider; + UserProvider _userProvider = Provider.of(context); + if (serviceRequestsProvider == null) { + serviceRequestsProvider = Provider.of(context); + serviceRequest = ModalRoute.of(context).settings.arguments; + } + + return Scaffold( + appBar: DefaultAppBar(title: context.translation.workOrder), + backgroundColor: const Color(0xfff8f9fb), + body: SafeArea( + child: FutureBuilder( + future: serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode), + builder: (context, snap) { + workOrders = snap.data as List; + if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); + if (snap.connectionState == ConnectionState.done && (snap.data?.length ?? 0) != 0) { + return SingleChildScrollView( + child: Column( + children: [ + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.all(21), + itemCount: workOrders.length, + separatorBuilder: (czt, index) => 21.height, + itemBuilder: (context, index) { + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + + return ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + primary: itemColor.withOpacity(.7), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), + //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), + onPressed: () { + // onPressed(request); + }, + child: Column( + children: [ + RequestInfoRow( + title: context.translation.callId, + content: serviceRequest.requestCode, + ), + RequestInfoRow( + title: context.translation.orderWorkNumber, + info: workOrders[index].workOrderNo.toString(), + ), + RequestInfoRow( + title: context.translation.visitDate, + info: workOrders[index].visitDate, + ), + RequestInfoRow(title: context.translation.assignedEmployee, info: workOrders[index].assignedEmployee?.name ?? ""), + RequestInfoRow( + title: context.translation.assetSN, + info: workOrders[index].callRequest.asset.assetSerialNo, + ), + RequestInfoRow( + title: context.translation.assetName, + info: workOrders[index].callRequest.asset.modelDefinition.assetName, + ), + RequestInfoRow( + title: context.translation.assetNumber, + info: workOrders[index].callRequest.asset.assetNumber, + ), + RequestInfoRow( + title: context.translation.model, + info: workOrders[index].callRequest.asset.modelDefinition.modelName, + ), + RequestInfoRow( + title: context.translation.site, + info: workOrders[index].callRequest.asset.site.custName, + ), + RequestInfoRow( + title: "Call last Situation", + info: workOrders[index].currentSituation.name ?? '', + ), + _userProvider.user.type == UsersTypes.engineer && workOrders[index].workOrderNo != null + ? Padding( + padding: EdgeInsets.all(32), + child: AButton( + text: context.translation.editServiceReport, + onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 + ? null + : () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => FutureServiceReport( + request: serviceRequest, + workOrder: workOrders[index], + )), + ); + }, + ), + ) + : SizedBox.shrink(), + ], + ), + ); + }, + ), + if (_userProvider.user.type == UsersTypes.engineer) + Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: AButton( + text: "Create Work Order", + onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 + ? null + : () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ), + ), + ), + ], + ), + ); + } else { + return Column( + children: [ + Expanded( + child: Center( + child: ASubTitle(context.translation.dataNotFound), + ), + ), + if (_userProvider.user.type == UsersTypes.engineer) + Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: AButton( + text: "Create Work Order", + onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 + ? null + : () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ), + ), + ), + ], + ); + } + }, + ))); + } +} diff --git a/lib/views/widgets/requests/service_request_list.dart b/lib/views/widgets/requests/service_request_list.dart index b8b24d47..53307445 100644 --- a/lib/views/widgets/requests/service_request_list.dart +++ b/lib/views/widgets/requests/service_request_list.dart @@ -4,7 +4,7 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; -import 'package:test_sa/views/pages/user/requests/request_details.dart'; +import 'package:test_sa/views/pages/user/requests/service_request_details.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import 'package:test_sa/views/widgets/requests/service_request_item.dart'; @@ -37,7 +37,7 @@ class ServiceRequestsList extends StatelessWidget { request: requests[itemIndex], onPressed: (request) { Navigator.of(context).push(MaterialPageRoute( - builder: (_) => RequestDetailsPage( + builder: (_) => ServiceRequestDetailsPage( serviceRequest: request, ))); }, diff --git a/lib/views/widgets/sound/sound_player.dart b/lib/views/widgets/sound/sound_player.dart index 74cf2571..0598ceed 100644 --- a/lib/views/widgets/sound/sound_player.dart +++ b/lib/views/widgets/sound/sound_player.dart @@ -1,5 +1,8 @@ import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/app_style/app_text_style.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import '../../app_style/colors.dart'; @@ -23,64 +26,73 @@ class _ASoundPlayerState extends State { bool _failedToLoad = false; AudioPlayer _audioPlayer; + Widget audioPlayerButton(IconData icon, VoidCallback onpress) { + return Container( + width: 48, + height: 48, + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder( + side: const BorderSide(width: 1, color: Color(0xFFEAF1F4)), + borderRadius: BorderRadius.circular(32), + ), + ), + child: Icon( + icon, + color: const Color(0xff163A51).withOpacity(0.5), + ), + ).onPress(onpress); + } + Widget _getAudioButton() { switch (_audioPlayer.state) { case PlayerState.playing: - return IconButton( - icon: const Icon(Icons.pause_rounded), - onPressed: () async { - _failedToLoad = false; - await _audioPlayer.pause(); - rebuild(); - }); + return audioPlayerButton(Icons.pause_rounded, () async { + _failedToLoad = false; + await _audioPlayer.pause(); + rebuild(); + }); case PlayerState.paused: - return IconButton( - icon: const Icon(Icons.play_arrow_rounded), - onPressed: () async { - _failedToLoad = false; - await _audioPlayer.resume(); - rebuild(); - }); + return audioPlayerButton(Icons.play_arrow_rounded, () async { + _failedToLoad = false; + await _audioPlayer.resume(); + rebuild(); + }); case PlayerState.completed: - return IconButton( - icon: const Icon(Icons.replay_rounded), - onPressed: () async { - _failedToLoad = false; - await _audioPlayer.stop(); - await _audioPlayer.resume(); - rebuild(); - }); + return audioPlayerButton(Icons.replay_rounded, () async { + _failedToLoad = false; + await _audioPlayer.stop(); + await _audioPlayer.resume(); + rebuild(); + }); case PlayerState.stopped: - return IconButton( - icon: Icon(_isLocalFile ? Icons.play_circle_fill_outlined : Icons.download_rounded), - onPressed: () async { - _failedToLoad = false; - try { - await _audioPlayer.play( - _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), - ); - rebuild(); - } on Exception catch (e) { - _failedToLoad = true; - } - }); + return audioPlayerButton(_isLocalFile ? Icons.play_circle_fill_outlined : Icons.download_rounded, () async { + _failedToLoad = false; + try { + await _audioPlayer.play( + _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), + ); + rebuild(); + } on Exception catch (e) { + _failedToLoad = true; + } + }); + default: - return IconButton( - icon: const Icon(Icons.replay_rounded), - onPressed: () async { - _failedToLoad = false; + return audioPlayerButton(Icons.replay_rounded, () async { + _failedToLoad = false; - try { - _audioPlayer.seek(const Duration(milliseconds: 0)); - _audioPlayer.stop(); - await _audioPlayer.play( - _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), - ); - rebuild(); - } on Exception catch (e) { - _failedToLoad = true; - } - }); + try { + _audioPlayer.seek(const Duration(milliseconds: 0)); + _audioPlayer.stop(); + await _audioPlayer.play( + _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), + ); + rebuild(); + } on Exception catch (e) { + _failedToLoad = true; + } + }); } } @@ -163,12 +175,15 @@ class _ASoundPlayerState extends State { children: [ Row( children: [ - Material(color: Colors.transparent, child: _getAudioButton()), - Expanded( + _getAudioButton(), + SliderTheme( + data: SliderTheme.of(context).copyWith(trackHeight: 2.0, thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 6.0), overlayShape: SliderComponentShape.noOverlay), child: Slider( value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, min: 0, max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, + activeColor: AppColor.primary70, + inactiveColor: AppColor.neutral30, onChangeStart: (value) { _sliderMoving = true; }, @@ -181,35 +196,12 @@ class _ASoundPlayerState extends State { _audioPlayer.seek(Duration(milliseconds: value.round())); rebuild(); }), - ), + ).paddingOnly(start: 8, end: 8).expanded, + _failedToLoad + ? Text("Failed to load", style: AppTextStyle.tiny.copyWith(color: AppColor.red60)) + : Text("${format(_audioPosition)}/${format(_audioTime)}", style: AppTextStyle.tiny.copyWith(color: AppColor.neutral50)), ], ), - Row( - children: [ - Expanded( - child: Visibility( - visible: _failedToLoad, - child: Row( - children: [ - Text( - "Failed to load", - style: Theme.of(context).textTheme.overline.copyWith(color: AColors.red), - textScaleFactor: AppStyle.getScaleFactor(context), - ), - ], - ), - ), - ), - Visibility( - visible: _audioPlayer.state != PlayerState.stopped, - child: Text( - "${format(_audioPosition)}/${format(_audioTime)}", - style: Theme.of(context).textTheme.overline, - textScaleFactor: AppStyle.getScaleFactor(context), - ), - ), - ], - ) ], ); } From 0170c6f5cbf1a5de39652d1f48bc2df2d01ecd19 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 19 Oct 2023 15:33:39 +0300 Subject: [PATCH 2/7] service request status color improvement. --- lib/views/app_style/colors.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/views/app_style/colors.dart b/lib/views/app_style/colors.dart index 92483a42..6afd9b6b 100644 --- a/lib/views/app_style/colors.dart +++ b/lib/views/app_style/colors.dart @@ -53,12 +53,14 @@ class AColors { return AColors.statusBlue; case 2: return AColors.statusYellowLight; + case 3: + return AColors.statusGreenLight; case 4: return AColors.statusRedLight; case 6: return AColors.statusGreenLight; case 5: - return AColors.orange; + return AColors.statusGreenLight; case 8: return AColors.statusGreenLight; case 9: @@ -72,12 +74,14 @@ class AColors { switch (id) { case 2: return AColors.statusYellow; + case 3: + return AColors.white; case 4: return AColors.deepRed; case 6: return AColors.green; case 5: - return AColors.orange; + return AColors.white; case 8: return AColors.green; case 9: From 0e30fef10cbd05f639971026e91bb78059174355 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 19 Oct 2023 16:19:25 +0300 Subject: [PATCH 3/7] work order list ui changed. --- assets/images/edit.svg | 8 + lib/l10n/app_en.arb | 4 +- .../requests/service_request_details.dart | 2 +- .../work_order/work_orders_list_page.dart | 242 +++++++++--------- 4 files changed, 131 insertions(+), 125 deletions(-) create mode 100644 assets/images/edit.svg diff --git a/assets/images/edit.svg b/assets/images/edit.svg new file mode 100644 index 00000000..fdf28a6d --- /dev/null +++ b/assets/images/edit.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ec5fbcf8..17a30b34 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -254,5 +254,7 @@ "pickAsset" : "Pick Asset", "firstAction" : "First Action", "workOrder" : "Work Orders", - "viewWorkOrder" : "View All Work Order" + "createWorkOrder" : "Create Work Order", + "viewWorkOrder" : "View All Work Order", + "serviceDetails": "Service Details" } \ No newline at end of file diff --git a/lib/views/pages/user/requests/service_request_details.dart b/lib/views/pages/user/requests/service_request_details.dart index 86f83c4f..71e896fd 100644 --- a/lib/views/pages/user/requests/service_request_details.dart +++ b/lib/views/pages/user/requests/service_request_details.dart @@ -185,7 +185,7 @@ class ServiceRequestDetailsPage extends StatelessWidget { } return Scaffold( - appBar: DefaultAppBar(title: context.translation.serviceRequest), + appBar: DefaultAppBar(title: context.translation.serviceDetails), backgroundColor: const Color(0xfff8f9fb), body: SafeArea( child: FutureBuilder( diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index a2dce886..a7b4ef7a 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -4,15 +4,21 @@ import 'package:test_sa/controllers/providers/api/service_requests_provider.dart import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/models/service_request/service_request.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart'; import 'package:test_sa/views/pages/user/requests/work_order/future_service_report.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; +import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; class WorkOrderListPage extends StatelessWidget { @@ -32,7 +38,7 @@ class WorkOrderListPage extends StatelessWidget { serviceRequestsProvider = Provider.of(context); serviceRequest = ModalRoute.of(context).settings.arguments; } - + print("serviceRequest.statusValue:${serviceRequest.statusValue}"); return Scaffold( appBar: DefaultAppBar(title: context.translation.workOrder), backgroundColor: const Color(0xfff8f9fb), @@ -42,137 +48,127 @@ class WorkOrderListPage extends StatelessWidget { builder: (context, snap) { workOrders = snap.data as List; if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); - if (snap.connectionState == ConnectionState.done && (snap.data?.length ?? 0) != 0) { - return SingleChildScrollView( - child: Column( - children: [ - ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.all(21), - itemCount: workOrders.length, - separatorBuilder: (czt, index) => 21.height, - itemBuilder: (context, index) { - Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; - Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; - return ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), - primary: itemColor.withOpacity(.7), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - ), - ), - //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - onPressed: () { - // onPressed(request); - }, - child: Column( + return Column( + children: [ + ListView.separated( + padding: const EdgeInsets.all(16), + itemCount: workOrders?.length ?? 0, + separatorBuilder: (czt, index) => 8.height, + itemBuilder: (context, index) { + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + + return Container( + decoration: ShapeDecoration( + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)], + ), + child: Column( + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - RequestInfoRow( - title: context.translation.callId, - content: serviceRequest.requestCode, - ), - RequestInfoRow( - title: context.translation.orderWorkNumber, - info: workOrders[index].workOrderNo.toString(), - ), - RequestInfoRow( - title: context.translation.visitDate, - info: workOrders[index].visitDate, - ), - RequestInfoRow(title: context.translation.assignedEmployee, info: workOrders[index].assignedEmployee?.name ?? ""), - RequestInfoRow( - title: context.translation.assetSN, - info: workOrders[index].callRequest.asset.assetSerialNo, + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + StatusLabel(label: workOrders[index].currentSituation.name, textColor: AppColor.orange60, backgroundColor: AppColor.orange40), + 8.height, + Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))), + ], + ).expanded, + if (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) + "edit".toSvgAsset(height: 48, width: 48).onPress(() { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => FutureServiceReport( + request: serviceRequest, + workOrder: workOrders[index], + )), + ); + }) + ], ), - RequestInfoRow( - title: context.translation.assetName, - info: workOrders[index].callRequest.asset.modelDefinition.assetName, - ), - RequestInfoRow( - title: context.translation.assetNumber, - info: workOrders[index].callRequest.asset.assetNumber, + 8.height, + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + Text( + '${context.translation.status}: ${workOrders[index].currentSituation.name}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), + ), + ], + ).expanded, + Text(workOrders[index].visitDate.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))), + ], ), - RequestInfoRow( - title: context.translation.model, - info: workOrders[index].callRequest.asset.modelDefinition.modelName, + Text( + '${context.translation.orderWorkNumber}: ${workOrders[index].workOrderNo}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), ), - RequestInfoRow( - title: context.translation.site, - info: workOrders[index].callRequest.asset.site.custName, + Text( + '${context.translation.assignedEmployee}: ${workOrders[index].assignedEmployee?.name ?? ""}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)), ), - RequestInfoRow( - title: "Call last Situation", - info: workOrders[index].currentSituation.name ?? '', + Text('${context.translation.assetSN}: ${workOrders[index].callRequest.asset.assetSerialNo ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), + Text('${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName ?? ""}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), + Text('${context.translation.assetNumber}: ${workOrders[index].callRequest.asset.assetNumber ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), + Text('${context.translation.model}: ${workOrders[index].callRequest.asset.modelDefinition.modelName ?? ""}', + style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), + Text('${context.translation.site}: ${workOrders[index].callRequest.asset.site.custName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), + Text('${"Call last Situation"}: ${workOrders[index].calllastSituation.name ?? '' ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'View Details', + style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF4A8DB7)), + ), + 4.width, + const Icon( + Icons.arrow_forward, + color: Color(0xFF4A8DB7), + size: 14, + ) + ], ), - _userProvider.user.type == UsersTypes.engineer && workOrders[index].workOrderNo != null - ? Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: context.translation.editServiceReport, - onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 - ? null - : () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FutureServiceReport( - request: serviceRequest, - workOrder: workOrders[index], - )), - ); - }, - ), - ) - : SizedBox.shrink(), ], - ), - ); - }, - ), - if (_userProvider.user.type == UsersTypes.engineer) - Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: AButton( - text: "Create Work Order", - onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 - ? null - : () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }, - ), - ), - ), - ], - ), - ); - } else { - return Column( - children: [ - Expanded( - child: Center( - child: ASubTitle(context.translation.dataNotFound), - ), - ), - if (_userProvider.user.type == UsersTypes.engineer) - Center( - child: Padding( - padding: const EdgeInsets.all(32), - child: AButton( - text: "Create Work Order", - onPressed: serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3 - ? null - : () { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); - }, - ), + ).paddingAll(16).onPress(() { + // onPressed(request); + }), + ], ), - ), - ], - ); - } + ); + }, + ).expanded, + if (_userProvider.user.type != UsersTypes.engineer && (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)) + AppFilledButton( + label: context.translation.createWorkOrder, + maxWidth: true, + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }).paddingOnly(start: 16, end: 16, bottom: 16) + ], + ); }, ))); } From e419b17bd10e5324824055a11a1318998f4dfa0c Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Thu, 19 Oct 2023 16:24:05 +0300 Subject: [PATCH 4/7] Service request design done --- assets/images/mic.svg | 4 + assets/images/warning.svg | 3 + assets/lottie/record.json | 1 + .../service_report_priority_provider.dart | 1 + lib/extensions/text_extensions.dart | 8 + lib/l10n/app_ar.arb | 10 +- lib/l10n/app_en.arb | 8 +- lib/main.dart | 9 +- .../service_request/service_request.dart | 17 + .../common_widgets/app_dashed_button.dart | 33 ++ .../equipment_status_provider.dart | 36 ++ .../priority_provider.dart | 36 ++ .../pages/user/requests/create_request.dart | 366 ++++++------------ lib/views/widgets/equipment/pick_asset.dart | 41 +- lib/views/widgets/sound/record_sound.dart | 140 +++---- pubspec.lock | 16 + pubspec.yaml | 3 + 17 files changed, 376 insertions(+), 356 deletions(-) create mode 100644 assets/images/mic.svg create mode 100644 assets/images/warning.svg create mode 100644 assets/lottie/record.json create mode 100644 lib/new_views/common_widgets/app_dashed_button.dart create mode 100644 lib/providers/service_request_providers/equipment_status_provider.dart create mode 100644 lib/providers/service_request_providers/priority_provider.dart diff --git a/assets/images/mic.svg b/assets/images/mic.svg new file mode 100644 index 00000000..33c6ee78 --- /dev/null +++ b/assets/images/mic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/warning.svg b/assets/images/warning.svg new file mode 100644 index 00000000..98708612 --- /dev/null +++ b/assets/images/warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/lottie/record.json b/assets/lottie/record.json new file mode 100644 index 00000000..5dbe123c --- /dev/null +++ b/assets/lottie/record.json @@ -0,0 +1 @@ +{"v":"5.7.8","fr":29.9700012207031,"ip":0,"op":41.0000016699642,"w":160,"h":64,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"REC Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[105.58,32.746,0],"ix":2,"l":2},"a":{"a":0,"k":[-19.17,-6.3,0],"ix":1,"l":2},"s":{"a":0,"k":[251,251,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[-0.378,0.583],[0,0.873],[0.82,0.674],[1.512,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0.768,-0.346],[0.378,-0.583],[0,-1.23],[-0.82,-0.674],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-26.01,0],[-23.18,0],[-23.18,-0.123],[-25.949,-5.353],[-24.231,-6.746],[-23.664,-8.93],[-24.894,-11.786],[-28.392,-12.797],[-33.147,-12.797],[-33.147,0],[-30.51,0],[-30.51,-4.685],[-28.41,-4.685]],"c":true},"ix":2},"nm":"R","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.343,-0.346],[0,-0.603],[0.363,-0.337],[0.662,0],[0,0]],"o":[[0,0],[0.709,0],[0.343,0.346],[0,0.592],[-0.363,0.337],[0,0],[0,0]],"v":[[-30.51,-10.661],[-28.392,-10.661],[-26.815,-10.143],[-26.3,-8.719],[-26.845,-7.326],[-28.383,-6.82],[-30.51,-6.82]],"c":true},"ix":2},"nm":"R","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.294117647059,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"R","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-13.511,-7.611],[-18.573,-7.611],[-18.573,-10.661],[-12.649,-10.661],[-12.649,-12.797],[-21.21,-12.797],[-21.21,0],[-12.632,0],[-12.632,-2.118],[-18.573,-2.118],[-18.573,-5.546],[-13.511,-5.546]],"c":true},"ix":2},"nm":"E","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.294117647059,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"E","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.401,-0.372],[0.814,0],[0.419,0.639],[0,1.383],[0,0],[-0.437,0.63],[-0.879,0],[-0.396,-0.372],[-0.065,-0.826],[0,0],[0.902,0.791],[1.477,0],[0.806,-0.501],[0.434,-0.937],[0,-1.23],[0,0],[-0.94,-1.104],[-1.641,0],[-0.917,0.791],[-0.1,1.377]],"o":[[-0.059,0.779],[-0.401,0.372],[-0.902,0],[-0.419,-0.639],[0,0],[0.012,-1.324],[0.436,-0.63],[0.809,0],[0.396,0.372],[0,0],[-0.141,-1.43],[-0.902,-0.791],[-1.066,0],[-0.806,0.501],[-0.434,0.938],[0,0],[0,1.928],[0.94,1.105],[1.5,0],[0.917,-0.791],[0,0]],"v":[[-3.226,-4.263],[-3.916,-2.536],[-5.739,-1.978],[-7.721,-2.936],[-8.35,-5.968],[-8.35,-6.935],[-7.677,-9.866],[-5.704,-10.811],[-3.898,-10.252],[-3.208,-8.455],[-0.571,-8.455],[-2.136,-11.786],[-5.704,-12.973],[-8.512,-12.221],[-10.371,-10.063],[-11.021,-6.812],[-11.021,-6.029],[-9.611,-1.481],[-5.739,0.176],[-2.114,-1.011],[-0.589,-4.263]],"c":true},"ix":2},"nm":"C","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.294117647059,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"C","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":41.0000016699642,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[31,32,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[127,127,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[147,147,100]},{"t":20.0000008146167,"s":[127,127,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[26.25,26.25],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.294117647059,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.375,0.375],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":41.0000016699642,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":40.0000016292334,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[31,32,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[127,127,100]},{"t":40.0000016292334,"s":[250,250,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[26.25,26.25],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.294117647059,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.375,0.375],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":41.0000016699642,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart index c9160a1f..0bcbf913 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart @@ -8,6 +8,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; +@Deprecated("Use the one inside lib/providers folder") class ServiceRequestPriorityProvider extends ChangeNotifier { //reset provider data void reset() { diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index 7a08a656..b89f6625 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:lottie/lottie.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -144,4 +145,11 @@ extension FilesExtension on String { BoxFit fit = BoxFit.contain, }) => Image.asset("assets/images/$this.png", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit); + LottieBuilder toLottieAsset({ + int width, + int height, + BoxFit fit = BoxFit.contain, + bool repeat = true, + }) => + Lottie.asset("assets/lottie/$this.json", width: width?.toScreenWidth, height: height?.toScreenHeight, fit: fit, repeat: repeat); } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index e3e12807..1b6e7504 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -1,6 +1,6 @@ { "serverErrorMessage": "الخدمة غير متاحة حاليا", - "failedRequestMessage": "الفشل في إكمال الطلب", + "failedRequestMessage": "فشل إكمال الطلب", "successfulRequestMessage": "تم إكمال الطلب بنجاح", "requestLockMessage": "انتظر حتى إكمال الطلب", "cancel": "إلغاء", @@ -252,5 +252,11 @@ "serialNumber" : "الرقم التسلسلي", "device" : "الجهاز", "pickAsset" : "إختر جهاز", - "firstAction" : "First Action" + "firstAction" : "First Action", + "priority" : "الأولوية", + "equipmentStatus" : "حالة المعدات", + "attachImage" : "إرفاق صورة", + "callComments" : "", + "comments" : "تعليقات", + "recordVoice" : "تسجيل صوت" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ec5fbcf8..040c3b8c 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -254,5 +254,11 @@ "pickAsset" : "Pick Asset", "firstAction" : "First Action", "workOrder" : "Work Orders", - "viewWorkOrder" : "View All Work Order" + "viewWorkOrder" : "View All Work Order", + "priority" : "Priority", + "equipmentStatus" : "Equipment Status", + "attachImage" : "Attach Image", + "callComments" : "Call Comments", + "comments": "Comments", + "recordVoice" : "Record Voice" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index ddcac114..49c29e7a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,10 +3,9 @@ import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:localization/localization.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; import 'package:test_sa/controllers/providers/api/departments_provider.dart'; import 'package:test_sa/controllers/providers/api/devices_provider.dart'; @@ -55,6 +54,8 @@ import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.d import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart'; +import 'package:test_sa/providers/service_request_providers/priority_provider.dart'; import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; @@ -78,8 +79,6 @@ import 'controllers/providers/api/user_provider.dart'; import 'controllers/providers/settings/setting_provider.dart'; import 'new_views/pages/new_gas_refill_request_page.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; - void main() async { WidgetsFlutterBinding.ensureInitialized(); if (Platform.isIOS) { @@ -159,6 +158,8 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => ServiceReportMaintenanceSituationProvider()), ChangeNotifierProvider(create: (_) => ServiceReportUsersProvider()), ChangeNotifierProvider(create: (_) => ServiceReportAssistantsEmployeeProvider()), + ChangeNotifierProvider(create: (_) => PriorityProvider()), + ChangeNotifierProvider(create: (_) => EquipmentStatusProvider()), ], child: GestureDetector( onTap: () { diff --git a/lib/models/service_request/service_request.dart b/lib/models/service_request/service_request.dart index 5769d0c1..350185fb 100644 --- a/lib/models/service_request/service_request.dart +++ b/lib/models/service_request/service_request.dart @@ -1,4 +1,7 @@ +import 'package:flutter/src/widgets/framework.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/fault_description.dart'; import 'package:test_sa/models/lookup.dart'; @@ -138,4 +141,18 @@ class ServiceRequest { priority: Lookup.fromJson(parsedJson['priority']), ); } + + Future validateNewRequest(BuildContext context) async { + if (device == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.device}"); + return false; + } else if (priority == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.priority}"); + return false; + } else if (defectType == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.equipmentStatus}"); + return false; + } + return true; + } } diff --git a/lib/new_views/common_widgets/app_dashed_button.dart b/lib/new_views/common_widgets/app_dashed_button.dart new file mode 100644 index 00000000..f6108cd6 --- /dev/null +++ b/lib/new_views/common_widgets/app_dashed_button.dart @@ -0,0 +1,33 @@ +import 'package:dotted_border/dotted_border.dart'; +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; + +import '../app_style/app_color.dart'; + +class AppDashedButton extends StatelessWidget { + final String title; + final VoidCallback onPressed; + + const AppDashedButton({@required this.title, @required this.onPressed, Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 2.toScreenWidth), + decoration: BoxDecoration(color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(10)), + child: DottedBorder( + strokeWidth: 2, + padding: EdgeInsets.symmetric(vertical: 16.toScreenHeight, horizontal: 16.toScreenWidth), + color: context.isDark ? AppColor.primary40 : AppColor.primary60, + dashPattern: const [4, 3], + radius: const Radius.circular(10), + borderType: BorderType.RRect, + child: title.heading6(context).custom(color: context.isDark ? AppColor.primary40 : AppColor.primary60).center, + ), + ).onPress(onPressed); + } +} diff --git a/lib/providers/service_request_providers/equipment_status_provider.dart b/lib/providers/service_request_providers/equipment_status_provider.dart new file mode 100644 index 00000000..71a5760f --- /dev/null +++ b/lib/providers/service_request_providers/equipment_status_provider.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class EquipmentStatusProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.equipmentStatus); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/providers/service_request_providers/priority_provider.dart b/lib/providers/service_request_providers/priority_provider.dart new file mode 100644 index 00000000..a1c4f10f --- /dev/null +++ b/lib/providers/service_request_providers/priority_provider.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; +import '../../models/lookup.dart'; + +class PriorityProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading == true) return -2; + loading = true; + notifyListeners(); + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getServiceReportPriority); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/views/pages/user/requests/create_request.dart b/lib/views/pages/user/requests/create_request.dart index 348f42bb..1429a4fa 100644 --- a/lib/views/pages/user/requests/create_request.dart +++ b/lib/views/pages/user/requests/create_request.dart @@ -1,43 +1,34 @@ import 'dart:convert'; import 'dart:io'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:image_picker/image_picker.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -import 'package:test_sa/controllers/validator/validator.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/service_request/service_request.dart'; -import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; -import 'package:test_sa/views/widgets/app_text_form_field.dart'; -import 'package:test_sa/views/widgets/date_and_time/time_picker.dart'; import 'package:test_sa/views/widgets/equipment/pick_asset.dart'; -import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/sound/record_sound.dart'; -import 'package:test_sa/views/widgets/sound/sound_player.dart'; -import 'package:test_sa/views/widgets/speech_to_text/speech_to_text.dart'; -import 'package:test_sa/views/widgets/status/service_request/service_request_defect_types_mune.dart'; -import 'package:test_sa/views/widgets/status/service_request/service_request_priority_mune.dart'; -import 'package:test_sa/views/widgets/status/service_request/service_request_through_mune.dart'; -import 'package:test_sa/views/widgets/status/service_request/service_request_types_mune.dart'; -import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; -import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart'; -import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart'; -import '../../../../models/device/device.dart'; -import '../../../../models/enums/translation_keys.dart'; +import '../../../../models/lookup.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_dashed_button.dart'; +import '../../../../new_views/common_widgets/app_lazy_loading.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../new_views/common_widgets/default_app_bar.dart'; -import '../../../widgets/status/service_request/service_request_first_action.dart'; -import '../../../widgets/status/service_request/service_request_loan_availability.dart'; +import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../../providers/service_request_providers/equipment_status_provider.dart'; +import '../../../../providers/service_request_providers/priority_provider.dart'; class CreateRequestPage extends StatefulWidget { static const String id = "/create-request"; @@ -50,6 +41,8 @@ class CreateRequestPage extends StatefulWidget { } class CreateRequestPageState extends State { + TextEditingController _commentController; + double _height; UserProvider _userProvider; SettingProvider _settingProvider; @@ -58,21 +51,17 @@ class CreateRequestPageState extends State { final List _deviceImages = []; bool _isLoading = false; bool _showDatePicker = false; - Device _asset; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); - TextEditingController _maintenanceController, _commentController, _reviewCommentController; DateTime _dateTime; bool isFirstActionSubmitted = false; @override void initState() { - _maintenanceController = TextEditingController(); _commentController = TextEditingController(); if (widget.serviceRequest != null) { _serviceRequest = widget.serviceRequest; - _asset = _serviceRequest.device; _deviceImages.addAll(_serviceRequest.devicePhotos.map((e) => File(e)).toList()); _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; if (_showDatePicker && _serviceRequest.visitDate != null) { @@ -107,7 +96,6 @@ class CreateRequestPageState extends State { @override void dispose() { - _maintenanceController.dispose(); _commentController.dispose(); super.dispose(); } @@ -127,7 +115,7 @@ class CreateRequestPageState extends State { return Scaffold( key: _scaffoldKey, - appBar: DefaultAppBar(title: context.translation.newServiceRequest), + appBar: DefaultAppBar(title: context.translation.newServiceRequest), body: SafeArea( child: LoadingManager( isLoading: _isLoading, @@ -143,235 +131,58 @@ class CreateRequestPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ PickAsset( - device: _asset, + device: _serviceRequest.device, onPickAsset: (asset) { - _asset = asset; + _serviceRequest.device = asset; setState(() {}); }, ), - const SizedBox( - height: 8, - ), - const ASubTitle("Priority"), - const SizedBox( - height: 4, - ), - ServiceRequestPriorityMenu( - initialValue: widget.serviceRequest?.priority, - onSelect: (status) { - _serviceRequest.priority = status; + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.priority, + initialValue: _serviceRequest?.priority, + onSelect: (value) { + _serviceRequest.priority = value; }, - enabled: widget.serviceRequest == null ? true : false, - ), - const SizedBox( - height: 8, ), - const ASubTitle("Equipment Status"), - const SizedBox( - height: 4, - ), - ServiceRequestDefectTypesMenu( - initialValue: _serviceRequest.defectType, - onSelect: (status) { - _serviceRequest.defectType = status; + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.equipmentStatus, + initialValue: _serviceRequest?.defectType, + onSelect: (value) { + _serviceRequest.defectType = value; }, - enabled: widget.serviceRequest == null ? true : false, ), - 12.height, - const SizedBox( - height: 8, + 8.height, + AppDashedButton(title: _serviceRequest.devicePhotos?.first?.split("/")?.last ?? context.translation.attachImage, onPressed: _attachImage), + 16.height, + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.callComments.heading5(context), ), - const ASubTitle("Type of Request"), - const SizedBox( - height: 4, + 8.height, + AppTextFormField( + controller: _commentController, + labelText: context.translation.comments, + suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16), ), - ServiceRequestTypesMenu( - initialValue: _serviceRequest.type, - onSelect: (status) { - _serviceRequest.type = status; + 8.height, + RecordSound( + onRecord: (audio) { + _serviceRequest.audio = audio; }, - enabled: false, - withDefaultItem: widget.serviceRequest == null, - ), - const SizedBox( - height: 8, - ), - const ASubTitle("Through"), - const SizedBox( - height: 4, - ), - ServiceRequestedThroughMenu( - initialValue: _serviceRequest.requestedThrough, - enabled: false, - ), - if (widget.serviceRequest != null) 12.height, - if (widget.serviceRequest != null) const ASubTitle("First Action"), - const SizedBox( - height: 4, - ), - if (widget.serviceRequest != null) - ServiceRequestedFirstAction( - initialValue: _serviceRequest.firstAction, - enabled: !isFirstActionSubmitted, - onSelect: (status) { - _dateTime = null; - _serviceRequest.firstAction = status; - _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; - _serviceRequestsProvider.notifyListeners(); - }, - ), - if (_showDatePicker) 12.height, - if (_showDatePicker) - ADateTimePicker( - date: _dateTime, - enable: !isFirstActionSubmitted, - from: DateTime.now(), - onDateTimePicker: (date) { - _dateTime = date; - setState(() {}); - }, - ), - if (widget.serviceRequest != null) 12.height, - if (widget.serviceRequest != null) const ASubTitle("Loan Availability"), - const SizedBox( - height: 4, - ), - if (widget.serviceRequest != null) - ServiceRequestedLoanAvailability( - initialValue: _serviceRequest.loanAvailability, - onSelect: (status) { - _serviceRequest.loanAvailability = status; - }, - ), - 12.height, - if (widget.serviceRequest != null) const ASubTitle("Comments"), - const SizedBox( - height: 4, - ), - if (widget.serviceRequest != null) - ATextFormField( - controller: _reviewCommentController, - initialValue: _serviceRequest.reviewComment, - hintText: context.translation.comment, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceRequest.reviewComment = value; - }, - enable: widget.serviceRequest != null ? false : true, - ), - 12.height, - MultiFilesPicker( - label: context.translation.deviceFiles, - files: _deviceImages, - enabled: widget.serviceRequest == null ? true : false, - ), - 12.height, - SpeechToTextButton( - controller: _maintenanceController, enabled: widget.serviceRequest == null ? true : false, ), - 12.height, - ATextFormField( - controller: _maintenanceController, - initialValue: _serviceRequest.callComments, - hintText: context.translation.maintenanceIssue, - prefixIconData: FontAwesomeIcons.triangleExclamation, - style: Theme.of(context).textTheme.titleLarge, - textInputType: TextInputType.multiline, - validator: (value) => widget.serviceRequest != null || Validator.hasValue(value) ? null : context.translation.maintenanceIssueRequired, - onSaved: (value) { - _serviceRequest.callComments = value; - }, - enable: widget.serviceRequest == null ? true : false, - ), - 12.height, - if (_serviceRequest.audio?.isNotEmpty == true) - ASoundPlayer( - audio: _serviceRequest.audio, - ) - else - RecordSound( - onRecord: (audio) { - _serviceRequest.audio = audio; - }, - enabled: widget.serviceRequest == null ? true : false, - ), - 12.height, - if (widget.serviceRequest != null) - ATextFormField( - controller: _commentController, - initialValue: _serviceRequest.comments, - hintText: context.translation.comment, - style: Theme.of(context).textTheme.titleMedium, - textInputType: TextInputType.multiline, - onSaved: (value) { - _serviceRequest.comments = value; - }, - ), + 16.height, ], ), ).expanded, AppFilledButton( - onPressed: () async { - if (!_formKey.currentState.validate()) return; - if (_asset?.id == null) { - Fluttertoast.showToast(msg: context.translation.pickDevice); - return; - } - if (_serviceRequest.firstAction?.name == "Need a visit" && _dateTime == null) { - Fluttertoast.showToast(msg: "first action is required"); - return; - } - if (widget.serviceRequest != null && (_serviceRequest?.engineerId == null || (_serviceRequest?.engineerId?.isEmpty ?? false))) { - await Fluttertoast.showToast(msg: "No Assigned Employee"); - return; - } - _formKey.currentState.save(); - _serviceRequest.deviceId = _asset?.id; - if (widget.serviceRequest == null) { - _serviceRequest.type = Provider.of(context, listen: false).getDefaultItem(); - } - _serviceRequest.requestedThrough = Provider.of(context, listen: false).getDefaultItem(); - _isLoading = true; - setState(() {}); - _serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList(); - if (_serviceRequest.audio != null) { - if (_isLocalUrl(_serviceRequest.audio)) { - final File file = File(_serviceRequest.audio); - _serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; - } - } - int status = 0; - if (widget.serviceRequest == null) { - status = await _serviceRequestsProvider.createRequest( - user: _userProvider.user, - host: _settingProvider.host, - serviceRequest: _serviceRequest, - ); - } else { - status = await _serviceRequestsProvider.updateDate( - user: _userProvider.user, - host: _settingProvider.host, - request: _serviceRequest, - date: _dateTime, - ); - } - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: context.translation.successfulRequestMessage, - ); - Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } - }, - label: context.translation.submitRequest), + onPressed: _submit, + label: context.translation.submitRequest, + ), ], ), ).paddingOnly(start: 16, end: 16, bottom: 24, top: 16), @@ -379,4 +190,81 @@ class CreateRequestPageState extends State { ), ); } + + _attachImage() async { + ImageSource source = await showDialog( + context: context, + builder: (dialogContext) => CupertinoAlertDialog( + actions: [ + TextButton( + child: Text(context.translation.pickFromCamera), + onPressed: () { + Navigator.of(dialogContext).pop(ImageSource.camera); + }, + ), + TextButton( + child: Text(context.translation.pickFromGallery), + onPressed: () { + Navigator.of(dialogContext).pop(ImageSource.gallery); + }, + ), + TextButton( + child: Text(context.translation.pickFromFiles), + onPressed: () async { + await _fromFilePicker(); + Navigator.pop(context); + }, + ), + ], + ), + ); + if (source == null) return; + + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); + if (pickedFile != null) { + _serviceRequest.devicePhotos ??= []; + _serviceRequest.devicePhotos?.clear(); + _serviceRequest.devicePhotos?.add(pickedFile.path); + setState(() {}); + } + } + + _fromFilePicker() async { + FilePickerResult result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], + ); + if (result?.files?.first != null) { + _serviceRequest.devicePhotos ??= []; + _serviceRequest.devicePhotos?.clear(); + _serviceRequest.devicePhotos?.add(result?.files?.first?.path); + setState(() {}); + } + } + + Future _submit() async { + if (_formKey.currentState.validate() && await _serviceRequest.validateNewRequest(context)) { + _formKey.currentState.save(); + _serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList(); + if (_serviceRequest.audio != null) { + if (_isLocalUrl(_serviceRequest.audio)) { + final File file = File(_serviceRequest.audio); + _serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; + } + } + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + int status = await _serviceRequestsProvider.createRequest( + user: _userProvider.user, + host: _settingProvider.host, + serviceRequest: _serviceRequest, + ); + Navigator.of(context); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); + Navigator.pop(context); + } else { + Fluttertoast.showToast(msg: context.translation.failedRequestMessage); + } + } + } } diff --git a/lib/views/widgets/equipment/pick_asset.dart b/lib/views/widgets/equipment/pick_asset.dart index 6221631a..06faaf8a 100644 --- a/lib/views/widgets/equipment/pick_asset.dart +++ b/lib/views/widgets/equipment/pick_asset.dart @@ -3,11 +3,10 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/enums/translation_keys.dart'; -import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/equipment/single_device_picker.dart'; import '../../../models/device/device.dart'; +import '../../../new_views/app_style/app_color.dart'; class PickAsset extends StatelessWidget { final Function(Device) onPickAsset; @@ -19,22 +18,36 @@ class PickAsset extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - AppTextFormField( - enable: false, - labelText: context.translation.device, - initialValue: context.translation.site, - suffixIcon: "qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight).paddingOnly(end: 16), - ).onPress(() async { - Device device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Device; - onPickAsset(device); - }), - if (device != null) 8.height, + Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], + ), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), + context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50), + ], + ).onPress(() async { + Device device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Device; + onPickAsset(device); + }).expanded, + "qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight).onPress(() { + /// TODO [Zaid] : open qr reader + }), + ], + ).paddingOnly(start: 16, end: 16, top: 8, bottom: 8), + ), if (device != null) Card( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - context.translation.myAssets.heading5(context), + device.modelDefinition?.assetName?.heading5(context), 8.height, "${context.translation.assetNo}: ${device.assetNumber}".bodyText(context), "${context.translation.manufacture}: ${device.modelDefinition?.manufacturerName}".bodyText(context), @@ -45,7 +58,7 @@ class PickAsset extends StatelessWidget { "${context.translation.site}: ${device.site?.custName}".bodyText(context), ], ).paddingAll(16), - ), + ).paddingOnly(top: 8), ], ); } diff --git a/lib/views/widgets/sound/record_sound.dart b/lib/views/widgets/sound/record_sound.dart index 3b6b75b6..3b116069 100644 --- a/lib/views/widgets/sound/record_sound.dart +++ b/lib/views/widgets/sound/record_sound.dart @@ -1,17 +1,20 @@ +import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_sound/flutter_sound.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:rive/rive.dart'; -import 'package:test_sa/views/widgets/buttons/app_icon_button2.dart'; -import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; -import 'package:test_sa/views/widgets/sound/sound_player.dart'; import 'package:record_mp3/record_mp3.dart'; -import '../../app_style/sizing.dart'; +import 'package:rive/rive.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; + +import '../../../new_views/app_style/app_color.dart'; +import '../../../new_views/common_widgets/app_text_form_field.dart'; class RecordSound extends StatefulWidget { final Function(String) onRecord; @@ -30,6 +33,8 @@ class _RecordSoundState extends State { bool _recording = false; String _record; Artboard _rive; + Timer _timer; + TextEditingController _timeController; @override void setState(VoidCallback fn) { @@ -39,7 +44,7 @@ class _RecordSoundState extends State { @override void initState() { super.initState(); - + _timeController = TextEditingController(); _recorderIsOpened = true; // RecordMp3.instance.start(recordFilePath, (type) { // // record fail callback @@ -70,6 +75,7 @@ class _RecordSoundState extends State { @override void dispose() { + _timeController?.dispose(); // Be careful : you must `close` the audio session when you have finished with it. RecordMp3.instance.stop(); //_myRecorder.closeRecorder(); @@ -80,7 +86,6 @@ class _RecordSoundState extends State { String recordingFileDirectory; _startRecording() async { - // await Permission.camera PermissionStatus status = await Permission.microphone.request(); if (!status.isGranted) { PermissionStatus status = await Permission.microphone.request(); @@ -89,6 +94,11 @@ class _RecordSoundState extends State { return; } } + _timer = Timer.periodic(const Duration(seconds: 1), (timer) { + setState(() { + _timeController.text = ((timer?.tick ?? 0) / 60)?.toStringAsFixed(2); + }); + }); _rive.addController(SimpleAnimation('recording')); if (!_recorderIsOpened) { // await _myRecorder.openRecorder(); @@ -111,7 +121,9 @@ class _RecordSoundState extends State { setState(() {}); return; } - + if (_timer?.isActive ?? false) { + _timer.cancel(); + } RecordMp3.instance.stop(); //String path = (await _myRecorder.stopRecorder()).toString(); @@ -137,94 +149,30 @@ class _RecordSoundState extends State { @override Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.only(left: 12, right: 0), - decoration: BoxDecoration( - color: const Color(0xfff5f5f5), - border: Border.all( - color: const Color(0xffefefef), + return Stack( + alignment: AlignmentDirectional.centerEnd, + children: [ + AppTextFormField( + enable: false, + controller: _timeController, + labelText: context.translation.recordVoice, + initialValue: (_timeController?.text?.isEmpty ?? true) ? "00:00" : _timeController?.text, + suffixIcon: (_recording ? "record".toLottieAsset(height: 24) : (_record != null ? "trash" : "mic").toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, height: 24)) + .paddingOnly(end: 16), ), - borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), - ), - child: Column( - children: [ - Row( - children: [ - Expanded( - child: _recording - ? Row( - children: [ - ASmallButton( - text: "done", - onPressed: () { - _stopRecording(); - }, - ), - Expanded( - child: Stack( - children: [ - SizedBox( - height: 24 * AppStyle.getScaleFactor(context), - child: Rive( - artboard: _rive, - )), - InkWell( - child: SizedBox( - height: 32 * AppStyle.getScaleFactor(context), - width: MediaQuery.of(context).size.width, - ), - onTap: () { - _cancelRecording(); - }, - ), - ], - ), - ), - ], - ) - : _record != null - ? Row( - children: [ - Expanded(child: ASoundPlayer(audio: _record)), - AIconButton2( - iconData: Icons.delete, - onPressed: () { - widget.onRecord(null); - _record = null; - setState(() {}); - }, - ) - ], - ) - : const Text("Record Voice"), - ), - Material( - color: Colors.transparent, - child: GestureDetector( - //key: ValueKey("voice"), - onTapDown: widget.enabled - ? (TapDownDetails details) async { - _startRecording(); - } - : null, - onTapUp: widget.enabled - ? (TapUpDetails details) async { - _stopRecording(); - } - : null, - onTapCancel: widget.enabled - ? () async { - _cancelRecording(); - } - : null, - //key: ValueKey("voice"), - child: const Padding(padding: EdgeInsets.all(12.0), child: Icon(Icons.mic)), - ), - ), - ], - ), - ], - ), + SizedBox(height: 50.toScreenHeight, width: 50.toScreenWidth).onPress(() { + if (_recording) { + _stopRecording(); + } else if (_record != null) { + _timeController?.text = "00:00"; + widget.onRecord(null); + _record = null; + setState(() {}); + } else { + _startRecording(); + } + }) + ], ); } } diff --git a/pubspec.lock b/pubspec.lock index b3a50550..538a911f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -209,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.8" + dotted_border: + dependency: "direct main" + description: + name: dotted_border + sha256: "108837e11848ca776c53b30bc870086f84b62ed6e01c503ed976e8f8c7df9c04" + url: "https://pub.dev" + source: hosted + version: "2.1.0" fake_async: dependency: transitive description: @@ -661,6 +669,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: "23522951540d20a57a60202ed7022e6376bed206a4eee1c347a91f58bd57eb9f" + url: "https://pub.dev" + source: hosted + version: "2.3.2" matcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7a84b17e..a52f678d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,6 +68,8 @@ dependencies: path_provider: ^2.1.0 open_file: ^3.3.2 localization: ^2.1.0 + dotted_border: ^2.1.0 + lottie: ^2.3.0 dev_dependencies: flutter_test: @@ -97,6 +99,7 @@ flutter: assets: - assets/ - assets/images/ + - assets/lottie/ - assets/subtitles/ - assets/rives/ - assets/translations/ From b4ea88e7db08759ab7099f7b2e4adae76b3a0e12 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Thu, 19 Oct 2023 16:29:43 +0300 Subject: [PATCH 5/7] _ --- lib/l10n/app_ar.arb | 12 ++++++------ lib/l10n/app_en.arb | 18 ++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 1b6e7504..aed0f553 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -253,10 +253,10 @@ "device" : "الجهاز", "pickAsset" : "إختر جهاز", "firstAction" : "First Action", - "priority" : "الأولوية", - "equipmentStatus" : "حالة المعدات", - "attachImage" : "إرفاق صورة", - "callComments" : "", - "comments" : "تعليقات", - "recordVoice" : "تسجيل صوت" + "priority" : "الأولوية", + "equipmentStatus" : "حالة المعدات", + "attachImage" : "إرفاق صورة", + "callComments" : "تعليقات الطلب", + "comments" : "تعليقات", + "recordVoice" : "تسجيل صوت" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f27fdf29..29433d6f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -256,14 +256,12 @@ "workOrder" : "Work Orders", "viewWorkOrder" : "View All Work Order", "createWorkOrder" : "Create Work Order", - "viewWorkOrder" : "View All Work Order", - "serviceDetails": "Service Details", - "priority" : "Priority", - "equipmentStatus" : "Equipment Status", - "attachImage" : "Attach Image", - "callComments" : "Call Comments", - "comments": "Comments", - "recordVoice" : "Record Voice" - - + "viewWorkOrder" : "View All Work Order", + "serviceDetails": "Service Details", + "priority" : "Priority", + "equipmentStatus" : "Equipment Status", + "attachImage" : "Attach Image", + "callComments" : "Call Comments", + "comments": "Comments", + "recordVoice" : "Record Voice" } \ No newline at end of file From 7d2afa23cc79a809e2aebf687b281c09ebd92d20 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Sun, 22 Oct 2023 09:43:45 +0300 Subject: [PATCH 6/7] add record player to the recorder --- lib/controllers/api_routes/urls.dart | 2 +- lib/views/widgets/sound/record_sound.dart | 60 ++++++++++++++--------- lib/views/widgets/sound/sound_player.dart | 9 ++-- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 870435ce..1001fb0e 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -102,7 +102,7 @@ class URLs { // employee static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get - static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get + static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get /// TODO : we also need to send the asset id // pentry static get getPentry => "$_baseUrl/return/pentry/details"; // get diff --git a/lib/views/widgets/sound/record_sound.dart b/lib/views/widgets/sound/record_sound.dart index 3b116069..d01edc03 100644 --- a/lib/views/widgets/sound/record_sound.dart +++ b/lib/views/widgets/sound/record_sound.dart @@ -12,15 +12,17 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/views/widgets/sound/sound_player.dart'; import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/common_widgets/app_text_form_field.dart'; class RecordSound extends StatefulWidget { final Function(String) onRecord; + final Function(String) onStop; final bool enabled; - const RecordSound({Key key, @required this.onRecord, this.enabled = true}) : super(key: key); + const RecordSound({Key key, @required this.onRecord, this.onStop, this.enabled = true}) : super(key: key); @override State createState() => _RecordSoundState(); @@ -31,6 +33,7 @@ class _RecordSoundState extends State { bool _recorderIsOpened = false; bool _recording = false; + bool _played = false; String _record; Artboard _rive; Timer _timer; @@ -96,7 +99,11 @@ class _RecordSoundState extends State { } _timer = Timer.periodic(const Duration(seconds: 1), (timer) { setState(() { - _timeController.text = ((timer?.tick ?? 0) / 60)?.toStringAsFixed(2); + String recordTime = ((timer?.tick ?? 0) / 60)?.toStringAsFixed(2)?.replaceFirst(".", ":"); + if (recordTime.length == 4 || recordTime.length == 7) { + recordTime = "0$recordTime"; + } + _timeController.text = recordTime; }); }); _rive.addController(SimpleAnimation('recording')); @@ -149,29 +156,36 @@ class _RecordSoundState extends State { @override Widget build(BuildContext context) { - return Stack( - alignment: AlignmentDirectional.centerEnd, + return Column( children: [ - AppTextFormField( - enable: false, - controller: _timeController, - labelText: context.translation.recordVoice, - initialValue: (_timeController?.text?.isEmpty ?? true) ? "00:00" : _timeController?.text, - suffixIcon: (_recording ? "record".toLottieAsset(height: 24) : (_record != null ? "trash" : "mic").toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, height: 24)) - .paddingOnly(end: 16), + Stack( + alignment: AlignmentDirectional.centerEnd, + children: [ + AppTextFormField( + enable: false, + controller: _timeController, + labelText: context.translation.recordVoice, + initialValue: (_timeController?.text?.isEmpty ?? true) ? "00:00" : _timeController?.text, + suffixIcon: + (_recording ? "record".toLottieAsset(height: 24) : (_record != null ? "trash" : "mic").toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, height: 24)) + .paddingOnly(end: 16), + ), + SizedBox(height: 50.toScreenHeight, width: 50.toScreenWidth).onPress(() { + if (_recording) { + _stopRecording(); + } else if (_record != null) { + _timeController?.text = "00:00"; + widget.onRecord(null); + _record = null; + setState(() {}); + } else { + _startRecording(); + } + }), + ], ), - SizedBox(height: 50.toScreenHeight, width: 50.toScreenWidth).onPress(() { - if (_recording) { - _stopRecording(); - } else if (_record != null) { - _timeController?.text = "00:00"; - widget.onRecord(null); - _record = null; - setState(() {}); - } else { - _startRecording(); - } - }) + if (_record != null) 8.height, + if (_record != null) ASoundPlayer(audio: _record), ], ); } diff --git a/lib/views/widgets/sound/sound_player.dart b/lib/views/widgets/sound/sound_player.dart index 0598ceed..ab687517 100644 --- a/lib/views/widgets/sound/sound_player.dart +++ b/lib/views/widgets/sound/sound_player.dart @@ -3,9 +3,6 @@ import 'package:flutter/material.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_text_style.dart'; -import 'package:test_sa/views/app_style/sizing.dart'; - -import '../../app_style/colors.dart'; class ASoundPlayer extends StatefulWidget { final String audio; @@ -31,7 +28,7 @@ class _ASoundPlayerState extends State { width: 48, height: 48, decoration: ShapeDecoration( - color: Colors.white, + color: Theme.of(context).cardColor, shape: RoundedRectangleBorder( side: const BorderSide(width: 1, color: Color(0xFFEAF1F4)), borderRadius: BorderRadius.circular(32), @@ -39,7 +36,7 @@ class _ASoundPlayerState extends State { ), child: Icon( icon, - color: const Color(0xff163A51).withOpacity(0.5), + color: Theme.of(context).primaryColor, ), ).onPress(onpress); } @@ -182,7 +179,7 @@ class _ASoundPlayerState extends State { value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, min: 0, max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, - activeColor: AppColor.primary70, + activeColor: Theme.of(context).primaryColor, inactiveColor: AppColor.neutral30, onChangeStart: (value) { _sliderMoving = true; From c49b66a4015b6ec53063c42a4b55b78d7f39e8b7 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 22 Oct 2023 11:31:39 +0300 Subject: [PATCH 7/7] sound player color fix. --- lib/views/widgets/sound/sound_player.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/views/widgets/sound/sound_player.dart b/lib/views/widgets/sound/sound_player.dart index ab687517..0598ceed 100644 --- a/lib/views/widgets/sound/sound_player.dart +++ b/lib/views/widgets/sound/sound_player.dart @@ -3,6 +3,9 @@ import 'package:flutter/material.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_text_style.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../../app_style/colors.dart'; class ASoundPlayer extends StatefulWidget { final String audio; @@ -28,7 +31,7 @@ class _ASoundPlayerState extends State { width: 48, height: 48, decoration: ShapeDecoration( - color: Theme.of(context).cardColor, + color: Colors.white, shape: RoundedRectangleBorder( side: const BorderSide(width: 1, color: Color(0xFFEAF1F4)), borderRadius: BorderRadius.circular(32), @@ -36,7 +39,7 @@ class _ASoundPlayerState extends State { ), child: Icon( icon, - color: Theme.of(context).primaryColor, + color: const Color(0xff163A51).withOpacity(0.5), ), ).onPress(onpress); } @@ -179,7 +182,7 @@ class _ASoundPlayerState extends State { value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, min: 0, max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, - activeColor: Theme.of(context).primaryColor, + activeColor: AppColor.primary70, inactiveColor: AppColor.neutral30, onChangeStart: (value) { _sliderMoving = true;