Merge remote-tracking branch 'origin/design_3.0_sdk_upgrade' into design_3.0_sdk_upgrade

# Conflicts:
#	lib/service_request_latest/views/components/verify_arrival_view.dart
design_3.0_latest
Sikander Saleem 1 year ago
commit d898dda015

@ -10,6 +10,7 @@ import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/new_models/gas_refill_model.dart';
import 'package:huawei_push/huawei_push.dart' as h_push;
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/service_request_latest/views/service_request_detail_main_view.dart';
import 'package:test_sa/views/pages/device_transfer/device_transfer_details.dart';
import 'package:test_sa/views/pages/user/gas_refill/gas_refill_details.dart';
import 'package:test_sa/views/pages/user/ppm/ppm_details_page.dart';
@ -65,7 +66,7 @@ class FirebaseNotificationManger {
}
static void _onMessageReceiveError(Object error) {
print("onMessageReceivedStream:${error?.toString()}");
print("onMessageReceivedStream:${error.toString()}");
}
static Future<bool> isGoogleServicesAvailable() async {
@ -83,7 +84,7 @@ class FirebaseNotificationManger {
Widget? serviceClass;
if (messageData["requestType"] == "Service request to engineer") {
serviceClass = ServiceRequestDetailsPage(serviceRequest: ServiceRequest(id: messageData["requestNumber"].toString()));
serviceClass = ServiceRequestDetailMain(requestId: messageData["requestNumber"]??'');
} else if (messageData["requestType"] == "Gas Refill") {
serviceClass = GasRefillDetailsPage(
priority: messageData["priority"],
@ -163,11 +164,14 @@ class FirebaseNotificationManger {
});
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('notification i got is ${message.toMap()}');
if (Platform.isAndroid) {
NotificationManger.showNotification(
title: message.notification?.title ?? "", subtext: message.notification?.body ?? "", hashcode: int.tryParse("1234" ?? "") ?? 1, payload: json.encode(message.data), context: context);
}
if(message.data["notificationType"]!='NurseConfirmArrive'){
NotificationManger.showNotification(
title: message.notification?.title ?? "", subtext: message.notification?.body ?? "", hashcode: int.tryParse("1234" ?? "") ?? 1, payload: json.encode(message.data), context: context);
}
}
return;
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {

@ -115,9 +115,10 @@ class AllRequestsProvider extends ChangeNotifier {
SearchAllRequestsModel? searchedModel;
Future<int> getAllRequests(BuildContext context, {int? typeTransaction, SearchAllRequestsModel? search}) async {
print('loading value is $isAllLoading');
if (isAllLoading == true) return -2;
isAllLoading = true;
if (_allRequestsAndCount == null) notifyListeners();
if (_allRequestsAndCount == null) notifyListeners();
Response response;
try {
if (search != null) {

@ -70,6 +70,7 @@ class _DashboardViewState extends State<DashboardView> {
if (isFCM) {
FirebaseNotificationManger.initialized(context);
NotificationManger.initialisation((notificationDetails) {
print('i am called with notification details ${notificationDetails.toString()}');
FirebaseNotificationManger.handleMessage(context, json.decode(notificationDetails.payload!));
}, (id, title, body, payload) async {});

@ -1,7 +1,5 @@
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/dashboard_latest/dashboard_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';

@ -79,8 +79,6 @@ import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_pa
import 'package:test_sa/views/widgets/departments/single_department_picker.dart';
import 'package:test_sa/views/widgets/equipment/asset_detail_page.dart';
import 'package:test_sa/views/widgets/equipment/single_device_picker.dart';
import 'controllers/notification/notification_manger.dart';
import 'controllers/providers/api/gas_refill_comments.dart';
import 'controllers/providers/api/user_provider.dart';
import 'controllers/providers/settings/setting_provider.dart';

@ -121,6 +121,7 @@ class RequestsDetails {
String? date;
String? siteTransferFrom;
String? siteTransferTo;
int? transactionType;
RequestsDetails({
this.id,
@ -144,6 +145,7 @@ class RequestsDetails {
this.siteTransferFrom,
this.siteTransferTo,
this.date,
this.transactionType
});
RequestsDetails.fromJson(Map<String, dynamic> json) {
@ -168,6 +170,7 @@ class RequestsDetails {
date = json['date'];
siteTransferFrom = json['siteTransferFrom'];
siteTransferTo = json['siteTransferTo'];
transactionType = json['transactionType'];
}
Map<String, dynamic> toJson() {
@ -193,6 +196,7 @@ class RequestsDetails {
data['date'] = date;
data['siteTransferFrom'] = siteTransferFrom;
data['siteTransferTo'] = siteTransferTo;
data['transactionType'] = transactionType;
return data;
}
}

@ -535,6 +535,8 @@ class WorkOrderHistory {
WorkOrderHistory({
required this.id,
required this.workorderStatus,
this.assetVerificationType,
this.photoVerfication,
required this.activityStatus,
required this.date,
required this.timeDifference,
@ -549,9 +551,11 @@ class WorkOrderHistory {
int? id;
Lookup? workorderStatus;
Lookup? assetVerificationType;
dynamic activityStatus;
DateTime? date;
String timeDifference ='';
String? photoVerfication;
WorkOrderAssignedEmployee? user;
Lookup? step;
DateTime? fixRemotlyStartTime;
@ -564,7 +568,9 @@ class WorkOrderHistory {
return WorkOrderHistory(
id: json["id"],
workorderStatus: json["workorderStatus"] == null ? null : Lookup.fromJson(json["workorderStatus"]),
assetVerificationType: json["assetVerificationType"] == null ? null : Lookup.fromJson(json["assetVerificationType"]),
activityStatus: json["activityStatus"],
photoVerfication: json["photoVerfication"],
date: DateTime.tryParse(json["date"] ?? ""),
user: json["user"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["user"]),
step: json["step"] == null ? null : Lookup.fromJson(json["step"]),
@ -580,6 +586,8 @@ class WorkOrderHistory {
Map<String, dynamic> toJson() => {
"id": id,
"workorderStatus": workorderStatus?.toJson(),
"assetVerificationType": assetVerificationType?.toJson(),
"photoVerfication": photoVerfication,
"activityStatus": activityStatus,
"date": date?.toIso8601String(),
"user": user?.toJson(),

@ -13,11 +13,9 @@ import 'package:test_sa/extensions/text_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_filled_button.dart';
import 'package:test_sa/new_views/pages/land_page/calendar_page.dart';
import 'package:test_sa/new_views/pages/land_page/create_request-type_bottomsheet.dart';
import 'package:test_sa/new_views/pages/land_page/my_request/my_requests_page.dart';
import 'package:test_sa/new_views/pages/settings_page.dart';
import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart';
import 'package:test_sa/views/widgets/equipment/single_device_picker.dart';
import '../../../controllers/providers/settings/setting_provider.dart';

@ -141,6 +141,6 @@ class GasRefillItemView extends StatelessWidget {
});
}
return SizedBox();
return const SizedBox();
}
}

@ -20,6 +20,7 @@ class PpmItemView extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(' type is ${requestData?.nameOfType}');
if (requestData != null) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -47,7 +48,7 @@ class PpmItemView extends StatelessWidget {
],
),
8.height,
(requestData?.typeTransaction ?? context.translation.ppmRequest).heading5(context),
(requestData?.nameOfType ?? context.translation.ppmRequest).heading5(context),
8.height,
'${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context),
// '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed

@ -56,7 +56,7 @@ class ServiceRequestItemView extends StatelessWidget {
// '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context),
// '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context),
'${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context),
if (requestData?.statusName == 'Cancelled') ...[
if (requestData?.statusName == 'Canceled') ...[
'${context.translation.rejectionReason}: ${requestData!.rejectReason}'.bodyText(context),
],
8.height,

@ -25,10 +25,10 @@ class RequestItemViewList extends StatelessWidget {
shrinkWrap: true,
itemBuilder: (cxt, index) {
if (isLoading) return const SizedBox().toRequestShimmer(cxt, isLoading);
bool isServiceRequest = list[index].nameOfType == "ServiceRequest";
bool isGasRefill = list[index].nameOfType == "GasRefill";
bool isAssetTransfer = list[index].nameOfType == "AssetTransfer";
bool isPPMs = list[index].nameOfType == "PPMs";
bool isServiceRequest = list[index].transactionType == 1;
bool isGasRefill = list[index].transactionType == 2;
bool isAssetTransfer = list[index].transactionType == 3;
bool isPPMs = list[index].transactionType == 4;
return isServiceRequest
? ServiceRequestItemView(requestDetails: list[index])

@ -6,7 +6,6 @@ import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/models/fault_description.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
class FaultDescriptionProvider extends ChangeNotifier {

@ -739,6 +739,7 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
body: activityMaintenanceHelperModel!.toJson(),
);
stateCode = response.statusCode;
print('response of activity maintenace part is ${response.body}');
if (response.statusCode >= 200 && response.statusCode < 300) {
// currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
// updateCurrentWorkOrder(currentWorkOrder);

@ -154,8 +154,10 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
children: [
StatusLabel(
label: activity.activityStatus?.name,
textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
textColor: AppColor.white10,
// textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!),
// backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.primary10,
),
"drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160),
if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)
@ -246,6 +248,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
}
Widget maintenanceActivityCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider, required BuildContext context, required Activities activity}) {
print('activity i got is ${activity.toJson()}');
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -256,8 +259,10 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
//TODO will be here when fixed from backend..
StatusLabel(
label: activity.activityStatus?.name,
textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
textColor: AppColor.white10,
// textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!),
// backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.primary10,
),
"drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160),
if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)

@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
class GetQRCodeView extends StatelessWidget {
final String qrCodeUrl = "https://your-qrcode-url.com/qrcode.png"; // Replace with your QR code URL
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('QR Code Dialog Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
showQRCodeDialog(context, qrCodeUrl);
},
child: Text('Show QR Code'),
),
),
);
}
// Function to display the QR code in a dialog
void showQRCodeDialog(BuildContext context, String qrCodeUrl) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Scan QR Code'),
content: Image.network(
qrCodeUrl,
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child; // Display the QR code once loaded
} else {
// Show a CircularProgressIndicator while the image is loading
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / (loadingProgress.expectedTotalBytes ?? 1)
: null,
),
);
}
},
errorBuilder: (context, error, stackTrace) {
// Display an error widget if the image fails to load
return Icon(Icons.error, color: Colors.red);
},
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // Close the dialog
},
child: Text('Close'),
),
],
);
},
);
}
}
void main() {
runApp(MaterialApp(home: GetQRCodeView()));
}

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.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';
@ -9,6 +10,7 @@ import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/views/widgets/buttons/app_back_button.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
@ -73,8 +75,6 @@ class HistoryLogView extends StatelessWidget {
child: Column(children: items),
);
}),
],
));
});
@ -95,11 +95,35 @@ class HistoryLogView extends StatelessWidget {
).expanded,
Expanded(
flex: 2,
//....
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (object.assetVerificationType?.value == 4 && object.photoVerfication != null) ...[
Padding(
padding: EdgeInsets.symmetric(vertical: 12.toScreenWidth),
child: InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!, height: 143.toScreenHeight)),
).onPress(() async {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: SafeArea(
child: Stack(
children: [
InteractiveViewer(child: Image.network(URLs.getFileUrl(object.photoVerfication ?? '')!)).center,
const ABackButton(),
],
),
),
),
),
);
}),
],
object.step!.name!.bodyText(context).custom(color: AppColor.black10),
object.timeDifference.isNotEmpty ? object.timeDifference.tinyFont(context).custom(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120) : const SizedBox(),
],
),
),
@ -123,7 +147,7 @@ class HistoryLogView extends StatelessWidget {
String statusText(String status) {
if (status == "new" || status == "open") {
return "Open Request".addTranslation;
} else if (status == "in progress") {
} else if (status == "in progress") {
return "Status update to In Progress".addTranslation;
} else if (status == "closed") {
return "Status update to Closed".addTranslation;

@ -335,7 +335,6 @@ class ServiceRequestDetailView extends StatelessWidget {
visitDate: requestDetailProvider.currentWorkOrder?.data?.needAVisitDateTime,
comment: requestDetailProvider.currentWorkOrder?.data?.needAVisitComment,
);
// requestDetailProvider.updateNeedVisitHelperModel(requestDetailProvider.needVisitHelperModel);
return const InitialVisitCard();
} else {
return const SizedBox();
@ -370,327 +369,3 @@ class ServiceRequestDetailView extends StatelessWidget {
}
}
// class RequestDetailView extends StatefulWidget {
// static const String id = "/call-details";
// ServiceRequest serviceRequest;
// bool fromTabView = false;
//
// RequestDetailView({Key? key, required this.serviceRequest, this.fromTabView = false}) : super(key: key);
//
// @override
// State<RequestDetailView> createState() => _RequestDetailViewState();
// }
//
// class _RequestDetailViewState extends State<RequestDetailView> {
// @override
// void initState() {
// super.initState();
// }
//
// void getServiceRequest({@required dynamic requestId}) {
// // setState(() {});
// WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) async {
// Provider.of<CommentsProvider>(context, listen: false).reset();
// ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
// serviceRequestsProvider.currentSelectedRequest = await serviceRequestsProvider.getServiceRequestObjectById(requestId: requestId);
// // setState(() {});
// });
// }
//
// @override
// Widget build(BuildContext context) {
// UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
//
// return !widget.fromTabView
// ? Scaffold(
// appBar: DefaultAppBar(title: context.translation.serviceDetails),
// body: Padding(
// padding: EdgeInsets.only(top: 12.toScreenHeight),
// child: Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) {
// return requestDetailCard(serviceRequestsProvider: serviceRequestsProvider, userProvider: _userProvider);
// }),
// ),
// )
// : Consumer<ServiceRequestsProvider>(builder: (context, serviceRequestsProvider, child) {
// return requestDetailCard(serviceRequestsProvider: serviceRequestsProvider, userProvider: _userProvider);
// });
// }
//
// Widget requestDetailCard({required ServiceRequestsProvider serviceRequestsProvider, required UserProvider userProvider}) {
// 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
// : Stack(
// children: [
// SingleChildScrollView(
// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// informationCard(serviceRequestsProvider.currentSelectedRequest!, userProvider),
//
// 40.height,
// // skipForLater(serviceRequestsProvider.currentSelectedRequest),
// // 20.height,
// const InitialVisitCard(),
// 20.height,
// ],
// ),
// ),
// FooterActionButton.requestDetailsFooterWidget(status: 7, context: context),
// ],
// ),
// );
// }
//
// Widget informationCard(ServiceRequest serviceRequest, UserProvider userProvider) {
// 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!,
// radius: 4,
// textColor: AppColor.getPriorityStatusTextColor(context, serviceRequest.priority!.id!),
// backgroundColor: AppColor.getPriorityStatusColor(context, serviceRequest.priority!.id!),
// ),
// 8.width,
// StatusLabel(
// radius: 4,
// 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 ?? false) ...[
// 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!),
// );
// }),
// //set condition for show asset detail button...
// if (true) ...[
// assetRetiredButton(serviceRequest: serviceRequest),
// ]
// ],
// ).toShadowContainer(context, padding: 0);
// }
//
// Widget assetRetiredButton({required ServiceRequest serviceRequest}) {
// return Padding(
// padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight, vertical: 12.toScreenWidth),
// child: AppFilledButton(
// label: context.translation.assetToBeRetired,
// maxWidth: true,
// buttonColor: Colors.white54,
// textColor: AppColor.red30,
// showBorder: true,
// onPressed: () async {
// // Navigator.push(context, MaterialPageRoute(builder: (context) => AssetRetired()));
// Navigator.push(context, MaterialPageRoute(builder: (context) => CreateNewRequest()));
// }),
// );
// }
//
// Widget skipForLater(ServiceRequest serviceRequest) {
// return Center(
// child: InkWell(
// onTap: () async {
// try {
// //use a common list
// AllRequestsProvider allRequestProvider = Provider.of<AllRequestsProvider>(context, listen: false);
// int index = allRequestProvider.requestDetailList!.requestsDetails!.indexWhere((element) => element.id.toString() == serviceRequest.id);
// if (index != -1 && index != allRequestProvider.requestDetailList!.requestsDetails!.length) {
// getServiceRequest(requestId: allRequestProvider.requestDetailList!.requestsDetails![index + 1].id.toString());
// }
// } catch (e) {
// print(e);
// }
// },
// child: Text(
// context.translation.skipForLater,
// style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, decoration: TextDecoration.underline, fontSize: 16),
// ),
// ),
// );
// }
// }

@ -1,4 +1,3 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
@ -16,7 +17,6 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d
import 'package:test_sa/service_request_latest/utilities/service_request_utils.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/verify_otp_view.dart';
import 'package:test_sa/views/widgets/bottom_sheets/request_approval_waiting_bottom_sheet.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
@ -225,14 +225,6 @@ class _VerifyArrivalViewState extends State<VerifyArrivalView> {
requestDetailProvider.isVerifyArrivalBottomSheetOpen=false;
});
bool ?isArrived = await ServiceRequestUtils.listenForApproval();
// bool? isArrived = (await showModalBottomSheet(
// context: context,
// useSafeArea: true,
// isScrollControlled: true,
// isDismissible: false,
// backgroundColor: Colors.transparent,
// builder: (context) => RequestApprovalBottomSheet(),
// ));
if (requestDetailProvider.isVerifyArrivalBottomSheetOpen) {
if (isArrived == null) {
"Requester not confirmed you arrival".showToast;
@ -250,7 +242,7 @@ class _VerifyArrivalViewState extends State<VerifyArrivalView> {
}
}
else{
print('bottomsheet closed ...');
log('bottomsheet closed ...');
}
}
}

