From ed759f5dcfbaa0336bc009b2292621326f76498e Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Mon, 16 Oct 2023 12:50:31 +0300 Subject: [PATCH] Still working on gas refill request --- assets/images/trash.svg | 4 + assets/translations/ar.json | 6 +- assets/translations/en.json | 6 +- lib/controllers/api_routes/urls.dart | 4 +- .../providers/api/hospitals_provider.dart | 6 +- lib/extensions/text_extensions.dart | 12 +- lib/extensions/widget_extensions.dart | 7 + lib/main.dart | 2 + .../call_request_for_work_order_model.dart | 5 +- lib/models/enums/translation_keys.dart | 4 + lib/models/gas_refill/gas_refill_details.dart | 1 + lib/models/gas_refill/gas_refill_model.dart | 1 + lib/models/new_models/assigned_employee.dart | 27 +++ lib/models/new_models/building.dart | 48 ++++ lib/models/new_models/department.dart | 39 +++ lib/models/new_models/floor.dart | 48 ++++ lib/models/new_models/gas_refill_model.dart | 225 ++++++++++++++++++ lib/models/new_models/site.dart | 43 ++++ lib/new_views/app_style/app_themes.dart | 1 + .../app_floating_action_button.dart | 24 +- .../single_item_drop_down_menu.dart | 80 +++---- lib/new_views/pages/login_page.dart | 2 +- .../pages/new_gas_refill_request_page.dart | 221 +++++++++++++---- .../pages/new_service_request_page.dart | 15 +- .../pages/new_transfer_request_page.dart | 15 +- .../gas_request_providers/site_provider.dart | 34 +++ lib/views/pages/user/land_page.dart | 59 ++--- 27 files changed, 783 insertions(+), 156 deletions(-) create mode 100644 assets/images/trash.svg create mode 100644 lib/models/new_models/assigned_employee.dart create mode 100644 lib/models/new_models/building.dart create mode 100644 lib/models/new_models/department.dart create mode 100644 lib/models/new_models/floor.dart create mode 100644 lib/models/new_models/gas_refill_model.dart create mode 100644 lib/models/new_models/site.dart create mode 100644 lib/providers/gas_request_providers/site_provider.dart diff --git a/assets/images/trash.svg b/assets/images/trash.svg new file mode 100644 index 00000000..881d16ba --- /dev/null +++ b/assets/images/trash.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/translations/ar.json b/assets/translations/ar.json index 6a205c3a..9830d14d 100644 --- a/assets/translations/ar.json +++ b/assets/translations/ar.json @@ -29,5 +29,9 @@ "department" : "القسم", "httpError" : "خطأ فشل الطلب", "tryAgain" : "أعد المحاولة", - "destinationSite" : "موقع الوجهة" + "destinationSite" : "موقع الوجهة", + "add": "أضف", + "site" : "الموقع", + "onlyNumbers": "يسمح بإدخال الأرقام فقط", + "youHaveToSelect" : "يجب عليك إختيار" } \ No newline at end of file diff --git a/assets/translations/en.json b/assets/translations/en.json index 2b801eb5..738c8772 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -29,5 +29,9 @@ "department" : "Department", "httpError" : "Error Request Failed", "tryAgain" : "Try Again", - "destinationSite" : "Destination Site" + "destinationSite" : "Destination Site", + "add": "Add", + "site" : "Site", + "onlyNumbers": "Only Numbers Allowed", + "youHaveToSelect" : "You have to select" } \ No newline at end of file diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 64815ebc..b5b933a8 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -24,8 +24,8 @@ class URLs { static get login => "$_baseUrl/MobileAuth/LoginIntegration"; // post static get register => "$_baseUrl/handle/create/user"; // post static get updateProfile => "$_baseUrl/update/user/profile"; // post - static get getHospitals => "$_baseUrl/Customer/GetCustomers"; // get - static get getHospitalsAutoComplete => "$_baseUrl/Customer/GetCustomersAutoComplete"; // get + static get getSites => "$_baseUrl/Customer/GetCustomers"; // get + static get getSitesAutoComplete => "$_baseUrl/Customer/GetCustomersAutoComplete"; // get static get getDepartments => "$_baseUrl/Customer/GetDepartmentLookup"; // get static get getEquipment => "$_baseUrl/Asset/GetAssets"; // get ?client=208051 diff --git a/lib/controllers/providers/api/hospitals_provider.dart b/lib/controllers/providers/api/hospitals_provider.dart index da0e2cd7..d9e6e42e 100644 --- a/lib/controllers/providers/api/hospitals_provider.dart +++ b/lib/controllers/providers/api/hospitals_provider.dart @@ -59,7 +59,7 @@ class HospitalsProvider extends ChangeNotifier { notifyListeners(); Response response; try { - response = await ApiManager.instance.post(URLs.getHospitals, body: { + response = await ApiManager.instance.post(URLs.getSites, body: { "pageNumber": (hospitals?.length ?? 0) ~/ pageItemNumber + 1, "pageSize": 50, if (title != null && title.isNotEmpty) "name": title, @@ -92,7 +92,7 @@ class HospitalsProvider extends ChangeNotifier { Future> getHospitalsList({String host, User user, String title}) async { Response response; try { - response = await ApiManager.instance.post(URLs.getHospitals, body: { + response = await ApiManager.instance.post(URLs.getSites, body: { "pageSize": 50, if (title != null && title.isNotEmpty) "name": title, }); @@ -126,7 +126,7 @@ class HospitalsProvider extends ChangeNotifier { if (searchVal.isNotEmpty) { searchVal = "?searchText=$searchVal"; } - response = await ApiManager.instance.get(URLs.getHospitalsAutoComplete + searchVal); + response = await ApiManager.instance.get(URLs.getSitesAutoComplete + searchVal); // response = await get( // Uri.parse(host + URLs.getHospitals // + ( title == null || title.isEmpty ? "" : "?name=$title" )), diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index d06ae91a..f9424b81 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -140,17 +140,17 @@ extension CapExtension on String { extension FilesExtension on String { SvgPicture toSvgAsset({ - double width, - double height, + int width, + int height, Color color, BoxFit fit = BoxFit.contain, }) => - SvgPicture.asset("assets/images/$this.svg", width: width, height: height, color: color, fit: fit); + SvgPicture.asset("assets/images/$this.svg", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit); Image toPngAsset({ - double width, - double height, + int width, + int height, Color color, BoxFit fit = BoxFit.contain, }) => - Image.asset("assets/images/$this.png", width: width, height: height, color: color, fit: fit); + Image.asset("assets/images/$this.png", width: width?.toScreenWidth, height: height?.toScreenHeight, color: color, fit: fit); } diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index d7dc6948..78fba845 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import '../new_views/app_style/app_color.dart'; + extension WidgetExtensions on Widget { Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); @@ -17,3 +20,7 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); } + +extension DividerExtension on Divider { + Divider defaultStyle(BuildContext context) => Divider(thickness: 1, color: context.isDark ? AppColor.neutral50 : AppColor.neutral30); +} diff --git a/lib/main.dart b/lib/main.dart index aa553293..30e6a0a6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:test_sa/providers/department_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart'; 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/views/pages/user/land_page.dart' as old; import 'controllers/providers/api/user_provider.dart'; @@ -61,6 +62,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => CylinderTypesProvider()), ChangeNotifierProvider(create: (_) => CylinderSizeProvider()), ChangeNotifierProvider(create: (_) => DepartmentProvider()), + ChangeNotifierProvider(create: (_) => SiteProvider()), ], child: GestureDetector( onTap: () { diff --git a/lib/models/call_request_for_work_order_model.dart b/lib/models/call_request_for_work_order_model.dart index 35b34551..60e78eeb 100644 --- a/lib/models/call_request_for_work_order_model.dart +++ b/lib/models/call_request_for_work_order_model.dart @@ -1,3 +1,4 @@ +import 'package:test_sa/models/base.dart'; import 'package:test_sa/models/lookup.dart'; class CallRequestForWorkOrder { @@ -413,13 +414,13 @@ class Site { } } -class Department { +class Department extends Base { int id; String departmentName; String departmentCode; String ntCode; - Department({this.id, this.departmentName, this.departmentCode, this.ntCode}); + Department({this.id, this.departmentName, this.departmentCode, this.ntCode}) : super(identifier: id.toString(), name: departmentName); Department.fromJson(Map json) { id = json['id']; diff --git a/lib/models/enums/translation_keys.dart b/lib/models/enums/translation_keys.dart index 552a83aa..b3b4a30f 100644 --- a/lib/models/enums/translation_keys.dart +++ b/lib/models/enums/translation_keys.dart @@ -30,4 +30,8 @@ enum TranslationKeys { httpError, tryAgain, destinationSite, + add, + site, + onlyNumbers, + youHaveToSelect, } diff --git a/lib/models/gas_refill/gas_refill_details.dart b/lib/models/gas_refill/gas_refill_details.dart index 0c9afe0e..50166779 100644 --- a/lib/models/gas_refill/gas_refill_details.dart +++ b/lib/models/gas_refill/gas_refill_details.dart @@ -1,5 +1,6 @@ import 'package:test_sa/models/lookup.dart'; +@Deprecated("Use the model inside lib/models/new_models folder") class GasRefillDetails { Lookup type; Lookup cylinderSize; diff --git a/lib/models/gas_refill/gas_refill_model.dart b/lib/models/gas_refill/gas_refill_model.dart index aeed1b85..cc34dc6a 100644 --- a/lib/models/gas_refill/gas_refill_model.dart +++ b/lib/models/gas_refill/gas_refill_model.dart @@ -6,6 +6,7 @@ import 'package:test_sa/models/lookup.dart'; import '../../controllers/api_routes/urls.dart'; import '../call_request_for_work_order_model.dart'; +@Deprecated("Use the new model [lib/models/new_models/gas_refill_model.dart]") class GasRefillModel { int id; diff --git a/lib/models/new_models/assigned_employee.dart b/lib/models/new_models/assigned_employee.dart new file mode 100644 index 00000000..937e5f71 --- /dev/null +++ b/lib/models/new_models/assigned_employee.dart @@ -0,0 +1,27 @@ +class AssignedEmployee { + AssignedEmployee({ + this.id, + this.name, + }); + + AssignedEmployee.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + } + String id; + String name; + AssignedEmployee copyWith({ + String id, + String name, + }) => + AssignedEmployee( + id: id ?? this.id, + name: name ?? this.name, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['name'] = name; + return map; + } +} diff --git a/lib/models/new_models/building.dart b/lib/models/new_models/building.dart new file mode 100644 index 00000000..00b1b1a9 --- /dev/null +++ b/lib/models/new_models/building.dart @@ -0,0 +1,48 @@ +import 'package:test_sa/models/new_models/floor.dart'; + +class Building { + Building({ + this.id, + this.name, + this.value, + this.floors, + }); + + Building.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['floors'] != null) { + floors = []; + json['floors'].forEach((v) { + floors.add(Floor.fromJson(v)); + }); + } + } + num id; + String name; + num value; + List floors; + Building copyWith({ + num id, + String name, + num value, + List floors, + }) => + Building( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + floors: floors ?? this.floors, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['name'] = name; + map['value'] = value; + if (floors != null) { + map['floors'] = floors.map((v) => v.toJson()).toList(); + } + return map; + } +} diff --git a/lib/models/new_models/department.dart b/lib/models/new_models/department.dart new file mode 100644 index 00000000..49037d45 --- /dev/null +++ b/lib/models/new_models/department.dart @@ -0,0 +1,39 @@ +class Department { + Department({ + this.id, + this.departmentName, + this.departmentCode, + this.ntCode, + }); + + Department.fromJson(dynamic json) { + id = json['id']; + departmentName = json['departmentName']; + departmentCode = json['departmentCode']; + ntCode = json['ntCode']; + } + num id; + String departmentName; + String departmentCode; + String ntCode; + Department copyWith({ + num id, + String departmentName, + String departmentCode, + String ntCode, + }) => + Department( + id: id ?? this.id, + departmentName: departmentName ?? this.departmentName, + departmentCode: departmentCode ?? this.departmentCode, + ntCode: ntCode ?? this.ntCode, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['departmentName'] = departmentName; + map['departmentCode'] = departmentCode; + map['ntCode'] = ntCode; + return map; + } +} diff --git a/lib/models/new_models/floor.dart b/lib/models/new_models/floor.dart new file mode 100644 index 00000000..56280ae6 --- /dev/null +++ b/lib/models/new_models/floor.dart @@ -0,0 +1,48 @@ +import 'package:test_sa/models/new_models/department.dart'; + +class Floor { + Floor({ + this.id, + this.name, + this.value, + this.departments, + }); + + Floor.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['departments'] != null) { + departments = []; + json['departments'].forEach((v) { + departments.add(Department.fromJson(v)); + }); + } + } + num id; + String name; + num value; + List departments; + Floor copyWith({ + num id, + String name, + num value, + List departments, + }) => + Floor( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + departments: departments ?? this.departments, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['name'] = name; + map['value'] = value; + if (departments != null) { + map['departments'] = departments.map((v) => v.toJson()).toList(); + } + return map; + } +} diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart new file mode 100644 index 00000000..37edb645 --- /dev/null +++ b/lib/models/new_models/gas_refill_model.dart @@ -0,0 +1,225 @@ +import 'package:flutter/cupertino.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/models/enums/translation_keys.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/assigned_employee.dart'; +import 'package:test_sa/models/new_models/building.dart'; +import 'package:test_sa/models/new_models/department.dart'; +import 'package:test_sa/models/new_models/floor.dart'; +import 'package:test_sa/models/new_models/site.dart'; + +class GasRefillModel { + GasRefillModel({ + this.id, + this.gazRefillNo, + this.expectedDate, + this.expectedTime, + this.startDate, + this.startTime, + this.endDate, + this.endTime, + this.engSignature, + this.nurseSignature, + this.workingHours, + this.site, + this.building, + this.floor, + this.department, + this.assignedEmployee, + this.status, + this.gazRefillDetails, + }); + + GasRefillModel.fromJson(dynamic json) { + id = json['id']; + gazRefillNo = json['gazRefillNo']; + expectedDate = json['expectedDate']; + expectedTime = json['expectedTime']; + startDate = json['startDate']; + startTime = json['startTime']; + endDate = json['endDate']; + endTime = json['endTime']; + engSignature = json['engSignature']; + nurseSignature = json['nurseSignature']; + workingHours = json['workingHours']; + site = json['site'] != null ? Site.fromJson(json['site']) : null; + building = json['building'] != null ? Building.fromJson(json['building']) : null; + floor = json['floor'] != null ? Floor.fromJson(json['floor']) : null; + department = json['department'] != null ? Department.fromJson(json['department']) : null; + assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; + status = json['status'] != null ? Lookup.fromJson(json['status']) : null; + if (json['gazRefillDetails'] != null) { + gazRefillDetails = []; + json['gazRefillDetails'].forEach((v) { + gazRefillDetails.add(GasRefillDetails.fromJson(v)); + }); + } + } + num id; + String gazRefillNo; + String expectedDate; + String expectedTime; + String startDate; + String startTime; + String endDate; + String endTime; + String engSignature; + String nurseSignature; + num workingHours; + Site site; + Building building; + Floor floor; + Department department; + AssignedEmployee assignedEmployee; + Lookup status; + List gazRefillDetails; + GasRefillModel copyWith({ + num id, + String gazRefillNo, + String expectedDate, + String expectedTime, + String startDate, + String startTime, + String endDate, + String endTime, + String engSignature, + String nurseSignature, + num workingHours, + Site site, + Building building, + Floor floor, + Department department, + AssignedEmployee assignedEmployee, + Lookup status, + List gazRefillDetails, + }) => + GasRefillModel( + id: id ?? this.id, + gazRefillNo: gazRefillNo ?? this.gazRefillNo, + expectedDate: expectedDate ?? this.expectedDate, + expectedTime: expectedTime ?? this.expectedTime, + startDate: startDate ?? this.startDate, + startTime: startTime ?? this.startTime, + endDate: endDate ?? this.endDate, + endTime: endTime ?? this.endTime, + engSignature: engSignature ?? this.engSignature, + nurseSignature: nurseSignature ?? this.nurseSignature, + workingHours: workingHours ?? this.workingHours, + site: site ?? this.site, + building: building ?? this.building, + floor: floor ?? this.floor, + department: department ?? this.department, + assignedEmployee: assignedEmployee ?? this.assignedEmployee, + status: status ?? this.status, + gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['gazRefillNo'] = gazRefillNo; + map['expectedDate'] = expectedDate; + map['expectedTime'] = expectedTime; + map['startDate'] = startDate; + map['startTime'] = startTime; + map['endDate'] = endDate; + map['endTime'] = endTime; + map['engSignature'] = engSignature; + map['nurseSignature'] = nurseSignature; + map['workingHours'] = workingHours; + if (site != null) { + map['site'] = site.toJson(); + } + if (building != null) { + map['building'] = building.toJson(); + } + if (floor != null) { + map['floor'] = floor.toJson(); + } + if (department != null) { + map['department'] = department.toJson(); + } + if (assignedEmployee != null) { + map['assignedEmployee'] = assignedEmployee.toJson(); + } + if (status != null) { + map['status'] = status.toMap(); + } + if (gazRefillDetails != null) { + map['gazRefillDetails'] = gazRefillDetails.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class GasRefillDetails { + GasRefillDetails({ + this.id, + this.gasType, + this.cylinderType, + this.cylinderSize, + this.requestedQty, + this.deliverdQty, + }); + + GasRefillDetails.fromJson(dynamic json) { + id = json['id']; + gasType = json['gasType'] != null ? Lookup.fromJson(json['gasType']) : null; + cylinderType = json['cylinderType'] != null ? Lookup.fromJson(json['cylinderType']) : null; + cylinderSize = json['cylinderSize'] != null ? Lookup.fromJson(json['cylinderSize']) : null; + requestedQty = json['requestedQty']; + deliverdQty = json['deliverdQty']; + } + num id; + Lookup gasType; + Lookup cylinderType; + Lookup cylinderSize; + num requestedQty; + num deliverdQty; + GasRefillDetails copyWith({ + num id, + Lookup gasType, + Lookup cylinderType, + Lookup cylinderSize, + num requestedQty, + num deliverdQty, + }) => + GasRefillDetails( + id: id ?? this.id, + gasType: gasType ?? this.gasType, + cylinderType: cylinderType ?? this.cylinderType, + cylinderSize: cylinderSize ?? this.cylinderSize, + requestedQty: requestedQty ?? this.requestedQty, + deliverdQty: deliverdQty ?? this.deliverdQty, + ); + Map toJson() { + final map = {}; + map['id'] = id; + if (gasType != null) { + map['gasType'] = gasType.toMap(); + } + if (cylinderType != null) { + map['cylinderType'] = cylinderType.toMap(); + } + if (cylinderSize != null) { + map['cylinderSize'] = cylinderSize.toMap(); + } + map['requestedQty'] = requestedQty; + map['deliverdQty'] = deliverdQty; + return map; + } + + Future validate(BuildContext context) async { + if (gasType == null) { + await Fluttertoast.showToast(msg: "${context.translate(TranslationKeys.youHaveToSelect)} ${context.translate(TranslationKeys.gasType)}"); + return false; + } else if (cylinderType == null) { + await Fluttertoast.showToast(msg: "${context.translate(TranslationKeys.youHaveToSelect)} ${context.translate(TranslationKeys.cylinderType)}"); + return false; + } else if (cylinderSize == null) { + await Fluttertoast.showToast(msg: "${context.translate(TranslationKeys.youHaveToSelect)} ${context.translate(TranslationKeys.cylinderSize)}"); + return false; + } + return true; + } +} diff --git a/lib/models/new_models/site.dart b/lib/models/new_models/site.dart new file mode 100644 index 00000000..849b458c --- /dev/null +++ b/lib/models/new_models/site.dart @@ -0,0 +1,43 @@ +import 'package:test_sa/models/base.dart'; +import 'package:test_sa/models/new_models/building.dart'; + +class Site extends Base { + Site({ + this.id, + this.custName, + this.buildings, + }) : super(identifier: id.toString(), name: custName); + + Site.fromJson(dynamic json) { + id = json['id']; + custName = json['custName']; + if (json['buildings'] != null) { + buildings = []; + json['buildings'].forEach((v) { + buildings.add(Building.fromJson(v)); + }); + } + } + num id; + String custName; + List buildings; + Site copyWith({ + num id, + String custName, + List buildings, + }) => + Site( + id: id ?? this.id, + custName: custName ?? this.custName, + buildings: buildings ?? this.buildings, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['custName'] = custName; + if (buildings != null) { + map['buildings'] = buildings.map((v) => v.toJson()).toList(); + } + return map; + } +} diff --git a/lib/new_views/app_style/app_themes.dart b/lib/new_views/app_style/app_themes.dart index cf39314f..14d76d76 100644 --- a/lib/new_views/app_style/app_themes.dart +++ b/lib/new_views/app_style/app_themes.dart @@ -55,6 +55,7 @@ class AppThemes { appBarTheme: AppBarTheme(elevation: 0, backgroundColor: AppColor.neutral60, iconTheme: ThemeData.dark().iconTheme.copyWith(color: AppColor.primary40)), cardTheme: ThemeData.dark().cardTheme.copyWith( elevation: 3, + color: AppColor.neutral60, shadowColor: Colors.white.withOpacity(0.05), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), ), diff --git a/lib/new_views/common_widgets/app_floating_action_button.dart b/lib/new_views/common_widgets/app_floating_action_button.dart index 09339a50..ac0ae631 100644 --- a/lib/new_views/common_widgets/app_floating_action_button.dart +++ b/lib/new_views/common_widgets/app_floating_action_button.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; import 'package:test_sa/new_views/pages/new_service_request_page.dart'; import 'package:test_sa/new_views/pages/new_transfer_request_page.dart'; @@ -47,19 +48,16 @@ class _AppFloatingActionButtonState extends State { child: Card( shape: Theme.of(context).cardTheme.copyWith().shape, margin: EdgeInsetsDirectional.only(start: 60.toScreenWidth), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 8.toScreenHeight), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const _FloatingButtonListTile(iconName: "gas_refill_request", label: TranslationKeys.gasRefillRequest, routeName: NewGasRefillRequestPage.routeName), - Padding(padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: const Divider()), - const _FloatingButtonListTile(iconName: "transfer_request", label: TranslationKeys.transferRequest, routeName: NewTransferRequestPage.routeName), - Padding(padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), child: const Divider()), - const _FloatingButtonListTile(iconName: "service_request", label: TranslationKeys.serviceRequest, routeName: NewServiceRequestPage.routeName), - ], - ), - ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const _FloatingButtonListTile(iconName: "gas_refill_request", label: TranslationKeys.gasRefillRequest, routeName: NewGasRefillRequestPage.routeName), + const Divider().defaultStyle(context).paddingOnly(left: 16, right: 16), + const _FloatingButtonListTile(iconName: "transfer_request", label: TranslationKeys.transferRequest, routeName: NewTransferRequestPage.routeName), + const Divider().defaultStyle(context).paddingOnly(left: 16, right: 16), + const _FloatingButtonListTile(iconName: "service_request", label: TranslationKeys.serviceRequest, routeName: NewServiceRequestPage.routeName), + ], + ).paddingOnly(top: 8, bottom: 8), ), ), ), diff --git a/lib/new_views/common_widgets/single_item_drop_down_menu.dart b/lib/new_views/common_widgets/single_item_drop_down_menu.dart index 5bc9f5c7..1860191b 100644 --- a/lib/new_views/common_widgets/single_item_drop_down_menu.dart +++ b/lib/new_views/common_widgets/single_item_drop_down_menu.dart @@ -88,48 +88,46 @@ class _SingleItemDropDownMenuState( + value: _selectedItem, + iconSize: 24, + isDense: true, + icon: const SizedBox.shrink(), + elevation: 0, + isExpanded: true, + hint: Text( + context.translate(TranslationKeys.select), + style: Theme.of(context).textTheme.bodyLarge, ), - DropdownButton( - value: _selectedItem, - iconSize: 24, - isDense: true, - icon: const SizedBox.shrink(), - elevation: 0, - isExpanded: true, - hint: Text( - context.translate(TranslationKeys.select), - style: Theme.of(context).textTheme.bodyLarge, - ), - style: TextStyle(color: Theme.of(context).primaryColor), - underline: const SizedBox.shrink(), - onChanged: widget.enabled == false - ? null - : (T newValue) { - setState(() { - _selectedItem = newValue; - }); - widget.onSelect(newValue); - }, - items: provider.items?.map>((value) { - return DropdownMenuItem( - value: value, - child: Text( - value?.name ?? "", - style: Theme.of(context).textTheme.bodyLarge, - ), - ); - })?.toList(), - ), - ], - ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: widget.enabled == false + ? null + : (T newValue) { + setState(() { + _selectedItem = newValue; + }); + widget.onSelect(newValue); + }, + items: provider.items?.map>((value) { + return DropdownMenuItem( + value: value, + child: Text( + value?.name ?? "", + style: Theme.of(context).textTheme.bodyLarge, + ), + ); + })?.toList(), + ), + ], ), ], ), diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 31dabd13..75930f70 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -47,7 +47,7 @@ class _LoginPageState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Hero(tag: "logo", child: "logo".toSvgAsset(height: 64.toScreenHeight)), + Hero(tag: "logo", child: "logo".toSvgAsset(height: 64)), 64.height, context.translate(TranslationKeys.login).heading2(context).custom(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.primary50 : AppColor.neutral50), context.translate(TranslationKeys.enterCredsToLogin).heading6(context).custom(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), diff --git a/lib/new_views/pages/new_gas_refill_request_page.dart b/lib/new_views/pages/new_gas_refill_request_page.dart index e445d074..deff5cfb 100644 --- a/lib/new_views/pages/new_gas_refill_request_page.dart +++ b/lib/new_views/pages/new_gas_refill_request_page.dart @@ -1,70 +1,199 @@ 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 'package:test_sa/models/enums/translation_keys.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/gas_refill_model.dart'; +import 'package:test_sa/models/new_models/site.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/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart'; import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; +import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; +import '../../controllers/validator/validator.dart'; import '../common_widgets/default_app_bar.dart'; -class NewGasRefillRequestPage extends StatelessWidget { +class NewGasRefillRequestPage extends StatefulWidget { static const String routeName = "/new_gas_refill_request_page"; const NewGasRefillRequestPage({Key key}) : super(key: key); + @override + State createState() => _NewGasRefillRequestPageState(); +} + +class _NewGasRefillRequestPageState extends State { + GasRefillDetails _currentDetails; + GasRefillModel _gasModel; + GlobalKey _formKey; + TextEditingController _quantityController; + + @override + void initState() { + super.initState(); + _formKey = GlobalKey(); + _currentDetails = GasRefillDetails(); + _gasModel = GasRefillModel(gazRefillDetails: []); + _quantityController = TextEditingController(); + } + + @override + void dispose() { + _quantityController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( appBar: const DefaultAppBar(title: TranslationKeys.newGasRefillRequest), - body: Padding( - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - child: SingleChildScrollView( - child: Column( - children: [ - 16.height, - SingleItemDropDownMenu( - context: context, - title: TranslationKeys.gasType, + body: Column( + children: [ + SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + children: [ + 16.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.gasType, + onSelect: (value) { + _currentDetails.gasType = value; + }, + ), + 8.height, + AppTextFormField( + controller: _quantityController, + labelText: TranslationKeys.quantity, + textInputType: TextInputType.number, + validator: (value) => Validator.hasValue(value) + ? Validator.isNumeric(value) + ? null + : context.translate(TranslationKeys.onlyNumbers) + : context.translate(TranslationKeys.requiredField), + onSaved: (text) { + _currentDetails.requestedQty = double.tryParse(text ?? "") ?? 0; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.cylinderType, + onSelect: (value) { + _currentDetails.cylinderType = value; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.cylinderSize, + onSelect: (value) { + _currentDetails.cylinderSize = value; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: TranslationKeys.destinationSite, + onSelect: (value) { + _gasModel.site = value; + }, + ), + // 8.height, + // SingleItemDropDownMenu( + // context: context, + // title: TranslationKeys.department, + // onSelect: (value) { + // _formModel.department = value; + // }, + // ), + 8.height, + AppFilledButton( + label: TranslationKeys.add, + maxWidth: true, + textColor: Colors.white, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, + onPressed: _add, + ), + 24.height, + ListView.builder( + shrinkWrap: true, + itemCount: _gasModel.gazRefillDetails?.length, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _gasModel.gazRefillDetails[index].gasType?.name?.heading5(context), + 8.height, + ("${context.translate(TranslationKeys.quantity)}: ${_gasModel.gazRefillDetails[index].requestedQty}").bodyText(context), + ("${context.translate(TranslationKeys.cylinderSize)}: ${_gasModel.gazRefillDetails[index].cylinderSize?.name}").bodyText(context), + ("${context.translate(TranslationKeys.cylinderType)}: ${_gasModel.gazRefillDetails[index].cylinderType?.name}").bodyText(context), + ], + ), + Container( + height: 48.toScreenWidth, + width: 48.toScreenWidth, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30), + ), + padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight), + child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50), + ).onPress(() { + _delete(index); + }), + ], + ), + const Divider().defaultStyle(context), + ("${context.translate(TranslationKeys.department)}: ${_gasModel.department?.departmentCode}").bodyText(context), + ("${context.translate(TranslationKeys.site)}: ${_gasModel.department?.departmentName}").bodyText(context), + ], + ).paddingAll(16), + ); + }, + ), + 40.height, + ], ), - 8.height, - const AppTextFormField( - labelText: TranslationKeys.quantity, - textInputType: TextInputType.number, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: TranslationKeys.cylinderType, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: TranslationKeys.cylinderSize, - ), - 8.height, - // SingleItemDropDownMenu( - // context: context, - // title: TranslationKeys.department, - // ), - // 8.height, - // SingleItemDropDownMenu( - // context: context, - // title: TranslationKeys.destinationSite, - // ), - // 8.height, - ], - ), - ), - ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: AppFilledButton( - label: TranslationKeys.submitRequest, - maxWidth: true, - onPressed: () {}, - ), + ), + ).expanded, + AppFilledButton(label: TranslationKeys.submitRequest, maxWidth: true, onPressed: _submit), + ], + ).paddingOnly(left: 16, right: 16, bottom: 24), ); } + + void _add() async { + if (_formKey.currentState.validate() && await _currentDetails.validate(context)) { + _formKey.currentState.save(); + _gasModel.gazRefillDetails.add(_currentDetails); + _quantityController.clear(); + _currentDetails = GasRefillDetails(); + setState(() {}); + } + } + + void _delete(index) { + _gasModel.gazRefillDetails.remove(_gasModel.gazRefillDetails[index]); + setState(() {}); + } + + void _submit() { + Navigator.pop(context); + } } diff --git a/lib/new_views/pages/new_service_request_page.dart b/lib/new_views/pages/new_service_request_page.dart index d6387383..1783c3f1 100644 --- a/lib/new_views/pages/new_service_request_page.dart +++ b/lib/new_views/pages/new_service_request_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/translation_keys.dart'; import '../common_widgets/app_filled_button.dart'; @@ -12,12 +13,14 @@ class NewServiceRequestPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: const DefaultAppBar(title: TranslationKeys.newServiceRequest), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: AppFilledButton( - label: TranslationKeys.submitRequest, - maxWidth: true, - onPressed: () {}, - ), + body: Column( + children: [ + SingleChildScrollView( + child: Column(children: []), + ).expanded, + AppFilledButton(label: TranslationKeys.submitRequest, maxWidth: true, onPressed: () {}) + ], + ).paddingOnly(left: 16, right: 16, bottom: 24), ); } } diff --git a/lib/new_views/pages/new_transfer_request_page.dart b/lib/new_views/pages/new_transfer_request_page.dart index 46d01688..96ad05eb 100644 --- a/lib/new_views/pages/new_transfer_request_page.dart +++ b/lib/new_views/pages/new_transfer_request_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/translation_keys.dart'; import '../common_widgets/app_filled_button.dart'; @@ -12,12 +13,14 @@ class NewTransferRequestPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: const DefaultAppBar(title: TranslationKeys.newTransferRequest), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: AppFilledButton( - label: TranslationKeys.submitRequest, - maxWidth: true, - onPressed: () {}, - ), + body: Column( + children: [ + SingleChildScrollView( + child: Column(children: []), + ).expanded, + AppFilledButton(label: TranslationKeys.submitRequest, maxWidth: true, onPressed: () {}) + ], + ).paddingOnly(left: 16, right: 16, bottom: 24), ); } } diff --git a/lib/providers/gas_request_providers/site_provider.dart b/lib/providers/gas_request_providers/site_provider.dart new file mode 100644 index 00000000..a9930131 --- /dev/null +++ b/lib/providers/gas_request_providers/site_provider.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:test_sa/models/new_models/site.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; + +import '../../controllers/api_routes/api_manager.dart'; +import '../../controllers/api_routes/urls.dart'; + +class SiteProvider extends LoadingListNotifier { + @override + Future getDate() async { + if (loading ?? false) return -2; + loading = true; + notifyListeners(); + try { + Response response = await ApiManager.instance.get(URLs.getSitesAutoComplete); + 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) => Site.fromJson(item)).toList(); + } + loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + loading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index 48bb5997..44c56661 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -11,7 +11,6 @@ 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/int_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; import 'package:test_sa/new_views/pages/new_transfer_request_page.dart'; import 'package:test_sa/views/app_style/colors.dart'; @@ -148,16 +147,17 @@ class _LandPageState extends State { mainAxisSpacing: 12, childAspectRatio: 1, children: [ - if (_userProvider.user != null && _userProvider.user.type == UsersTypes.normal_user) - LandPageItem( - // text: _subtitle.newServiceRequest, - text: "New Service Request", - icon: FontAwesomeIcons.screwdriverWrench, - onPressed: () { - // Navigator.of(context).pushNamed(CreateRequestPage.id); - Navigator.of(context).pushNamed(NewServiceRequestPage.routeName); - }, - ), + /// enable this condition when the nurse account works + // if (_userProvider.user != null && _userProvider.user.type == UsersTypes.normal_user) + LandPageItem( + // text: _subtitle.newServiceRequest, + text: "New Service Request", + icon: FontAwesomeIcons.screwdriverWrench, + onPressed: () { + // Navigator.of(context).pushNamed(CreateRequestPage.id); + Navigator.of(context).pushNamed(NewServiceRequestPage.routeName); + }, + ), LandPageItem( // text: _subtitle.trackServiceRequest, text: "Track Service Request", @@ -183,15 +183,16 @@ class _LandPageState extends State { // Navigator.of(context).pushNamed(PreventiveMaintenanceVisitsPage.id); // }, // ), - if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) - LandPageItem( - text: "Request Gas Refill", - icon: FontAwesomeIcons.truckFast, - onPressed: () { - // Navigator.of(context).pushNamed(RequestGasRefill.id); - Navigator.of(context).pushNamed(NewGasRefillRequestPage.routeName); - }, - ), + /// enable this condition when the nurse account works + // if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) + LandPageItem( + text: "Request Gas Refill", + icon: FontAwesomeIcons.truckFast, + onPressed: () { + // Navigator.of(context).pushNamed(RequestGasRefill.id); + Navigator.of(context).pushNamed(NewGasRefillRequestPage.routeName); + }, + ), LandPageItem( text: "Track Gas Refill", icon: Icons.content_paste_search, @@ -214,14 +215,16 @@ class _LandPageState extends State { Navigator.of(context).pushNamed(TrackDeviceTransferPage.id); }, ), - if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) - LandPageItem( - text: "Create Sub Work Order", - svgPath: "assets/images/sub_workorder_icon.svg", - onPressed: () { - Navigator.of(context).pushNamed(SearchSubWorkOrderPage.id); - }, - ), + + /// enable this condition when the nurse account works + // if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) + LandPageItem( + text: "Create Sub Work Order", + svgPath: "assets/images/sub_workorder_icon.svg", + onPressed: () { + Navigator.of(context).pushNamed(SearchSubWorkOrderPage.id); + }, + ), ], ), ],