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/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/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/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/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/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 b6767296..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';
@@ -46,7 +47,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 +55,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 +63,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 +71,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 +78,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 +85,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 +92,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 +99,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 +106,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 +113,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,
@@ -154,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 a07a6771..aed0f553 100644
--- a/lib/l10n/app_ar.arb
+++ b/lib/l10n/app_ar.arb
@@ -1,6 +1,6 @@
{
"serverErrorMessage": "الخدمة غير متاحة حاليا",
- "failedRequestMessage": "الفشل في إكمال الطلب",
+ "failedRequestMessage": "فشل إكمال الطلب",
"successfulRequestMessage": "تم إكمال الطلب بنجاح",
"requestLockMessage": "انتظر حتى إكمال الطلب",
"cancel": "إلغاء",
@@ -251,5 +251,12 @@
"model" : "الطراز",
"serialNumber" : "الرقم التسلسلي",
"device" : "الجهاز",
- "pickAsset" : "إختر جهاز"
+ "pickAsset" : "إختر جهاز",
+ "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 57522750..29433d6f 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -251,5 +251,17 @@
"model" : "Model",
"serialNumber" : "Serial Number",
"device" : "Device",
- "pickAsset" : "Pick Asset"
+ "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",
+ "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 110f3295..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';
@@ -67,6 +68,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';
@@ -77,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) {
@@ -158,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: () {
@@ -197,6 +199,7 @@ class MyApp extends StatelessWidget {
TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(),
SearchSubWorkOrderPage.id: (_) => const SearchSubWorkOrderPage(),
CreateSubWorkOrderPage.id: (_) => const CreateSubWorkOrderPage(),
+ WorkOrderListPage.id: (_) => WorkOrderListPage(),
},
),
),
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/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/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/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:
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/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..71e896fd
--- /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.serviceDetails),
+ 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..a7b4ef7a
--- /dev/null
+++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart
@@ -0,0 +1,175 @@
+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/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 {
+ 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;
+ }
+ print("serviceRequest.statusValue:${serviceRequest.statusValue}");
+ 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());
+
+ 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: [
+ 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],
+ )),
+ );
+ })
+ ],
+ ),
+ 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))),
+ ],
+ ),
+ Text(
+ '${context.translation.orderWorkNumber}: ${workOrders[index].workOrderNo}',
+ style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
+ ),
+ Text(
+ '${context.translation.assignedEmployee}: ${workOrders[index].assignedEmployee?.name ?? ""}',
+ style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
+ ),
+ 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,
+ )
+ ],
+ ),
+ ],
+ ).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)
+ ],
+ );
+ },
+ )));
+ }
+}
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/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/record_sound.dart b/lib/views/widgets/sound/record_sound.dart
index 3b6b75b6..d01edc03 100644
--- a/lib/views/widgets/sound/record_sound.dart
+++ b/lib/views/widgets/sound/record_sound.dart
@@ -1,23 +1,28 @@
+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:record_mp3/record_mp3.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/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 'package:record_mp3/record_mp3.dart';
-import '../../app_style/sizing.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();
@@ -28,8 +33,11 @@ class _RecordSoundState extends State {
bool _recorderIsOpened = false;
bool _recording = false;
+ bool _played = false;
String _record;
Artboard _rive;
+ Timer _timer;
+ TextEditingController _timeController;
@override
void setState(VoidCallback fn) {
@@ -39,7 +47,7 @@ class _RecordSoundState extends State {
@override
void initState() {
super.initState();
-
+ _timeController = TextEditingController();
_recorderIsOpened = true;
// RecordMp3.instance.start(recordFilePath, (type) {
// // record fail callback
@@ -70,6 +78,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 +89,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 +97,15 @@ class _RecordSoundState extends State {
return;
}
}
+ _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
+ setState(() {
+ 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'));
if (!_recorderIsOpened) {
// await _myRecorder.openRecorder();
@@ -111,7 +128,9 @@ class _RecordSoundState extends State {
setState(() {});
return;
}
-
+ if (_timer?.isActive ?? false) {
+ _timer.cancel();
+ }
RecordMp3.instance.stop();
//String path = (await _myRecorder.stopRecorder()).toString();
@@ -137,94 +156,37 @@ 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 Column(
+ children: [
+ 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();
+ }
+ }),
+ ],
),
- 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)),
- ),
- ),
- ],
- ),
- ],
- ),
+ 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 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),
- ),
- ),
- ],
- )
],
);
}
diff --git a/pubspec.lock b/pubspec.lock
index 4b2e01a2..2ec601f7 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -217,6 +217,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:
@@ -669,6 +677,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 26ea7c35..a52f678d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -68,7 +68,8 @@ dependencies:
path_provider: ^2.1.0
open_file: ^3.3.2
localization: ^2.1.0
- buttons_tabbar: ^1.3.7+1
+ dotted_border: ^2.1.0
+ lottie: ^2.3.0
dev_dependencies:
flutter_test:
@@ -98,6 +99,7 @@ flutter:
assets:
- assets/
- assets/images/
+ - assets/lottie/
- assets/subtitles/
- assets/rives/
- assets/translations/