From 4d70fe2c36a49640c57ef1fb4f68ab58025b3548 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 22 Jun 2023 16:56:20 +0300 Subject: [PATCH] improvements --- lib/controllers/api_routes/api_manager.dart | 10 +- lib/views/pages/login.dart | 12 +- .../create_sub_workorder_page.dart | 506 +++++++++--------- .../search_sub_workorder_page.dart | 13 +- .../sub_workorder/workorder_details.dart | 29 +- lib/views/pages/user/land_page.dart | 2 +- 6 files changed, 304 insertions(+), 268 deletions(-) diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart index f40b309c..54d0fc0d 100644 --- a/lib/controllers/api_routes/api_manager.dart +++ b/lib/controllers/api_routes/api_manager.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:developer'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:http/http.dart' as http; import 'package:http/http.dart'; @@ -51,9 +52,12 @@ class ApiManager { headers.addAll(_headers); Uri _url = Uri.parse(url); - // print(_url); - // print(headers); - // log(json.encode(body)); + if (!kReleaseMode) { + print("URL:$_url"); + print("Headers:$headers"); + print("Body:$body"); + } + var request = http.Request('POST', _url); request.body = json.encode(body); request.headers.addAll(headers); diff --git a/lib/views/pages/login.dart b/lib/views/pages/login.dart index 65585b85..e77b67da 100644 --- a/lib/views/pages/login.dart +++ b/lib/views/pages/login.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; @@ -114,9 +115,16 @@ class _LoginState extends State { host: _settingProvider.host, ); if (status >= 200 && status < 300) { - _settingProvider.setUser(_userProvider.user); + if(_userProvider.user.isAuthenticated ?? false) { + _settingProvider.setUser(_userProvider.user); + Navigator.of(context).pushNamed(LandPage.id); + } else { + Fluttertoast.showToast(msg: _userProvider.user.message); + } + + // if (_userProvider.user.isActive) - Navigator.of(context).pushNamed(LandPage.id); + // else // Fluttertoast.showToast(msg: _subtitle.activationAlert); } else { diff --git a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart index 66941a76..9b1ba0b9 100644 --- a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -7,6 +7,8 @@ import 'package:fluttertoast/fluttertoast.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_types_provider.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/call_request_for_work_order_model.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/models/service_request/search_work_order.dart'; @@ -33,6 +35,7 @@ import '../../widgets/titles/app_sub_title.dart'; class CreateSubWorkOrderPage extends StatefulWidget { static const id = "/CreateSubWorkOrder"; final SearchWorkOrder workOrder; + const CreateSubWorkOrderPage({this.workOrder, Key key}) : super(key: key); @override @@ -57,286 +60,299 @@ class _CreateSubWorkOrderPageState extends State { supplier: null, ); _serviceReport = ServiceReport(id: widget.workOrder.id, type: widget.workOrder.assetType, equipmentStatus: widget.workOrder.equipmentStatus); + _isLoading = true; super.initState(); } + var assetTypesProvider; + CallRequestForWorkOrder _callRequestForWorkOrder; + Future getAssetType() async { + //if (assetTypesProvider == null) { Provider.of(context, listen: false).reset(); - final assetTypesProvider = Provider.of(context, listen: false); + assetTypesProvider = Provider.of(context, listen: false); + _callRequestForWorkOrder = await Provider.of(context).getCallRequestForWorkOrder(callId: widget.workOrder.callRequest.id.toString()); await assetTypesProvider.getTypes(); _subWorkOrders?.assetType = assetTypesProvider.statuses?.firstWhere( - (element) => element.value == widget.workOrder?.callRequest?.assetType, + (element) => element.value == _callRequestForWorkOrder.assetType, orElse: () => null, ); + setState(() { + _isLoading = false; + }); + //} } @override Widget build(BuildContext context) { + if (_callRequestForWorkOrder == null) { + getAssetType(); + } final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Scaffold( body: SafeArea( - child: FutureBuilder( - future: getAssetType(), - builder: (context, snap) => snap.connectionState == ConnectionState.waiting - ? const ALoading() - : SingleChildScrollView( - child: Form( - key: _formKey, - child: Column( - children: [ - Container( - color: AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), - child: Column( - children: [ - Row( - children: [ - const ABackButton(), - Expanded( - child: Center( - child: Text( - "New Work Order", - style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + child: _isLoading + ? const ALoading() + : Column( + children: [ + SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + children: [ + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Column( + children: [ + Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "New Work Order", + style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), ), ), - ), - const SizedBox( - width: 48, - ) - ], - ), - ], + const SizedBox( + width: 48, + ) + ], + ), + ], + ), ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), - child: Column( - children: [ - WorkOrderDetails( - item: widget.workOrder, - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const ASubTitle("Equipment status"), - if (_validate && _subWorkOrders?.equipmentStatus == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + child: Column( + children: [ + WorkOrderDetails(item: widget.workOrder, assetType: _subWorkOrders?.assetType), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Equipment status"), + if (_validate && _subWorkOrders?.equipmentStatus == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, ), - const SizedBox( - height: 4, - ), - ServiceRequestDefectTypesMenu( - initialValue: _serviceReport.equipmentStatus, - onSelect: (status) { - _subWorkOrders.equipmentStatus = status; - _serviceReport.equipmentStatus = status; - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const ASubTitle("Return to Service"), - if (_validate && _subWorkOrders.visitDate == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, + ServiceRequestDefectTypesMenu( + initialValue: _serviceReport.equipmentStatus, + onSelect: (status) { + _subWorkOrders.equipmentStatus = status; + _serviceReport.equipmentStatus = status; + setState(() {}); + }, ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Expanded( - child: ADatePicker( - date: DateTime.tryParse(_subWorkOrders.visitDate ?? ""), - from: DateTime(1950), - onDatePicker: (date) { - _subWorkOrders.visitDate = date?.toIso8601String(); - setState(() {}); - }, - ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Return to Service"), + if (_validate && _subWorkOrders.visitDate == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, ), - ], - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle("Failure ${subtitle.reasons}"), - if (_validate && _subWorkOrders.reason == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, + const SizedBox( + height: 4, ), - const SizedBox( - height: 4, - ), - ServiceReportReasonsMenu( - initialValue: _serviceReportReason, - onSelect: (status) { - _serviceReportReason = status; - _subWorkOrders.reason = status; - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(subtitle.faultDescription), - if (_validate && _subWorkOrders.faultDescription == null) - ASubTitle( - subtitle.requiredWord, - color: Colors.red, - ), - const SizedBox( - height: 4, - ), - ServiceReportFaultDescription( - requestId: widget.workOrder?.callRequest?.id?.toString(), - initialValue: _subWorkOrders?.faultDescription, - onSelect: (status) { - _subWorkOrders.faultDescription = status; - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const ASubTitle("Solution"), - const SizedBox(height: 4), - ATextFormField(labelText: _subWorkOrders?.faultDescription?.workPerformed ?? "", textInputType: TextInputType.multiline, enable: false), - ], - ), - const SizedBox(height: 8), - InkWell( - onTap: () async { - await showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => WorkOrderDetailsBottomSheet(subWorkOrder: _subWorkOrders), - ); - log(_subWorkOrders?.toJson()?.toString()); - }, - child: Card( - child: ListTile( - title: Row( + Row( children: [ - Text( - "WO Details", - style: Theme.of(context).textTheme.bodyMedium, + Expanded( + child: ADatePicker( + date: DateTime.tryParse(_subWorkOrders.visitDate ?? ""), + from: DateTime(1950), + onDatePicker: (date) { + _subWorkOrders.visitDate = date?.toIso8601String(); + setState(() {}); + }, + ), ), - const Text("*", style: TextStyle(color: Colors.red)), ], ), - trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle("Failure ${subtitle.reasons}"), + if (_validate && _subWorkOrders.reason == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceReportReasonsMenu( + initialValue: _serviceReportReason, + onSelect: (status) { + _serviceReportReason = status; + _subWorkOrders.reason = status; + setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(subtitle.faultDescription), + if (_validate && _subWorkOrders.faultDescription == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceReportFaultDescription( + requestId: widget.workOrder?.callRequest?.id?.toString(), + initialValue: _subWorkOrders?.faultDescription, + onSelect: (status) { + _subWorkOrders.faultDescription = status; + if(mounted) + setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Solution"), + const SizedBox(height: 4), + ATextFormField(labelText: _subWorkOrders?.faultDescription?.workPerformed ?? "", textInputType: TextInputType.multiline, enable: false), + ], + ), + const SizedBox(height: 8), + InkWell( + onTap: () async { + await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => WorkOrderDetailsBottomSheet(subWorkOrder: _subWorkOrders), + ); + log(_subWorkOrders?.toJson()?.toString()); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "WO Details", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), ), ), - ), - const SizedBox(height: 8), - InkWell( - onTap: () async { - await showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => SparePartsBottomSheet(subWorkOrder: _subWorkOrders), - ); - log(_subWorkOrders?.toJson()?.toString()); - }, - child: Card( - child: ListTile( - title: Row( - children: [ - Text( - "Spare Parts", - style: Theme.of(context).textTheme.bodyMedium, - ), - const Text("*", style: TextStyle(color: Colors.red)), - ], + const SizedBox(height: 8), + InkWell( + onTap: () async { + await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => SparePartsBottomSheet(subWorkOrder: _subWorkOrders), + ); + log(_subWorkOrders?.toJson()?.toString()); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "Spare Parts", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), ), - trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), ), ), - ), - const SizedBox(height: 8), - AMiniOneImagePicker( - image: _image, - onPick: (image) { - _image = image; - _subWorkOrders.attachmentsWorkOrder ??= []; - _subWorkOrders.attachmentsWorkOrder.add(AttachmentsWorkOrder(name: "${image.path.split("/").last}|${base64Encode(image.readAsBytesSync())}")); - }, - ), - const SizedBox(height: 50), - ], + const SizedBox(height: 8), + AMiniOneImagePicker( + image: _image, + onPick: (image) { + _image = image; + _subWorkOrders.attachmentsWorkOrder ??= []; + _subWorkOrders.attachmentsWorkOrder.add(AttachmentsWorkOrder(name: "${image.path.split("/").last}|${base64Encode(image.readAsBytesSync())}")); + }, + ), + const SizedBox(height: 50), + ], + ), ), - ), - ], + ], + ), + ), + ).expanded, + Padding( + padding: const EdgeInsets.all(16.0), + child: AButton( + text: subtitle.create, + onPressed: () async { + _subWorkOrders.parentWOId = widget.workOrder.id; + _validate = true; + setState(() {}); + if (validate()) { + if (_subWorkOrders.startofWorkTime == null) { + Fluttertoast.showToast(msg: "${subtitle.startDate} required"); + return; + } else if (_subWorkOrders.endofWorkTime == null) { + Fluttertoast.showToast(msg: "${subtitle.endDate} required"); + return; + } else if (_subWorkOrders.calllastSituation == null) { + Fluttertoast.showToast(msg: "${subtitle.callLastSituation} required"); + return; + } + _validate = false; + _isLoading = true; + setState(() {}); + if (_formKey.currentState?.validate() ?? false) {} + _formKey.currentState?.save(); + final serviceRequestsProvider = Provider.of(context, listen: false); + final status = await serviceRequestsProvider.createSubWorkOrder(workOrder: _subWorkOrders); + _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: serviceRequestsProvider.stateCode, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + } + }, ), ), - ), - ), - ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - floatingActionButton: Padding( - padding: const EdgeInsets.all(16.0), - child: AButton( - text: subtitle.create, - onPressed: () async { - _subWorkOrders.parentWOId = widget.workOrder.id; - _validate = true; - setState(() {}); - if (validate()) { - if (_subWorkOrders.startofWorkTime == null) { - Fluttertoast.showToast(msg: "${subtitle.startDate} required"); - return; - } else if (_subWorkOrders.endofWorkTime == null) { - Fluttertoast.showToast(msg: "${subtitle.endDate} required"); - return; - } else if (_subWorkOrders.calllastSituation == null) { - Fluttertoast.showToast(msg: "${subtitle.callLastSituation} required"); - return; - } - _validate = false; - _isLoading = true; - setState(() {}); - if (_formKey.currentState?.validate() ?? false) {} - _formKey.currentState?.save(); - final serviceRequestsProvider = Provider.of(context, listen: false); - final status = await serviceRequestsProvider.createSubWorkOrder(workOrder: _subWorkOrders); - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: serviceRequestsProvider.stateCode, subtitle: subtitle); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); - } - } - }, - ), + ], + ), ), ); } diff --git a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart index af4b0418..952c831e 100644 --- a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart +++ b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart @@ -9,6 +9,7 @@ import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/pages/sub_workorder/workorder_list.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field_new.dart'; import '../../../controllers/api_routes/http_status_manger.dart'; import '../../../controllers/localization/localization.dart'; @@ -133,10 +134,13 @@ class _SearchSubWorkOrderPageState extends State { woId: _searchWorkOrders.id?.toString(), ), const SizedBox(height: 16), - ATextFormField( - labelText: "Site", - onSaved: (value) { - _site = value; + HospitalAutoCompleteField( + initialValue:_site, + onSearch: (value) { + _site = value.name; + setState(() { + + }); }, ), const SizedBox(height: 16), @@ -194,7 +198,6 @@ class _SearchSubWorkOrderPageState extends State { _isLoading = false; setState(() {}); if (serviceRequestsProvider.stateCode >= 200 && serviceRequestsProvider.stateCode < 300) { - Fluttertoast.showToast(msg: _subtitle.requestCompleteSuccessfully); Navigator.push( context, MaterialPageRoute( diff --git a/lib/views/pages/sub_workorder/workorder_details.dart b/lib/views/pages/sub_workorder/workorder_details.dart index 82cdb666..6383f586 100644 --- a/lib/views/pages/sub_workorder/workorder_details.dart +++ b/lib/views/pages/sub_workorder/workorder_details.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:test_sa/models/lookup.dart'; import '../../../controllers/localization/localization.dart'; import '../../../models/service_request/search_work_order.dart'; @@ -8,7 +9,9 @@ import '../../app_style/sizing.dart'; class WorkOrderDetails extends StatelessWidget { final SearchWorkOrder item; - WorkOrderDetails({@required this.item,Key key}) : super(key: key); + Lookup assetType; + + WorkOrderDetails({@required this.item, this.assetType, Key key}) : super(key: key); Subtitle _subtitle; @override @@ -30,15 +33,15 @@ class WorkOrderDetails extends StatelessWidget { ), child: Column( children: [ - _buildRow(_subtitle.callId, item.callRequest?.id?.toString()??"", context), - _buildRow(_subtitle.assetNumber, item.callRequest?.asset?.assetNumber??"", context), + _buildRow(_subtitle.callId, item.callRequest?.id?.toString() ?? "", context), + _buildRow(_subtitle.assetNumber, item.callRequest?.asset?.assetNumber ?? "", context), _buildRow("WO No", item.workOrderNo, context), - _buildRow(_subtitle.assetName, item.callRequest?.asset?.assetNumber??'', context), - _buildRow(_subtitle.department, item.callRequest?.asset?.department??'', context), - _buildRow(_subtitle.assetSN, item.callRequest?.asset?.assetSerialNo??'', context), - _buildRow(_subtitle.model, item.callRequest?.asset?.modelDefinition?.modelName??"", context), - _buildRow("Manufacturer", item.callRequest?.asset?.modelDefinition?.manufacturerName??"", context), - _buildRow(_subtitle.site, item.callRequest?.asset?.site?.custName??"", context), + _buildRow(_subtitle.assetName, item.callRequest?.asset?.assetNumber ?? '', context), + _buildRow(_subtitle.department, item.callRequest?.asset?.department ?? '', context), + _buildRow(_subtitle.assetSN, item.callRequest?.asset?.assetSerialNo ?? '', context), + _buildRow(_subtitle.model, item.callRequest?.asset?.modelDefinition?.modelName ?? "", context), + _buildRow("Manufacturer", item.callRequest?.asset?.modelDefinition?.manufacturerName ?? "", context), + _buildRow(_subtitle.site, item.callRequest?.asset?.site?.custName ?? "", context), ], ), ), @@ -53,16 +56,18 @@ class WorkOrderDetails extends StatelessWidget { ), borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), ), - child: _buildRow("Asset Type", item.assetType?.name??"", context),) + child: _buildRow("Asset Type", assetType?.name ?? (item.assetType?.name ?? ""), context), + ) ], ); } - Widget _buildRow(String title, String value, BuildContext context){ + + Widget _buildRow(String title, String value, BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - title+" : ", + title + " : ", style: Theme.of(context).textTheme.subtitle2.copyWith(fontWeight: FontWeight.bold), ), //if (item.clientName != null) diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index 1e90af98..e6e9d608 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -212,7 +212,7 @@ class _LandPageState extends State { Navigator.of(context).pushNamed(TrackDeviceTransferPage.id); }, ), - // if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) + if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) LandPageItem( text: "Search Work Order", svgPath: "assets/images/sub_workorder_icon.svg",