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), - ), - ), - ], - ) ], ); }