@ -4,7 +4,6 @@ import 'package:provider/provider.dart';
import 'package:test_sa/dashboard_latest/dashboard_provider.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';
class WeeklyCalendarFragment extends StatefulWidget {

@ -1,6 +1,5 @@
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';

@ -3,10 +3,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_fault_description_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';

@ -86,7 +86,6 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
//TODO add check...
// enable: !isCurrentUserIsAssistantEmp,
onSelect: (employee) {
print('on select called...${employee?.toJson()}');
if (employee == null) {
requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = [];
} else {
@ -122,11 +121,11 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel?.startTime,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.endTime,
startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
workingHoursController: _workingHoursController,
updateModel: (hours){
requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours;
});
}
});
@ -160,7 +159,13 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
}
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
// assignWorkingHours(requestDetailProvider: requestDetailProvider);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate,
workingHoursController: _workingHoursController,
updateModel: (hours){
requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours;
});
}
});
},

@ -5,7 +5,6 @@ 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/service_request/service_report.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
import 'package:test_sa/models/service_request/supplier_details.dart';

@ -1,22 +1,17 @@
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/status_drop_down/report/service_report_repair_location_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/service_request/service_report.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/providers/service_request_providers/last_situation_provider.dart';
import 'package:test_sa/providers/work_order/activity_status_provider.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../../models/lookup.dart';
import '../../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
@ -31,14 +26,7 @@ class InternalMaintenanceRequest extends StatefulWidget {
}
class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest> with TickerProviderStateMixin {
ServiceRequest? _request;
ServiceRequestsProvider? _serviceRequestsProvider;
ServiceRequestDetailProvider? _requestDetailProvider;
ServiceStatusProvider? _assetTypeProvider;
ActivityStatusProvider? _activityStatusProvider;
ServiceReport? _serviceReport;
bool _isLoading = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _workingHoursController = TextEditingController();
final TextEditingController _travellingHoursController = TextEditingController();
@ -46,9 +34,7 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
@override
void initState() {
_activityStatusProvider = Provider.of<ActivityStatusProvider>(context, listen: false);
_requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
_requestDetailProvider?.activityMaintenanceHelperModel?.activityStatus = _requestDetailProvider?.activityMaintenanceHelperModel?.activityStatus ?? statusLookup;
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_travellingHoursController.text =
@ -64,17 +50,7 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
super.dispose();
}
void getRequestForWorkOrder() async {
_isLoading = true;
setState(() {});
_serviceReport?.callRequest = await _serviceRequestsProvider?.getCallRequestForWorkOrder(callId: _request?.id ?? '0');
await _assetTypeProvider?.getTypes();
_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
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_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';

@ -15,7 +15,6 @@ 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/activity_status_provider.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart';

@ -4,8 +4,6 @@ import 'package:provider/provider.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/string_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/views/widgets/date_and_time/date_picker.dart';

@ -3,7 +3,6 @@ import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/devices_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';

@ -1,6 +1,5 @@
import 'package:flutter/material.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/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
@ -11,7 +10,6 @@ import 'package:test_sa/models/enums/work_order_next_step.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/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.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/history_log_view.dart';
import 'components/service_request_detail_view.dart';
@ -33,7 +31,6 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
@ -43,8 +40,6 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
_requestProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
await _requestProvider.getWorkOrderById(id: widget.requestId);
print('nextstep i got is ${_requestProvider.currentWorkOrder?.data?.nextStep?.workOrderNextStepEnum}');
print('loading value is ${_requestProvider.isLoading}');
if (isNurse && (_requestProvider.currentWorkOrder?.data?.nextStep?.workOrderNextStepEnum == WorkOrderNextStepEnum.waitingForRequesterToConfirm)) {
ServiceRequestBottomSheet.nurseVerifyArrivalBottomSheet(context: context);
}
@ -67,13 +62,12 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.normal_user;
return WillPopScope(
onWillPop: () async {
// Implement custom back button handling logic here
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
if (requestDetailProvider.timer != null && requestDetailProvider.timer!.isActive) {
requestDetailProvider.stopTimer();
}
stopTimer();
return true; // Return true if you want to allow popping the screen, false otherwise
return true;
},
child: Scaffold(
backgroundColor: AppColor.neutral100,

@ -6,6 +6,7 @@ import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/service_request/pending_service_request_model.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/service_request_detail_main_view.dart';
import 'package:test_sa/views/pages/user/requests/service_request_details.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart';
@ -64,10 +65,7 @@ class PendingServiceRequestScreen extends StatelessWidget {
],
),
).onPress(() {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => ServiceRequestDetailsPage(
serviceRequest: ServiceRequest(id: pendingAssetServiceRequest.details![index].id.toString()),
)));
Navigator.of(context).push(MaterialPageRoute(builder: (_) => ServiceRequestDetailMain(requestId: pendingAssetServiceRequest.details![index].id ?? 0)));
})));
}
}

