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

design_3.0_latest
muhammad.abbasi 1 year ago
commit ec34de11c5

@ -14,6 +14,7 @@ import 'package:test_sa/dashboard_latest/widgets/app_bar_widget.dart';
import 'package:test_sa/dashboard_latest/widgets/progress_fragment.dart';
import 'package:test_sa/dashboard_latest/widgets/requests_fragment.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/service_request_latest/request_detail_provider.dart';
@ -113,6 +114,7 @@ class _DashboardViewState extends State<DashboardView> {
@override
Widget build(BuildContext context) {
bool isNurse = (Provider.of<UserProvider>(context, listen: false).user!.type) == UsersTypes.normal_user;
return Scaffold(
// backgroundColor: AppColor.background(context),
appBar: PreferredSize(
@ -133,7 +135,7 @@ class _DashboardViewState extends State<DashboardView> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [16.height, ProgressFragment(), const RequestsFragment(), const RequestCategoryFragment()],
children: [16.height, ProgressFragment(), 16.height, if (!isNurse) const RequestsFragment(), const RequestCategoryFragment()],
),
),
),

@ -19,7 +19,7 @@ class RequestsFragment extends StatelessWidget {
Widget build(BuildContext context) {
return Consumer<DashBoardProvider>(
builder: (context, snapshot, _) => GridView(
padding: const EdgeInsets.only(top: 16, left: 16, right: 16),
padding: const EdgeInsets.only( left: 16, right: 16),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4, childAspectRatio: 72 / 84, crossAxisSpacing: 2, mainAxisSpacing: 12),

@ -4,7 +4,6 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
@ -17,10 +16,9 @@ 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/service_request_latest/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/activities_list_view.dart';
import 'package:test_sa/service_request_latest/views/request_detail_main_view.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/images/new_multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.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';
@ -42,7 +40,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
bool _isLoading = false;
List<SparePart> _spareParts = [];
List<File> _files = [];
List<MultiFilesPickerModel> _files = [];
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _partQtyController = TextEditingController();
@ -55,22 +53,21 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
_partsProvider = Provider.of<PartsProvider>(context, listen: false);
_requestDetailProvider = Provider.of<RequestDetailProvider>(context, listen: false);
_requestDetailProvider?.sparePartHelperModel = SparePartHelperModel(
id: _requestDetailProvider?.sparePartHelperModel?.id??0,
workOrderId:_requestDetailProvider?.sparePartHelperModel?.workOrderId?? _requestDetailProvider?.currentWorkOrder?.data?.requestId,
sparePartAttachments:_requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?? [],
sparePart:_requestDetailProvider?.sparePartHelperModel?.sparePart?? SparePart(),
id: _requestDetailProvider?.sparePartHelperModel?.id ?? 0,
workOrderId: _requestDetailProvider?.sparePartHelperModel?.workOrderId ?? _requestDetailProvider?.currentWorkOrder?.data?.requestId,
sparePartAttachments: _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments ?? [],
sparePart: _requestDetailProvider?.sparePartHelperModel?.sparePart ?? SparePart(),
quantity: _requestDetailProvider?.sparePartHelperModel?.quantity,
activityStatusId: _requestDetailProvider?.sparePartHelperModel?.activityStatusId,
comment: _requestDetailProvider?.sparePartHelperModel?.comment??'',
comment: _requestDetailProvider?.sparePartHelperModel?.comment ?? '',
);
_partQtyController.text =_requestDetailProvider?.sparePartHelperModel?.quantity!=null? _requestDetailProvider!.sparePartHelperModel!.quantity.toString():'';
_oracleNoController.text = _requestDetailProvider?.sparePartHelperModel?.sparePart?.oracleCode!=null?_requestDetailProvider!.sparePartHelperModel!.sparePart!.oracleCode!:'';
_descriptionController.text =_requestDetailProvider?.sparePartHelperModel?.comment!=null? _requestDetailProvider!.sparePartHelperModel!.comment!:'';
_partQtyController.text = _requestDetailProvider?.sparePartHelperModel?.quantity != null ? _requestDetailProvider!.sparePartHelperModel!.quantity.toString() : '';
_oracleNoController.text = _requestDetailProvider?.sparePartHelperModel?.sparePart?.oracleCode != null ? _requestDetailProvider!.sparePartHelperModel!.sparePart!.oracleCode! : '';
_descriptionController.text = _requestDetailProvider?.sparePartHelperModel?.comment != null ? _requestDetailProvider!.sparePartHelperModel!.comment! : '';
scheduleMicrotask(() async {
_isLoading = true;
_files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => File(e.name!)).toList() ?? [];
_files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => MultiFilesPickerModel(e.id!, File(e.name!))).toList() ?? [];
setState(() {});
_spareParts = await _partsProvider!.getPartsList(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id);
@ -95,6 +92,11 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
super.dispose();
}
bool _isLocalUrl(String url) {
if (url.isEmpty != false) return false;
return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\');
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -129,10 +131,10 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
initialValue: requestDetailProvider.sparePartHelperModel?.sparePart,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
onSelect: (part) {
if(part!=null){
if (part != null) {
requestDetailProvider.sparePartHelperModel?.sparePart = part;
_oracleNoController.text = part.oracleCode??'';
requestDetailProvider.updateSparePartHelperModel(_requestDetailProvider?.sparePartHelperModel);
_oracleNoController.text = part.oracleCode ?? '';
requestDetailProvider.updateSparePartHelperModel(_requestDetailProvider?.sparePartHelperModel);
}
},
),
@ -185,14 +187,14 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
},
),
12.height,
MultiFilesPicker(
NewMultiFilesPicker(
label: context.translation.attachQuotation,
files: _files,
buttonIcon: 'quotation_icon'.toSvgAsset(),
buttonColor: AppColor.primary10,
onChange: (List<File> file){
for (var element in file) {
print('path is ${element.path}');
onChange: (List<MultiFilesPickerModel> list) {
for (var element in list) {
print('path is ${element.file.path}');
}
},
),
@ -205,41 +207,23 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
).paddingAll(12).expanded,
FooterActionButton.footerContainer(
child: AppFilledButton(
label:_requestDetailProvider?.sparePartHelperModel?.id==0? context.translation.addSparePartActivity:context.translation.updateSparePartActivity,
label: _requestDetailProvider?.sparePartHelperModel?.id == 0 ? context.translation.addSparePartActivity : context.translation.updateSparePartActivity,
buttonColor: AppColor.green70,
onPressed: () async {
// List<SparePartAttachments> attachmentList = [];
// List<File> localFile = [];
// for (var file in _files) {
// print('loop executed..${file.path}');
// if(_requestDetailProvider?.sparePartHelperModel?.sparePartAttachments!=null){
// for (var attachment in _requestDetailProvider!.sparePartHelperModel!.sparePartAttachments!) {
// if(file.path==attachment.name){
// print('name i got is ${attachment.name}');
// attachmentList.add(attachment);
// }
// }
// }
// else{
// print('file path i got is ${file.path}');
// localFile.add(file);
// }
// attachmentList.add(SparePartAttachments(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
// requestDetailProvider.sparePartHelperModel?.sparePartAttachments
// ?.add(SparePartAttachments(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
// }
// for(var item in localFile){
// attachmentList.add(SparePartAttachments(id: 0, name: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}"));
// }
requestDetailProvider.sparePartHelperModel?.sparePartAttachments?.clear();
for (var pickerObject in _files) {
String fileData = _isLocalUrl(pickerObject.file.path)
? ("${pickerObject.file.path.split("/").last}|${base64Encode(File(pickerObject.file.path).readAsBytesSync())}")
: pickerObject.file.path;
requestDetailProvider.sparePartHelperModel?.sparePartAttachments?.add(SparePartAttachments(id: pickerObject.id, name: fileData));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
int status = -1;
if(_requestDetailProvider?.sparePartHelperModel?.id==0){
if (_requestDetailProvider?.sparePartHelperModel?.id == 0) {
status = await requestDetailProvider.createActivitySparePart();
}
else{
} else {
status = await requestDetailProvider.updateActivitySparePart();
}
if (status == 200) {
await requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!);

@ -0,0 +1,291 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.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 '../../../new_views/common_widgets/app_dashed_button.dart';
import 'multi_image_picker_item.dart';
class MultiFilesPickerModel {
int id;
File file;
MultiFilesPickerModel(this.id, this.file);
}
class NewMultiFilesPicker extends StatefulWidget {
final String label;
final bool error;
final List<MultiFilesPickerModel> files;
final bool enabled, onlyImages;
double? buttonHeight;
Widget? buttonIcon;
Color? buttonColor;
final Function(List<MultiFilesPickerModel>)? onChange;
final bool showAsGrid;
NewMultiFilesPicker(
{Key? key,
this.files = const <MultiFilesPickerModel>[],
required this.label,
this.error = false,
this.buttonHeight,
this.buttonIcon,
this.enabled = true,
this.onlyImages = false,
this.onChange,
this.showAsGrid = false,
this.buttonColor})
: super(key: key);
@override
State<NewMultiFilesPicker> createState() => _MultiFilesPickerState();
}
class _MultiFilesPickerState extends State<NewMultiFilesPicker> {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppDashedButton(
title: widget.label,
height: widget.buttonHeight,
buttonColor: widget.buttonColor,
icon: widget.buttonIcon,
onPressed: (widget.enabled == false)
? () {}
: widget.showAsGrid
? showFileSourceSheet
: onFilePicker),
16.height,
if (widget.files.isNotEmpty)
Wrap(
spacing: 8.toScreenWidth,
children: List.generate(
widget.files!.length,
(index) {
File image = widget.files![index].file;
return MultiFilesPickerItem(
file: image,
enabled: widget.enabled,
onRemoveTap: (image) {
if (!widget.enabled) {
return;
}
widget.files.remove(image);
if (widget.onChange != null) {
widget.onChange!(widget.files);
}
setState(() {});
},
);
},
),
),
],
);
}
fromFilePicker() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowMultiple: true,
allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'],
);
if (result != null) {
for (var path in result.paths) {
widget.files.add(MultiFilesPickerModel(0, File(path!)));
}
setState(() {});
}
}
void showFileSourceSheet() async {
if (widget.files.length >= 5) {
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return;
}
ImageSource source = (await showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Attach File".heading4(context),
12.height,
GridView(
padding: EdgeInsets.all(0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
children: <Widget>[
gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)),
gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)),
gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async {
await fromFilePicker();
Navigator.pop(context);
}),
],
),
12.height,
],
).paddingAll(21),
)) as ImageSource;
if (source == null) return;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) {
File fileImage = File(pickedFile.path);
if (fileImage != null) {
widget.files.add(MultiFilesPickerModel(0, fileImage));
if (widget.onChange != null) {
widget.onChange!(widget.files);
}
setState(() {});
}
}
}
Widget gridItem(IconData iconData, String title) {
return Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Color(0xffF1F1F1), width: 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(iconData, color: Color(0xff7D859A), size: 36),
Text(
title,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
),
],
),
);
}
onFilePicker() async {
if (widget.files.length >= 5) {
Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5);
return;
}
ImageSource? source = await showModalBottomSheet<ImageSource>(
context: context,
builder: (BuildContext context) {
Widget listCard({required String icon, required String label, required VoidCallback onTap}) {
return GestureDetector(
onTap: onTap,
child: Container(
constraints: BoxConstraints(minWidth: 111.toScreenWidth, minHeight: 111.toScreenHeight),
padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth, vertical: 12.toScreenHeight),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12), border: Border.all(width: 1, color: AppColor.white70)),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
icon.toSvgAsset(),
24.height,
label.bodyText2(context).custom(color: AppColor.black20),
],
),
),
);
}
return Container(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
listCard(
icon: 'camera_icon',
label: '${context.translation.open}\n${context.translation.camera}',
onTap: () {
Navigator.of(context).pop(ImageSource.camera);
},
),
listCard(
icon: 'gallery_icon',
label: '${context.translation.open}\n${context.translation.gallery}',
onTap: () {
Navigator.of(context).pop(ImageSource.gallery);
},
),
listCard(
icon: 'file_icon',
label: '${context.translation.open}\n${context.translation.files}',
onTap: () async {
await fromFilePicker();
Navigator.pop(context);
},
),
],
),
);
},
);
// ImageSource source = await showDialog(
// context: context,
// builder: (dialogContext) => CupertinoAlertDialog(
// actions: <Widget>[
// TextButton(
// child: Text(context.translation.pickFromCamera),
// onPressed: () {
// Navigator.of(dialogContext).pop(ImageSource.camera);
// },
// ),
// TextButton(
// child: Text(context.translation.pickFromGallery),
// onPressed: () {
// Navigator.of(dialogContext).pop(ImageSource.gallery);
// },
// ),
// TextButton(
// child: Text(context.translation.pickFromFiles),
// onPressed: () async {
// await fromFilePicker();
// Navigator.pop(context);
// },
// ),
// ],
// ),
// );
if (source == null) return;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) {
File fileImage = File(pickedFile.path);
if (fileImage != null) {
widget.files.add(MultiFilesPickerModel(0, fileImage));
if (widget.onChange != null) {
widget.onChange!(widget.files);
}
setState(() {});
}
}
setState(() {});
}
}
Loading…
Cancel
Save