· 4 years ago · May 27, 2021, 10:56 PM
1import 'dart:convert';
2import 'dart:io';
3
4import 'package:drivar/controllers/rideController.dart';
5import 'package:drivar/libraries/convert_mediaQuery.dart';
6import 'package:drivar/libraries/globals.dart' as globals;
7import 'package:drivar/navigations.dart';
8import 'package:flutter/rendering.dart';
9import '../index.dart';
10import 'package:drivar/screens/home/index.dart';
11import 'package:drivar/widgets/dropdown.dart';
12import 'package:drivar/widgets/index_sub_appBar.dart';
13import 'package:drivar/widgets/photo_picker.dart';
14import 'package:drivar/widgets/textfields.dart';
15import 'package:image_picker/image_picker.dart';
16import 'package:flutter/material.dart';
17
18import '../../colors.dart';
19import 'IndexLayout.dart';
20
21Color lActiveColor = Colors.white;
22Color lInActivecolor = Colors.white54;
23
24class LocalView02 extends StatefulWidget {
25 final String pickupLocation;
26 final String pickupLocationID;
27 final String destinationLocation;
28 final String destinationLocationID;
29 final String deliveryType;
30 final String deliveryRoute;
31
32 const LocalView02({
33 Key key, this.pickupLocation, this.pickupLocationID,
34 this.destinationLocation, this.destinationLocationID,
35 this.deliveryType, this.deliveryRoute,
36 }) : super(key: key);
37
38 @override
39 _LocalView02State createState() => _LocalView02State();
40}
41
42class _LocalView02State extends State<LocalView02> {
43 final picker = ImagePicker();
44 File selectedFile;
45 bool hasSelectedFile = false;
46 String errMsg = "";
47 int errChk = 0;
48 String dropdownValue = 'Select weight measures';
49 // var images = List.filled(4, []);
50 List images = [];
51 int numberOfImages = 0;
52
53 final txtPackageNameController = TextEditingController();
54 final txtNumberController = TextEditingController();
55 final txtPhoneController = TextEditingController();
56 final txtNameController = TextEditingController();
57 final txtNoteController = TextEditingController();
58
59 _imgFromCamera() async {
60 final pickedFile = await picker.getImage(
61 source: ImageSource.camera, imageQuality: 50
62 );
63
64
65 if(pickedFile != null) {
66 setState(() {
67 selectedFile = File(pickedFile.path);
68 hasSelectedFile = true;
69 numberOfImages = numberOfImages + 1;
70 });
71 // images[numberOfImages].add(selectedFile);
72 images.add(selectedFile);
73 } else {
74 print('===============No image selected from camera.');
75 hasSelectedFile = false;
76 }
77
78 }
79
80 _imgFromGallery() async {
81 final pickedFile = await picker.getImage(
82 source: ImageSource.gallery, imageQuality: 50
83 );
84
85 setState(() {
86 if(pickedFile != null) {
87 selectedFile = File(pickedFile.path);
88 hasSelectedFile = true;
89 } else {
90 print('===========No image selected from gallery.');
91 hasSelectedFile = false;
92 }
93 });
94 }
95
96 void _showPicker(context) {
97 showModalBottomSheet(
98 context: context,
99 builder: (BuildContext bc) {
100 return SafeArea(
101 child: Container(
102 child: new Wrap(
103 children: <Widget>[
104 new ListTile(
105 leading: new Icon(Icons.photo_library),
106 title: new Text('Photo Library'),
107 onTap: () {
108 _imgFromGallery();
109 Navigator.of(context).pop();
110 }),
111 new ListTile(
112 leading: new Icon(Icons.photo_camera),
113 title: new Text('Camera'),
114 onTap: () {
115 _imgFromCamera();
116 Navigator.of(context).pop();
117 },
118 ),
119 ],
120 ),
121 ),
122 );
123 }
124 );
125 }
126
127 Widget dropdown (BuildContext context) {
128 return Container(
129 margin: EdgeInsets.symmetric(
130 vertical:
131 ConvertToMediaQuery().convertHeightToMediaQuery(10, context)),
132 padding: EdgeInsets.symmetric(
133 vertical: ConvertToMediaQuery().convertHeightToMediaQuery(5, context),
134 horizontal: ConvertToMediaQuery().convertWidthToMediaQuery(3, context)
135 ),
136 width: ConvertToMediaQuery().convertWidthToMediaQuery(160, context),
137 decoration: BoxDecoration(
138 borderRadius: BorderRadius.all(
139 new Radius.circular(10.0),
140 ),
141 color: Colors.white,
142 boxShadow: customShadow
143 ),
144 child: DropdownButton<String>(
145 value: dropdownValue,
146 icon: Icon(Icons.arrow_drop_down),
147 iconSize: 24,
148 elevation: 16,
149 style: TextStyle(
150 color: Colors.black
151 ),
152 onChanged: (String newValue) {
153 setState(() {
154 dropdownValue = newValue;
155 });
156 },
157 items: <String>['Select weight measures', 'Kg']
158 .map<DropdownMenuItem<String>>((String value) {
159 return DropdownMenuItem<String>(
160 value: value,
161 child: Text(value),
162 );
163 })
164 .toList(),
165 ),
166 );
167 }
168
169 showAlertDialog(BuildContext context) {
170 // set up the button
171 Widget okButton = TextButton(
172 child: Text("OK"),
173 onPressed: () {
174 Navigator.of(context, rootNavigator: true).pop();
175 },
176 );
177
178 // set up the AlertDialog
179 AlertDialog alert = AlertDialog(
180 title: Text("Error"),
181 content: Text(errMsg),
182 actions: [
183 okButton,
184 ],
185 );
186
187 // show the dialog
188 showDialog(
189 context: context,
190 builder: (BuildContext context) {
191 return alert;
192 },
193 );
194 }
195
196 _handleSubmit() async {
197 String recepientName = txtNameController.text;
198 String itemName = txtPackageNameController.text;
199 String note = txtNoteController.text;
200 String phone = txtPhoneController.text;
201 double number = double.parse(txtNumberController.text);
202 List<int> imageBytes = selectedFile.readAsBytesSync();
203 String baseImage = base64Encode(imageBytes);
204 if (
205 recepientName.isEmpty ||
206 itemName.isEmpty ||
207 phone.isEmpty ||
208 number == null ||
209 baseImage.isEmpty
210 ) {
211 setState(() {
212 errMsg = "No empty fields!";
213 errChk = 1;
214 });
215 showAlertDialog(context);
216 }
217
218 print('Image path - $baseImage');
219
220 Navigator.push
221 (
222 context,
223 MaterialPageRoute(builder: (context) => LocalView03(
224 pickupLocationID: widget.pickupLocationID,
225 pickupLocation: widget.pickupLocation,
226 destinationLocationID: widget.destinationLocationID,
227 destinationLocation: widget.destinationLocation,
228 packageName: itemName,
229 packageSize: number,
230 packageImage: images,
231 recipientName: recepientName,
232 recipientNumber: phone,
233 note: note,
234 deliveryType: widget.deliveryType,
235 deliveryRoute: widget.deliveryRoute,
236 )
237 )
238 );
239 }
240
241 @override
242 Widget build(BuildContext context) {
243 final Size screenSize = MediaQuery.of(context).size;
244
245 return Scaffold(
246 backgroundColor: primarySwatch,
247 appBar: PreferredSize(
248 preferredSize: Size(screenSize.width, 120.0),
249 child: IndexSubAppBar(
250 title: "Package Details",
251 num: "2",
252 position: 2,
253 ),
254 ),
255 body: Container(
256 decoration: BoxDecoration(
257 borderRadius: BorderRadius.only(
258 topLeft: Radius.circular(16.0),
259 topRight: Radius.circular(16.0),
260 ),
261 color: Colors.white,
262 ),
263 padding: const EdgeInsets.all(15.0),
264 child: Stack(
265 children: [
266 Container(
267 margin: const EdgeInsets.only(bottom: 50.0, left: 10.0),
268 child: SingleChildScrollView(
269 child: Column(
270 crossAxisAlignment: CrossAxisAlignment.start,
271 children: [
272 textEntry(context, "Product Details", 16.0, FontWeight.bold, Colors.black),
273 entryField(
274 context,
275 "What package are you sending?",
276 txtPackageNameController,
277 ),
278 Row(
279 mainAxisAlignment: MainAxisAlignment.spaceBetween,
280 children: [
281 dropdown(context),
282 sizedEntryNumber(
283 context,
284 "Enter number",
285 120.00,
286 txtNumberController
287 )
288 ],
289 ),
290 textEntry(context, "Upload Pictures", 14.0, FontWeight.bold, Colors.black),
291 Row(
292 children: [
293 Container(
294 padding: EdgeInsets.symmetric(
295 horizontal: ConvertToMediaQuery().convertWidthToMediaQuery(20, context),
296 vertical: ConvertToMediaQuery().convertHeightToMediaQuery(10, context)
297 ),
298 decoration: BoxDecoration(
299 color: navMenu,
300 borderRadius: BorderRadius.all(
301 new Radius.circular(10)
302 )
303 ),
304 child: GestureDetector(
305 onTap: () => _showPicker(context),
306 child: Column(
307 children: [
308 Icon(Icons.camera_alt),
309 textEntry(context, "click to upload", 9.0, FontWeight.w600, Colors.grey)
310 ],
311 ),
312 ),
313 ),
314 SizedBox(width: 20),
315 Container(
316 height: ConvertToMediaQuery().convertHeightToMediaQuery(170, context),
317 width: ConvertToMediaQuery().convertWidthToMediaQuery(170, context),
318 child: (hasSelectedFile == true)
319 ? ListView.builder(
320 scrollDirection: Axis.horizontal,
321 itemCount: images.length,
322 itemBuilder: (BuildContext context, int index) {
323 return Container(
324 child: Image.file(images[index]
325 ),
326 height: ConvertToMediaQuery().convertHeightToMediaQuery(70, context),
327 width: ConvertToMediaQuery().convertWidthToMediaQuery(70, context),
328
329 );
330 },
331 ) : Image.asset("assets/images/imgUploadImage.png"),
332 ),
333 // Container(
334 // child: (hasSelectedFile == true
335 // ? Image.file(selectedFile)
336 // : Image.asset("assets/images/imgUploadImage.png")
337 // ),
338 // height: ConvertToMediaQuery().convertHeightToMediaQuery(70, context),
339 // width: ConvertToMediaQuery().convertWidthToMediaQuery(70, context),
340 // ),
341 ],
342 ),
343
344 SizedBox(height: ConvertToMediaQuery().convertHeightToMediaQuery(13, context),),
345 textEntry(context, "Recipient details", 14.0, FontWeight.bold, Colors.black),
346 entryField(
347 context,
348 "Recipient's name",
349 txtNameController,
350 ),
351 entryField(
352 context,
353 "Recipient's phone number",
354 txtPhoneController,
355 keyboardType: TextInputType.number
356 ),
357
358 Container(
359 margin: const EdgeInsets.only(bottom: 20.0, top: 10.0),
360 child: Column(
361 crossAxisAlignment: CrossAxisAlignment.start,
362 children: [
363 textEntry(
364 context,
365 "Additional note",
366 14.0,
367 FontWeight.bold,
368 Colors.black
369 ),
370 textArea(
371 context,
372 "Any note about the package?",
373 txtNoteController
374 ),
375 ],
376 ),
377 ),
378 ],
379 ),
380 ),
381 ),
382 Align(
383 alignment: FractionalOffset.bottomCenter,
384 child: Container(
385 child: Row(
386 children: [
387 Container(
388 padding: const EdgeInsets.all(5.0),
389 decoration: BoxDecoration(
390 borderRadius: BorderRadius.all(
391 Radius.circular(5.0),
392 ),
393 ),
394 child: IconButton(
395 icon: Icon(Icons.arrow_back),
396 onPressed: () => Navigator.push(
397 context, MaterialPageRoute(
398 builder: (context) => HomeScreen()
399 )
400 )
401 ),
402 ),
403 SizedBox(
404 width: ConvertToMediaQuery().convertWidthToMediaQuery(5.0, context),
405 ),
406 Expanded(
407 child: InkWell(
408 onTap: _handleSubmit,
409 child: Container(
410 padding: const EdgeInsets.all(5.0),
411 height: ConvertToMediaQuery().convertHeightToMediaQuery(50, context),
412 decoration: BoxDecoration(
413 color: primaryColor,
414 borderRadius: BorderRadius.all(Radius.circular(5))
415 ),
416 child: Center(
417 child: Text(
418 "Confirm Details",
419 style: TextStyle(
420 color: Colors.white,
421 fontWeight: FontWeight.bold
422 ),
423 )
424 ),
425 ),
426 )
427 )
428 ],
429 ),
430 ),
431 )
432 ],
433 ),
434 ),
435 );
436 }
437}
438
439class LocalView03 extends StatefulWidget {
440 final String pickupLocation;
441 final String pickupLocationID;
442 final String destinationLocation;
443 final String destinationLocationID;
444 final String deliveryType;
445 final String deliveryRoute;
446 final double packageSize;
447 final String note;
448 final String packageName;
449 final String recipientName;
450 final String recipientNumber;
451 final List packageImage;
452
453 const LocalView03({
454 Key key, this.pickupLocation, this.pickupLocationID,
455 this.destinationLocation, this.destinationLocationID,
456 this.deliveryType, this.deliveryRoute, this.packageSize,
457 this.note, this.packageName, this.recipientName,
458 this.packageImage, this.recipientNumber,
459 }) : super(key: key);
460
461 @override
462 _LocalView03State createState() => _LocalView03State();
463}
464
465class _LocalView03State extends State<LocalView03> {
466 String tripCost = globals.tripCost;
467 dynamic result;
468
469 @override
470 void initState() {
471 getToAddress();
472 super.initState();
473 }
474
475 String toAddress;
476
477 getToAddress() async {
478 String location = globals.toLocation;
479 setState(() {
480 toAddress = location;
481 });
482 }
483
484 void _handleSubmit() async {
485 print(''
486 '${widget.pickupLocation}\n '
487 '${widget.pickupLocationID}\n'
488 '${widget.destinationLocation}\n'
489 '${widget.destinationLocationID}\n'
490 '${widget.deliveryType}\n'
491 '${widget.deliveryRoute}\n'
492 '${widget.packageSize}\n'
493 '${widget.note}\n'
494 '${widget.packageName}\n'
495 '${widget.recipientName}\n'
496 '${widget.recipientNumber}\n'
497
498 );
499 result = await packageDelivery(
500 widget.pickupLocation,
501 widget.pickupLocationID,
502 widget.destinationLocation,
503 widget.destinationLocationID,
504 widget.deliveryType,
505 widget.deliveryRoute,
506 // "dispatch",
507 // "local",
508 widget.packageSize,
509 widget.note,
510 widget.packageName,
511 widget.recipientName,
512 widget.recipientNumber,
513 widget.packageImage,
514 );
515
516 if (result is int) {
517 print(globals.riderId);
518 print(result);
519 print("Hurray!");
520 Navigator.pushNamed(context, REQUESTPICKUP);
521 } else print("E choke");
522 }
523
524
525 @override
526 Widget build(BuildContext context) {
527 final Size screenSize = MediaQuery.of(context).size;
528 return Scaffold(
529 backgroundColor: primarySwatch,
530 appBar: PreferredSize(
531 preferredSize: Size(screenSize.width, 120.0),
532 child: IndexSubAppBar(
533 title: "Confirm details",
534 num: "3",
535 position: 3,
536 ),
537 ),
538
539 body: Container(
540 decoration: BoxDecoration(
541 borderRadius: BorderRadius.only(
542 topLeft: Radius.circular(16.0),
543 topRight: Radius.circular(16.0),
544 ),
545 color: Colors.white,
546 ),
547 padding: const EdgeInsets.all(15.0),
548 child: Stack(
549 children: [
550 Container(
551 child: Column(
552 crossAxisAlignment: CrossAxisAlignment.start,
553 children: [
554 textEntry(context, "Order Details", 16.0, FontWeight.bold, Colors.black),
555 Container(
556 padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
557 margin: EdgeInsets.only(top: 20.0, bottom: 15.0),
558 decoration: BoxDecoration(
559 color: Colors.green,
560 borderRadius: BorderRadius.all(
561 Radius.circular(20.0),
562 )
563 ),
564 child: textEntry(context, "Instant booking", 12.0, FontWeight.w500, Colors.white),
565 ),
566 Row(
567 mainAxisAlignment: MainAxisAlignment.spaceBetween,
568 children: [
569 Column(
570 crossAxisAlignment: CrossAxisAlignment.start,
571 children: [
572 textEntry(context, "Local", 18.0, FontWeight.w900, Colors.black),
573 textEntry(context, "Destination", 13.0, FontWeight.w500, Colors.black54),
574 ],
575 ),
576
577 Column(
578 crossAxisAlignment: CrossAxisAlignment.end,
579 children: [
580 textEntry(context, "Estimated Price", 14.0, FontWeight.w500, Colors.black87),
581 textEntry(context, "\u{20A6}6,000", 18.0, FontWeight.w900, Colors.black),
582 ],
583 )
584 ],
585 ),
586 SizedBox(height: ConvertToMediaQuery().convertHeightToMediaQuery(30, context)),
587 Row(
588 mainAxisAlignment: MainAxisAlignment.spaceBetween,
589 children: [
590 Container(
591 width: 200.0,
592 child: Row(
593 children: [
594 Icon(Icons.near_me),
595 Expanded(child: textEntry(
596 context,
597 toAddress,
598 12.0,
599 FontWeight.w700,
600 Colors.black,
601 ))
602 ],
603 ),
604 ),
605 GestureDetector(
606 onTap: () => Navigator.push(
607 context, MaterialPageRoute(
608 builder: (context) => FirstDestinationIndexView())),
609 child: textEntry(
610 context,
611 "Change Destination",
612 10.0,
613 FontWeight.w400,
614 Colors.red
615 ),
616 )
617 ],
618 ),
619 SizedBox(height: ConvertToMediaQuery().convertHeightToMediaQuery(10, context)),
620 Container(
621 padding: const EdgeInsets.symmetric(horizontal: 9.0),
622 child: Divider(
623 color: Colors.black,
624 ),
625 ),
626 ],
627 ),
628 ),
629 Align(
630 alignment: FractionalOffset.bottomCenter,
631 child: Container(
632 child: Row(
633 children: [
634 Container(
635 padding: const EdgeInsets.all(5.0),
636 decoration: BoxDecoration(
637 borderRadius: BorderRadius.all(
638 Radius.circular(5.0),
639 ),
640 ),
641 child: IconButton(
642 icon: Icon(Icons.arrow_back),
643 onPressed: () => Navigator.push(
644 context, MaterialPageRoute(
645 builder: (context) => LocalView02()))
646 ),
647 ),
648 SizedBox(
649 width: ConvertToMediaQuery().convertWidthToMediaQuery(5.0, context),
650 ),
651 Expanded(
652 child: GestureDetector(
653 onTap: _handleSubmit,
654 child: Container(
655 padding: const EdgeInsets.all(5.0),
656 height: ConvertToMediaQuery().convertHeightToMediaQuery(50, context),
657 decoration: BoxDecoration(
658 color: primaryColor,
659 borderRadius: BorderRadius.all(Radius.circular(5))
660 ),
661 child: Center(
662 child: Text(
663 "Confirm Pickup",
664 style: TextStyle(
665 color: Colors.white,
666 fontWeight: FontWeight.bold
667 ),
668 )
669 ),
670 ),
671 )
672 )
673 ],
674 ),
675 ),
676 )
677 ],
678 ),
679 ),
680 );
681 }
682}
683
684
685// API CALLS
686
687Future<dynamic> packageDelivery(
688 String pickupLocation,
689 String pickupLocationID,
690 String destinationLocation,
691 String destinationLocationID,
692 String deliveryType,
693 String deliveryRoute,
694 double packageSize,
695 String note,
696 String packageName,
697 String recipientName,
698 String recipientNumber,
699 List packageImage,
700 ) async {
701 try {
702 Map<String, String> header = {
703 "Accept": "multipart/form-data",
704 "Content-type": "application/json",
705 "Authorization": "access"
706 };
707
708 Uri uri = Uri.parse(ApiUtil().rideHailing());
709 MultipartRequest multipartRequest = MultipartRequest("POST", uri);
710 multipartRequest.headers.addAll(header);
711 multipartRequest.fields['pickup_place_id'] = pickupLocationID;
712 multipartRequest.fields['pickup_description'] = pickupLocation;
713 multipartRequest.fields['destination_place_id'] = destinationLocationID;
714 multipartRequest.fields['destination_description'] = destinationLocation;
715 multipartRequest.fields['trip_type'] = deliveryType;
716 multipartRequest.fields['package_name'] = packageName;
717 multipartRequest.fields['package_size'] = packageSize.toString();
718 multipartRequest.fields['package_note'] = note;
719 multipartRequest.fields['package_name'] = packageName;
720 multipartRequest.fields['package_route'] = deliveryRoute;
721 multipartRequest.fields['package_recipient_phone'] = recipientNumber;
722 multipartRequest.fields['package_recipient_name'] = recipientName;
723 List files = [];
724 if (packageImage != null) {
725 for (var i = 0; i < packageImage.length; i++) {
726 var fileData = packageImage[i].readAsBytesSync();
727 files.add(fileData);
728 // var length = await packageImage.length();
729
730 MultipartFile multipartFile = MultipartFile.fromBytes(
731 'package_photos[]', files,
732 filename: packageImage[i].path,
733 contentType: MediaType("image", getFileType(packageImage[i].path)
734 ));
735 multipartRequest.files.add(multipartFile);
736 }
737 }
738
739 var res = await multipartRequest.send();
740 String strResponse = await res.stream.bytesToString();
741 print(".....print out response....");
742 print(strResponse);
743 var resJson = jsonDecode(strResponse)
744 if (resJson['message'] == "ok") {
745 return 1;
746 } else {
747 return resJson["errors"][0];
748 }
749 } catch(e) {
750 print(e);
751 print("Error occurred trying to request delivery");
752 }
753}
754
755String getFileType(String str) {
756 int ind = str.lastIndexOf('.');
757 String fileExt = str.substring(ind + 1);
758 return fileExt;
759}