@ -1,3 +1,5 @@
//TODO old Flow ..
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/comments_provider.dart';
@ -14,7 +16,6 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/pages/user/requests/comments_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';

@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/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';
@ -9,6 +11,7 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/ppm_checklist_status_provider.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
class PentryPMChecklistForm extends StatefulWidget {
final List<PpmChecklists>? models;
@ -25,18 +28,21 @@ class _PentryPMChecklistFormState extends State<PentryPMChecklistForm> {
@override
Widget build(BuildContext context) {
List<PpmChecklists>? list = widget.models?.where((element) => element.task != null).toList();
return (list?.isEmpty ?? true)
? context.translation.noDataFound.heading5(context).center
SettingProvider settingProvider = Provider.of<SettingProvider>(context,listen:false);
print('value of asset group is ${settingProvider.assetGroup?.toJson()}');
// List<PpmChecklists>? list = widget.models?.where((element) => element.task != null).toList();
List<PpmChecklists>? list = widget.models??[];
return (list.isEmpty)
? const NoDataFound().center
: ListView.builder(
padding: EdgeInsets.only(top: 16.toScreenHeight),
itemCount: list?.length ?? 0,
itemCount: list.length ,
shrinkWrap: true,
itemBuilder: (context, index) {
return Card(
child: ExpansionTile(
shape: const Border(),
title: (list![index].instructionTextId == null ? (list[index].task ?? "") : (list[index].text ?? "")).heading5(context),
title: (list[index].instructionTextId == null ? (list[index].task ?? "") : (list[index].text ?? "")).heading5(context),
onExpansionChanged: (value) {
if (!value) {
showLabel.remove(index);

Loading…
Cancel
Save