diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index cc5527d7..02e5f581 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip diff --git a/assets/images/ask_otp_icon.svg b/assets/images/ask_otp_icon.svg new file mode 100644 index 00000000..125c8ec9 --- /dev/null +++ b/assets/images/ask_otp_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/ask_requester_icon.svg b/assets/images/ask_requester_icon.svg new file mode 100644 index 00000000..27a23080 --- /dev/null +++ b/assets/images/ask_requester_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/delete_icon.svg b/assets/images/delete_icon.svg new file mode 100644 index 00000000..66b294bb --- /dev/null +++ b/assets/images/delete_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/edit_icon.svg b/assets/images/edit_icon.svg new file mode 100644 index 00000000..3b49167b --- /dev/null +++ b/assets/images/edit_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/login_top_bg.png b/assets/images/login_top_bg.png new file mode 100644 index 00000000..0034abc3 Binary files /dev/null and b/assets/images/login_top_bg.png differ diff --git a/assets/images/maintenance_icon.svg b/assets/images/maintenance_icon.svg new file mode 100644 index 00000000..c58f5940 --- /dev/null +++ b/assets/images/maintenance_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/overdue.svg b/assets/images/overdue.svg index ee9de58c..ece17cbd 100644 --- a/assets/images/overdue.svg +++ b/assets/images/overdue.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/assets/images/retired_asset_icon.svg b/assets/images/retired_asset_icon.svg new file mode 100644 index 00000000..49b49b55 --- /dev/null +++ b/assets/images/retired_asset_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/scan_qr_icon.svg b/assets/images/scan_qr_icon.svg new file mode 100644 index 00000000..a9eec41b --- /dev/null +++ b/assets/images/scan_qr_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/spare_part_icon.svg b/assets/images/spare_part_icon.svg new file mode 100644 index 00000000..6da137b4 --- /dev/null +++ b/assets/images/spare_part_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/take_device_photo_icon.svg b/assets/images/take_device_photo_icon.svg new file mode 100644 index 00000000..a9eec41b --- /dev/null +++ b/assets/images/take_device_photo_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/lib/app_strings/app_asset.dart b/lib/app_strings/app_asset.dart new file mode 100644 index 00000000..ced32514 --- /dev/null +++ b/lib/app_strings/app_asset.dart @@ -0,0 +1,13 @@ +class AppAsset{ + static String loginTopBg = 'assets/images/login_top_bg.png'; + static String askOtpIcon = 'assets/images/ask_otp_icon.svg'; + static String askRequesterIcon = 'assets/images/ask_requester_icon.svg'; + static String scanQrIcon = 'assets/images/scan_qr_icon.svg'; + static String takeDevicePhotoIcon = 'assets/images/take_device_photo_icon.svg'; + static String maintenanceIcon = 'assets/images/maintenance_icon.svg'; + static String retiredAssetIcon = 'assets/images/retired_asset_icon.svg'; + static String sparePartIcon = 'assets/images/spare_part_icon.svg'; + static String editIcon = 'assets/images/edit_icon.svg'; + static String deleteIcon = 'assets/images/delete_icon.svg'; + static String overDueIcon = 'assets/images/overdue.svg'; +} \ No newline at end of file diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index f996ac10..11e73fde 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -1,8 +1,8 @@ class URLs { URLs._(); - static const host1 = "https://atomsm.hmg.com"; // production url - // static const host1 = "https://atomsmdev.hmg.com"; // local UAT url + // static const host1 = "https://atomsm.hmg.com"; // production url + static const host1 = "https://atomsmdev.hmg.com"; // local UAT url // static String _baseUrl = "$_host/mobile"; static String _baseUrl = "$_host/v2/mobile"; // new V2 apis diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 742e8add..002350ec 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -17,15 +17,36 @@ class AllRequestsProvider extends ChangeNotifier { bool isOverdueLoading = false; bool isHighPriorityLoading = false; bool isCalendarLoading = false; + bool _isFilterRequestLoading = false; + + + + int _currentListIndex = 0; + + int get currentListIndex => _currentListIndex; + + set currentListIndex(int value) { + _currentListIndex = value; + notifyListeners(); + } int stateCode; AllRequestsAndCount allRequestsAndCount; - AllRequestsAndCount openRequests; - AllRequestsAndCount inProgressRequests; - AllRequestsAndCount completedRequests; + AllRequestsAndCount _openRequests; + AllRequestsAndCount _inProgressRequests; + AllRequestsAndCount _completedRequests; + AllRequestsAndCount _filterRequest; AllRequestsAndCount overdueRequests; AllRequestsAndCount highPriorityRequests; + + bool isLoadingList = false; + + updateIsLoadingList(value) { + isLoadingList = value; + notifyListeners(); + } + AllRequestsAndCount calendarRequests; final pageItemNumber = 10; @@ -41,6 +62,7 @@ class AllRequestsProvider extends ChangeNotifier { } void resetRequestsApiData() { + print('reset api data called..'); highPriorityRequests = null; overdueRequests = null; openRequests = null; @@ -51,13 +73,13 @@ class AllRequestsProvider extends ChangeNotifier { stateCode = null; } - void getRequests() { + Future getRequests() async { resetRequestsApiData(); - getHighPriorityRequests(pagination: true); - getOverdueRequests(pagination: true); - getOpenRequests(pagination: true); - getInProgressRequests(pagination: true); - getCompletedRequests(pagination: true); + await getHighPriorityRequests(pagination: true); + await getOverdueRequests(pagination: true); + await getOpenRequests(pagination: true); + await getInProgressRequests(pagination: true); + await getCompletedRequests(pagination: true); } SearchAllRequestsModel searchedModel; @@ -70,11 +92,7 @@ class AllRequestsProvider extends ChangeNotifier { try { if (search != null) { searchedModel = search; - } - - - - else { + } else { searchedModel = null; } final type = typeTransaction == null @@ -318,6 +336,7 @@ class AllRequestsProvider extends ChangeNotifier { } Future getInProgressRequests({bool pagination = false, bool reset = false}) async { + print('get inprogress request called..'); if (isInProgressLoading == true) return -2; if (reset) { inProgressRequests = null; @@ -343,13 +362,19 @@ class AllRequestsProvider extends ChangeNotifier { body["pageSize"] = pageItemNumber; } response = await ApiManager.instance.post(URLs.getAllRequestsAndCount, body: body); - + print('response body of inprogress is ${response.body}'); stateCode = response.statusCode; + print('state code is $stateCode'); if (response.statusCode >= 200 && response.statusCode < 300) { if (inProgressRequests == null) { + print('in in null check...'); inProgressRequests = AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0]); + notifyListeners(); + print('data in null check is ${inProgressRequests.requestsDetails.length}'); } else { inProgressRequests.requestsDetails.addAll(AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0]).requestsDetails); + print('data i have in provider is ${inProgressRequests.requestsDetails.length}'); + notifyListeners(); } if (inProgressRequests.requestsDetails.length >= pageItemNumber) { nextPage = true; @@ -370,6 +395,60 @@ class AllRequestsProvider extends ChangeNotifier { return -1; } } + Future getFilterRequests({bool pagination = false, int status}) async { + // if (filterRequest == null || pagination) { + // isFilterRequestLoading = true; + // notifyListeners(); + // } + isFilterRequestLoading = true; + Response response; + try { + Map body = { + "typeTransaction": [1, 2, 3, 4], + "statusTransaction": [status], + "priority": [], + "displayData": [] + }; + if (pagination) { + body["pageNumber"] = 0; + body["pageSize"] = 0; + } else { + body["pageNumber"] = pageNum++; + body["pageSize"] = pageItemNumber; + } + response = await ApiManager.instance.post(URLs.getAllRequestsAndCount, body: body); + print('response body is ${response.body}'); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + if (filterRequest == null) { + filterRequest = AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0]); + isFilterRequestLoading = false; + notifyListeners(); + print('filter list data in provider is ${filterRequest.requestsDetails.length}'); + } else { + filterRequest.requestsDetails.addAll(AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0]).requestsDetails); + isFilterRequestLoading = false; + notifyListeners(); + } + if (filterRequest.requestsDetails.length >= pageItemNumber) { + nextPage = true; + } else { + nextPage = false; + } + notifyListeners(); + } else { + filterRequest = null; + } + isFilterRequestLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isFilterRequestLoading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } Future getCompletedRequests({bool pagination = false, bool reset = false}) async { if (isCompleteLoading == true) return -2; @@ -405,6 +484,7 @@ class AllRequestsProvider extends ChangeNotifier { } else { completedRequests.requestsDetails.addAll(AllRequestsAndCount.fromJson(json.decode(response.body)["data"][0]).requestsDetails); } + print('completed request length is ${completedRequests.requestsDetails.length}'); if (completedRequests.requestsDetails.length >= pageItemNumber) { nextPage = true; } else { @@ -425,6 +505,41 @@ class AllRequestsProvider extends ChangeNotifier { } } + + AllRequestsAndCount get inProgressRequests => _inProgressRequests; + + set inProgressRequests(AllRequestsAndCount value) { + _inProgressRequests = value; + notifyListeners(); + } + + AllRequestsAndCount get completedRequests => _completedRequests; + + set completedRequests(AllRequestsAndCount value) { + _completedRequests = value; + notifyListeners(); + } + + AllRequestsAndCount get openRequests => _openRequests; + + set openRequests(AllRequestsAndCount value) { + _openRequests = value; + notifyListeners(); + } + + AllRequestsAndCount get filterRequest => _filterRequest; + + set filterRequest(AllRequestsAndCount value) { + _filterRequest = value; + notifyListeners(); + } + bool get isFilterRequestLoading => _isFilterRequestLoading; + + set isFilterRequestLoading(bool value) { + _isFilterRequestLoading = value; + notifyListeners(); + } + // Future getCloseRequests() async { // if (isCloseLoading == true) return -2; // isCloseLoading = true; diff --git a/lib/controllers/providers/api/notifications_provider.dart b/lib/controllers/providers/api/notifications_provider.dart index 4cbd1a7e..75fec696 100644 --- a/lib/controllers/providers/api/notifications_provider.dart +++ b/lib/controllers/providers/api/notifications_provider.dart @@ -53,6 +53,7 @@ class NotificationsProvider extends ChangeNotifier { response = await ApiManager.instance.post(URLs.getSystemNotifications, body: body); stateCode = response.statusCode; + print('notifaction response is ${response}'); if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received // List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 1d9cd6c1..e3890ddc 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -16,6 +16,7 @@ import 'package:test_sa/models/service_request/pending_service_request_model.dar import 'package:test_sa/models/service_request/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/service_request/service_request_search.dart'; +import 'package:test_sa/models/service_request/spare_parts.dart'; import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart'; import 'package:test_sa/models/service_request/supplier_engineer_model.dart'; import 'package:test_sa/models/timer_model.dart'; @@ -41,13 +42,46 @@ class ServiceRequestsProvider extends ChangeNotifier { // like 400 customer request failed // 500 service not available int stateCode; + bool _isDetialLoading=false; - // true if there is next page in product list and false if not + bool get isDetialLoading => _isDetialLoading; + + set isDetialLoading(bool value) { + _isDetialLoading = value; + notifyListeners(); + } // true if there is next page in product list and false if not bool nextPage = true; + TimeOfDay _selectedTime ; + + TimeOfDay get selectedTime => _selectedTime; - // list of user requests + set selectedTime(TimeOfDay value) { + _selectedTime = value; + notifyListeners(); + } // list of user requests List serviceRequests; List workOrders = []; + List _sparePartList = []; + + + + SparePartsWorkOrders _initialSelectedSparePart = SparePartsWorkOrders(); + ServiceRequest _currentSelectedRequest; + int _selectedListIndex = 0; + + int get selectedListIndex => _selectedListIndex; + + set selectedListIndex(int value) { + _selectedListIndex = value; + notifyListeners(); + } + + ServiceRequest get currentSelectedRequest => _currentSelectedRequest; + + set currentSelectedRequest(ServiceRequest value) { + _currentSelectedRequest = value; + notifyListeners(); + } // when requests in-process _loading = true // done _loading = true @@ -591,13 +625,17 @@ class ServiceRequestsProvider extends ChangeNotifier { Future getServiceRequestObjectById({@required String requestId}) async { try { + isDetialLoading = true; Response response = await ApiManager.instance.get(URLs.getServiceRequestById + "?callRequestId=$requestId"); if (response.statusCode >= 200 && response.statusCode < 300) { + isDetialLoading=false; return ServiceRequest.fromJson(json.decode(response.body)["data"]); } else { + isDetialLoading=false; return null; } } catch (error) { + isDetialLoading=false; return null; } } @@ -693,4 +731,17 @@ class ServiceRequestsProvider extends ChangeNotifier { return res; } } + + SparePartsWorkOrders get initialSelectedSparePart => _initialSelectedSparePart; + + set initialSelectedSparePart(SparePartsWorkOrders value) { + _initialSelectedSparePart = value; + notifyListeners(); + } + List get sparePartList => _sparePartList; + + set sparePartList(List value) { + _sparePartList = value; + notifyListeners(); + } } diff --git a/lib/dashboard_latest/dashboard_view.dart b/lib/dashboard_latest/dashboard_view.dart new file mode 100644 index 00000000..b5bf1cf6 --- /dev/null +++ b/lib/dashboard_latest/dashboard_view.dart @@ -0,0 +1,139 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; +import 'package:test_sa/controllers/notification/notification_manger.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/notifications_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/dashboard_latest/widgets/app_bar_widget.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/user.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart'; +import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart'; +import 'package:test_sa/utilities/request_utils.dart'; + +import '../new_views/pages/land_page/dashboard_fragments/request_category_fragment.dart'; + +class DashboardView extends StatefulWidget { + final VoidCallback onDrawerPress; + + const DashboardView({Key key, this.onDrawerPress}) : super(key: key); + + @override + State createState() => _DashboardViewState(); +} + +class _DashboardViewState extends State { + int _currentPage = 0; + bool isFCM = true; + User user; + + SettingProvider settingProvider; + UserProvider userProvider; + + AllRequestsProvider allRequestsProvider; + + NotificationsProvider notificationsProvider; + + @override + void initState() { + super.initState(); + getInitialData(); + } + + void getInitialData() { + scheduleMicrotask(() async { + userProvider = Provider.of(context, listen: false); + settingProvider = Provider.of(context, listen: false); + allRequestsProvider = Provider.of(context, listen: false); + user = userProvider.user; + await getAllRequests(); + + if (isFCM) { + FirebaseNotificationManger.initialized(context); + NotificationManger.initialisation((notificationDetails) { + FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload)); + }, (id, title, body, payload) async {}); + + isFCM = false; + } + }); + } + + Future getAllRequests() async { + allRequestsProvider.isAllLoading = true; + allRequestsProvider.isFilterRequestLoading = true; + allRequestsProvider.currentListIndex = 0; + allRequestsProvider.filterRequest = null; + var tabs = RequestUtils.getTabs(userType: userProvider.user.type, context: context); + Future.wait([ + allRequestsProvider.getRequests(), + allRequestsProvider.getFilterRequests(pagination: false, status: tabs[0]['status']), + ]).whenComplete(() { + allRequestsProvider.isAllLoading = false; + }); + + print('user provider user data is ${userProvider.user.type}'); + await notificationsProvider.getSystemNotifications(user: userProvider.user, resetProvider: true); + } + + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + // backgroundColor: AppColor.background(context), + appBar: PreferredSize( + preferredSize: const Size.fromHeight(kToolbarHeight), + child: AppBarWidget( + onDrawerPress: widget.onDrawerPress, + )), + body: RefreshIndicator( + onRefresh: () async { + await getInitialData(); + return Future.delayed(const Duration(milliseconds: 250)); + }, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.welcome, + style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + user == null ? "" : (user?.username ?? ""), + style: AppTextStyles.heading2.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, fontWeight: FontWeight.w600), + ), + // 24.height, + + ProgressFragment(), + 35.height, + SizedBox(height: 105.toScreenHeight, child: const RequestsFragment()), + const RequestCategoryFragment() + ], + ).paddingOnly(start: 16, end: 16, top: 0, bottom: 8), + ], + ), + ), + ), + ); + } +} diff --git a/lib/dashboard_latest/widgets/app_bar_widget.dart b/lib/dashboard_latest/widgets/app_bar_widget.dart new file mode 100644 index 00000000..451436d7 --- /dev/null +++ b/lib/dashboard_latest/widgets/app_bar_widget.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/notifications_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/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; + +import '../../controllers/providers/api/user_provider.dart'; +import '../../models/user.dart'; + +class AppBarWidget extends StatelessWidget { + final VoidCallback onDrawerPress; + const AppBarWidget({Key key, this.onDrawerPress}) : super(key: key); + + @override + Widget build(BuildContext context) { + return AppBar( + automaticallyImplyLeading: false, + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + titleSpacing: 0, + title: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Consumer(builder: (context, snapshot, _) { + return CircleAvatar( + radius: 24, + backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.neutral40, + child: Padding( + padding: const EdgeInsets.all(1), // Border radius + child: ClipOval( + child: snapshot.profileImage != null + ? Image.file(snapshot.profileImage) + : (snapshot.user.profilePhotoName?.isNotEmpty ?? false) + ? Image.network(snapshot.user.profilePhotoName) + : const Icon(Icons.person, size: 24, color: Colors.white), + ), + ), + ); + }).onPress(onDrawerPress), + const Spacer(), + Consumer( + builder: (context, settingProvider,child) { + return Container( + padding: const EdgeInsets.fromLTRB(12, 6, 6, 6), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: AppColor.background(context), + boxShadow: const [ + BoxShadow( + color: Color(0x07000000), + blurRadius: 14, + offset: Offset(0, 0), + spreadRadius: 0, + ) + ], + ), + child: DropdownButton( + value: settingProvider.assetGroup, + //iconSize: 24, + isDense: true, + icon: const Icon(Icons.keyboard_arrow_down), + elevation: 8, + // dropdownColor: Colors.amber, + borderRadius: BorderRadius.circular(8), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: (newValue) { + if (settingProvider.assetGroup != newValue) { + settingProvider.setAssetGroup(newValue); + WidgetsBinding.instance.addPostFrameCallback((_) { + Provider.of(context, listen: false).getRequests(); + Provider.of(context, listen: false).getSystemNotifications(user: Provider.of(context, listen: false).user, resetProvider: true); + }); + } + }, + items: Provider.of(context, listen: false).user.assetGroups.map>((value) { + return DropdownMenuItem( + value: value, + child: Text( + value?.name ?? "", + style: Theme.of(context).textTheme.bodyLarge, + ), + ); + })?.toList(), + ), + ); + } + ), + 16.width, + Stack( + alignment: Alignment.topRight, + children: [ + Icon(Icons.notifications, color: context.isDark ? AppColor.neutral30 : AppColor.neutral20, size: 30).paddingOnly(top: 6, end: 0), + // todo @sikander will add count for unread notifications + // Positioned( + // top: 0, + // right: 0, + // child: Container( + // padding: const EdgeInsets.all(4), + // decoration: const ShapeDecoration( + // color: Color(0xFFD02127), + // shape: CircleBorder(), + // ), + // child: Text("", style: AppTextStyles.bodyText), + // ), + // ) + ], + ).onPress(() { + Navigator.of(context).pushNamed(NotificationsPage.id); + }), + ], + ).paddingOnly(start: 16, end: 16), + ); + } +} diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index d33cee7d..325bded8 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -16,6 +16,7 @@ extension TextStyles on String { Text heading4(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading4, context.isDark ? AppColor.neutral30 : AppColor.neutral50); Text heading5(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading5, context.isDark ? AppColor.neutral30 : AppColor.neutral50); + Text customHeadingText(BuildContext context) => getTextWithStyle(this, AppTextStyles.customHeadingText, context.isDark ? AppColor.neutral30 : AppColor.neutral50); Text heading6(BuildContext context) => getTextWithStyle(this, AppTextStyles.heading6, context.isDark ? AppColor.neutral30 : AppColor.neutral50); @@ -31,12 +32,15 @@ extension TextStyles on String { } extension CustomText on Text { - Text custom({Color color, FontWeight fontWeight, TextAlign align}) { + Text custom({Color color, FontWeight fontWeight, TextAlign align,double fontSize,double lineHeight,double letterSpacing}) { return Text( data, textAlign: align, style: style.copyWith( color: color, + height: lineHeight, + letterSpacing: letterSpacing, + fontSize: fontSize, fontWeight: fontWeight, ), ); @@ -81,6 +85,14 @@ abstract class AppTextStyles { fontStyle: FontStyle.normal, decoration: TextDecoration.none, ); + static const TextStyle customHeadingText = TextStyle( + fontFamily: 'Poppins', + fontSize: 27, // Font size in logical pixels + fontWeight: FontWeight.w500, // Equivalent to font-weight: 500 + height: 31 / 27, // Line height (in Flutter, it's a multiplier of font size) + letterSpacing: -0.04 * 27, // Letter spacing, converted to logical pixels + color: Colors.black, // Set your desired text color + ); static final TextStyle heading6 = TextStyle( fontSize: 16.toScreenWidth, diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index a2b9761c..75b08f86 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -53,6 +53,7 @@ extension WidgetExtensions on Widget { Widget toShadowContainer(BuildContext context, {bool showShadow = true, double padding = 16}) => showShadow ? Container( padding: EdgeInsets.all(padding), + width: double.infinity, decoration: ShapeDecoration( color: AppColor.background(context), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), @@ -61,6 +62,18 @@ extension WidgetExtensions on Widget { child: this, ) : this; + + Widget toShadowCircleContainer(BuildContext context, {bool showShadow = true, double padding = 16}) => showShadow + ? Container( + padding: EdgeInsets.all(padding), + decoration: BoxDecoration( + color: AppColor.background(context), + shape: BoxShape.circle, + boxShadow: [boxShadowR14], + ), + child: this, + ) + : this; } extension DividerExtension on Divider { diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 33f48a18..673ff6ad 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -15,11 +15,17 @@ "name": "الاسم", "email": "البريد الالكتروني", "phoneNumber": "رقم الهاتف", + "Sign in to your": "تسجيل الدخول إلى حسابك", + "account": "الحساب", "password": "كلمة المرور", "confirmPassword": "تاكيد كلمة المرور", "signIn": "تسجيل الدخول", + "letSignInToAccount": "لنقم بتسجيل الدخول إلى حسابك", "signUp": "انشاء حساب", + "sparePartDetails": "تفاصيل قطع الغيار", + "attachQuotation": "إرفاق العرض", "forgetPassword": "نسيت كلمة المرور", + "addSparePartActivity": "إضافة نشاط قطع الغيار", "acceptTermsAndConditions": "موافقة علي الشروط والاحكام", "emailValidateMessage": "البريد الالكتروني غير صحيح", "nameValidateMessage": "الاسم مطلوب", @@ -172,7 +178,24 @@ "number": "رقم", "operatingHours": "ساعات العمل", "partName": "اسم القطعة", + "startTime": "وقت البدء", + "endTime": "وقت الانتهاء", + "pickTime" : "اختر الوقت", + "readCompleteThread" : "اقرأ الموضوع بالكامل", + "askOtpFromRequester": "طلب رمز التحقق من مقدم الطلب", + "verify": "تحقق", + "resend": "إعادة الإرسال", + "resendIn": "إعادة الإرسال خلال", + "checkOutOtherMethods": "اطلع على طرق أخرى.", + "otpSentToNumber": "تم إرسال رمز التحقق إلى الرقم", + "havingTroubleReceivingOtp": "تواجه صعوبة في استلام رمز التحقق؟", "quantity": "كمية", + "oracleNo": "رقم أوراكل", + "no": "لا", + "yes": "نعم", + "fixed": "تم الإصلاح", + "fillDetails": "يرجى ملء التفاصيل أدناه", + "addSparePartActionHeading": "هل تريد إنشاء طلب قطع غيار آخر؟", "reasons": "الاسباب", "reason": "السبب", "reportStatus": "حالة التقرير", @@ -189,7 +212,30 @@ "assignedEmployee": "الموظف المعين", "assetSN": "رقم تسلسلي للاصل ", "assetName": "اسم الاصل", + "accept": "قبول", + "reject": "رفض", + "skipForLater": "تخطي لاحقًا", + "rejectionReason": "سبب الرفض", + "setVisitDate": "تحديد تاريخ الزيارة", + "verifyArrival": "التحقق من الوصول", + "scanQr": "مسح رمز QR", + "scanQrDetail": "قم بمسح رمز QR الخاص بالجهاز أو التقط صورة للجهاز من الموقع", + "askRequester": "اطلب من مقدم الطلب التحقق", + "askRequesterDetail": "اطلب من مقدم الطلب التحقق من وصولك من خلال تطبيق Atoms.", + "askOtp": "اطلب رمز OTP من مقدم الطلب", + "askOtpDetail": "اطلب رمز OTP من مقدم الطلب للتحقق من وصولك", + "takeDevicePhoto": "التقط صورة للجهاز", + "takeDevicePhotoDetail": "قم بمسح رمز QR الخاص بالجهاز أو التقط صورة للجهاز من الموقع", "assetNumber": "رقم الاصل", + "assetDetail": "تفاصيل الأصل", + "requestDetail": "تفاصيل الطلب", + "activities": "الأنشطة", + "selectActivityType": "اختر نوع النشاط", + "sparePartRequest": "طلب قطع غيار", + "sparePartRequestDetail": "اطلب من مقدم الطلب التحقق من وصولك من خلال تطبيق Atoms.", + "maintenanceRequest": "طلب صيانة", + "assetToBeRetired": "الأصل الذي سيتم إخراجه من الخدمة", + "createNewActivity": "إنشاء نشاط جديد", "site": "الموقع", "maintenanceSituation": "موقع الصيانه", "currentSituation": "الموقع الحالي", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2c157481..882498e7 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -17,8 +17,12 @@ "phoneNumber": "Phone Number", "password": "Password", "confirmPassword": "Confirm Password", + "skipForLater": "Skip For Later", "signIn": "Sign In", + "letSignInToAccount": "Let’s sign in to your account", "signUp": "Sign Up", + "accept": "Accept", + "reject": "Reject", "forgetPassword": "Forget Password", "acceptTermsAndConditions": "Accept Terms And Conditions", "emailValidateMessage": "Not valid email", @@ -71,6 +75,9 @@ "details": "Details", "device": "Asset", "deviceArName": "Asset Ar Name", + "sparePartDetails": "Spare Part Details", + "attachQuotation": "Attach Quotation", + "addSparePartActivity": "Add Spare Part Activity", "deviceName": "Asset Name", "deviceImages": "Asset Images", "deviceModel": "Asset Model", @@ -109,6 +116,7 @@ "pickHospital": "Pick Site", "pickUnite": "Pick Unit", "policy": "Policy", + "fixed": "Fixed", "reason1": "The engineer didn't confirm visit date with 2 hours from the request time", "reason2": "The engineer change the visit date without coordination with me", "reason3": "the engineer didn't attend on date/time", @@ -175,7 +183,9 @@ "operatingHours": "Operating Hours", "partName": "Part Name", "quantity": "Quantity", + "oracleNo": "Oracle No.", "reasons": "Reasons", + "addSparePartActionHeading": "Do you want to create another spare part request?", "reason": "Reason", "reportStatus": "Report Status", "reportType": "Report Type", @@ -188,6 +198,8 @@ "assetSN": "Asset S.N", "assetName": "Asset Name", "assetNumber": "Asset Number", + "assetDetail": "Asset Detail", + "requestDetail": "Request Details", "site": "Site", "maintenanceSituation": "Maintenance Situation", "currentSituation": "Current Situation", @@ -200,6 +212,11 @@ "repairLocation": "Repair Location", "travelingExpense": "Traveling Expense", "startDate": "Start Date", + "startTime": "Start Time", + "endTime": "End Time", + "no": "No", + "fillDetails": "Please fill the below details", + "yes": "Yes", "requestedQuantity": "Requested Quantity", "deliveredQuantity": "Delivered Quantity", "endDate": "End Date", @@ -215,6 +232,8 @@ "pickFile" : "Pick File", "login" : "Login", "enterCredsToLogin" : "Enter your credential to login", + "signInToYour" : "Sign in to your", + "account" : "account", "forgotPassword" : "Forgot Password?", "password" : "Password", "username" : "Username", @@ -262,11 +281,22 @@ "filter" : "Filter", "pickAsset" : "Pick Asset", "firstAction" : "First Action", + "rejectionReason" : "Rejection Reason", "workOrder" : "Work Order", "workOrders" : "Work Orders", "viewWorkOrder" : "View All Work Order", "createWorkOrder" : "Create Work Order", "serviceDetails": "Service Details", + "setVisitDate": "Set Date Of Visit", + "verifyArrival": "Verify Arrival", + "scanQr": "Scan QR", + "scanQrDetail": "Scan QR Code of the device or take the photo of the device from location", + "askRequester": "Ask Requester to Verify", + "askRequesterDetail": "Ask requester to verify your arrival through Atoms Application.", + "askOtp": "Ask OTP From Requester", + "askOtpDetail": "Ask OTP from requester to verify you arrival", + "takeDevicePhoto": "Take Device Photo", + "takeDevicePhotoDetail": "Scan QR Code of the device or take the photo of the device from location", "priority" : "Request Priority", "equipmentStatus" : "Equipment Status", "jopStatus" : "Jop Status", @@ -305,6 +335,15 @@ "applyFilter" : "Apply Filter", "pmDateRange" : "PM Date Range", "pickDate" : "Pick Date", + "verify" : "Verify", + "resend": "Resend", + "resendIn": "Resend In", + "havingTroubleReceivingOtp": "Having trouble receiving OTP?", + "askOtpFromRequester" : "Ask OTP From Requester", + "checkOutOtherMethods": "Check out other methods.", + "otpSentToNumber": "An OTP sent to the number", + "pickTime" : "Pick Time", + "readCompleteThread" : "Read Complete thread", "pickADate" : "Pick a date", "firstActionStatus" : "First Action Status", "loanAvailability" : "Loan Availability", @@ -382,6 +421,13 @@ "solution" : "Solution", "technicalComment" : "Technical Comment", "recentActivities" : "Recent Activities", + "activities" : "Activities", + "createNewActivity" : "Create New Activity", + "selectActivityType" : "Select Activity Type", + "sparePartRequest" : "Spare Part Request", + "sparePartRequestDetail" : "Ask requester to verify your arrival through Atoms Application.", + "maintenanceRequest" : "Maintenance Request", + "assetToBeRetired" : "Asset to be retired", "problemDesc" : "Problem Description", "source": "Source", "costCodeName" : "Cost Code Name", diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index b5aaf79c..f8968378 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -5,11 +5,13 @@ class AppColor { AppColor._(); //primary + static const Color primary10 = Color(0xff3DA5E5); static const Color primary30 = Color(0xffA2E2F8); static const Color primary40 = Color(0xff75BDE0); static const Color primary50 = Color(0xff4A8DB7); static const Color primary60 = Color(0xff3B7097); static const Color primary70 = Color(0xff163A51); + static const Color primary80 = Color(0xff161D27); //texts static const Color neutral10 = Color(0xffBCBCBC); @@ -19,13 +21,24 @@ class AppColor { static const Color neutral50 = Color(0xff3B3D4A); static const Color neutral60 = Color(0xff2C2C31); static const Color neutral70 = Color(0xff111427); + static const Color neutral80 = Color(0xffF3F3F3); + static const Color neutral90 = Color(0xffF7F9FB); + static const Color neutral100 = Color(0xffF4F6FC); //background - static const Color backgroundLight = Color(0xffF7F9FB); + static const Color backgroundLight = Color(0xfff7f9fb); static const Color backgroundDark = Color(0xff111427); + //white + static const Color white20 = Color(0xffF7F9FB); + static const Color white30 = Color(0xffE7EBF2); + +//black + static const Color balck10 = Color(0xff3B3D4A); + //red static const Color red40 = Color(0xffFFDBDC); + static const Color red50 = Color(0xffD02127); static const Color red60 = Color(0xff8C050A); @@ -33,19 +46,23 @@ class AppColor { static const Color green40 = Color(0xffBAFFE1); static const Color green50 = Color(0xff62BE96); static const Color green60 = Color(0xff065E38); + static const Color green70 = Color(0xff54C166); //orange static const Color orange40 = Color(0xffFFEDBC); static const Color orange50 = Color(0xffCC9B14); static const Color orange60 = Color(0xff886400); - static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff1FA269) : green50; + // static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff1FA269) : green50; + static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff54C166) : green50; + // static Color blueStatus(BuildContext context) => context.isDark ? primary40 : primary50; static Color blueStatus(BuildContext context) => context.isDark ? primary40 : primary50; static Color redStatus(BuildContext context) => context.isDark ? const Color(0xffFFB6B8) : red40; - static Color yellowStatus(BuildContext context) => context.isDark ? const Color(0xffFFDA76) : orange40; + // static Color yellowStatus(BuildContext context) => context.isDark ? const Color(0xffFFDA76) : orange40; + static Color yellowStatus(BuildContext context) => context.isDark ? const Color(0xffFFC945) : orange40; static Color background(BuildContext context) => context.isDark ? neutral60 : Colors.white; diff --git a/lib/new_views/common_widgets/app_dashed_button.dart b/lib/new_views/common_widgets/app_dashed_button.dart index 6fc2c61e..7d2a0b02 100644 --- a/lib/new_views/common_widgets/app_dashed_button.dart +++ b/lib/new_views/common_widgets/app_dashed_button.dart @@ -22,11 +22,11 @@ class AppDashedButton extends StatelessWidget { child: DottedBorder( strokeWidth: 2, padding: EdgeInsets.symmetric(vertical: 16.toScreenHeight, horizontal: 16.toScreenWidth), - color: context.isDark ? AppColor.primary40 : AppColor.primary60, + color: context.isDark ? AppColor.primary40 : AppColor.primary10, 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, + child: title.heading6(context).custom(color: context.isDark ? AppColor.primary40 : AppColor.primary10).center, ), ).onPress(onPressed); } diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index 3fe19929..700eb011 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -15,6 +15,7 @@ class AppTextFormField extends StatefulWidget { final TextInputType textInputType; final String initialValue; final TextStyle style; + final TextStyle labelStyle; final bool enable; final TextAlign textAlign; final FocusNode node; @@ -28,6 +29,7 @@ class AppTextFormField extends StatefulWidget { final Color backgroundColor; final bool alignLabelWithHint; final bool showShadow; + final EdgeInsets contentPadding; final bool showWithoutDecoration; final void Function() onTap; @@ -37,6 +39,7 @@ class AppTextFormField extends StatefulWidget { this.validator, this.node, this.onChange, + this.labelStyle, this.obscureText, this.showPassword, this.hintText, @@ -45,6 +48,7 @@ class AppTextFormField extends StatefulWidget { this.initialValue, this.enable = true, this.style, + this.contentPadding, this.textAlign, this.suffixIcon, this.prefixIcon, @@ -98,7 +102,7 @@ class _AppTextFormFieldState extends State { focusedBorder: border, enabledBorder: border, errorBorder: border, - contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth), + contentPadding:widget.contentPadding?? EdgeInsets.symmetric(vertical: 12.toScreenHeight, horizontal: 16.toScreenWidth), constraints: const BoxConstraints(), suffixIconConstraints: const BoxConstraints(minWidth: 0), filled: true, @@ -112,6 +116,7 @@ class _AppTextFormFieldState extends State { floatingLabelStyle: AppTextStyle.body1?.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20), hintText: widget.hintText ?? "", labelText: widget.labelText ?? "", + labelStyle: widget.labelStyle, prefixIcon: widget.prefixIcon ?? (widget.prefixIconData == null ? null diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart index e34be09d..d846fedc 100644 --- a/lib/new_views/common_widgets/default_app_bar.dart +++ b/lib/new_views/common_widgets/default_app_bar.dart @@ -22,9 +22,10 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { const Icon(Icons.arrow_back_ios).onPress(() { Navigator.of(context).pop(); }), + 10.width, Text( title ?? "", - style: AppTextStyles.heading3?.copyWith(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + style: AppTextStyles.heading3?.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ).expanded, ], ), 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 4043a76b..d037fd06 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 @@ -19,6 +19,8 @@ class SingleItemDropDownMenu final bool showAsBottomSheet; final List staticData; final String title; + final double height; + final bool showShadow ; final Color backgroundColor; final bool loading; @@ -31,8 +33,10 @@ class SingleItemDropDownMenu this.onSelect, this.initialValue, this.enabled = true, + this.height, this.showAsBottomSheet = false, this.staticData, + this.showShadow=true, this.backgroundColor, this.loading, }) : super(key: key); @@ -116,7 +120,7 @@ class _SingleItemDropDownMenuState 0 && isSelected && !loading + ? badges.Badge( + badgeContent: Text( + count.toString(), + style: const TextStyle( + color: AppColor.white20, + fontWeight: FontWeight.normal, + ), + ), + badgeStyle: const badges.BadgeStyle(padding: EdgeInsets.symmetric(horizontal: 5, vertical: 3), badgeColor: AppColor.red50), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + color: isSelected ? AppColor.primary10 : AppColor.white30, + border: !isSelected ? Border.all(color: Colors.white54, width: 1) : null, + ), + child: Center( + child: Text( + label, + style: AppTextStyles.bodyText.copyWith( + color: isSelected ? Colors.white : Colors.black, + ), + )), + ).toShimmer(isShow: loading, radius: 7), + ) + : Container( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + color: isSelected ? AppColor.primary10 : AppColor.white30, + border: !isSelected ? Border.all(color: AppColor.white30, width: 1) : null, + ), + child: Center( + child: Text( + label, + style: AppTextStyles.bodyText.copyWith( + color: isSelected ? Colors.white : Colors.black, + ), + )), + ).toShimmer(isShow: loading, radius: 7), + ); + } +} + +class TabButtonData { + final String label; + final bool isSelected; + final int totalCount; + final VoidCallback onPressed; + + TabButtonData({ + @required this.label, + @required this.isSelected, + @required this.totalCount, + @required this.onPressed, + }); +} diff --git a/lib/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart b/lib/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart index 5d3afe75..3015288c 100644 --- a/lib/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart +++ b/lib/new_views/pages/land_page/dashboard_fragments/progress_fragment.dart @@ -1,14 +1,163 @@ +// import 'package:flutter/material.dart'; +// // import 'package:test_sa/pie_chart/pie_chart.dart'; +// import 'package:provider/provider.dart'; +// import 'package:syncfusion_flutter_charts/charts.dart'; +// import 'package:test_sa/controllers/providers/api/all_requests_provider.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/new_views/app_style/app_color.dart'; +// import 'package:test_sa/new_views/pages/land_page/widgets/request_item_view_list.dart'; +// +// import '../../../../controllers/providers/api/user_provider.dart'; +// import '../../../../models/enums/user_types.dart'; +// +// class ProgressFragment extends StatelessWidget { +// ProgressFragment({Key key}) : super(key: key); +// +// UserProvider _userProvider; +// +// AllRequestsProvider _provider; +// +// @override +// Widget build(BuildContext context) { +// _userProvider = Provider.of(context); +// bool isCurrentUserNotEngineer = (_userProvider.user.type != UsersTypes.engineer); +// return Consumer( +// builder: (context, snapshot, _) { +// if (_provider == null) { +// _provider = snapshot; +// if (isCurrentUserNotEngineer) { +// _provider.getOpenRequests(reset: true); +// } +// _provider.getInProgressRequests(reset:true); +// _provider.getCompletedRequests(reset:true); +// } +// +// int total = (snapshot.completedRequests?.total?.count ?? 0) + (snapshot.inProgressRequests?.total?.count ?? 0) + (isCurrentUserNotEngineer ? (snapshot.openRequests?.total?.count ?? 0) : 0); +// +// final List chartData = [ +// ChartData('Completed', snapshot.completedRequests?.total?.count?.toDouble() ?? 0.0, AppColor.greenStatus(context)), +// ChartData('In Progress', snapshot.inProgressRequests?.total?.count?.toDouble() ?? 0.0, AppColor.yellowStatus(context)), +// ]; +// +// if (isCurrentUserNotEngineer) { +// chartData.insert(1, ChartData('Open', snapshot.openRequests?.total?.count?.toDouble() ?? 0.0, AppColor.blueStatus(context))); +// } +// +// return Column( +// children: [ +// AspectRatio( +// aspectRatio: 398 / 237, +// child: Stack( +// alignment: Alignment.center, +// children: [ +// SfCircularChart( +// tooltipBehavior: TooltipBehavior( +// enable: true, +// // elevation: 2, +// color: context.isDark ? Color(0xFF111427) : Color(0xffF7F9FB), +// textStyle: context.isDark ? null : TextStyle(color: Colors.black87, fontSize: 12), +// ), +// legend: Legend( +// //isVisible: true, +// ), +// series: [ +// DoughnutSeries( +// dataSource: chartData, +// radius: "110%", +// innerRadius: "60%", +// pointColorMapper: (ChartData data, _) => data.color, +// xValueMapper: (ChartData data, _) => data.x, +// yValueMapper: (ChartData data, _) => data.y, +// dataLabelMapper: (ChartData data, _) => data.x, +// dataLabelSettings: DataLabelSettings( +// isVisible: true, +// textStyle: TextStyle(color: context.isDark ? Colors.white : Colors.black87, fontSize: 12), +// labelPosition: ChartDataLabelPosition.outside, +// //useSeriesColor: true, +// ), +// ) +// ]).toShimmer(isShow: snapshot.isOpenLoading || snapshot.isInProgressLoading || snapshot.isCompleteLoading, radius: 300).paddingAll(12).toShadowContainer(context), +// Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// Text( +// context.translation.total, +// style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), +// ), +// Text( +// "$total", +// style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), +// ), +// ], +// ), +// ], +// ), +// ).paddingOnly(start: 16, end: 16, bottom: 16), +// DefaultTabController( +// length: isCurrentUserNotEngineer ? 3 : 2, +// child: Column( +// children: [ +// Container( +// margin: const EdgeInsets.only(left: 16, right: 16), +// decoration: BoxDecoration(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, borderRadius: BorderRadius.circular(16)), +// child: TabBar( +// //controller: _tabController, +// padding: EdgeInsets.zero, +// labelColor: context.isDark ? AppColor.neutral30 : AppColor.neutral60, +// unselectedLabelColor: context.isDark ? AppColor.neutral10 : AppColor.neutral20, +// unselectedLabelStyle: AppTextStyles.bodyText, +// labelStyle: AppTextStyles.bodyText, +// indicatorPadding: const EdgeInsets.all(4), +// indicator: BoxDecoration(color: context.isDark ? AppColor.neutral60 : Theme.of(context).cardColor, borderRadius: BorderRadius.circular(13)), +// onTap: (index) { +// // setState(() {}); +// }, +// tabs: [ +// if (isCurrentUserNotEngineer) Tab(text: context.translation.open, height: 57.toScreenHeight), +// Tab(text: context.translation.inProgress, height: 57.toScreenHeight), +// Tab(text: context.translation.completed, height: 57.toScreenHeight), +// ], +// ), +// ), +// 8.height, +// TabBarView( +// children: [ +// if (isCurrentUserNotEngineer) RequestItemViewList(snapshot.openRequests?.requestsDetails ?? [], snapshot.isOpenLoading), +// RequestItemViewList(snapshot.inProgressRequests?.requestsDetails ?? [], snapshot.isInProgressLoading), +// RequestItemViewList(snapshot.completedRequests?.requestsDetails ?? [], snapshot.isCompleteLoading), +// ], +// ).expanded, +// ], +// ), +// ).expanded, +// ], +// ); +// }, +// ); +// } +// } +// +// class ChartData { +// ChartData(this.x, this.y, this.color); +// +// final String x; +// final double y; +// final Color color; +// } +// +// + import 'package:flutter/material.dart'; -// import 'package:test_sa/pie_chart/pie_chart.dart'; import 'package:provider/provider.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.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/new_views/app_style/app_color.dart'; -import 'package:test_sa/new_views/pages/land_page/widgets/request_item_view_list.dart'; import '../../../../controllers/providers/api/user_provider.dart'; import '../../../../models/enums/user_types.dart'; @@ -26,19 +175,23 @@ class ProgressFragment extends StatelessWidget { bool isCurrentUserNotEngineer = (_userProvider.user.type != UsersTypes.engineer); return Consumer( builder: (context, snapshot, _) { - if (_provider == null) { - _provider = snapshot; - if (isCurrentUserNotEngineer) { - _provider.getOpenRequests(reset: true); - } - _provider.getInProgressRequests(reset:true); - _provider.getCompletedRequests(reset:true); - } + // WidgetsBinding.instance.addPostFrameCallback((_) { + // if (_provider == null) { + // _provider = snapshot; + // if (isCurrentUserNotEngineer) { + // _provider.getOpenRequests(reset: true); + // } + // _provider.getInProgressRequests(reset:true); + // _provider.getCompletedRequests(reset:true); + // } + // + // }); int total = (snapshot.completedRequests?.total?.count ?? 0) + (snapshot.inProgressRequests?.total?.count ?? 0) + (isCurrentUserNotEngineer ? (snapshot.openRequests?.total?.count ?? 0) : 0); final List chartData = [ ChartData('Completed', snapshot.completedRequests?.total?.count?.toDouble() ?? 0.0, AppColor.greenStatus(context)), + // snapshot.openRequests?.total?.count!=0? ChartData('Open', snapshot.openRequests?.total?.count?.toDouble() ?? 0.0, AppColor.blueStatus(context)), ChartData('In Progress', snapshot.inProgressRequests?.total?.count?.toDouble() ?? 0.0, AppColor.yellowStatus(context)), ]; @@ -57,12 +210,12 @@ class ProgressFragment extends StatelessWidget { tooltipBehavior: TooltipBehavior( enable: true, // elevation: 2, - color: context.isDark ? Color(0xFF111427) : Color(0xffF7F9FB), - textStyle: context.isDark ? null : TextStyle(color: Colors.black87, fontSize: 12), + color: context.isDark ? const Color(0xFF111427) : const Color(0xffF7F9FB), + textStyle: context.isDark ? null : const TextStyle(color: Colors.black87, fontSize: 12), ), legend: Legend( - //isVisible: true, - ), + //isVisible: true, + ), series: [ DoughnutSeries( dataSource: chartData, @@ -79,7 +232,7 @@ class ProgressFragment extends StatelessWidget { //useSeriesColor: true, ), ) - ]).toShimmer(isShow: snapshot.isOpenLoading || snapshot.isInProgressLoading || snapshot.isCompleteLoading, radius: 300).paddingAll(12).toShadowContainer(context), + ]).toShimmer(isShow: snapshot.isAllLoading, radius: 300).paddingAll(12).toShadowContainer(context), Column( mainAxisSize: MainAxisSize.min, children: [ @@ -95,44 +248,7 @@ class ProgressFragment extends StatelessWidget { ), ], ), - ).paddingOnly(start: 16, end: 16, bottom: 16), - DefaultTabController( - length: isCurrentUserNotEngineer ? 3 : 2, - child: Column( - children: [ - Container( - margin: const EdgeInsets.only(left: 16, right: 16), - decoration: BoxDecoration(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, borderRadius: BorderRadius.circular(16)), - child: TabBar( - //controller: _tabController, - padding: EdgeInsets.zero, - labelColor: context.isDark ? AppColor.neutral30 : AppColor.neutral60, - unselectedLabelColor: context.isDark ? AppColor.neutral10 : AppColor.neutral20, - unselectedLabelStyle: AppTextStyles.bodyText, - labelStyle: AppTextStyles.bodyText, - indicatorPadding: const EdgeInsets.all(4), - indicator: BoxDecoration(color: context.isDark ? AppColor.neutral60 : Theme.of(context).cardColor, borderRadius: BorderRadius.circular(13)), - onTap: (index) { - // setState(() {}); - }, - tabs: [ - if (isCurrentUserNotEngineer) Tab(text: context.translation.open, height: 57.toScreenHeight), - Tab(text: context.translation.inProgress, height: 57.toScreenHeight), - Tab(text: context.translation.completed, height: 57.toScreenHeight), - ], - ), - ), - 8.height, - TabBarView( - children: [ - if (isCurrentUserNotEngineer) RequestItemViewList(snapshot.openRequests?.requestsDetails ?? [], snapshot.isOpenLoading), - RequestItemViewList(snapshot.inProgressRequests?.requestsDetails ?? [], snapshot.isInProgressLoading), - RequestItemViewList(snapshot.completedRequests?.requestsDetails ?? [], snapshot.isCompleteLoading), - ], - ).expanded, - ], - ), - ).expanded, + ), ], ); }, @@ -147,3 +263,4 @@ class ChartData { final double y; final Color color; } + diff --git a/lib/new_views/pages/land_page/dashboard_fragments/recent_activites_fragment.dart b/lib/new_views/pages/land_page/dashboard_fragments/recent_activites_fragment.dart index 1f6f857c..addb46a7 100644 --- a/lib/new_views/pages/land_page/dashboard_fragments/recent_activites_fragment.dart +++ b/lib/new_views/pages/land_page/dashboard_fragments/recent_activites_fragment.dart @@ -1,3 +1,75 @@ +//Older code +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; +// import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +// import 'package:test_sa/controllers/providers/api/notifications_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/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/new_views/app_style/app_color.dart'; +// import 'package:test_sa/views/widgets/notifications/notification_item.dart'; +// +// class RecentActivitiesFragment extends StatelessWidget { +// RecentActivitiesFragment({Key key}) : super(key: key); +// +// //NotificationsProvider _notificationsProvider; +// +// @override +// Widget build(BuildContext context) { +// //_notificationsProvider ??= Provider.of(context, listen: false); +// return Consumer(builder: (context, _notificationsProvider, _) { +// return RefreshIndicator( +// onRefresh: () { +// Provider.of(context, listen: false).getRequests(); +// _notificationsProvider.getSystemNotifications(user: Provider.of(context, listen: false).user,resetProvider: true); +// return Future.delayed(const Duration(microseconds: 250)); +// }, +// child: SingleChildScrollView( +// padding: const EdgeInsets.all(16), +// child: Container( +// decoration: ShapeDecoration( +// color: AppColor.background(context), +// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), +// shadows: [boxShadowR14], +// ), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// context.translation.recentActivities +// .heading5(context) +// .toShimmer( +// isShow: _notificationsProvider.isLoading, +// ) +// .paddingOnly(top: 16, start: 16, end: 16), +// ListView.separated( +// shrinkWrap: true, +// physics: const NeverScrollableScrollPhysics(), +// padding: const EdgeInsets.all(16), +// itemCount: _notificationsProvider.notifications.length, +// separatorBuilder: (context, itemIndex) => const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), +// itemBuilder: (context, itemIndex) { +// // todo add priority & progress tag to show chip +// return NotificationItem( +// isLoading: _notificationsProvider.isLoading, +// notification: _notificationsProvider.notifications[itemIndex], +// onPressed: (notification) { +// FirebaseNotificationManger.handleMessage(context, notification.toNotificationJson()); +// }, +// ); +// }, +// ), +// ], +// ), +// ), +// ), +// ); +// }); +// } +// } + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; @@ -5,8 +77,10 @@ import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/notifications_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/text_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/app_style/app_color.dart'; import 'package:test_sa/views/widgets/notifications/notification_item.dart'; @@ -19,6 +93,8 @@ class RecentActivitiesFragment extends StatelessWidget { Widget build(BuildContext context) { //_notificationsProvider ??= Provider.of(context, listen: false); return Consumer(builder: (context, _notificationsProvider, _) { + UserProvider _userProvider = Provider.of(context); + bool isCurrentUserNotEngineer = (_userProvider.user.type != UsersTypes.engineer); return RefreshIndicator( onRefresh: () { Provider.of(context, listen: false).getRequests(); @@ -26,42 +102,37 @@ class RecentActivitiesFragment extends StatelessWidget { return Future.delayed(const Duration(microseconds: 250)); }, child: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Container( - decoration: ShapeDecoration( - color: AppColor.background(context), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), - shadows: [boxShadowR14], - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - context.translation.recentActivities - .heading5(context) - .toShimmer( - isShow: _notificationsProvider.isLoading, - ) - .paddingOnly(top: 16, start: 16, end: 16), - ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.all(16), - itemCount: _notificationsProvider.notifications.length, - separatorBuilder: (context, itemIndex) => const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), - itemBuilder: (context, itemIndex) { - // todo add priority & progress tag to show chip - return NotificationItem( + // padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: _notificationsProvider.notifications.length, + // separatorBuilder: (context, itemIndex) => const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), + itemBuilder: (context, itemIndex) { + // todo add priority & progress tag to show chip + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 12), + margin:const EdgeInsets.symmetric(vertical: 8), + decoration: ShapeDecoration( + color: AppColor.background(context), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + shadows: [boxShadowR14], + ), + child: NotificationItem( isLoading: _notificationsProvider.isLoading, notification: _notificationsProvider.notifications[itemIndex], onPressed: (notification) { FirebaseNotificationManger.handleMessage(context, notification.toNotificationJson()); }, - ); - }, - ), - ], - ), + ), + ); + }, + ), + ], ), ), ); diff --git a/lib/new_views/pages/land_page/dashboard_fragments/request_category_fragment.dart b/lib/new_views/pages/land_page/dashboard_fragments/request_category_fragment.dart new file mode 100644 index 00000000..16e35b66 --- /dev/null +++ b/lib/new_views/pages/land_page/dashboard_fragments/request_category_fragment.dart @@ -0,0 +1,265 @@ +//Older code +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; +// import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +// import 'package:test_sa/controllers/providers/api/notifications_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/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/new_views/app_style/app_color.dart'; +// import 'package:test_sa/views/widgets/notifications/notification_item.dart'; +// +// class RequestCategoryFragment extends StatelessWidget { +// RequestCategoryFragment({Key key}) : super(key: key); +// +// //NotificationsProvider _notificationsProvider; +// +// @override +// Widget build(BuildContext context) { +// //_notificationsProvider ??= Provider.of(context, listen: false); +// return Consumer(builder: (context, _notificationsProvider, _) { +// return RefreshIndicator( +// onRefresh: () { +// Provider.of(context, listen: false).getRequests(); +// _notificationsProvider.getSystemNotifications(user: Provider.of(context, listen: false).user,resetProvider: true); +// return Future.delayed(const Duration(microseconds: 250)); +// }, +// child: SingleChildScrollView( +// padding: const EdgeInsets.all(16), +// child: Container( +// decoration: ShapeDecoration( +// color: AppColor.background(context), +// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), +// shadows: [boxShadowR14], +// ), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// context.translation.recentActivities +// .heading5(context) +// .toShimmer( +// isShow: _notificationsProvider.isLoading, +// ) +// .paddingOnly(top: 16, start: 16, end: 16), +// ListView.separated( +// shrinkWrap: true, +// physics: const NeverScrollableScrollPhysics(), +// padding: const EdgeInsets.all(16), +// itemCount: _notificationsProvider.notifications.length, +// separatorBuilder: (context, itemIndex) => const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), +// itemBuilder: (context, itemIndex) { +// // todo add priority & progress tag to show chip +// return NotificationItem( +// isLoading: _notificationsProvider.isLoading, +// notification: _notificationsProvider.notifications[itemIndex], +// onPressed: (notification) { +// FirebaseNotificationManger.handleMessage(context, notification.toNotificationJson()); +// }, +// ); +// }, +// ), +// ], +// ), +// ), +// ), +// ); +// }); +// } +// } + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/notifications_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/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/all_requests_and_count_model.dart'; +import 'package:test_sa/models/enums/user_types.dart'; +import 'package:test_sa/models/user.dart'; +import 'package:test_sa/new_views/common_widgets/tab_button.dart'; +import 'package:test_sa/new_views/pages/land_page/dashboard_fragments/request_category_list.dart'; +import 'package:test_sa/utilities/request_utils.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + +class RequestCategoryFragment extends StatefulWidget { + // final AllRequestsAndCount allRequestsAndCount; + + // const RequestCategoryFragment({Key key, this.allRequestsAndCount}) : super(key: key); + const RequestCategoryFragment({ + Key key, + }) : super(key: key); + + @override + State createState() => _RequestCategoryFragmentState(); +} + +class _RequestCategoryFragmentState extends State { + @override + void initState() { + // TODO: implement initState + // getInitialList(); + print('init state called...'); + super.initState(); + } + + // Future getInitialList() async { + // UserProvider userProvider = Provider.of(context, listen: false); + // + // AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); + // UsersTypes usersType = userProvider.user.type; + // var tabs = RequestUtils.getTabs(userType: usersType, context: context); + // allRequestsProvider.currentListIndex = 0; + // allRequestsProvider.filterRequest = null; + // await allRequestsProvider.getFilterRequests(pagination: false, status: tabs[0]['status']); + // + // print('tabs lenght is ${tabs.length}'); + // } + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, allRequestProvider, child) { + return Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ + context.translation.allRequests.heading4(context).paddingOnly(top: 16, bottom: 16), + getTabs( + requestsProvider: allRequestProvider, + context: context, + userType: Provider.of(context, listen: false).user.type, + ), + // Row( + // children: _buildTabButtons(isEngineer: Provider.of(context, listen: false).user.type == UsersTypes.engineer, allRequestsProvider: allRequestProvider), + // ), + 10.height, + allRequestProvider.isFilterRequestLoading||allRequestProvider.filterRequest==null?Column( + mainAxisSize: MainAxisSize.max, + children: List.generate( 3 , (index) { + return Padding( + padding: EdgeInsets.symmetric(vertical: 10.toScreenHeight,horizontal: 0), + child: const SizedBox().toRequestShimmer(context, allRequestProvider.isFilterRequestLoading), + ); + })): RequestCategoryList(allRequestProvider.filterRequest.requestsDetails ?? [], allRequestProvider.isFilterRequestLoading), + // if (allRequestProvider.isLoadingList) ...[ + // const Center(child: CircularProgressIndicator()), + // ] else ...[ + // RequestCategoryList(allRequestProvider.dashBoardFilterList?.requestsDetails ?? [], allRequestProvider.dashBoardFilterListLoading), + // ] + ]); + }); + } + + Widget getTabs({@required BuildContext context, @required AllRequestsProvider requestsProvider, @required UsersTypes userType}) { + List tabs = []; + switch (userType) { + case UsersTypes.engineer: + tabs = RequestUtils.getTabs(userType: UsersTypes.engineer, context: context); + return Row( + children: tabs.map((item) { + return tabWidget( + label: item['label'], + status: item['status'], + selectedTab: tabs.indexOf(item), + requestsProvider: requestsProvider, + ); + }).toList(), + ); + case UsersTypes.normal_user: + tabs = RequestUtils.getTabs(userType: UsersTypes.normal_user, context: context); + return Row( + children: tabs.map((item) { + return tabWidget( + label: item['label'], + status: item['status'], + selectedTab: tabs.indexOf(item), + requestsProvider: requestsProvider, + ); + }).toList(), + ); + default: + return const SizedBox(); + } + } + + Widget tabWidget({@required int selectedTab, @required String label, @required int status, double width, @required AllRequestsProvider requestsProvider}) { + return Padding( + padding: const EdgeInsets.only(right: 12), + child: TabButton( + label: label, + loading: requestsProvider.isFilterRequestLoading, + isSelected: requestsProvider.currentListIndex == selectedTab, + count: requestsProvider.filterRequest != null ? requestsProvider.filterRequest.total.count : 0, + onPressed: () async { + requestsProvider.currentListIndex = selectedTab; + requestsProvider.filterRequest = null; + await requestsProvider.getFilterRequests(status: status); + requestsProvider.isInProgressLoading = false; + requestsProvider.pageNum = 1; + // requestsProvider.dashBoardFilterList = requestsProvider.openRequests.requestsDetails; + }, + )); + } +} + +//tabs code... +// +// List _getTabButtonData({@required bool isEngineer, @required AllRequestsProvider allRequestsProvider, @required int totalCount}) { +// List tabList = []; +// List> tabs = []; +// print('dashboard filter list data is ${allRequestsProvider.dashBoardFilterList}'); +// +// if (!isEngineer && allRequestsProvider.dashBoardFilterList != null && allRequestsProvider.dashBoardFilterList.isNotEmpty) { +// tabList.add(TabButtonData( +// label: 'New Request', +// isSelected: allRequestsProvider.currentListIndex == 0, +// totalCount: totalCount, +// onPressed: () { +// allRequestsProvider.currentListIndex = 0; +// allRequestsProvider.dashBoardFilterList = allRequestsProvider.openRequests.requestsDetails; +// }, +// )); +// } +// tabList.add(TabButtonData( +// label: 'In Progress', +// isSelected: allRequestsProvider.currentListIndex == (isEngineer ? 0 : 1), +// totalCount: totalCount, +// onPressed: () { +// allRequestsProvider.currentListIndex = isEngineer ? 0 : 1; +// allRequestsProvider.dashBoardFilterList = allRequestsProvider.inProgressRequests.requestsDetails; +// }, +// )); +// tabList.add( +// TabButtonData( +// label: 'Completed', +// isSelected: allRequestsProvider.currentListIndex == (isEngineer ? 1 : 2), +// totalCount: totalCount, +// onPressed: () { +// allRequestsProvider.currentListIndex = isEngineer ? 1 : 2; +// allRequestsProvider.dashBoardFilterList = allRequestsProvider.completedRequests.requestsDetails; +// }, +// ), +// ); +// return tabList; +// } +// +// List _buildTabButtons({@required bool isEngineer, @required AllRequestsProvider allRequestsProvider}) { +// int totalCount = 0; +// print('build tab button called'); +// if (allRequestsProvider.dashBoardFilterList != null) { +// totalCount = allRequestsProvider.dashBoardFilterList.length; +// } +// return _getTabButtonData(isEngineer: isEngineer, allRequestsProvider: allRequestsProvider, totalCount: totalCount).map((tab) { +// return Padding( +// padding: const EdgeInsets.only(left: 10.0), +// child: TabButton( +// label: tab.label, +// isSelected: tab.isSelected, +// count: totalCount, +// onPressed: tab.onPressed, +// ), +// ); +// }).toList(); +// } diff --git a/lib/new_views/pages/land_page/dashboard_fragments/request_category_list.dart b/lib/new_views/pages/land_page/dashboard_fragments/request_category_list.dart new file mode 100644 index 00000000..099cc983 --- /dev/null +++ b/lib/new_views/pages/land_page/dashboard_fragments/request_category_list.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/models/all_requests_and_count_model.dart'; +import 'package:test_sa/new_views/pages/land_page/requests/asset_item_view.dart'; +import 'package:test_sa/new_views/pages/land_page/requests/gas_refill_item_view.dart'; +import 'package:test_sa/new_views/pages/land_page/requests/ppm_item_view.dart'; +import 'package:test_sa/new_views/pages/land_page/requests/service_request_item_view.dart'; + +class RequestCategoryList extends StatelessWidget { + final List list; + final bool isLoading; + + const RequestCategoryList(this.list, this.isLoading, {Key key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: List.generate(isLoading ? 6 : list.length, (index) { + // if (isLoading) { + // return const SizedBox().toRequestShimmer(context, isLoading); + // } + // else { + return Padding( + padding: EdgeInsets.symmetric(vertical: 10.toScreenHeight), + child: _buildRequestItem(list[index])); + // } + })); + } + + Widget _buildRequestItem(RequestsDetails request) { + bool isServiceRequest = request.nameOfType == "ServiceRequest"; + bool isGasRefill = request.nameOfType == "GasRefill"; + bool isAssetTransfer = request.nameOfType == "AssetTransfer"; + bool isPPMs = request.nameOfType == "PPMs"; + + if (isServiceRequest) { + return ServiceRequestItemView(request); + } else if (isGasRefill) { + return GasRefillItemView(request); + } else if (isPPMs) { + return PpmItemView(request); + } else if (isAssetTransfer) { + return AssetItemView(request); + } else { + return Container( + height: 100, + width: double.infinity, + color: Colors.grey, + ); + } + } +} diff --git a/lib/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart b/lib/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart index 38588c18..c3d4ddac 100644 --- a/lib/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart +++ b/lib/new_views/pages/land_page/dashboard_fragments/requests_fragment.dart @@ -1,3 +1,107 @@ +//older code.... +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/api_routes/api_manager.dart'; +// import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +// import 'package:test_sa/controllers/providers/api/notifications_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/text_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/app_style/app_color.dart'; +// import 'package:test_sa/new_views/common_widgets/app_floating_action_button.dart'; +// import 'package:test_sa/new_views/pages/land_page/requests_list_page.dart'; +// +// class RequestsFragment extends StatelessWidget { +// const RequestsFragment({Key key}) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// // todo check here, nurse can add request not engineer +// floatingActionButton: const AppFloatingActionButton(), +// body: Consumer( +// builder: (context, snapshot, _) => RefreshIndicator( +// onRefresh: () { +// snapshot.getRequests(); +// Provider.of(context, listen: false).getSystemNotifications(user: Provider.of(context, listen: false).user, resetProvider: true); +// return Future.delayed(const Duration(microseconds: 250)); +// }, +// child: GridView( +// padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), +// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 191 / 237, crossAxisSpacing: 16, mainAxisSpacing: 16), +// children: [ +// listItem( +// snapshot.highPriorityRequests?.total?.count, +// "high_priority", +// context.translation.highPriority, +// context, +// snapshot.isHighPriorityLoading, +// 0, +// context.isDark ? AppColor.redStatus(context) : AppColor.red50, +// ), +// listItem(snapshot.overdueRequests?.total?.count, "overdue", context.translation.overdue, context, snapshot.isOverdueLoading, 1, AppColor.yellowStatus(context)), +// listItem(snapshot.openRequests?.total?.count, "new_request", ApiManager.instance.user.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, context, +// snapshot.isOpenLoading, 2, AppColor.primary40), +// listItem(snapshot.completedRequests?.total?.count, "complete_request", context.translation.completed, context, snapshot.isCompleteLoading, 3, AppColor.greenStatus(context)), +// ], +// ), +// ), +// ), +// ); +// } +// +// Widget listItem(int value, String icon, String title, BuildContext context, bool isLoading, int index, Color iconColor) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Row( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// value?.toString() ?? "-", +// style: AppTextStyles.heading1.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, height: 1), +// ).toShimmer(isShow: isLoading).expanded, +// 8.width, +// (icon ?? "").toSvgAsset(height: 48, width: 48, color: iconColor)?.toShimmer(isShow: isLoading), +// ], +// ).expanded, +// Text( +// "$title\n${context.translation.requests}", +// style: AppTextStyles.heading5.copyWith( +// color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, +// ), +// ).toShimmer(isShow: isLoading), +// 8.height, +// Row( +// mainAxisSize: MainAxisSize.min, +// children: [ +// Text( +// context.translation.viewDetails, +// style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.primary40 : AppColor.primary50), +// ), +// 4.width, +// Icon( +// Icons.arrow_forward, +// color: context.isDark ? AppColor.primary40 : AppColor.primary50, +// size: 14, +// ) +// ], +// ).toShimmer(isShow: isLoading), +// ], +// ).toShadowContainer(context).onPress(isLoading +// ? null +// : () async { +// await Navigator.push(context, MaterialPageRoute(builder: (context) => RequestsListPage(index))); +// Provider.of(context, listen: false).getRequests(); +// }); +// } +// } + + + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart'; @@ -8,6 +112,7 @@ 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:badges/badges.dart' as badges; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_floating_action_button.dart'; @@ -18,83 +123,380 @@ class RequestsFragment extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - // todo check here, nurse can add request not engineer - floatingActionButton: const AppFloatingActionButton(), - body: Consumer( - builder: (context, snapshot, _) => RefreshIndicator( - onRefresh: () { - snapshot.getRequests(); - Provider.of(context, listen: false).getSystemNotifications(user: Provider.of(context, listen: false).user, resetProvider: true); - return Future.delayed(const Duration(microseconds: 250)); - }, - child: GridView( - padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, childAspectRatio: 191 / 237, crossAxisSpacing: 16, mainAxisSpacing: 16), - children: [ - gridItem( - snapshot.highPriorityRequests?.total?.count, - "high_priority", - context.translation.highPriority, - context, - snapshot.isHighPriorityLoading, - 0, - context.isDark ? AppColor.redStatus(context) : AppColor.red50, - ), - gridItem(snapshot.overdueRequests?.total?.count, "overdue", context.translation.overdue, context, snapshot.isOverdueLoading, 1, AppColor.yellowStatus(context)), - gridItem(snapshot.openRequests?.total?.count, "new_request", ApiManager.instance.user.type == UsersTypes.engineer ? context.translation.inProgress : context.translation.newR, context, - snapshot.isOpenLoading, 2, AppColor.primary40), - gridItem(snapshot.completedRequests?.total?.count, "complete_request", context.translation.completed, context, snapshot.isCompleteLoading, 3, AppColor.greenStatus(context)), - ], - ), + return Consumer( + builder: (context, snapshot, _) => RefreshIndicator( + onRefresh: () async { + snapshot.getRequests(); + await Provider.of(context, listen: false) + .getSystemNotifications( + user: Provider.of(context, listen: false).user, + resetProvider: true, + ); + return Future.delayed(const Duration(milliseconds: 250)); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildListItems(context, snapshot), ), ), ); } - Widget gridItem(int value, String icon, String title, BuildContext context, bool isLoading, int index, Color iconColor) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - value?.toString() ?? "-", - style: AppTextStyles.heading1.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, height: 1), - ).toShimmer(isShow: isLoading).expanded, - 8.width, - (icon ?? "").toSvgAsset(height: 48, width: 48, color: iconColor)?.toShimmer(isShow: isLoading), - ], - ).expanded, - Text( - "$title\n${context.translation.requests}", - style: AppTextStyles.heading5.copyWith( - color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, + List _buildListItems(BuildContext context, AllRequestsProvider snapshot) { + final Map requestItems = { + 'high_priority': { + 'count': snapshot.highPriorityRequests?.total?.count, + 'translation': context.translation.highPriority, + 'isLoading': snapshot.isAllLoading, + 'color': context.isDark ? AppColor.redStatus(context) : AppColor.red50, + }, + 'overdue': { + 'count': snapshot.overdueRequests?.total?.count, + 'translation': context.translation.overdue, + 'isLoading': snapshot.isAllLoading, + 'color': AppColor.yellowStatus(context), + }, + 'new_request': { + 'count': snapshot.openRequests?.total?.count, + 'translation': ApiManager.instance.user.type == UsersTypes.engineer + ? context.translation.inProgress + : context.translation.newR, + 'isLoading': snapshot.isAllLoading, + 'color': AppColor.primary40, + }, + 'complete_request': { + 'count': snapshot.completedRequests?.total?.count, + 'translation': context.translation.completed, + 'isLoading': snapshot.isAllLoading, + 'color': AppColor.greenStatus(context), + }, + }; + + return requestItems.entries.map((entry) { + final key = entry.key; + final value = entry.value; + + return listItem( + value['count'], + key, + value['translation'], + context, + value['isLoading'], + requestItems.keys.toList().indexOf(key), + value['color'], + ); + }).toList(); + } + + Widget listItem( + int value, + String icon, + String title, + BuildContext context, + bool isLoading, + int index, + Color iconColor, + ) { + return GestureDetector( + onTap: isLoading + ? null + : () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RequestsListPage(index), ), - ).toShimmer(isShow: isLoading), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.translation.viewDetails, - style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.primary40 : AppColor.primary50), + ); + Provider.of(context, listen: false) + .getRequests(); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + value != null && value > 0&&!isLoading + ? badges.Badge( + badgeContent: Text( + value.toString(), + style: const TextStyle( + color: AppColor.white20, + fontWeight: FontWeight.normal, + ), + ), + badgeStyle: const badges.BadgeStyle( + padding: EdgeInsets.all(4), + badgeColor: AppColor.red50 ), - 4.width, - Icon( - Icons.arrow_forward, - color: context.isDark ? AppColor.primary40 : AppColor.primary50, - size: 14, - ) - ], - ).toShimmer(isShow: isLoading), - ], - ).toShadowContainer(context).onPress(isLoading - ? null - : () async { - await Navigator.push(context, MaterialPageRoute(builder: (context) => RequestsListPage(index))); - Provider.of(context, listen: false).getRequests(); - }); + child: Container( + child: (icon ?? "") + .toSvgAsset(height: 26, width: 26, color: iconColor) + ?.toShimmer(isShow: isLoading), + ).toShadowCircleContainer(context,padding: 18), + ) + : Container( + child: (icon ?? "") + .toSvgAsset(height: 26, width: 26, color: iconColor) + ?.toShimmer(isShow: isLoading), + ).toShadowCircleContainer(context,padding: 18), + 10.height, + Text( + title, + style: AppTextStyles.bodyText.copyWith( + color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, + ), + ), + ], + ), + ); } } + + +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/api_routes/api_manager.dart'; +// import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +// import 'package:test_sa/controllers/providers/api/notifications_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/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:badges/badges.dart' as badges; +// import 'package:test_sa/models/enums/user_types.dart'; +// import 'package:test_sa/new_views/app_style/app_color.dart'; +// import 'package:test_sa/new_views/common_widgets/app_floating_action_button.dart'; +// import 'package:test_sa/new_views/pages/land_page/requests_list_page.dart'; +// +// class RequestsFragment extends StatelessWidget { +// const RequestsFragment({Key key}) : super(key: key); +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// // todo check here, nurse can add request not engineer +// floatingActionButton: const AppFloatingActionButton(), +// body: Consumer( +// builder: (context, snapshot, _) => RefreshIndicator( +// onRefresh: () { +// snapshot.getRequests(); +// Provider.of(context, listen: false) +// .getSystemNotifications( +// user: Provider.of(context, listen: false) +// .user, +// resetProvider: true); +// return Future.delayed(const Duration(microseconds: 250)); +// }, +// child: Container( +// height: 200.toScreenHeight, +// color: Colors.blue, +// child: Wrap( +// children: [ +// listItem( +// snapshot.highPriorityRequests?.total?.count, +// "high_priority", +// context.translation.highPriority, +// context, +// snapshot.isHighPriorityLoading, +// 0, +// context.isDark ? AppColor.redStatus(context) : AppColor.red50, +// ), +// ], +// ), +// // child: ListView( +// // // padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16), +// // children: [ +// // listItem( +// // snapshot.highPriorityRequests?.total?.count, +// // "high_priority", +// // context.translation.highPriority, +// // context, +// // snapshot.isHighPriorityLoading, +// // 0, +// // context.isDark ? AppColor.redStatus(context) : AppColor.red50, +// // ), +// // listItem( +// // snapshot.overdueRequests?.total?.count, +// // "overdue", +// // context.translation.overdue, +// // context, +// // snapshot.isOverdueLoading, +// // 1, +// // AppColor.yellowStatus(context), +// // ), +// // listItem( +// // snapshot.openRequests?.total?.count, +// // "new_request", +// // ApiManager.instance.user.type == UsersTypes.engineer +// // ? context.translation.inProgress +// // : context.translation.newR, +// // context, +// // snapshot.isOpenLoading, +// // 2, +// // AppColor.primary40, +// // ), +// // listItem( +// // snapshot.completedRequests?.total?.count, +// // "complete_request", +// // context.translation.completed, +// // context, +// // snapshot.isCompleteLoading, +// // 3, +// // AppColor.greenStatus(context), +// // ), +// // ], +// // ), +// )), +// ), +// ); +// } +// +// Widget listItem( +// int value, +// String icon, +// String title, +// BuildContext context, +// bool isLoading, +// int index, +// Color iconColor, +// ) { +// value = 4; +// return GestureDetector( +// onTap: isLoading +// ? null +// : () async { +// await Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => RequestsListPage(index))); +// Provider.of(context, listen: false) +// .getRequests(); +// }, +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// value!=null&&value > 0 +// ? badges.Badge( +// badgeContent: Text( +// value.toString(), +// style: const TextStyle( +// color: AppColor.white20, +// // fontSize: 1.3.h, +// fontWeight: FontWeight.normal), +// ), +// badgeStyle: badges.BadgeStyle( +// padding: EdgeInsets.all(9), +// ), +// child: Container( +// padding: const EdgeInsets.all(20), +// decoration: const BoxDecoration( +// shape: BoxShape.circle, +// //TODO add color according to theme... +// color: AppColor.white20, // Background color of the circle +// ), +// child: (icon ?? "") +// .toSvgAsset(height: 40, width: 40, color: iconColor) +// ?.toShimmer(isShow: isLoading), +// )) +// : Container( +// padding: const EdgeInsets.all(20), +// decoration: const BoxDecoration( +// shape: BoxShape.circle, +// //TODO add color according to theme... +// color: AppColor.white20, // Background color of the circle +// ), +// child: (icon ?? "") +// .toSvgAsset(height: 48, width: 48, color: iconColor) +// ?.toShimmer(isShow: isLoading), +// ), +// // Container( +// // padding: const EdgeInsets.all(20), +// // decoration: const BoxDecoration( +// // shape: BoxShape.circle, +// // //TODO add color according to theme... +// // color: AppColor.white20, // Background color of the circle +// // ), +// // child: (icon ?? "") +// // .toSvgAsset(height: 48, width: 48, color: iconColor) +// // ?.toShimmer(isShow: isLoading), +// // ), +// 20.height, +// Text( +// title, +// style: AppTextStyles.heading5.copyWith( +// color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, +// ), +// ), +// // Text( +// // "$title\n${context.translation.requests}", +// // style: AppTextStyles.heading5.copyWith( +// // color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, +// // ), +// // ).toShimmer(isShow: isLoading), +// // 8.height, +// // Row( +// // mainAxisSize: MainAxisSize.min, +// // children: [ +// // Text( +// // context.translation.viewDetails, +// // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.primary40 : AppColor.primary50), +// // ), +// // 4.width, +// // Icon( +// // Icons.arrow_forward, +// // color: context.isDark ? AppColor.primary40 : AppColor.primary50, +// // size: 14, +// // ) +// // ], +// // ).toShimmer(isShow: isLoading), +// ], +// ), +// ); +// } +// +// // Widget listItem(int value, String icon, String title, BuildContext context, bool isLoading, int index, Color iconColor) { +// // return Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // Row( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // //TODO add this to badges +// // // Text( +// // // value?.toString() ?? "-", +// // // style: AppTextStyles.heading1.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, height: 1), +// // // ).toShimmer(isShow: isLoading).expanded, +// // // 8.width, +// // (icon ?? "").toSvgAsset(height: 48, width: 48, color: iconColor)?.toShimmer(isShow: isLoading), +// // ], +// // ), +// // // Text( +// // // "$title\n${context.translation.requests}", +// // // style: AppTextStyles.heading5.copyWith( +// // // color: context.isDark ? AppColor.neutral30 : AppColor.neutral50, +// // // ), +// // // ).toShimmer(isShow: isLoading), +// // // 8.height, +// // // Row( +// // // mainAxisSize: MainAxisSize.min, +// // // children: [ +// // // Text( +// // // context.translation.viewDetails, +// // // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.primary40 : AppColor.primary50), +// // // ), +// // // 4.width, +// // // Icon( +// // // Icons.arrow_forward, +// // // color: context.isDark ? AppColor.primary40 : AppColor.primary50, +// // // size: 14, +// // // ) +// // // ], +// // // ).toShimmer(isShow: isLoading), +// // ], +// // ).toShadowContainer(context).onPress(isLoading +// // ? null +// // : () async { +// // await Navigator.push(context, MaterialPageRoute(builder: (context) => RequestsListPage(index))); +// // Provider.of(context, listen: false).getRequests(); +// // }); +// // } +// } diff --git a/lib/new_views/pages/land_page/land_page.dart b/lib/new_views/pages/land_page/land_page.dart index 8b3f37d8..0dbd7ed2 100644 --- a/lib/new_views/pages/land_page/land_page.dart +++ b/lib/new_views/pages/land_page/land_page.dart @@ -5,6 +5,7 @@ import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/app_settings.dart'; +import 'package:test_sa/dashboard_latest/dashboard_view.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'; @@ -101,7 +102,7 @@ class _LandPageState extends State { if (_userProvider == null) { _userProvider = Provider.of(context, listen: false); _pages = [ - DashboardPage(onDrawerPress: (() { + DashboardView(onDrawerPress: (() { _scaffoldKey.currentState.isDrawerOpen ? _scaffoldKey.currentState.closeDrawer() : _scaffoldKey.currentState.openDrawer(); })), // const old_page.LandPage(), diff --git a/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart index 2d4d0a11..1a6d916e 100644 --- a/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart +++ b/lib/new_views/pages/land_page/my_request/all_requests_search_page.dart @@ -1,3 +1,5 @@ +//All request page + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; diff --git a/lib/new_views/pages/land_page/my_request/my_requests_page.dart b/lib/new_views/pages/land_page/my_request/my_requests_page.dart index ec8f6c4d..4cc643f0 100644 --- a/lib/new_views/pages/land_page/my_request/my_requests_page.dart +++ b/lib/new_views/pages/land_page/my_request/my_requests_page.dart @@ -1,3 +1,5 @@ +//request main page + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; @@ -12,6 +14,7 @@ import 'package:test_sa/new_views/pages/land_page/my_request/all_requests_search import 'package:test_sa/new_views/pages/land_page/widgets/request_item_view_list.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; + class MyRequestsPage extends StatefulWidget { const MyRequestsPage({Key key}) : super(key: key); @@ -28,6 +31,7 @@ class _MyRequestsPageState extends State { @override Widget build(BuildContext context) { + if (_provider == null) { requestsList = [ context.translation.allRequests, diff --git a/lib/new_views/pages/land_page/requests/service_request_item_view.dart b/lib/new_views/pages/land_page/requests/service_request_item_view.dart index 0bc18630..28a5c5ff 100644 --- a/lib/new_views/pages/land_page/requests/service_request_item_view.dart +++ b/lib/new_views/pages/land_page/requests/service_request_item_view.dart @@ -1,3 +1,4 @@ +//service request item page import 'package:flutter/material.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -6,6 +7,8 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/service_request/service_request.dart'; +import 'package:test_sa/service_request_latest/views/components/history_log_view.dart'; +import 'package:test_sa/service_request_latest/views/request_detail_view.dart'; import 'package:test_sa/views/pages/user/requests/service_request_details.dart'; import '../../../../views/widgets/requests/request_status.dart'; @@ -15,7 +18,7 @@ class ServiceRequestItemView extends StatelessWidget { final RequestsDetails request; final bool showShadow; - const ServiceRequestItemView(this.request, {Key key, this.showShadow = true}) : super(key: key); + ServiceRequestItemView(this.request, {Key key, this.showShadow = true}) : super(key: key); @override Widget build(BuildContext context) { @@ -65,10 +68,12 @@ class ServiceRequestItemView extends StatelessWidget { ), ], ).toShadowContainer(context, showShadow: showShadow).onPress(() { + //Older code... + Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ServiceRequestDetailsPage( - serviceRequest: ServiceRequest(id: request.id.toString()), - ))); + builder: (_) => ServiceRequestDetailView( + serviceRequest: ServiceRequest(id: request.id.toString()), + ))); }); } } diff --git a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart index d75e0af0..0f2a2e21 100644 --- a/lib/new_views/pages/land_page/widgets/request_item_view_list.dart +++ b/lib/new_views/pages/land_page/widgets/request_item_view_list.dart @@ -1,3 +1,4 @@ +//request tab page import 'package:flutter/material.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -21,6 +22,7 @@ class RequestItemViewList extends StatelessWidget { ? NoItemFound(message: context.translation.noDataFound) : ListView.separated( padding: const EdgeInsets.all(16), + shrinkWrap: true, itemBuilder: (cxt, index) { if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading); bool isServiceRequest = list[index].nameOfType == "ServiceRequest"; diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 33cbaad8..0efe789f 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -1,7 +1,148 @@ +//older code... + +// import 'package:flutter/material.dart'; +// import 'package:fluttertoast/fluttertoast.dart'; +// import 'package:provider/provider.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; +// import 'package:test_sa/controllers/providers/settings/app_settings.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/new_views/app_style/app_color.dart'; +// import 'package:test_sa/new_views/pages/land_page/land_page.dart'; +// +// import '../../controllers/providers/api/user_provider.dart'; +// import '../../controllers/providers/settings/setting_provider.dart'; +// import '../../controllers/validator/validator.dart'; +// import '../../models/user.dart'; +// import '../common_widgets/app_filled_button.dart'; +// import '../common_widgets/app_text_form_field.dart'; +// +// class LoginPage extends StatefulWidget { +// static const String routeName = "/login_page"; +// +// const LoginPage({Key key}) : super(key: key); +// +// @override +// State createState() => _LoginPageState(); +// } +// +// class _LoginPageState extends State { +// final User _user = User(); +// UserProvider _userProvider; +// SettingProvider _settingProvider; +// final GlobalKey _formKey = GlobalKey(); +// +// bool rememberMe = false; +// +// @override +// Widget build(BuildContext context) { +// _userProvider = Provider.of(context); +// if (_settingProvider == null) { +// _settingProvider = Provider.of(context); +// rememberMe = _settingProvider.rememberMe; +// if (rememberMe) { +// _user.userName = _settingProvider.username; +// _user.password = _settingProvider.password; +// } +// } +// +// return Form( +// key: _formKey, +// child: Scaffold( +// body: Column( +// children: [ +// SingleChildScrollView( +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Hero(tag: "logo", child: "logo".toSvgAsset(height: 64)), +// 64.height, +// context.translation.login.heading2(context).custom(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.primary50 : AppColor.neutral50), +// context.translation.enterCredsToLogin.heading6(context).custom(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), +// 32.height, +// AppTextFormField( +// initialValue: _user?.userName, +// validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField, +// labelText: context.translation.username, +// textInputType: TextInputType.text, +// onSaved: (value) { +// _user.userName = value; +// }, +// ), +// 16.height, +// AppTextFormField( +// initialValue: _user?.password, +// labelText: context.translation.password, +// obscureText: true, +// validator: (value) => Validator.isValidPassword(value) +// ? null +// : value.isEmpty +// ? context.translation.requiredField +// : context.translation.passwordLengthMessage, +// onSaved: (value) { +// _user.password = value; +// }, +// ), +// 8.height, +// Row( +// children: [ +// Checkbox( +// value: rememberMe, +// activeColor: AppColor.blueStatus(context), +// onChanged: (value) { +// setState(() { +// rememberMe = value; +// }); +// }), +// "Remember Me".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50).expanded, +// ], +// ), +// 16.height, +// Align( +// alignment: AlignmentDirectional.centerEnd, +// child: InkWell( +// onTap: () { +// /// TODO [zaid] : push to another screen +// }, +// child: context.translation.forgotPassword.bodyText(context).custom(color: AppColor.primary50, fontWeight: FontWeight.w500), +// ), +// ), +// ], +// ), +// ).center.expanded, +// AppFilledButton(label: context.translation.login, maxWidth: true, onPressed: _login), +// ], +// ).paddingOnly(start: 16, end: 16, bottom: 24, top: 24), +// ), +// ); +// } +// +// Future _login() async { +// if (!_formKey.currentState.validate()) return; +// _formKey.currentState.save(); +// int status = await _userProvider.login(context: context, user: _user); +// if (status >= 200 && status < 300 && _userProvider.user.isAuthenticated ?? false) { +// await _settingProvider.setUser(_userProvider.user); +// (await SharedPreferences.getInstance()).remove(ASettings.localAuth); +// await _settingProvider.setRememberMe(_user.userName, _user.password, rememberMe); +// +// /// The below line for the new design +// // Navigator.pushNamed(context, LandPage.routeName); +// Navigator.pushNamed(context, LandPage.routeName); +// } else { +// Fluttertoast.showToast(msg: _userProvider.user?.message ?? context.translation.failedToCompleteRequest); +// } +// } +// } + import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:test_sa/app_strings/app_asset.dart'; import 'package:test_sa/controllers/providers/settings/app_settings.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -9,6 +150,7 @@ import 'package:test_sa/extensions/text_extensions.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/pages/land_page/land_page.dart'; +import 'package:test_sa/views/widgets/buttons/rounded_back_button.dart'; import '../../controllers/providers/api/user_provider.dart'; import '../../controllers/providers/settings/setting_provider.dart'; @@ -49,72 +191,119 @@ class _LoginPageState extends State { return Form( key: _formKey, child: Scaffold( - body: Column( - children: [ - SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Hero(tag: "logo", child: "logo".toSvgAsset(height: 64)), - 64.height, - context.translation.login.heading2(context).custom(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.primary50 : AppColor.neutral50), - context.translation.enterCredsToLogin.heading6(context).custom(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), - 32.height, - AppTextFormField( - initialValue: _user?.userName, - validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField, - labelText: context.translation.username, - textInputType: TextInputType.text, - onSaved: (value) { - _user.userName = value; - }, - ), - 16.height, - AppTextFormField( - initialValue: _user?.password, - labelText: context.translation.password, - obscureText: true, - validator: (value) => Validator.isValidPassword(value) - ? null - : value.isEmpty - ? context.translation.requiredField - : context.translation.passwordLengthMessage, - onSaved: (value) { - _user.password = value; - }, + backgroundColor: AppColor.background(context), + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: double.infinity, + height: 293.toScreenHeight, + padding: EdgeInsets.only(left: 16.toScreenWidth), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(AppAsset.loginTopBg), + fit: BoxFit.cover, // Adjusts the image to cover the entire container + ), ), - 8.height, - Row( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, children: [ - Checkbox( - value: rememberMe, - activeColor: AppColor.blueStatus(context), - onChanged: (value) { - setState(() { - rememberMe = value; - }); - }), - "Remember Me".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50).expanded, + SizedBox( + height: 146.toScreenHeight, + ), + // RoundedBackButton( + // icon: Icons.arrow_back_ios, + // onPressed: () { + // ///There is no previous screen + // }, + // backgroundColor: context.isDark ? AppColor.primary80 : AppColor.primary80), + + context.translation.signInToYour.customHeadingText(context).custom( + color: AppColor.white20, + ), + context.translation.account.customHeadingText(context).custom( + color: AppColor.white20, + ), + 25.height, + context.translation.letSignInToAccount.customHeadingText(context).custom( + color: AppColor.white20, + fontWeight: FontWeight.w500, + fontSize: 12, + ), ], ), - 16.height, - Align( - alignment: AlignmentDirectional.centerEnd, - child: InkWell( - onTap: () { - /// TODO [zaid] : push to another screen - }, - child: context.translation.forgotPassword.bodyText(context).custom(color: AppColor.primary50, fontWeight: FontWeight.w500), - ), + ), + SizedBox(height: 47.toScreenHeight,), + Padding( + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppTextFormField( + initialValue: _user?.userName, + //TODO add the color according to theme.... + backgroundColor: AppColor.white20, + validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField, + labelText: context.translation.username, + textInputType: TextInputType.text, + showWithoutDecoration: true, + contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight), + onSaved: (value) { + _user.userName = value; + }, + ), + 18.height, + AppTextFormField( + initialValue: _user?.password, + showWithoutDecoration: true, + labelText: context.translation.password, + //TODO add the color according to theme.... + backgroundColor: AppColor.white20, + contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight), + obscureText: true, + validator: (value) => Validator.isValidPassword(value) + ? null + : value.isEmpty + ? context.translation.requiredField + : context.translation.passwordLengthMessage, + onSaved: (value) { + _user.password = value; + }, + ), + 16.height, + Align( + alignment: AlignmentDirectional.centerEnd, + child: InkWell( + onTap: () { + /// TODO [zaid] : push to another screen + }, + child: context.translation.forgotPassword.bodyText(context).custom(color: AppColor.primary10, fontWeight: FontWeight.w500), + ), + ), + Row( + children: [ + Checkbox( + value: rememberMe, + activeColor: AppColor.blueStatus(context), + onChanged: (value) { + setState(() { + rememberMe = value; + }); + }), + "Remember Me".bodyText(context).custom(color: context.isDark ? AppColor.primary50 : AppColor.neutral50).expanded, + ], + ), + 50.height, + AppFilledButton(label: context.translation.signIn,buttonColor: AppColor.primary10, maxWidth: true, onPressed: _login), + ], ), - ], - ), - ).center.expanded, - AppFilledButton(label: context.translation.login, maxWidth: true, onPressed: _login), - ], - ).paddingOnly(start: 16, end: 16, bottom: 24, top: 24), - ), + ), + ], + ), + )), ); } diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart new file mode 100644 index 00000000..c654cf9e --- /dev/null +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -0,0 +1,146 @@ +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/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/service_request_latest/views/components/bottom_sheets/activity_type_bottomsheet.dart'; +import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.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/update_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; +import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; +import 'package:test_sa/views/widgets/requests/request_status.dart'; + +class ActivitiesListView extends StatelessWidget { + static const String id = "/activities-list"; + + ActivitiesListView({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // UserProvider _userProvider = Provider.of(context); + // SettingProvider _settingProvider = Provider.of(context); + List workOrders = []; + UserProvider _userProvider = Provider.of(context); + return Scaffold( + appBar: DefaultAppBar(title: context.translation.activities), + //backgroundColor: const Color(0xfff8f9fb), + body: Consumer(builder: (context, serviceRequestsProvider, child) { + return SafeArea( + child: FutureBuilder( + future: serviceRequestsProvider.searchWorkOrders(callId: serviceRequestsProvider.currentSelectedRequest?.requestCode), + builder: (context, snap) { + if (snap.connectionState == ConnectionState.waiting) return const Center(child: CircularProgressIndicator()); + workOrders = snap.data as List; + return Column( + children: [ + (workOrders.isEmpty) + ? NoItemFound(message: context.translation.noDataFound).expanded + : ListView.separated( + padding: const EdgeInsets.all(16), + itemCount: workOrders.length, + separatorBuilder: (czt, index) => 8.height, + itemBuilder: (context, index) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + StatusLabel( + label: workOrders[index].currentSituation.name, + textColor: AppColor.getRequestStatusTextColorByName(context, workOrders[index].currentSituation.name), + backgroundColor: AppColor.getRequestStatusColorByName(context, workOrders[index].currentSituation.name), + ), + 8.height, + Text(serviceRequestsProvider.currentSelectedRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), + Text( + '${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.currentSituation}: ${workOrders[index].currentSituation.name}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.viewDetails, + style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + ), + 4.width, + Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + ], + ), + ], + ).onPress(() { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrders[index], serviceRequest: serviceRequestsProvider.currentSelectedRequest)), + ); + }).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (_userProvider.user.type == UsersTypes.engineer && + serviceRequestsProvider.currentSelectedRequest.statusValue != 5 && + serviceRequestsProvider.currentSelectedRequest.statusValue != 3) + "edit".toSvgAsset(height: 48, width: 48).onPress(() { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequestsProvider.currentSelectedRequest, workOrder: workOrders[index])), + ); + }), + if (_userProvider.user.type == UsersTypes.engineer && + serviceRequestsProvider.currentSelectedRequest.statusValue != 5 && + serviceRequestsProvider.currentSelectedRequest.statusValue != 3) + 8.height, + Text(workOrders[index].visitDate?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : const Color(0xFF3B3D4A))), + ], + ) + ], + ).toShadowContainer(context); + }, + ).expanded, + if (_userProvider.user.type == UsersTypes.engineer && (serviceRequestsProvider.currentSelectedRequest.statusValue != 5 && serviceRequestsProvider.currentSelectedRequest.statusValue != 3)) + AppFilledButton( + label: context.translation.createNewActivity, + maxWidth: true, + onPressed: () async{ + ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context); + // bool shouldReloadData = (await showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // backgroundColor: Colors.transparent, + // // builder: (context) => ActivityTypeBottomSheet(), + // builder: (context) => FixRemotlyBottomSheet(), + // )) as bool; + // if (shouldReloadData ?? false) { + // // getServiceRequest(); + // } + // Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequestsProvider.serviceRequest))); + }, + ).paddingOnly(start: 16, end: 16, bottom: 16) + ], + ); + }, + ), + ); + }), + ); + } +} diff --git a/lib/service_request_latest/views/components/activity_card_view.dart b/lib/service_request_latest/views/components/activity_card_view.dart new file mode 100644 index 00000000..1665ad0a --- /dev/null +++ b/lib/service_request_latest/views/components/activity_card_view.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_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/views/pages/user/requests/work_order/update_service_report.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; + +import '../../../../views/widgets/requests/request_status.dart'; + +class ActivityCardView extends StatelessWidget { + final SearchWorkOrder workOrder; + final ServiceRequest serviceRequest; + final bool showShadow; + + ActivityCardView(this.workOrder, this.serviceRequest, {Key key, this.showShadow = true}) : super(key: key); + + @override + Widget build(BuildContext context) { + UserProvider _userProvider = Provider.of(context, listen: false); + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + StatusLabel( + label: workOrder.currentSituation.name, + textColor: AppColor.getRequestStatusTextColorByName(context, workOrder.currentSituation.name), + backgroundColor: AppColor.getRequestStatusColorByName(context, workOrder.currentSituation.name), + ), + 8.height, + Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), + Text( + '${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.currentSituation}: ${workOrder.currentSituation.name}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.readCompleteThread, + style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context), decoration: TextDecoration.underline), + ), + // 4.width, + // Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + ], + ), + ], + ).onPress(() { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrder, serviceRequest: serviceRequest)), + ); + }).expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) + "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrder)), + ); + }), + if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) 8.height, + Text(workOrder.visitDate?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : const Color(0xFF3B3D4A))), + ], + ) + ], + ).toShadowContainer(context); + } +} diff --git a/lib/service_request_latest/views/components/bottom_sheets/action_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/action_bottomsheet.dart new file mode 100644 index 00000000..ffb56002 --- /dev/null +++ b/lib/service_request_latest/views/components/bottom_sheets/action_bottomsheet.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; +import 'package:provider/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/service_request_latest/views/components/verify_arrival_view.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import '../../../../controllers/providers/api/service_requests_provider.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; + +class ActionBottomSheet extends StatelessWidget { + final String title; + final String button1Text; + final String button2Text; + final VoidCallback button1Tap; + final VoidCallback button2Tap; + + ActionBottomSheet({Key key, @required this.title, this.button1Text, this.button2Text, this.button1Tap, this.button2Tap}) : super(key: key); + + final GlobalKey _formKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Consumer(builder: (context, serviceRequestProvider, child) { + return Wrap( + children: [ + Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: title.heading4(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: 200.toScreenHeight, + child: AppFilledButton( + label: button1Text ?? context.translation.no, + loading: false, + buttonColor: AppColor.neutral40, + textColor: AppColor.balck10, + onPressed: button1Tap ?? + () async { + Navigator.pop(context); + // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest); + // Navigator.pop(context, true); + }, + ), + ), + SizedBox( + width: 200.toScreenHeight, + child: AppFilledButton( + label: context.translation.yes, + buttonColor: AppColor.primary10, + loading: false, + onPressed:button2Tap, + ), + ), + ], + ) + ], + ), + ) + ], + ); + }); + } +} diff --git a/lib/service_request_latest/views/components/bottom_sheets/activity_type_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/activity_type_bottomsheet.dart new file mode 100644 index 00000000..ed66fe34 --- /dev/null +++ b/lib/service_request_latest/views/components/bottom_sheets/activity_type_bottomsheet.dart @@ -0,0 +1,129 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/app_strings/app_asset.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.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/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/service_request_latest/views/components/spare_part_request.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart'; + +class ActivityTypeBottomSheet extends StatelessWidget { + ActivityTypeBottomSheet({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final List> items = [ + {'heading': context.translation.sparePartRequest, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.sparePartIcon}, + {'heading': context.translation.maintenanceRequest, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.maintenanceIcon}, + {'heading': context.translation.assetToBeRetired, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.retiredAssetIcon}, + ]; + return Wrap( + children: [ + Consumer(builder: (context, serviceRequestsProvider, child) { + return Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: AppColor.background(context), + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: SafeArea( + child: Column( + children: [ + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.selectActivityType.heading4(context).paddingOnly(top: 16, bottom: 16), + ), + ListView.builder( + shrinkWrap: true, + padding: EdgeInsets.zero, + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + return listItem( + icon: item['icon'], + heading: item['heading'], + subHeading: item['subHeading'], + context: context, + onTap: () { + onItemTap(serviceRequest: serviceRequestsProvider.currentSelectedRequest, index: index, context: context); + }); + }, + ), + ], + ), + ), + ); + }), + ], + ); + } + + Widget listItem({@required BuildContext context, @required String icon, @required String heading, @required String subHeading, @required VoidCallback onTap}) { + return Padding( + padding: EdgeInsets.only(bottom: 8.toScreenHeight), + child: Card( + color: AppColor.neutral80, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + // Circular border radius + ), + // color: Colors.white, + child: ListTile( + minVerticalPadding: 8, + horizontalTitleGap: 10, + onTap: onTap, + contentPadding: const EdgeInsets.all(8), + leading: SvgPicture.asset(icon), + title: Text( + heading, + style: AppTextStyles.heading5, + ), + subtitle: Text( + subHeading, + style: AppTextStyles.bodyText, + ), + ), + ), + ); + } + + void onItemTap({@required int index, @required ServiceRequest serviceRequest, @required BuildContext context}) { + print('on item tap i got index is $index'); + switch (index) { + case 0: + Navigator.of(context).push(MaterialPageRoute(builder: (_) =>const SparePartRequest())); + + break; + case 1: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => ActivitiesListView()), + // ); + break; + case 2: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const ScanQrView()), + // ); + break; + case 2: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const ScanQrView()), + // ); + break; + } + // ScanQr + } +} diff --git a/lib/service_request_latest/views/components/bottom_sheets/initial_visit_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/initial_visit_bottomsheet.dart new file mode 100644 index 00000000..3c04ce0f --- /dev/null +++ b/lib/service_request_latest/views/components/bottom_sheets/initial_visit_bottomsheet.dart @@ -0,0 +1,217 @@ +import 'package:flutter/material.dart'; +import 'package:provider/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/service_request_latest/views/components/verify_arrival_view.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import '../../../../controllers/providers/api/service_requests_provider.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; + +class InitialVisitBottomSheet extends StatelessWidget { + + InitialVisitBottomSheet({Key key,}) : super(key: key); + + final GlobalKey _formKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + final userProvider = Provider.of(context, listen: false); + return Consumer( + builder: (context, serviceRequestProvider,child) { + return Wrap( + children: [ + Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.setVisitDate.heading5(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16), + ), + + 8.height, + ADatePicker( + label: context.translation.visitDate, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.visitDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest.date))) { + "Visit Date time must be greater then request date".showToast; + return; + } + serviceRequestProvider.currentSelectedRequest.visitDate = selectedDateTime?.toIso8601String(); + } + } + }); + } + }, + ), + // ], + + if (serviceRequestProvider.currentSelectedRequest.firstAction?.id == 404 && Provider.of(context, listen: false).assetGroup.id == 1) ...[ + 8.height, + Row( + children: [ + ADatePicker( + label: context.translation.startDate, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.startDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + + serviceRequestProvider.currentSelectedRequest.startDate = selectedDateTime?.toIso8601String(); + + } + } + }); + } + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endDate, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.endDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + serviceRequestProvider.currentSelectedRequest.endDate = selectedDateTime?.toIso8601String(); + serviceRequestProvider.currentSelectedRequest.workingHours = + (((DateTime.parse(serviceRequestProvider.currentSelectedRequest.endDate).difference(DateTime.parse(serviceRequestProvider.currentSelectedRequest.startDate)).inSeconds ?? 0) / 60) / 60).toStringAsFixed(2); + } + } + }); + } + }, + ).expanded, + ], + ) + ], + + /// Loan availability not required + // 8.height, + // SingleItemDropDownMenu( + // context: context, + // title: context.translation.loanAvailability, + // initialValue: _serviceRequest.loanAvailability, + // onSelect: (status) { + // setState(() { + // _serviceRequest.loanAvailability = status; + // if (_serviceRequest.loanAvailability.value != 1) { + // asset = null; + // } + // }); + // }, + // ), + // if (_serviceRequest?.loanAvailability?.value == 1) 8.height, + // if (_serviceRequest?.loanAvailability?.value == 1) + // PickAsset( + // device: asset ?? _serviceRequest.device, + // onPickAsset: (asset) { + // setState(() { + // this.asset = asset; + // }); + // }, + // ), + 8.height, + AppTextFormField( + labelText: context.translation.comments, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + onChange: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + onSaved: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + ), + 16.height, + Consumer( + builder: (context, snapshot, _) => AppFilledButton( + label: context.translation.save, + loading: snapshot.isLoading ?? false, + onPressed: () async { + _formKey.currentState.save(); + + // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest); + // Navigator.pop(context, true); + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => VerifyArrivalView())); + }, + ), + ), + 16.height, + ], + ), + ), + ), + ) + ], + ); + } + ); + } +} diff --git a/lib/service_request_latest/views/components/bottom_sheets/reject_request_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/reject_request_bottomsheet.dart new file mode 100644 index 00000000..2566c764 --- /dev/null +++ b/lib/service_request_latest/views/components/bottom_sheets/reject_request_bottomsheet.dart @@ -0,0 +1,236 @@ +import 'package:flutter/material.dart'; +import 'package:provider/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/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/device/asset.dart'; +import '../../../../controllers/providers/api/service_requests_provider.dart'; +import '../../../../models/lookup.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../../providers/service_request_providers/first_action_provider.dart'; + +class RejectRequestBottomSheet extends StatelessWidget { + + RejectRequestBottomSheet({Key key,}) : super(key: key); + + final GlobalKey _formKey = GlobalKey(); + Asset asset; + + + @override + Widget build(BuildContext context) { + final userProvider = Provider.of(context, listen: false); + return Consumer( + builder: (context, requestDetailProvider,child) { + return Wrap( + children: [ + Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.rejectionReason.heading3(context).custom(fontWeight: FontWeight.w600).paddingOnly(top: 16, bottom: 16), + ), + SingleItemDropDownMenu( + context: context, + title: context.translation.rejectionReason, + initialValue: requestDetailProvider.currentSelectedRequest.firstAction, //_currentSelectedRequest.firstAction, + onSelect: (value) { + // setState(() { + //_currentSelectedRequest.firstAction = value; + requestDetailProvider.currentSelectedRequest.firstAction = value; + if (requestDetailProvider.currentSelectedRequest.firstAction.value != 2) { + requestDetailProvider.currentSelectedRequest.visitDate = null; + } + // }); + }, + ), + // if (requestDetailProvider.currentSelectedRequest.firstAction?.value == 2) ...[ + // 8.height, + // ADatePicker( + // label: context.translation.visitDate, + // date: DateTime.tryParse(requestDetailProvider.currentSelectedRequest.visitDate ?? ""), + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // if (selectedDate != null) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + // if (selectedDateTime != null) { + // if (selectedDateTime.isBefore(DateTime.parse(requestDetailProvider.currentSelectedRequest.date))) { + // "Visit Date time must be greater then request date".showToast; + // return; + // } + // + // // setState(() { + // requestDetailProvider.currentSelectedRequest.visitDate = selectedDateTime?.toIso8601String(); + // // }); + // } + // } + // }); + // } + // }, + // ), + // ], + // + // if (requestDetailProvider.currentSelectedRequest.firstAction?.id == 404 && Provider.of(context, listen: false).assetGroup.id == 1) ...[ + // 8.height, + // Row( + // children: [ + // ADatePicker( + // label: context.translation.startDate, + // date: DateTime.tryParse(requestDetailProvider.currentSelectedRequest.startDate ?? ""), + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // if (selectedDate != null) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + // if (selectedDateTime != null) { + // requestDetailProvider.currentSelectedRequest.startDate = selectedDateTime?.toIso8601String(); + // } + // } + // }); + // } + // }, + // ).expanded, + // 8.width, + // ADatePicker( + // label: context.translation.endDate, + // date: DateTime.tryParse(requestDetailProvider.currentSelectedRequest.endDate ?? ""), + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // if (selectedDate != null) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + // if (selectedDateTime != null) { + // requestDetailProvider.currentSelectedRequest.endDate = selectedDateTime?.toIso8601String(); + // requestDetailProvider.currentSelectedRequest.workingHours = + // (((DateTime.parse(requestDetailProvider.currentSelectedRequest.endDate).difference(DateTime.parse(requestDetailProvider.currentSelectedRequest.startDate)).inSeconds ?? 0) / 60) / 60).toStringAsFixed(2); + // } + // } + // }); + // } + // }, + // ).expanded, + // ], + // ) + // ], + + /// Loan availability not required + // 8.height, + // SingleItemDropDownMenu( + // context: context, + // title: context.translation.loanAvailability, + // initialValue: _currentSelectedRequest.loanAvailability, + // onSelect: (status) { + // setState(() { + // _currentSelectedRequest.loanAvailability = status; + // if (_currentSelectedRequest.loanAvailability.value != 1) { + // asset = null; + // } + // }); + // }, + // ), + // if (_currentSelectedRequest?.loanAvailability?.value == 1) 8.height, + // if (_currentSelectedRequest?.loanAvailability?.value == 1) + // PickAsset( + // device: asset ?? _currentSelectedRequest.device, + // onPickAsset: (asset) { + // setState(() { + // this.asset = asset; + // }); + // }, + // ), + 8.height, + AppTextFormField( + labelText: context.translation.comments, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + onChange: (text) { + requestDetailProvider.currentSelectedRequest.comments = text; + }, + onSaved: (text) { + requestDetailProvider.currentSelectedRequest.comments = text; + }, + ), + 16.height, + Consumer( + builder: (context, snapshot, _) => AppFilledButton( + label: context.translation.reject, + maxWidth: true, + buttonColor: Colors.white54, + textColor: AppColor.red50, + showBorder: true, + loading: snapshot.isLoading ?? false, + onPressed: () async { + _formKey.currentState.save(); + // requestDetailProvider.serviceRequest.device = asset; + await snapshot.updateRequest(user: userProvider.user, request: requestDetailProvider.currentSelectedRequest); + Navigator.pop(context, true); + }, + ), + ), + 16.height, + ], + ), + ), + ), + ) + ], + ); + } + ); + } +} diff --git a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart new file mode 100644 index 00000000..cb6ad769 --- /dev/null +++ b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart @@ -0,0 +1,860 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/app_strings/app_asset.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/device/asset.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; +import 'package:test_sa/models/timer_model.dart'; +import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/service_request_providers/first_action_provider.dart'; +import 'package:test_sa/service_request_latest/views/components/spare_part_request.dart'; +import 'package:test_sa/service_request_latest/views/components/verify_arrival_view.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/date_and_time/time_picker.dart'; +import 'package:test_sa/views/widgets/timer/app_timer.dart'; +import '../../../../controllers/providers/api/service_requests_provider.dart'; +import '../../../../new_views/app_style/app_color.dart'; +import '../../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; + +// class FixRemotlyBottomSheet extends StatelessWidget { +// +// FixRemotlyBottomSheet({Key key,}) : super(key: key); +// +// final GlobalKey _formKey = GlobalKey(); +// +// @override +// Widget build(BuildContext context) { +// return Consumer( +// builder: (context, serviceRequestProvider,child) { +// return StatefulBuilder( +// builder: (BuildContext context, StateSetter setState) { +// return Container( +// clipBehavior: Clip.antiAlias, +// margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), +// decoration: BoxDecoration( +// color: AppColor.background(context), +// borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), +// ), +// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), +// child: Form( +// key: _formKey, +// child: SingleChildScrollView( +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Center( +// child: Container( +// width: 40.toScreenWidth, +// height: 5.toScreenHeight, +// decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), +// ), +// ), +// Align( +// alignment: AlignmentDirectional.centerStart, +// child: context.translation.fillDetails.heading5(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16), +// ), +// +// 8.height, +// ADatePicker( +// label: context.translation.date, +// height: 80.toScreenHeight, +// backgroundColor: AppColor.neutral90, +// date: DateTime.tryParse(serviceRequestProvider.serviceRequest.startDate ?? ""), +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// if (selectedDate != null) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// if (selectedDateTime != null) { +// if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.serviceRequest.date))) { +// "Visit Date time must be greater then request date".showToast; +// return; +// } +// +// setState(() { +// serviceRequestProvider.serviceRequest.startDate = selectedDateTime?.toIso8601String(); +// }); +// } +// } +// }); +// } +// }, +// ), +// 8.height, +// ATimePicker( +// label: context.translation.startTime, +// height: 80.toScreenHeight, +// backgroundColor: AppColor.neutral90, +// hint:context.translation.pickTime, +// time: serviceRequestProvider.selectedTime, +// onTimePicker: (selectedTime) { +// //TODO handle selected time here. +// if (selectedTime != null) { +// setState(() { +// serviceRequestProvider.selectedTime = selectedTime; +// }); +// // DateTime selectedDateTime = DateTime( +// // selectedDate.year, +// // selectedDate.month, +// // selectedDate.day, +// // selectedTime.hour, +// // selectedTime.minute, +// // ); +// // if (selectedDateTime != null) { +// // if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.serviceRequest.date))) { +// // "Visit Date time must be greater then request date".showToast; +// // return; +// // } +// // +// +// // } +// } +// }, +// ), +// 8.height, +// ATimePicker( +// label: context.translation.endTime, +// height: 80.toScreenHeight, +// backgroundColor: AppColor.neutral90, +// hint:context.translation.pickTime, +// time: serviceRequestProvider.selectedTime, +// onTimePicker: (selectedTime) { +// //TODO handle selected time here. +// if (selectedTime != null) { +// setState(() { +// serviceRequestProvider.selectedTime = selectedTime; +// }); +// } +// }, +// ), +// 8.height, +// Container( +// width: double.infinity, +// height: 80.toScreenHeight, +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(10), +// color:AppColor.neutral90, +// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], +// ), +// padding: EdgeInsets.symmetric(horizontal: 20.toScreenWidth,vertical: 10.toScreenHeight), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// context.translation.workingHours.bodyText2(context), +// //TODo calculate the hours and write here. +// 'No of hours'.bodyText(context).custom(color:AppColor.balck10), +// ], +// ), +// +// ), +// 8.height, +// AppTextFormField( +// labelText: context.translation.comments, +// textInputType: TextInputType.multiline, +// alignLabelWithHint: true, +// backgroundColor: AppColor.neutral90, +// onChange: (text) { +// serviceRequestProvider.serviceRequest.comments = text; +// }, +// onSaved: (text) { +// serviceRequestProvider.serviceRequest.comments = text; +// }, +// ), +// 16.height, +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// SizedBox( +// width: 200.toScreenHeight, +// child: AppFilledButton( +// label: context.translation.cancel, +// loading: false, +// buttonColor: Colors.transparent, +// showBorder: true, +// textColor: AppColor.balck10, +// onPressed: +// () async { +// Navigator.pop(context); +// // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest); +// // Navigator.pop(context, true); +// }, +// ), +// ), +// SizedBox( +// width: 200.toScreenHeight, +// child: AppFilledButton( +// label: context.translation.fixed, +// buttonColor: AppColor.green70, +// loading: false, +// onPressed:(){ +// +// }, +// ), +// ), +// ], +// ), +// 16.height, +// ], +// ), +// ), +// ), +// ); +// } +// ); +// } +// ); +// } +// } + +class ServiceRequestBottomSheet { + static Future fixRemotelyBottomSheet({@required BuildContext context}) { + final GlobalKey _formKey = GlobalKey(); + return showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => Consumer(builder: (context, serviceRequestProvider, child) { + return Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: AppColor.background(context), + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: StatefulBuilder( + builder: (context, setState) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.fillDetails.heading5(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16), + ), + 8.height, + ADatePicker( + label: context.translation.date, + hideShadow: true, + height: 80.toScreenHeight, + backgroundColor: AppColor.neutral90, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.startDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest.date))) { + "Visit Date time must be greater then request date".showToast; + return; + } + + setState(() { + serviceRequestProvider.currentSelectedRequest.startDate = selectedDateTime?.toIso8601String(); + }); + print('start date i got is ${serviceRequestProvider.currentSelectedRequest.startDate}'); + } + } + }); + } + }, + ), + + // ATimePicker( + // label: context.translation.startTime, + // height: 80.toScreenHeight, + // backgroundColor: AppColor.neutral90, + // hint: context.translation.pickTime, + // time: serviceRequestProvider.selectedTime, + // onTimePicker: (selectedTime) { + // //TODO handle selected time here. + // if (selectedTime != null) { + // // setState(() { + // serviceRequestProvider.selectedTime = selectedTime; + // // }); + // // DateTime selectedDateTime = DateTime( + // // selectedDate.year, + // // selectedDate.month, + // // selectedDate.day, + // // selectedTime.hour, + // // selectedTime.minute, + // // ); + // // if (selectedDateTime != null) { + // // if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.serviceRequest.date))) { + // // "Visit Date time must be greater then request date".showToast; + // // return; + // // } + // // + // + // // } + // } + // }, + // ), + // 8.height, + // ATimePicker( + // label: context.translation.endTime, + // height: 80.toScreenHeight, + // backgroundColor: AppColor.neutral90, + // hint: context.translation.pickTime, + // time: serviceRequestProvider.selectedTime, + // onTimePicker: (selectedTime) { + // //TODO handle selected time here. + // if (selectedTime != null) { + // // setState(() { + // serviceRequestProvider.selectedTime = selectedTime; + // // }); + // } + // }, + // ), + 8.height, + SizedBox( + width: double.infinity, + height: 80.toScreenHeight, + // padding: EdgeInsets.symmetric(horizontal: 20.toScreenWidth, vertical: 10.toScreenHeight), + child: + AppTimer( + label: context.translation.workingHours, + timer: TimerModel(), + decoration: BoxDecoration( + color: context.isDark ? AppColor.neutral20 : AppColor.neutral90, + borderRadius: BorderRadius.circular(10), + // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + // enabled: serviceRequestProvider.currentSelectedRequest.date == null, + enabled: true, + onChange: (timer) async { + print('timer i got is ${timer.toString()}'); + return true; + }, + ), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // context.translation.workingHours.bodyText2(context), + // //TODo calculate the hours and write here. + // 'No of hours'.bodyText(context).custom(color: AppColor.balck10), + // ], + // ), + ), + 8.height, + AppTextFormField( + labelText: context.translation.comments, + textInputType: TextInputType.multiline, + showWithoutDecoration: true, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, + alignLabelWithHint: true, + onChange: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + onSaved: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + ), + 16.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: 200.toScreenHeight, + child: AppFilledButton( + label: context.translation.cancel, + loading: false, + buttonColor: Colors.transparent, + showBorder: true, + textColor: AppColor.balck10, + onPressed: () async { + Navigator.pop(context); + // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest); + // Navigator.pop(context, true); + }, + ), + ), + SizedBox( + width: 200.toScreenHeight, + child: AppFilledButton( + label: context.translation.fixed, + buttonColor: AppColor.green70, + loading: false, + onPressed: () {}, + ), + ), + ], + ), + 16.height, + ], + ); + } + ), + ), + ), + ); + })); + } + + static Future initialVisitBottomSheet({@required BuildContext context}) { + final GlobalKey _formKey = GlobalKey(); + return showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => Consumer(builder: (context, serviceRequestProvider, child) { + return Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.setVisitDate.heading5(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16), + ), + + 8.height, + ADatePicker( + label: context.translation.visitDate, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.visitDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + if (selectedDateTime.isBefore(DateTime.parse(serviceRequestProvider.currentSelectedRequest.date))) { + "Visit Date time must be greater then request date".showToast; + return; + } + serviceRequestProvider.currentSelectedRequest.visitDate = selectedDateTime?.toIso8601String(); + } + } + }); + } + }, + ), + // ], + + if (serviceRequestProvider.currentSelectedRequest.firstAction?.id == 404 && Provider.of(context, listen: false).assetGroup.id == 1) ...[ + 8.height, + Row( + children: [ + ADatePicker( + label: context.translation.startDate, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.startDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + serviceRequestProvider.currentSelectedRequest.startDate = selectedDateTime?.toIso8601String(); + } + } + }); + } + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endDate, + date: DateTime.tryParse(serviceRequestProvider.currentSelectedRequest.endDate ?? ""), + formatDateWithTime: true, + onDatePicker: (selectedDate) { + if (selectedDate != null) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (selectedDateTime != null) { + serviceRequestProvider.currentSelectedRequest.endDate = selectedDateTime?.toIso8601String(); + serviceRequestProvider.currentSelectedRequest.workingHours = + (((DateTime.parse(serviceRequestProvider.currentSelectedRequest.endDate).difference(DateTime.parse(serviceRequestProvider.currentSelectedRequest.startDate)).inSeconds ?? + 0) / + 60) / + 60) + .toStringAsFixed(2); + } + } + }); + } + }, + ).expanded, + ], + ) + ], + 8.height, + AppTextFormField( + labelText: context.translation.comments, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + onChange: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + onSaved: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + ), + 16.height, + Consumer( + builder: (context, snapshot, _) => AppFilledButton( + label: context.translation.save, + loading: snapshot.isLoading ?? false, + onPressed: () async { + _formKey.currentState.save(); + + // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest); + // Navigator.pop(context, true); + Navigator.of(context).push(MaterialPageRoute(builder: (_) => VerifyArrivalView())); + }, + ), + ), + 16.height, + ], + ), + ), + ), + ); + })); + } + + static Future rejectRequestBottomSheet({@required BuildContext context}) { + final GlobalKey _formKey = GlobalKey(); + final userProvider = Provider.of(context, listen: false); + return showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => Consumer(builder: (context, serviceRequestProvider, child) { + return Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.rejectionReason.heading3(context).custom(fontWeight: FontWeight.w600).paddingOnly(top: 16, bottom: 16), + ), + SingleItemDropDownMenu( + context: context, + title: context.translation.rejectionReason, + initialValue: serviceRequestProvider.currentSelectedRequest.firstAction, //_serviceRequest.firstAction, + onSelect: (value) { + serviceRequestProvider.currentSelectedRequest.firstAction = value; + if (serviceRequestProvider.currentSelectedRequest.firstAction.value != 2) { + serviceRequestProvider.currentSelectedRequest.visitDate = null; + } + }, + ), + 8.height, + AppTextFormField( + labelText: context.translation.comments, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + onChange: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + onSaved: (text) { + serviceRequestProvider.currentSelectedRequest.comments = text; + }, + ), + 16.height, + Consumer( + builder: (context, snapshot, _) => AppFilledButton( + label: context.translation.reject, + maxWidth: true, + buttonColor: Colors.white54, + textColor: AppColor.red50, + showBorder: true, + loading: snapshot.isLoading ?? false, + onPressed: () async { + _formKey.currentState.save(); + // serviceRequestProvider.serviceRequest.device = asset; + await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.currentSelectedRequest); + Navigator.pop(context, true); + }, + ), + ), + 16.height, + ], + ), + ), + ), + ); + })); + } + + static Future activityTypeBottomSheet({@required BuildContext context}) { + final List> items = [ + {'heading': context.translation.sparePartRequest, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.sparePartIcon}, + {'heading': context.translation.maintenanceRequest, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.maintenanceIcon}, + {'heading': context.translation.assetToBeRetired, 'subHeading': context.translation.sparePartRequestDetail, 'icon': AppAsset.retiredAssetIcon}, + ]; + Widget listItem({@required BuildContext context, @required String icon, @required String heading, @required String subHeading, @required VoidCallback onTap}) { + return Padding( + padding: EdgeInsets.only(bottom: 8.toScreenHeight), + child: Card( + color: AppColor.neutral80, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + // Circular border radius + ), + // color: Colors.white, + child: ListTile( + minVerticalPadding: 8, + horizontalTitleGap: 10, + onTap: onTap, + contentPadding: const EdgeInsets.all(8), + leading: SvgPicture.asset(icon), + title: Text( + heading, + style: AppTextStyles.heading5, + ), + subtitle: Text( + subHeading, + style: AppTextStyles.bodyText, + ), + ), + ), + ); + } + + void onItemTap({@required int index, @required ServiceRequest serviceRequest, @required BuildContext context}) { + print('on item tap i got index is $index'); + switch (index) { + case 0: + Navigator.of(context).push(MaterialPageRoute(builder: (_) => const SparePartRequest())); + + break; + case 1: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => ActivitiesListView()), + // ); + break; + case 2: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const ScanQrView()), + // ); + break; + case 2: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const ScanQrView()), + // ); + break; + } + // ScanQr + } + + return showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: false, + backgroundColor: Colors.transparent, + builder: (context) => Consumer(builder: (context, serviceRequestProvider, child) { + return Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: AppColor.background(context), + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: SafeArea( + child: Column( + children: [ + Align( + alignment: AlignmentDirectional.centerStart, + child: context.translation.selectActivityType.heading4(context).paddingOnly(top: 16, bottom: 16), + ), + ListView.builder( + shrinkWrap: true, + padding: EdgeInsets.zero, + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + return listItem( + icon: item['icon'], + heading: item['heading'], + subHeading: item['subHeading'], + context: context, + onTap: () { + onItemTap(serviceRequest: serviceRequestProvider.currentSelectedRequest, index: index, context: context); + }); + }, + ), + ], + ), + ), + ); + })); + } + + static Future actionBottomSheet({@required BuildContext context, @required String title, String button1Text, String button2Text, VoidCallback button1Tap, VoidCallback button2Tap}) { + final GlobalKey _formKey = GlobalKey(); + final userProvider = Provider.of(context, listen: false); + return showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => Consumer(builder: (context, serviceRequestProvider, child) { + return Container( + clipBehavior: Clip.antiAlias, + margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)), + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40.toScreenWidth, + height: 5.toScreenHeight, + decoration: BoxDecoration(color: AppColor.neutral40, borderRadius: BorderRadius.circular(30)), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: title.heading4(context).custom(fontWeight: FontWeight.w500).paddingOnly(top: 16, bottom: 16), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + width: 200.toScreenHeight, + child: AppFilledButton( + label: button1Text ?? context.translation.no, + loading: false, + buttonColor: AppColor.neutral40, + textColor: AppColor.balck10, + onPressed: button1Tap ?? + () async { + Navigator.pop(context); + // await snapshot.updateRequest(user: userProvider.user, request: serviceRequestProvider.serviceRequest); + // Navigator.pop(context, true); + }, + ), + ), + SizedBox( + width: 200.toScreenHeight, + child: AppFilledButton( + label: context.translation.yes, + buttonColor: AppColor.primary10, + loading: false, + onPressed: button2Tap, + ), + ), + ], + ) + ], + ), + ); + })); + } +} diff --git a/lib/service_request_latest/views/components/history_log_view.dart b/lib/service_request_latest/views/components/history_log_view.dart new file mode 100644 index 00000000..188464fb --- /dev/null +++ b/lib/service_request_latest/views/components/history_log_view.dart @@ -0,0 +1,60 @@ +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/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.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/common_widgets/default_app_bar.dart'; + +class HistoryLogView extends StatelessWidget { + const HistoryLogView({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.neutral100, + body: Padding( + padding: EdgeInsets.symmetric(vertical: 50.toScreenHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + historyLogCard(context: context,date: DateTime.now()), + historyLogCard(context: context,date: DateTime.now()), + historyLogCard(context: context,date: DateTime.now()), + historyLogCard(context: context,date: DateTime.now()), + ], + ), + ), + ); + } + + Widget historyLogCard({@required BuildContext context, @required DateTime date}) { + return SizedBox( + width: double.infinity, + child: Padding( + padding: EdgeInsets.only(left: 16.toScreenWidth, bottom: 16.toScreenHeight, top: 12.toScreenHeight), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + Text( + date.toString().toServiceRequestCardFormat, + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral20), + ), + ], + ), + 50.width, + Expanded( + child: 'Requester acknowledged adc dld a'.heading6(context), + ), + ], + ), + ), + ).toShadowContainer(context).paddingOnly(start: 16, end: 16); + } +} diff --git a/lib/service_request_latest/views/components/scan_qr_view.dart b/lib/service_request_latest/views/components/scan_qr_view.dart new file mode 100644 index 00000000..23740b79 --- /dev/null +++ b/lib/service_request_latest/views/components/scan_qr_view.dart @@ -0,0 +1,72 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:qr_code_scanner/qr_code_scanner.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; + + +class ScanQrView extends StatefulWidget { + const ScanQrView({Key key}) : super(key: key); + + @override + _ScanQrViewState createState() => _ScanQrViewState(); +} + +class _ScanQrViewState extends State { + Barcode result; + QRViewController _controller; + bool _scanDone = false; + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR_scanner'); + + // In order to get hot reload to work we need to pause the camera if the platform + // is android, or resume the camera if the platform is iOS. + @override + void reassemble() { + super.reassemble(); + if (Platform.isAndroid) { + _controller?.pauseCamera(); + } else if (Platform.isIOS) { + _controller?.resumeCamera(); + } + } + + @override + void dispose() { + super.dispose(); + _controller?.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + + body: Stack( + children: [ + QRView( + key: qrKey, + onQRViewCreated: (QRViewController controller) { + setState(() { + _controller = controller; + }); + controller.scannedDataStream.listen((scanData) { + if (!_scanDone) { + _scanDone = true; + Navigator.of(context).pop(scanData.code); + } + }); + }, + overlay: QrScannerOverlayShape(borderColor: Colors.red, borderRadius: 10, borderLength: 30, borderWidth: 10, cutOutSize: 280), + ), + Padding( + padding: EdgeInsets.all(12.0), + child: SizedBox( + height: 100.toScreenHeight, + child: DefaultAppBar(title: context.translation.scanQr)), + ) + ], + ), + ); + } +} diff --git a/lib/service_request_latest/views/components/spare_part_request.dart b/lib/service_request_latest/views/components/spare_part_request.dart new file mode 100644 index 00000000..68077dec --- /dev/null +++ b/lib/service_request_latest/views/components/spare_part_request.dart @@ -0,0 +1,250 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/attachment.dart'; +import 'package:test_sa/controllers/providers/api/parts_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/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/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/device/asset.dart'; +import 'package:test_sa/models/service_request/service_report.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/single_item_drop_down_menu.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/providers/work_order/reason_provider.dart'; +import 'package:test_sa/service_request_latest/views/components/bottom_sheets/action_bottomsheet.dart'; +import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/part_no_button.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; +import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart'; +import '../../../../../models/lookup.dart'; +import '../../../../../models/service_request/spare_parts.dart'; +import '../../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../../new_views/common_widgets/default_app_bar.dart'; +import '../../../controllers/validator/validator.dart'; + +class SparePartRequest extends StatefulWidget { + static const String id = "/spare-part-request"; + + const SparePartRequest({Key key}) : super(key: key); + + @override + _SparePartRequestState createState() => _SparePartRequestState(); +} + +class _SparePartRequestState extends State with TickerProviderStateMixin { + UserProvider _userProvider; + SettingProvider _settingProvider; + ServiceRequestsProvider _serviceRequestsProvider; + ServiceStatusProvider _assetTypeProvider; + PartsProvider _partsProvider; + ServiceReport _serviceReport; + bool _isLoading = false; + List _spareParts = []; + + final List _files = []; + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + final TextEditingController _faultController = TextEditingController(); + final TextEditingController _workPreformedController = TextEditingController(); + final TextEditingController _partQtyController = TextEditingController(); + final TextEditingController _oracleNoController = TextEditingController(); + + @override + void initState() { + _serviceReport = ServiceReport( + // returnToService: DateTime.now(), + // //type: const Lookup(value: 2), + // device: widget.request.device, + sparePartsWorkOrders: [], + ); + super.initState(); + if (context.mounted) { + ServiceRequestsProvider serviceRequestsProvider = Provider.of(context, listen: false); + Provider.of(context, listen: false).reset(); + Provider.of(context, listen: false).reset(); + Provider.of(context, listen: false).serviceRequestId = serviceRequestsProvider.currentSelectedRequest.id; + } + // _isLoading = true; + } + + Asset loanAvailabilityAsset; + + @override + void dispose() { + _faultController.dispose(); + _workPreformedController.dispose(); + _partQtyController.dispose(); + super.dispose(); + } + + void getRequestForWorkOrder() async { + _isLoading = true; + setState(() {}); + ServiceRequestsProvider serviceRequestsProvider = Provider.of(context, listen: false); + _serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: serviceRequestsProvider.currentSelectedRequest.id); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee; + _serviceReport.equipmentStatus = _serviceReport.callRequest?.defectType; + _serviceReport.serviceType = Lookup(id: 65, name: "Interval", value: 1); // default value in service type as in web + _spareParts = await _partsProvider.getPartsList(assetId: serviceRequestsProvider.currentSelectedRequest.deviceId); + _isLoading = false; + setState(() {}); + } + + @override + Widget build(BuildContext context) { + _userProvider = Provider.of(context); + _settingProvider = Provider.of(context); + _serviceRequestsProvider = Provider.of(context); + _assetTypeProvider = Provider.of(context); + _partsProvider = Provider.of(context); + if (_serviceReport.callRequest == null) { + getRequestForWorkOrder(); + } + _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _serviceReport.callRequest?.assetType, + orElse: () => null, + ); + + return Scaffold( + key: _scaffoldKey, + appBar: DefaultAppBar(title: context.translation.sparePartRequest), + body: Consumer(builder: (context, serviceRequestProvider, child) { + return SafeArea( + child: LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Form( + key: _formKey, + child: Column( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + context.translation.sparePartDetails.heading5(context), + 12.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.partNo, + staticData: _spareParts, + height: 80.toScreenHeight, + showShadow: false, + initialValue: serviceRequestProvider.initialSelectedSparePart.sparePart, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, + onSelect: (part) { + serviceRequestProvider.initialSelectedSparePart = SparePartsWorkOrders(id: 0, sparePart: part, qty: 0); + }, + ), + 15.height, + AppTextFormField( + controller: _partQtyController, + labelText: context.translation.quantity, + textInputType: TextInputType.number, + contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight), + showWithoutDecoration: true, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, + enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null, + validator: (value) => value == null || value.isEmpty + ? context.translation.requiredField + : Validator.isNumeric(value) + ? null + : context.translation.onlyNumbers, + onSaved: (text) { + serviceRequestProvider.initialSelectedSparePart.qty = num.tryParse(text ?? ""); + }, + ), + 15.height, + AppTextFormField( + controller: _oracleNoController, + labelText: context.translation.oracleNo, + textInputType: TextInputType.number, + contentPadding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 20.toScreenHeight), + showWithoutDecoration: true, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, + enable: serviceRequestProvider.initialSelectedSparePart != null && serviceRequestProvider.initialSelectedSparePart.sparePart?.id != null, + validator: (value) => value == null || value.isEmpty + ? context.translation.requiredField + : Validator.isNumeric(value) + ? null + : context.translation.onlyNumbers, + onSaved: (text) { + //TODO set the values... + // serviceRequestProvider.initialSelectedSparePart. = num.tryParse(text ?? ""); + }, + ), + 15.height, + AppTextFormField( + initialValue: _serviceReport?.comment, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, + labelText: context.translation.description, + alignLabelWithHint: true, + showWithoutDecoration: true, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.comment = value; + }, + ), + 15.height, + MultiFilesPicker(label: context.translation.attachQuotation, files: _files), + ], + ).paddingAll(16), + ), + 8.height, + ], + ), + ).expanded, + AppFilledButton( + label: context.translation.addSparePartActivity, + buttonColor: AppColor.green70, + onPressed: () async { + ServiceRequestBottomSheet.actionBottomSheet(context: context, title: context.translation.addSparePartActionHeading); + // bool shouldReloadData = (await showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // backgroundColor: Colors.transparent, + // builder: (context) => ActionBottomSheet(title: context.translation.addSparePartActionHeading), + // )) as bool; + // if (shouldReloadData ?? false) {} + //TODO write add sparepart logic + + // if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate(context)))) { + // setState(() {}); + // return; + // } + // _formKey.currentState.save(); + // _serviceReport.attachmentsWorkOrder ??= []; + // if (_files.isEmpty) _serviceReport.attachmentsWorkOrder = []; + // for (var file in _files) { + // _serviceReport.attachmentsWorkOrder.add(Attachment(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}")); + // } + // final user = Provider.of(context, listen: false).user; + // await _serviceRequestsProvider.createServiceReport(context, report: _serviceReport, request: serviceRequestProvider.serviceRequest, user: user); + }, + ), + ], + ).paddingAll(16), + ), + ), + ); + }), + ); + } +} diff --git a/lib/service_request_latest/views/components/verify_arrival_view.dart b/lib/service_request_latest/views/components/verify_arrival_view.dart new file mode 100644 index 00000000..5aa9d97a --- /dev/null +++ b/lib/service_request_latest/views/components/verify_arrival_view.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/app_strings/app_asset.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.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/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/service_request_latest/views/components/scan_qr_view.dart'; +import 'package:test_sa/views/widgets/qr/scan_qr.dart'; + +import 'activities_list_view.dart'; + +class VerifyArrivalView extends StatelessWidget { + VerifyArrivalView({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final List> items = [ + {'heading': context.translation.scanQr, 'subHeading': context.translation.scanQrDetail, 'icon': AppAsset.scanQrIcon}, + {'heading': context.translation.askRequester, 'subHeading': context.translation.askRequesterDetail, 'icon': AppAsset.askRequesterIcon}, + {'heading': context.translation.askOtp, 'subHeading': context.translation.askOtpDetail, 'icon': AppAsset.askOtpIcon}, + {'heading': context.translation.takeDevicePhoto, 'subHeading': context.translation.takeDevicePhotoDetail, 'icon': AppAsset.takeDevicePhotoIcon}, + ]; + return Scaffold( + appBar: DefaultAppBar(title: context.translation.verifyArrival), + //backgroundColor: const Color(0xfff8f9fb), + body: Consumer(builder: (context, serviceRequestsProvider, child) { + return SafeArea( + child: ListView.builder( + padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight), + // padding: EdgeInsets.zero, + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + return listItem( + icon: item['icon'], + heading: item['heading'], + subHeading: item['subHeading'], + context: context, + onTap: () { + + onItemTap(serviceRequest: serviceRequestsProvider.currentSelectedRequest, index: index,context: context); + }); + }, + ), + ); + }), + ); + } + + Widget listItem({@required BuildContext context, @required String icon, @required String heading, @required String subHeading, @required VoidCallback onTap}) { + return Padding( + padding: EdgeInsets.only(left: 16.toScreenWidth,right: 16.toScreenWidth,bottom: 12.toScreenHeight), + + child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(14), // Circular border radius + ), + color: Colors.white, + child: + ListTile( + minVerticalPadding: 12, + horizontalTitleGap: 10, + onTap: onTap, + // contentPadding: const EdgeInsets.all(12), + leading: SvgPicture.asset(icon), + title: Text( + heading, + style: AppTextStyles.heading5, + ), + subtitle: Text( + subHeading, + style: AppTextStyles.bodyText, + ), + ), + ), + ); + } + + void onItemTap({@required int index, @required ServiceRequest serviceRequest,@required BuildContext context}) { + print('on item tap i got index is $index'); + switch(index){ + case 0: + Navigator.push( + context, + MaterialPageRoute(builder: (context) => const ScanQrView()), + ); + break;case 1: + //push to specific screen... + Navigator.push( + context, + MaterialPageRoute(builder: (context) => ActivitiesListView()), + ); + break;case 2: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const ScanQrView()), + // ); + break;case 2: + //push to specific screen... + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const ScanQrView()), + // ); + break; + } + // ScanQr + } +} diff --git a/lib/service_request_latest/views/components/verify_otp_view.dart b/lib/service_request_latest/views/components/verify_otp_view.dart new file mode 100644 index 00000000..fff00916 --- /dev/null +++ b/lib/service_request_latest/views/components/verify_otp_view.dart @@ -0,0 +1,124 @@ +import 'package:flutter/material.dart'; +import 'package:pinput/pinput.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/timer_model.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; +import 'package:test_sa/views/widgets/timer/app_timer.dart'; + +class VerifyOtpView extends StatelessWidget { + const VerifyOtpView({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final defaultPinTheme = PinTheme( + width: 51.toScreenWidth, + height: 63.toScreenHeight, + textStyle: const TextStyle( + fontSize: 22, + color: Colors.black, + ), + decoration: BoxDecoration( + color: AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: Colors.transparent), + ), + ); + return Scaffold( + backgroundColor: AppColor.neutral100, + appBar: DefaultAppBar(title: context.translation.askOtpFromRequester), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 12.height, + SizedBox( + width: double.infinity, + child: Padding( + padding: EdgeInsets.only(left: 16.toScreenWidth, bottom: 16.toScreenHeight, top: 12.toScreenHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + context.translation.verify.heading5(context), + 12.height, + context.translation.otpSentToNumber.bodyText(context), + Padding( + padding: EdgeInsets.symmetric( + vertical: 50.toScreenHeight, + ), + child: Center( + child: Pinput( + length: 4, + defaultPinTheme: defaultPinTheme, + focusedPinTheme: defaultPinTheme.copyWith( + decoration: defaultPinTheme.decoration?.copyWith( + border: Border.all(color: AppColor.neutral100), + ), + ), + onCompleted: (pin) => debugPrint(pin), + ), + ), + ), + Row( + children: [ + context.translation.resendIn.bodyText(context), + 7.width, + ValueListenableBuilder( + //add actual timer value... + valueListenable: ValueNotifier("0:00"), + builder: (context, value, _) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + value.bodyText(context).custom( + color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, + ), + ], + ); + }, + ), + 7.width, + InkWell( + onTap: (){ + //other method check.. + }, + child: Text(context.translation.resend,style: const TextStyle( + color: AppColor.primary10, + decoration: TextDecoration.underline, + ),), + ), + ], + ), + ], + ), + ), + ).toShadowContainer(context).paddingOnly(start: 16, end: 16), + Padding( + padding: EdgeInsets.only(left: 17.toScreenWidth, top: 24.toScreenHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + context.translation.havingTroubleReceivingOtp.heading6(context), + 3.height, + InkWell( + onTap: (){ + //other method check.. + }, + child: Text(context.translation.checkOutOtherMethods,style: const TextStyle( + color: AppColor.primary10, + decoration: TextDecoration.underline, + ),), + ), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/service_request_latest/views/request_detail_view.dart b/lib/service_request_latest/views/request_detail_view.dart new file mode 100644 index 00000000..dd0f041d --- /dev/null +++ b/lib/service_request_latest/views/request_detail_view.dart @@ -0,0 +1,393 @@ +import 'package:another_flushbar/flushbar.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/comments_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/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/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; +import 'package:test_sa/service_request_latest/views/components/bottom_sheets/reject_request_bottomsheet.dart'; +import 'package:test_sa/service_request_latest/views/components/verify_otp_view.dart'; +import 'package:test_sa/utilities/general_utils.dart'; +import 'package:test_sa/views/pages/user/requests/comments_bottom_sheet.dart'; +import 'package:test_sa/views/pages/user/requests/first_action_bottom_sheet.dart'; +import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart'; +import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.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/request_status.dart'; +import 'package:test_sa/views/widgets/sound/sound_player.dart'; + +import 'components/bottom_sheets/initial_visit_bottomsheet.dart'; + +class ServiceRequestDetailView extends StatefulWidget { + static const String id = "/call-details"; + ServiceRequest serviceRequest; + + ServiceRequestDetailView({Key key, this.serviceRequest}) : super(key: key); + + @override + State createState() => _ServiceRequestDetailViewState(); +} + +class _ServiceRequestDetailViewState extends State { + bool loading = false; + + // ServiceRequest serviceRequest; + + @override + void initState() { + super.initState(); + getServiceRequest(requestId: widget.serviceRequest.id); + } + + void getServiceRequest({@required dynamic requestId}) { + // setState(() {}); + WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) async { + Provider.of(context, listen: false).reset(); + ServiceRequestsProvider serviceRequestsProvider = Provider.of(context, listen: false); + serviceRequestsProvider.currentSelectedRequest = await serviceRequestsProvider.getServiceRequestObjectById(requestId: requestId); + // setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + UserProvider _userProvider = Provider.of(context, listen: false); + + Widget informationCard(ServiceRequest serviceRequest) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + StatusLabel( + label: serviceRequest.priority.name, + id: serviceRequest.priority.id, + textColor: AppColor.getPriorityStatusTextColor(context, serviceRequest.priority.id), + backgroundColor: AppColor.getPriorityStatusColor(context, serviceRequest.priority.id), + ), + 8.width, + StatusLabel( + label: serviceRequest.statusLabel, + textColor: AppColor.getRequestStatusTextColor(context, serviceRequest.statusValue), + backgroundColor: AppColor.getRequestStatusColor(context, serviceRequest.statusValue), + ), + 1.width.expanded, + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (_userProvider.user.type == UsersTypes.normal_user) + context.translation.code.toSvgAsset(width: 48).onPress(() { + Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest))); + }), + if (_userProvider.user.type == UsersTypes.engineer) 16.height, + Text( + serviceRequest.date.toServiceRequestCardFormat, + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + ], + ) + ], + ), + Text( + context.translation.assetDetails, + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + '${context.translation.assetName}: ${serviceRequest.deviceEnName?.cleanupWhitespace?.capitalizeFirstOfEach}'.bodyText(context), + // 8.height, + Text( + '${context.translation.assetNumber}: ${serviceRequest.device?.assetNumber}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + + Text( + '${context.translation.equipmentStatus}: ${serviceRequest.defectType?.name}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.manufacture}: ${serviceRequest.device.modelDefinition.manufacturerName?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.model}: ${serviceRequest.device.modelDefinition.modelName?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.site}: ${serviceRequest.device.site?.custName?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.building}: ${serviceRequest.device.building?.name?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.floor}: ${serviceRequest.device.floor?.name?.cleanupWhitespace?.capitalizeFirstOfEach ?? ""}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.department}: ${serviceRequest.device.department?.departmentName?.cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.room}: ${(serviceRequest.device.room?.name ?? "").cleanupWhitespace?.capitalizeFirstOfEach}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + ], + ).expanded, + ], + ), + 8.height, + const Divider().defaultStyle(context), + + //... request details starts here.... + Text( + context.translation.requestDetail, + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + Text( + '${context.translation.requestType}: ${serviceRequest.type.name}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.requestNo}: ${serviceRequest.requestCode}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + Text( + '${context.translation.requesterName}: ${serviceRequest.callCreatedBy?.name ?? "-"}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + + 8.height, + if ((serviceRequest.callComments ?? "").isNotEmpty) ...[ + const Divider().defaultStyle(context), + 8.height, + Text( + serviceRequest.callComments, + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + ], + if (serviceRequest.devicePhotos.isNotEmpty) ...[ + 8.height, + const Divider().defaultStyle(context), + FilesList(images: serviceRequest.devicePhotos), + ], + if (serviceRequest.audio?.isNotEmpty ?? false) ...[ + const Divider().defaultStyle(context), + 16.height, + ASoundPlayer(audio: serviceRequest.audio), + 8.height, + ], + ], + ).paddingOnly(start: 16, end: 16, top: 16, bottom: 8), + (_userProvider.user.type == UsersTypes.normal_user + ? Container( + height: 50, + padding: const EdgeInsets.only(left: 16, right: 16), + alignment: Alignment.center, + width: double.infinity, + decoration: ShapeDecoration( + color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20), + bottomRight: Radius.circular(20), + ), + ), + ), + child: Row( + children: [ + Text( + '${context.translation.commentHere}...', + style: AppTextStyles.heading6.copyWith( + color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), + ), + ).expanded, + "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), + ], + ), + ) + : Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider().defaultStyle(context), + 16.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.viewComments, + style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + ), + 4.width, + Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + ], + ), + ], + ).paddingOnly(bottom: 16, start: 16, end: 16)) + .onPress(() { + showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + useRootNavigator: true, + backgroundColor: Colors.transparent, + builder: (context) => CommentsBottomSheet(requestId: serviceRequest.id), + ); + }), + ], + ).toShadowContainer(context, padding: 0); + } + + return Scaffold( + appBar: DefaultAppBar(title: context.translation.serviceDetails), + //backgroundColor: const Color(0xfff8f9fb), + body: Consumer(builder: (context, serviceRequestsProvider, child) { + return SafeArea( + child: serviceRequestsProvider.isDetialLoading + ? const ALoading().center + : serviceRequestsProvider.currentSelectedRequest == null + ? Text( + context.translation.noDataFound, + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ).center + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: informationCard(serviceRequestsProvider.currentSelectedRequest), + ).expanded, + Center( + child: InkWell( + onTap: () async { + AllRequestsProvider allRequestProvider = Provider.of(context, listen: false); + int index = allRequestProvider.filterRequest.requestsDetails.indexWhere((element) => element.id.toString() == serviceRequestsProvider.currentSelectedRequest.id); + print('index i got is $index'); + if (index != -1 && index != allRequestProvider.filterRequest.requestsDetails.length) { + print('loading value is $loading'); + getServiceRequest(requestId: allRequestProvider.filterRequest.requestsDetails[index + 1].id.toString()); + print('call the api with next id ...${allRequestProvider.filterRequest.requestsDetails[index + 1].id.toString()}'); + } + }, + child: Text( + context.translation.skipForLater, + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, decoration: TextDecoration.underline, fontSize: 16), + ), + ), + ), + 20.height, + if (_userProvider.user.type == UsersTypes.engineer || + (serviceRequestsProvider.currentSelectedRequest.statusValue == 5 || serviceRequestsProvider.currentSelectedRequest.statusValue == 3)) + (serviceRequestsProvider.currentSelectedRequest?.firstAction == null + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + AppFilledButton( + label: context.translation.reject, + maxWidth: true, + buttonColor: Colors.white54, + textColor: AppColor.red50, + showBorder: true, + onPressed: () async { + print('service request value is ${serviceRequestsProvider.currentSelectedRequest.type}'); + ServiceRequestBottomSheet.rejectRequestBottomSheet(context: context); + // bool shouldReloadData = (await showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // backgroundColor: Colors.transparent, + // builder: (context) => RejectRequestBottomSheet(), + // )) as bool; + // if (shouldReloadData ?? false) { + // getServiceRequest(); + // } + }, + ).expanded, + const SizedBox( + width: 20, + ), + AppFilledButton( + label: context.translation.accept, + maxWidth: true, + buttonColor: AppColor.green70, + onPressed: () async { + // GeneralUtils.showFlushBar(context: context); + Navigator.of(context).push(MaterialPageRoute(builder: (_) => const VerifyOtpView())); + + // ServiceRequestBottomSheet.fixRemotelyBottomSheet(context: context); + // bool shouldReloadData = (await showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // backgroundColor: Colors.transparent, + // builder: (context) => InitialVisitBottomSheet(), + // )) as bool; + // if (shouldReloadData ?? false) { + // getServiceRequest(); + // } + }, + ).expanded, + ], + ) + // ? AppFilledButton( + // label: context.translation.firstAction, + // maxWidth: true, + // onPressed: () async { + // bool shouldReloadData = (await showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // backgroundColor: Colors.transparent, + // builder: (context) => FirstActionBottomSheet(request: serviceRequestsProvider.serviceRequest), + // )) as bool; + // if (shouldReloadData ?? false) { + // getServiceRequest(); + // } + // }, + // ) + : AppFilledButton( + label: context.translation.viewWorkOrder, + maxWidth: true, + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => WorkOrderListPage(serviceRequest: serviceRequestsProvider.currentSelectedRequest)), + ); + // Navigator.of(context).pushNamed(WorkOrderListPage.id, arguments: serviceRequest); + }, + )) + .paddingOnly(start: 16, end: 16, bottom: 24), + ], + ), + ); + }), + ); + } +} diff --git a/lib/utilities/general_utils.dart b/lib/utilities/general_utils.dart new file mode 100644 index 00000000..43633bc4 --- /dev/null +++ b/lib/utilities/general_utils.dart @@ -0,0 +1,48 @@ +import 'package:another_flushbar/flushbar.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; + +class GeneralUtils{ + + static Duration parseTimeString(String timeString) { + try { + print('time string i got is ${timeString}'); + List timeParts = timeString.split(':'); + + int hours = int.parse(timeParts[0]); + int minutes = int.parse(timeParts[1]); + int seconds = int.parse(timeParts[2]); + + print(''); + + return Duration(hours: hours, minutes: minutes, seconds: seconds); + } catch (e) { + if (kDebugMode) { + print("Error parsing time string: $e"); + } + return Duration.zero; // Return zero duration in case of an error + } + } + static Widget showFlushBar({@required BuildContext context,String title,String message,double duration}){ + return Flushbar( + flushbarPosition: FlushbarPosition.TOP, + backgroundColor: AppColor.green70, + title:title?? "Hey Ninja", + message:message?? "Lorem Ipsum is simply dummy text of the printing and typesetting industry", + duration: Duration(seconds:duration?? 3), + flushbarStyle: FlushbarStyle.GROUNDED, + reverseAnimationCurve: Curves.easeInOut, + mainButton: IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: const Icon( + Icons.close, + color: AppColor.white20, + ), + ), + )..show(context); + } +} \ No newline at end of file diff --git a/lib/utilities/request_utils.dart b/lib/utilities/request_utils.dart new file mode 100644 index 00000000..81c441cc --- /dev/null +++ b/lib/utilities/request_utils.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/enums/user_types.dart'; + +class RequestUtils{ + static List> getTabs({@required UsersTypes userType,@required BuildContext context}) { + List> tabs = []; + if(userType==UsersTypes.engineer){ + tabs.add({'label':'In Progress','status':2}); + tabs.add({'label':'Completed','status':4}); + return tabs; + } + tabs.add({'label':'New Request','status':1}); + tabs.add({'label':'In Progress','status':2}); + tabs.add({'label':'Completed','status':4}); + return tabs; + + } +} \ No newline at end of file diff --git a/lib/views/app_style/colors.dart b/lib/views/app_style/colors.dart index 0c4f5e3b..82a7302c 100644 --- a/lib/views/app_style/colors.dart +++ b/lib/views/app_style/colors.dart @@ -132,7 +132,7 @@ // } // } // -// static Color getPriorityStatusColor(int id) { +// static Color getPriorityStatusColor(int id) {l // switch (id) { // case 81: // return AColors.statusGreenLight; diff --git a/lib/views/pages/user/requests/requests_page.dart b/lib/views/pages/user/requests/requests_page.dart index bb69111a..9f020ca3 100644 --- a/lib/views/pages/user/requests/requests_page.dart +++ b/lib/views/pages/user/requests/requests_page.dart @@ -44,7 +44,8 @@ class _ServiceRequestsPageState extends State with TickerPr _serviceRequestsProvider.reset(); await _serviceRequestsProvider.getRequests(hospitalId: _userProvider.user.clientId); }, - child: ServiceRequestsList( + child: + ServiceRequestsList( nextPage: _serviceRequestsProvider.nextPage, onLazyLoad: () async { await _serviceRequestsProvider.getRequests(hospitalId: _userProvider.user.clientId); diff --git a/lib/views/pages/user/requests/work_order/work_order_details_page.dart b/lib/views/pages/user/requests/work_order/work_order_details_page.dart index 7c99f4bc..d711c931 100644 --- a/lib/views/pages/user/requests/work_order/work_order_details_page.dart +++ b/lib/views/pages/user/requests/work_order/work_order_details_page.dart @@ -32,7 +32,7 @@ class WorkOrderDetailsPage extends StatelessWidget { Widget build(BuildContext context) { UserProvider userProvider = Provider.of(context); return Scaffold( - appBar: DefaultAppBar(title: context.translation.workOrder), + appBar: DefaultAppBar(title: context.translation.activities), body: FutureBuilder( future: Provider.of(context).getSingleServiceReport(context, reportId: workOrder.id), builder: (context, snapshot) { @@ -98,7 +98,7 @@ class WorkOrderDetailsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ if (userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) - Align(alignment: AlignmentDirectional.centerEnd, child: "edit".toSvgAsset(height: 48, width: 48)).onPress(() { + Align(alignment: AlignmentDirectional.centerEnd, child: "edit_icon".toSvgAsset(height: 21, width: 21)).onPress(() { Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdateServiceReport(workOrder: workOrder, request: serviceRequest))); }), // if (userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) 8.height, diff --git a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart index 37fabe53..b29e2383 100644 --- a/lib/views/pages/user/requests/work_order/work_orders_list_page.dart +++ b/lib/views/pages/user/requests/work_order/work_orders_list_page.dart @@ -13,6 +13,7 @@ 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/service_request_latest/views/components/activity_card_view.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/update_service_report.dart'; import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart'; @@ -34,7 +35,7 @@ class WorkOrderListPage extends StatelessWidget { UserProvider _userProvider = Provider.of(context); serviceRequestsProvider ??= Provider.of(context); return Scaffold( - appBar: DefaultAppBar(title: context.translation.workOrders), + appBar: DefaultAppBar(title: context.translation.activities), //backgroundColor: const Color(0xfff8f9fb), body: SafeArea( child: FutureBuilder( @@ -51,64 +52,67 @@ class WorkOrderListPage extends StatelessWidget { itemCount: workOrders.length, separatorBuilder: (czt, index) => 8.height, itemBuilder: (context, index) { - return Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - StatusLabel( - label: workOrders[index].currentSituation.name, - textColor: AppColor.getRequestStatusTextColorByName(context, workOrders[index].currentSituation.name), - backgroundColor: AppColor.getRequestStatusColorByName(context, workOrders[index].currentSituation.name), - ), - 8.height, - Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), - Text( - '${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName?.cleanupWhitespace?.capitalizeFirstOfEach}', - style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), - ), - Text( - '${context.translation.currentSituation}: ${workOrders[index].currentSituation.name}', - style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), - ), - 16.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.translation.viewDetails, - style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), - ), - 4.width, - Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) - ], - ), - ], - ).onPress(() { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrders[index], serviceRequest: serviceRequest)), - ); - }).expanded, - Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) - "edit".toSvgAsset(height: 48, width: 48).onPress(() { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrders[index])), - ); - }), - if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) 8.height, - Text(workOrders[index].visitDate?.toServiceRequestCardFormat ?? "", - textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : const Color(0xFF3B3D4A))), - ], - ) - ], - ).toShadowContainer(context); + return ActivityCardView(workOrders[index], serviceRequest); + + //older code.... + // Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Column( + // mainAxisSize: MainAxisSize.min, + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // StatusLabel( + // label: workOrders[index].currentSituation.name, + // textColor: AppColor.getRequestStatusTextColorByName(context, workOrders[index].currentSituation.name), + // backgroundColor: AppColor.getRequestStatusColorByName(context, workOrders[index].currentSituation.name), + // ), + // 8.height, + // Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), + // Text( + // '${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName?.cleanupWhitespace?.capitalizeFirstOfEach}', + // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + // ), + // Text( + // '${context.translation.currentSituation}: ${workOrders[index].currentSituation.name}', + // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + // ), + // 16.height, + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // context.translation.viewDetails, + // style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + // ), + // 4.width, + // Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14) + // ], + // ), + // ], + // ).onPress(() { + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrders[index], serviceRequest: serviceRequest)), + // ); + // }).expanded, + // Column( + // crossAxisAlignment: CrossAxisAlignment.end, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) + // "edit".toSvgAsset(height: 48, width: 48).onPress(() { + // Navigator.of(context).push( + // MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrders[index])), + // ); + // }), + // if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3) 8.height, + // Text(workOrders[index].visitDate?.toServiceRequestCardFormat ?? "", + // textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : const Color(0xFF3B3D4A))), + // ], + // ) + // ], + // ).toShadowContainer(context); }, ).expanded, if (_userProvider.user.type == UsersTypes.engineer && (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)) diff --git a/lib/views/widgets/buttons/rounded_back_button.dart b/lib/views/widgets/buttons/rounded_back_button.dart new file mode 100644 index 00000000..4a5d9755 --- /dev/null +++ b/lib/views/widgets/buttons/rounded_back_button.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class RoundedBackButton extends StatelessWidget { + final VoidCallback onPressed; + final IconData icon; + final Color backgroundColor; + final Color iconColor; + + const RoundedBackButton({Key key, this.onPressed,@required this.icon,this.backgroundColor,this.iconColor}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only(left: 8), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: backgroundColor??Colors.blue, // Background color of the circle + ), + child: Padding( + padding: const EdgeInsets.all(8), + child: Icon( + icon, + color: iconColor??Colors.white, + size: 22, // Adjust the icon size as needed + ), + ), + ); + } +} diff --git a/lib/views/widgets/date_and_time/date_picker.dart b/lib/views/widgets/date_and_time/date_picker.dart index 983163bc..8fa843b8 100644 --- a/lib/views/widgets/date_and_time/date_picker.dart +++ b/lib/views/widgets/date_and_time/date_picker.dart @@ -11,16 +11,22 @@ class ADatePicker extends StatelessWidget { final DateTime from; final DateTime to; final String label; + final bool hideShadow; + final String hint; final Function(DateTime) onDatePicker; final bool enable, withBorder; final Color backgroundColor; final bool formatDateWithTime; + final double height; const ADatePicker({ Key key, @required this.label, this.withBorder = true, + this.height, this.backgroundColor, + this.hideShadow=false, + this.hint, this.date, this.formatDateWithTime = false, this.onDatePicker, @@ -32,6 +38,7 @@ class ADatePicker extends StatelessWidget { @override Widget build(BuildContext context) { return Container( + height:height, decoration: BoxDecoration( color: backgroundColor ?? (context.isDark && (enable == false) @@ -41,7 +48,7 @@ class ADatePicker extends StatelessWidget { : AppColor.background(context)), borderRadius: BorderRadius.circular(10), border: withBorder ? Border.all(width: 1, color: Theme.of(context).scaffoldBackgroundColor) : const Border(), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + boxShadow: hideShadow?null: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), child: Row( @@ -54,7 +61,7 @@ class ADatePicker extends StatelessWidget { children: [ label.tinyFont(context), (date?.toIso8601String == null - ? context.translation.pickADate + ?hint?? context.translation.pickADate : (formatDateWithTime ? date?.toIso8601String()?.toFirstActionFormat : (date?.toIso8601String()?.split("T")?.first ?? context.translation.pickADate))) .bodyText(context) .custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), diff --git a/lib/views/widgets/date_and_time/time_picker.dart b/lib/views/widgets/date_and_time/time_picker.dart index 135083fb..2752d455 100644 --- a/lib/views/widgets/date_and_time/time_picker.dart +++ b/lib/views/widgets/date_and_time/time_picker.dart @@ -1,73 +1,87 @@ -///todo deleted -// import 'package:flutter/material.dart'; -// import 'package:test_sa/views/app_style/sizing.dart'; -// -// class ADateTimePicker extends StatelessWidget { -// final DateTime date; -// final DateTime from; -// final DateTime to; -// final Function(DateTime) onDateTimePicker; -// final bool enable; -// -// const ADateTimePicker({Key key, this.date, this.onDateTimePicker, this.from, this.to, this.enable}) : super(key: key); -// -// @override -// Widget build(BuildContext context) { -// return ElevatedButton( -// style: ElevatedButton.styleFrom( -// foregroundColor: Colors.white, -// textStyle: Theme.of(context).textTheme.subtitle2, -// shape: RoundedRectangleBorder( -// borderRadius: BorderRadius.circular(12 * AppStyle.getScaleFactor(context)), -// ), -// ), -// child: Text( -// date == null ? "Pick Time" : date.toString().substring(0, date.toString().lastIndexOf(":")), -// textScaleFactor: AppStyle.getScaleFactor(context), -// ), -// onPressed: enable -// ? () async { -// // TimeOfDay picked = await showTimePicker(context: context, initialTime: TimeOfDay.now()); -// onDateTimePicker(await showDateTimePicker(context: context, initialDate: date, firstDate: from, lastDate: to)); -// } -// : null, -// ); -// } -// } -// -// Future showDateTimePicker({ -// BuildContext context, -// DateTime initialDate, -// DateTime firstDate, -// DateTime lastDate, -// }) async { -// initialDate ??= DateTime.now(); -// firstDate ??= initialDate.subtract(const Duration(days: 365 * 100)); -// lastDate ??= firstDate.add(const Duration(days: 365 * 200)); -// -// final DateTime selectedDate = await showDatePicker( -// context: context, -// initialDate: initialDate, -// firstDate: firstDate, -// lastDate: lastDate, -// ); -// -// if (selectedDate == null) return null; -// -// if (!context.mounted) return selectedDate; -// -// final TimeOfDay selectedTime = await showTimePicker( -// context: context, -// initialTime: TimeOfDay.fromDateTime(selectedDate), -// ); -// -// return selectedTime == null -// ? selectedDate -// : DateTime( -// selectedDate.year, -// selectedDate.month, -// selectedDate.day, -// selectedTime.hour, -// selectedTime.minute, -// ); -// } +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/string_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; + +class ATimePicker extends StatelessWidget { + final TimeOfDay time; + final String label; + final String hint; + final Function(TimeOfDay) onTimePicker; + final bool enable, withBorder; + final Color backgroundColor; + final double height; + + const ATimePicker({ + Key key, + @required this.label, + this.withBorder = true, + this.height, + this.backgroundColor, + this.hint, + this.time, + this.onTimePicker, + this.enable = true, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + print('initial time in picker is $time'); + return Container( + height:height, + decoration: BoxDecoration( + color: backgroundColor ?? + (context.isDark && (enable == false) + ? AppColor.neutral50 + : (enable == false) + ? AppColor.neutral40 + : AppColor.background(context)), + borderRadius: BorderRadius.circular(10), + border: withBorder ? Border.all(width: 1, color: Theme.of(context).scaffoldBackgroundColor) : const Border(), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight), + child: Row( + children: [ + // enable + // ? + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + label.tinyFont(context), + (time == null + ?hint?? context.translation.pickTime + : (time.format(context)?? context.translation.pickADate)) + .bodyText(context) + .custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ], + ).expanded, + //: label.bodyText(context).paddingOnly(top: 8, bottom: 8), + enable ? 16.width : const Spacer(), + "calender".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null), + ], + ), + ).onPress(enable + ? () async { + // Define the initial time + TimeOfDay initialTime = TimeOfDay.now(); + + // Show the time picker with the initial time set + TimeOfDay pickedTime = await showTimePicker( + context: context, + initialTime: initialTime, + ); + + // Handle the selected time (if user didn't cancel) + if (pickedTime != null) { + if (onTimePicker != null) onTimePicker(pickedTime); + print("Selected time: ${pickedTime.format(context)}"); + } + } + : null); + } +} diff --git a/lib/views/widgets/requests/service_request_list.dart b/lib/views/widgets/requests/service_request_list.dart index 782769e8..9827338f 100644 --- a/lib/views/widgets/requests/service_request_list.dart +++ b/lib/views/widgets/requests/service_request_list.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -16,6 +18,7 @@ class ServiceRequestsList extends StatelessWidget { @override Widget build(BuildContext context) { + print('servies request page'); if (requests.length == 0) { return NoItemFound( message: context.translation.noServiceRequestFound, diff --git a/lib/views/widgets/timer/app_timer.dart b/lib/views/widgets/timer/app_timer.dart index 920e552f..55bf230c 100644 --- a/lib/views/widgets/timer/app_timer.dart +++ b/lib/views/widgets/timer/app_timer.dart @@ -14,6 +14,7 @@ class AppTimer extends StatefulWidget { final TimerModel timer; final Future Function(TimerModel) onChange; final TextStyle style; + final BoxDecoration decoration; final bool enabled; final String label; @@ -25,6 +26,7 @@ class AppTimer extends StatefulWidget { this.timer, this.onChange, this.style, + this.decoration, this.timerProgress, this.enabled = true, }) : super(key: key); @@ -111,7 +113,7 @@ class _AppTimerState extends State { width: 100 * AppStyle.getScaleFactor(context), height: 56.toScreenHeight, padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - decoration: BoxDecoration( + decoration:widget.decoration?? BoxDecoration( color: context.isDark && (widget.enabled == false) ? AppColor.neutral60 : (widget.enabled == false) diff --git a/localization_error.txt b/localization_error.txt new file mode 100644 index 00000000..b7a7b76f --- /dev/null +++ b/localization_error.txt @@ -0,0 +1,9 @@ +{ + "ar": [ + "returnToService", + "signInToYour", + "overdue", + "newR", + "noDataFound" + ] +} diff --git a/pubspec.lock b/pubspec.lock index 1fcfc4de..0fdf4ad9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.10" + another_flushbar: + dependency: "direct main" + description: + name: another_flushbar + sha256: "19bf9520230ec40b300aaf9dd2a8fefcb277b25ecd1c4838f530566965befc2a" + url: "https://pub.dev" + source: hosted + version: "1.12.30" archive: dependency: transitive description: @@ -89,6 +97,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + badges: + dependency: "direct main" + description: + name: badges + sha256: "6e7f3ec561ec08f47f912cfe349d4a1707afdc8dda271e17b046aa6d42c89e77" + url: "https://pub.dev" + source: hosted + version: "3.1.1" boolean_selector: dependency: transitive description: @@ -949,6 +965,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" + pinput: + dependency: "direct main" + description: + name: pinput + sha256: "7bf9aa7d0eeb3da9f7d49d2087c7bc7d36cd277d2e94cc31c6da52e1ebb048d0" + url: "https://pub.dev" + source: hosted + version: "5.0.0" platform: dependency: transitive description: @@ -1274,6 +1298,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + universal_platform: + dependency: transitive + description: + name: universal_platform + sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" + url: "https://pub.dev" + source: hosted + version: "1.1.0" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index c8ea53d4..f79dc6ee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,8 @@ dependencies: flutter_sound: ^9.2.13 permission_handler: ^10.2.0 rive: ^0.9.1 + another_flushbar: + pinput: audioplayers: ^1.1.1 flare_flutter: ^3.0.2 signature: ^5.3.0 @@ -75,6 +77,8 @@ dependencies: table_calendar: ^3.0.8 image_cropper: ^3.0.3 touchable: ^0.2.1 + badges: ^3.1.1 +# buttons_tabbar: ^1.1.2 flutter_month_picker: ^0.0.2 syncfusion_flutter_charts: ^21.2.3 local_auth: ^2.1.6