diff --git a/lib/api/kurirApi.dart b/lib/api/kurirApi.dart index 9959518..c5978aa 100644 --- a/lib/api/kurirApi.dart +++ b/lib/api/kurirApi.dart @@ -1,4 +1,6 @@ // ignore_for_file: non_constant_identifier_names, file_names +// ignore: unused_import +import 'dart:developer' as dev; import 'dart:async'; import 'dart:convert'; @@ -17,6 +19,67 @@ class KurirApi { client.close(); } + // get all pengiriman status ='Dalam Pengesahan Kurir' + static Future> + getAllPengirimanDalamPengesahanKurir() async { + client = http.Client(); + late Map result; + + bool _cek_jaringan = await cek_jaringan(client); + + log("cek jaringan : " + _cek_jaringan.toString()); + var storage = GetStorage(); + var username = storage.read("username"); + var password = storage.read("password"); + var id = storage.read("id"); + + if (!_cek_jaringan) { + result = { + 'status': 500, + 'message': + "Tidak dapat terhubung ke server, Sila periksa koneksi internet anda" + }; + } else { + // wait for 3 sec + // await Future.delayed(Duration(seconds: 3)); + // result = {'status': 200, 'message': "sini dia"}; + + try { + // log("${globals.http_to_server}api/kurir/get_all_kurir_dalam_pengesahan?username=$username&password=$password&id=$id"); + var response = await client.get( + Uri.parse( + "${globals.http_to_server}api/kurir/pengiriman_kurir_dalam_pengesahan?username=$username&password=$password&id=$id"), + headers: { + "Accept": "application/json", + // "authorization": + // "Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}", + "crossDomain": "true" + }).timeout(const Duration(seconds: 10)); + final data = jsonDecode(response.body); + // log(data.toString()); + // log("ini status : " + response.statusCode.toString()); + if (response.statusCode == 200) { + result = { + 'status': 200, + 'message': data['message'], + 'data': data['data'] + }; + } else { + result = {'status': 400, 'message': "Server Error", 'data': data}; + } + } catch (e) { + // dev.log(e.toString()); + result = { + 'status': 500, + 'message': + "Tidak dapat terhubung ke server, Sila periksa koneksi internet anda" + }; + } + } + + return result; + } + // cek pengaturan kurir static Future> cekPengaturanKurir() async { client = http.Client(); diff --git a/lib/api/notification_api.dart b/lib/api/notification_api.dart new file mode 100644 index 0000000..ab008f4 --- /dev/null +++ b/lib/api/notification_api.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:flutter_native_timezone/flutter_native_timezone.dart'; +import 'package:rxdart/rxdart.dart'; +import 'package:timezone/timezone.dart' as tz; +// import 'package:timezone/tzdata.dart' as tz; + +// ignore: avoid_classes_with_only_static_members +class NotificationApi { + // Below is the code for initializing the plugin using var _notificationPlugin + static final _notifications = FlutterLocalNotificationsPlugin(); + static final onNotifications = BehaviorSubject(); + + static Future showNotification({ + required int id, + String? title, + String? body, + String? payload, + }) async => + _notifications.show( + id, + title, + body, + await _notificanDetails(), + payload: payload, + ); + + // static Future showScheduleNotification() async => + // _notifications.zonedSchedule( + // 0, + // 'Cek Laporan', + // "Laporan Baru Mungkin Ada, Sila Cek Di Aplikasi", + // // tz.TZDateTime.from(scheduledDate, tz.local), + // _scheduleDaily(const Time(18)), + // await _notificanDetails(), + // payload: "Laporan Baru Mungkin Ada, Sila Cek Di Aplikasi", + // androidAllowWhileIdle: true, + // uiLocalNotificationDateInterpretation: + // UILocalNotificationDateInterpretation.absoluteTime, + // matchDateTimeComponents: DateTimeComponents.time, + // ); + + static Future _notificanDetails() async { + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + 'your channel id', + 'your channel name', + channelDescription: 'your channel description', + importance: Importance.max, + // priority: Priority.high, + // ticker: 'ticker', + ); + return const NotificationDetails( + android: androidPlatformChannelSpecifics, + iOS: IOSNotificationDetails(), + ); + } + + static Future init( + {bool initScheduled = false, BuildContext? context}) async { + const android = AndroidInitializationSettings('app_icon'); + const iOS = IOSInitializationSettings(); + const settings = InitializationSettings(android: android, iOS: iOS); + + final details = await _notifications.getNotificationAppLaunchDetails(); + if (details != null && details.didNotificationLaunchApp) { + onNotifications.add(details.payload); + } + + await _notifications.initialize( + settings, + onSelectNotification: (payload) async { + onNotifications.add(payload); + }, + ); + + if (initScheduled) { + final locationName = await FlutterNativeTimezone.getLocalTimezone(); + tz.setLocalLocation(tz.getLocation(locationName)); + } + } + + // static tz.TZDateTime _scheduleDaily(Time time) { + // final tz.TZDateTime now = tz.TZDateTime.now(tz.local); + // final scheduledDate = tz.TZDateTime(tz.local, now.year, now.month, now.day, + // time.hour, time.minute, time.second); + // // if (scheduledDate.isBefore(now)) { + // // scheduledDate = scheduledDate.add(const Duration(days: 1)); + // // } + // return scheduledDate.isBefore(now) + // ? scheduledDate.add(const Duration(days: 1)) + // : scheduledDate; + // } +} diff --git a/lib/binding/infoPengirimanBinding.dart b/lib/binding/infoPengirimanBinding.dart new file mode 100644 index 0000000..9fcfe91 --- /dev/null +++ b/lib/binding/infoPengirimanBinding.dart @@ -0,0 +1,11 @@ +// ignore_for_file: file_names + +import 'package:get/get.dart'; +import 'package:kurir/controller/after_login/pengirim/infoPengirimanController.dart'; + +class InfoPengirimanBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => InfoPengirimanController()); + } +} diff --git a/lib/binding/kurirIndexBinding.dart b/lib/binding/kurirIndexBinding.dart index bb0ce74..daf642e 100644 --- a/lib/binding/kurirIndexBinding.dart +++ b/lib/binding/kurirIndexBinding.dart @@ -1,9 +1,10 @@ // ignore_for_file: file_names import 'package:get/get.dart'; -import 'package:kurir/controller/after_login/kurir/pengaturanController.dart'; import '../controller/after_login/kurir/indexController.dart'; +import '../controller/after_login/kurir/pengaturanController.dart'; +import '../controller/after_login/kurir/pengirimanController.dart'; class KurirIndexBinding extends Bindings { @override @@ -11,5 +12,6 @@ class KurirIndexBinding extends Bindings { Get.lazyPut(() => KurirIndexController()); Get.lazyPut(() => PengaturanKurirController()); + Get.lazyPut(() => PengirimanKurirController()); } } diff --git a/lib/binding/pengirimIndexBinding.dart b/lib/binding/pengirimIndexBinding.dart index b41f498..1ac0779 100644 --- a/lib/binding/pengirimIndexBinding.dart +++ b/lib/binding/pengirimIndexBinding.dart @@ -1,10 +1,11 @@ // ignore_for_file: file_names import 'package:get/get.dart'; -import 'package:kurir/controller/after_login/pengirim/kirimBarangController.dart'; -import 'package:kurir/controller/after_login/pengirim/logKirimanController.dart'; import '../controller/after_login/pengirim/indexController.dart'; +import '../controller/after_login/pengirim/kirimBarangController.dart'; +import '../controller/after_login/pengirim/listKurirController.dart'; +import '../controller/after_login/pengirim/logKirimanController.dart'; class PengirimIndexBinding extends Bindings { @override @@ -14,5 +15,7 @@ class PengirimIndexBinding extends Bindings { Get.lazyPut(() => KirimBarangController()); Get.lazyPut(() => LogKirimanController()); + + Get.lazyPut(() => ListKurirController()); } } diff --git a/lib/binding/pengirimProfileBinding.dart b/lib/binding/pengirimProfileBinding.dart new file mode 100644 index 0000000..6f30bbf --- /dev/null +++ b/lib/binding/pengirimProfileBinding.dart @@ -0,0 +1,13 @@ +// ignore_for_file: file_names + +import 'package:get/get.dart'; +import 'package:kurir/controller/after_login/pengirim/pengirimProfileController.dart'; + +class PengirimProfileBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut( + () => PengirimProfileController(), + ); + } +} diff --git a/lib/controller/after_login/kurir/indexController.dart b/lib/controller/after_login/kurir/indexController.dart index 4214743..551c658 100644 --- a/lib/controller/after_login/kurir/indexController.dart +++ b/lib/controller/after_login/kurir/indexController.dart @@ -4,10 +4,12 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:kurir/controller/after_login/kurir/pengaturanController.dart'; import 'package:socket_io_client/socket_io_client.dart'; +import 'pengaturanController.dart'; +import 'pengirimanController.dart'; + class KurirIndexController extends GetxController { late Socket socket; @@ -27,6 +29,15 @@ class KurirIndexController extends GetxController { // Get.put(PengaturanKurirController()); + break; + case 1: + final ctrl = Get.put( + PengirimanKurirController(), + ); + ctrl.onInit(); + + // Get.put(PengaturanKurirController()); + break; default: } @@ -63,7 +74,8 @@ class KurirIndexController extends GetxController { ), ], currentIndex: _indexTap.value, - selectedItemColor: const Color.fromARGB(255, 148, 183, 229), + selectedItemColor: const Color.fromARGB(255, 2, 72, 72), + unselectedItemColor: const Color.fromARGB(255, 199, 214, 234), onTap: (index) => _onItemTapped(index, context), ); } diff --git a/lib/controller/after_login/kurir/pengirimanController.dart b/lib/controller/after_login/kurir/pengirimanController.dart new file mode 100644 index 0000000..17c1a75 --- /dev/null +++ b/lib/controller/after_login/kurir/pengirimanController.dart @@ -0,0 +1,415 @@ +// ignore_for_file: file_names + +import 'dart:developer' as dev; + +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_polyline_points/flutter_polyline_points.dart'; +import 'package:get/get.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:kurir/function/allFunction.dart'; + +import '../../../api/kurirApi.dart'; +import '../../../api/pengirimApi.dart'; +import '../../../models/pengirimimanModel.dart'; + +import 'package:kurir/globals.dart' as globals; + +class PengirimanKurirController extends GetxController { + RxList pengirimanModelList = [].obs; + RxInt loadPengiriman = 0.obs; + + late GoogleMapController mapController; + final Set markers = {}; + final Set polylines = {}; + List _polylineCoordinates = []; + final PolylinePoints _polylinePoints = PolylinePoints(); + final String _googleAPiKey = globals.api_key; + + List? _listLatLng; + + // late GoogleMapController mapController; + final _initialCameraPosition = const CameraPosition( + target: LatLng(-3.5621854706823193, 119.7612856634139), + zoom: 12.5, + ); + + @override + void onReady() { + super.onReady(); + dev.log("sini on ready pengiriman"); + pengirimanAll(); + } + + pengirimanAll() async { + loadPengiriman.value = 0; + pengirimanModelList.value = []; + Map _data = + await KurirApi.getAllPengirimanDalamPengesahanKurir(); + + if (_data['status'] == 200) { + if (_data['data'].length > 0) { + pengirimanModelList.value = + _data['data'].map((e) => PengirimanModel.fromJson(e)).toList(); + } else { + pengirimanModelList.value = []; + } + loadPengiriman.value = 1; + } else { + pengirimanModelList.value = []; + loadPengiriman.value = 2; + } + } + + String timeZoneAdd8(time) { + // add 8 hours to timezone + // createdAt.add(Duration(hours: 8)); + // dev.log(createdAt.toString()); + var _time = DateTime.parse(time).add(const Duration(hours: 8)); + // dev.log(_time.toString()); + // seperate date and time + var _date = _time.toString().split(" ")[0]; + var _time2 = _time.toString().split(" ")[1]; + // only take the hour and minute + _time2 = _time2.split(":")[0] + ":" + _time2.split(":")[1]; + // if the hour is less than 10, add 0 before + if (_time2.split(":")[0].length == 1) { + _time2 = "0" + _time2; + } + // if the minute is less than 10, add 0 before + if (_time2.split(":")[1].length == 1) { + _time2 = _time2 + "0"; + } + // if past 12:00, add "PM" + if (int.parse(_time2.split(":")[0]) >= 12) { + _time2 = _time2 + " PM"; + } else { + _time2 = _time2 + " AM"; + } + + return _date + " | " + _time2; + } + + String cekHarga( + double distance, int biayaMinimal, int biayaMaksimal, int biayaPerKilo) { + // + double hargaPerKiloTotal = biayaPerKilo * distance; + double hargaTotalMinimal = hargaPerKiloTotal + biayaMinimal; + double hargaTotalMaksimal = hargaPerKiloTotal + biayaMaksimal; + + return "Rp. " + + AllFunction.thousandSeperatorDouble(hargaTotalMinimal) + + " - Rp. " + + AllFunction.thousandSeperatorDouble(hargaTotalMaksimal); + } + + cekDistance(LatLng latLngPengiriman, LatLng latLngPermulaan) async { + dev.log("sini dia berlaku"); + PolylineResult _result = await _polylinePoints.getRouteBetweenCoordinates( + _googleAPiKey, + PointLatLng(latLngPermulaan.latitude, latLngPermulaan.longitude), + PointLatLng(latLngPengiriman.latitude, latLngPengiriman.longitude), + travelMode: TravelMode.driving, + // travelMode: TravelMode.driving, + ); + + // log(_result.points.toString() + "ini dia"); + if (_result.points.isNotEmpty) { + double distance = await PengirimApi.jarak_route( + latLngPermulaan.latitude, + latLngPermulaan.longitude, + latLngPengiriman.latitude, + latLngPengiriman.longitude, + ); + + dev.log(distance.toString() + "ini dia"); + + return distance; + } else { + return 0; + } + } + + void showMapDialog(BuildContext context, PengirimanModel data) async { + await EasyLoading.show( + status: 'Loading Peta...', + maskType: EasyLoadingMaskType.black, + ); + markers.clear(); + polylines.clear(); + _polylineCoordinates = []; + _listLatLng = null; + // _polylinePoints.clear(); + + LatLng _latLng_pengiriman = LatLng( + double.parse(data.kordinatPengiriman!.lat!), + double.parse(data.kordinatPengiriman!.lng!), + ); + + LatLng _latLng_permulaan = LatLng( + double.parse(data.kordinatPermulaan!.lat!), + double.parse(data.kordinatPermulaan!.lng!), + ); + + await setPolylines( + _latLng_pengiriman, + _latLng_permulaan, + ); + + markers.add( + Marker( + markerId: const MarkerId("permulaan"), + position: LatLng(double.parse(data.kordinatPermulaan!.lat!), + double.parse(data.kordinatPermulaan!.lng!)), + infoWindow: const InfoWindow( + title: "Lokasi Permulaan", + ), + ), + ); + + markers.add( + Marker( + markerId: const MarkerId("pengiriman"), + position: LatLng(double.parse(data.kordinatPengiriman!.lat!), + double.parse(data.kordinatPengiriman!.lng!)), + infoWindow: const InfoWindow( + title: "LokasiPengiriman", + ), + ), + ); + // await 1 sec + // await Future.delayed(Duration(seconds: 1)); + Get.dialog(_MapDialogBox( + data: data, + onBounds: onBounds, + markers: markers, + polylines: polylines, + initialCameraPosition: _initialCameraPosition, + cekDistance: cekDistance, + )); + + await EasyLoading.dismiss(); + } + + setPolylines(LatLng latLng_pengiriman, LatLng latLng_permulaan) async { + PolylineResult _result = await _polylinePoints.getRouteBetweenCoordinates( + _googleAPiKey, + PointLatLng(latLng_permulaan.latitude, latLng_permulaan.longitude), + PointLatLng(latLng_pengiriman.latitude, latLng_pengiriman.longitude), + travelMode: TravelMode.driving, + // travelMode: TravelMode.driving, + ); + + // log(_result.points.toString() + "ini dia"); + if (_result.points.isNotEmpty) { + // loop through all PointLatLng points and convert them + // to a list of LatLng, required by the Polyline + _listLatLng = [latLng_permulaan]; + for (var point in _result.points) { + _polylineCoordinates.add(LatLng(point.latitude, point.longitude)); + _listLatLng!.add(LatLng(point.latitude, point.longitude)); + } + _listLatLng!.add(latLng_pengiriman); + + Polyline polyline = Polyline( + polylineId: const PolylineId("poly"), + color: const Color.fromARGB(255, 40, 122, 198), + points: _polylineCoordinates, + width: 3, + ); + polylines.add(polyline); + } + } + + void onBounds(GoogleMapController controller) { + mapController = controller; + mapController.animateCamera( + CameraUpdate.newLatLngBounds( + AllFunction.computeBounds(_listLatLng!), + 15, + ), + ); + } + + lihat_foto_kiriman(BuildContext context, String fotoPengiriman) { + if (fotoPengiriman != "") { + Get.dialog( + _FotoPengirimanDialogBox( + fotoPengiriman: fotoPengiriman, + ), + ); + } else { + Get.snackbar( + "Info", + "Foto Barang Pengiriman Masih Dalam Proses Upload", + icon: const Icon( + Icons.info_outline_rounded, + color: Colors.white, + ), + backgroundColor: const Color.fromARGB(255, 71, 203, 240), + duration: const Duration(seconds: 3), + snackPosition: SnackPosition.TOP, + ); + } + } +} + +class _MapDialogBox extends StatelessWidget { + const _MapDialogBox( + {Key? key, + required this.markers, + required this.polylines, + required this.onBounds, + required this.initialCameraPosition, + required this.cekDistance, + required this.data}) + : super(key: key); + + final Set markers; + final Set polylines; + final void Function(GoogleMapController controller) onBounds; + final CameraPosition initialCameraPosition; + final PengirimanModel data; + final Function cekDistance; + + @override + Widget build(BuildContext context) { + return AlertDialog( + backgroundColor: Color.fromARGB(255, 104, 164, 164), + content: Container( + height: Get.height * 0.5, + child: GoogleMap( + mapType: MapType.normal, + mapToolbarEnabled: true, + rotateGesturesEnabled: true, + myLocationButtonEnabled: true, + markers: markers, + polylines: polylines, + // liteModeEnabled: true, + initialCameraPosition: initialCameraPosition, + onMapCreated: onBounds, + // onCameraMove: _onCameraMove, + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + const SizedBox(), + FutureBuilder( + future: cekDistance( + LatLng(double.parse(data.kordinatPengiriman!.lat!), + double.parse(data.kordinatPengiriman!.lng!)), + LatLng(double.parse(data.kordinatPermulaan!.lat!), + double.parse(data.kordinatPermulaan!.lng!))), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Container( + width: 200, + child: TextFormField( + enabled: false, + style: TextStyle(color: Colors.white), + initialValue: snapshot.data.toString() + " km", + decoration: InputDecoration( + labelText: 'Jarak Pengiriman', + labelStyle: TextStyle(color: Colors.white), + filled: true, + fillColor: Colors.transparent, + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + ), + ); + } else if (snapshot.hasError) { + return Text( + "Error mengambil data", + style: const TextStyle( + fontSize: 15, + color: Colors.white, + overflow: TextOverflow.ellipsis, + ), + ); + } else { + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + Colors.white, + ), + ), + ); + } + }, + ), + const SizedBox() + ], + ), + const SizedBox( + height: 10, + ), + ], + ); + } +} + +class _FotoPengirimanDialogBox extends StatelessWidget { + const _FotoPengirimanDialogBox({Key? key, required this.fotoPengiriman}) + : super(key: key); + + final String fotoPengiriman; + + @override + Widget build(BuildContext context) { + return AlertDialog( + backgroundColor: Color.fromARGB(255, 104, 164, 164), + title: const Text( + "Foto Pengiriman", + style: TextStyle(color: Colors.white), + ), + content: Container( + height: Get.height * 0.5, + width: Get.width * 0.6, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(20), + ), + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.grey, + spreadRadius: 1, + blurRadius: 10, + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/loading.gif'), + fit: BoxFit.cover, + ), + ), + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: NetworkImage(fotoPengiriman), + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/controller/after_login/pengirim/indexController.dart b/lib/controller/after_login/pengirim/indexController.dart index da65e75..a84ed97 100644 --- a/lib/controller/after_login/pengirim/indexController.dart +++ b/lib/controller/after_login/pengirim/indexController.dart @@ -5,6 +5,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:kurir/controller/after_login/pengirim/kirimBarangController.dart'; +import 'package:kurir/controller/after_login/pengirim/listKurirController.dart'; import 'package:kurir/controller/after_login/pengirim/logKirimanController.dart'; class PengirimIndexController extends GetxController { @@ -26,6 +27,12 @@ class PengirimIndexController extends GetxController { _init.onInit(); } + if (index == 2) { + // Get.lazyPut(() => KirimBarangController()); + var _init = Get.put(ListKurirController()); + _init.onReady(); + } + _indexTap.value = index; } @@ -60,7 +67,7 @@ class PengirimIndexController extends GetxController { ), ], currentIndex: _indexTap.value, - selectedItemColor: const Color.fromARGB(255, 148, 183, 229), + selectedItemColor: const Color.fromARGB(255, 2, 72, 72), onTap: (index) => _onItemTapped(index, context), ); } @@ -68,7 +75,7 @@ class PengirimIndexController extends GetxController { _onItemTapped(int index, BuildContext context) { log("sini on item tapped"); if (index == 3) { - Get.offAllNamed('/profilePengirim'); + Get.offAndToNamed('/pengirimIndex/profilePengirim'); } _indexTap.value = index; diff --git a/lib/controller/after_login/pengirim/infoPengirimanController.dart b/lib/controller/after_login/pengirim/infoPengirimanController.dart new file mode 100644 index 0000000..7936818 --- /dev/null +++ b/lib/controller/after_login/pengirim/infoPengirimanController.dart @@ -0,0 +1,374 @@ +// ignore_for_file: file_names, non_constant_identifier_names + +import 'dart:developer' as dev; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_polyline_points/flutter_polyline_points.dart'; +import 'package:kurir/api/pengirimApi.dart'; +import 'package:kurir/function/allFunction.dart'; +import 'package:kurir/globals.dart' as globals; + +import 'package:get/get.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:kurir/models/pengirimimanModel.dart'; + +class InfoPengirimanController extends GetxController { + final dynamic _argumicData = Get.arguments; + late PengirimanModel pengirimanModel; + // late String jumlah_pembayaran; + String dummyTest = "heheheheh"; + + late GoogleMapController mapController; + final _initialCameraPosition = const CameraPosition( + target: LatLng(-3.5621854706823193, 119.7612856634139), + zoom: 12.5, + ); + final Set _markers = {}; + final Set _polylines = {}; + final List _polylineCoordinates = []; + final PolylinePoints _polylinePoints = PolylinePoints(); + final String _googleAPiKey = globals.api_key; + + List? _listLatLng; + TextEditingController distance_travel_controller = TextEditingController(); + TextEditingController price_controller = TextEditingController(); + + RxBool loadingMaps = false.obs; + + @override + void onInit() { + // ignore: todo + // TODO: implement onInit + pengirimanModel = _argumicData['pengiriman_model']; + dev.log(" ini idnya ${pengirimanModel.fotoPengiriman}"); + distance_travel_controller.text = "loading..."; + price_controller.text = "loading..."; + set_the_maps(pengirimanModel.kordinatPengiriman!, + pengirimanModel.kordinatPermulaan!); + super.onInit(); + } + + set_the_maps(KordinatPengiriman kordinat_pengiriman, + KordinatPermulaan kordinat_permulaan) async { + LatLng _latLng_pengiriman = LatLng( + double.parse(kordinat_pengiriman.lat!), + double.parse(kordinat_pengiriman.lng!), + ); + + LatLng _latLng_permulaan = LatLng( + double.parse(kordinat_permulaan.lat!), + double.parse(kordinat_permulaan.lng!), + ); + _markers.add( + Marker( + markerId: const MarkerId("permulaan"), + position: LatLng(double.parse(kordinat_permulaan.lat!), + double.parse(kordinat_permulaan.lng!)), + infoWindow: const InfoWindow( + title: "Lokasi Permulaan", + ), + ), + ); + + _markers.add( + Marker( + markerId: const MarkerId("pengiriman"), + position: LatLng(double.parse(kordinat_pengiriman.lat!), + double.parse(kordinat_pengiriman.lng!)), + infoWindow: const InfoWindow( + title: "LokasiPengiriman", + ), + ), + ); + await setPolylines( + _latLng_pengiriman, + _latLng_permulaan, + ); + } + + setPolylines(LatLng latLng_pengiriman, LatLng latLng_permulaan) async { + // dev.log("sini dia berlaku"); + PolylineResult _result = await _polylinePoints.getRouteBetweenCoordinates( + _googleAPiKey, + PointLatLng(latLng_permulaan.latitude, latLng_permulaan.longitude), + PointLatLng(latLng_pengiriman.latitude, latLng_pengiriman.longitude), + travelMode: TravelMode.driving, + // travelMode: TravelMode.driving, + ); + + // log(_result.points.toString() + "ini dia"); + if (_result.points.isNotEmpty) { + // loop through all PointLatLng points and convert them + // to a list of LatLng, required by the Polyline + _listLatLng = [latLng_permulaan]; + for (var point in _result.points) { + _polylineCoordinates.add(LatLng(point.latitude, point.longitude)); + _listLatLng!.add(LatLng(point.latitude, point.longitude)); + } + _listLatLng!.add(latLng_pengiriman); + loadingMaps.value = true; + // GoogleMapController _controller2; + // _onBounds(_controller2); + + Polyline polyline = Polyline( + polylineId: const PolylineId("poly"), + color: const Color.fromARGB(255, 40, 122, 198), + points: _polylineCoordinates, + width: 3, + ); + _polylines.add(polyline); + + double distance = await PengirimApi.jarak_route( + latLng_permulaan.latitude, + latLng_permulaan.longitude, + latLng_pengiriman.latitude, + latLng_pengiriman.longitude, + ); + + // dev.log(distance.toString() + "ini dia"); + distance_travel_controller.text = "$distance km"; + double _min_price = distance * pengirimanModel.biaya!.biayaPerKilo! + + pengirimanModel.biaya!.biayaMinimal!; + // rounded to the nearest 1000 + _min_price = (_min_price / 1000).round() * 1000; + double _max_price = distance * pengirimanModel.biaya!.biayaPerKilo! + + pengirimanModel.biaya!.biayaMaksimal!; + // rounded to the nearest 1000 + _max_price = (_max_price / 1000).round() * 1000; + price_controller.text = + "Rp. ${AllFunction.thousandSeperatorDouble(_min_price)} - Rp. ${AllFunction.thousandSeperatorDouble(_max_price)}"; + loadingMaps.value = true; + } + } + + show_maps_dialog() async { + await EasyLoading.show( + status: 'Loading Peta', + maskType: EasyLoadingMaskType.black, + ); + Get.dialog( + AlertDialog( + title: const Text("Rute Pengiriman"), + content: Container( + height: Get.height * 0.5, + decoration: const BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey, + blurRadius: 10, + spreadRadius: 2, + ), + ], + ), + child: SingleChildScrollView( + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + constraints: const BoxConstraints( + minHeight: 200, + maxHeight: 300, + minWidth: 300, + maxWidth: 500, + ), + child: googleMaps(), + ), + ), + ), + ), + ), + ); + await EasyLoading.dismiss(); + } + + Widget googleMaps() { + return GoogleMap( + mapType: MapType.normal, + mapToolbarEnabled: true, + rotateGesturesEnabled: true, + myLocationButtonEnabled: true, + markers: _markers, + polylines: _polylines, + // liteModeEnabled: true, + initialCameraPosition: _initialCameraPosition, + onMapCreated: _onBounds, + // onCameraMove: _onCameraMove, + ); + } + + void _onBounds(GoogleMapController controller) { + mapController = controller; + if (_listLatLng != null) + // ignore: curly_braces_in_flow_control_structures + mapController.animateCamera( + CameraUpdate.newLatLngBounds( + AllFunction.computeBounds(_listLatLng!), + 15, + ), + ); + } + + show_kurir_dialog() { + Get.dialog( + AlertDialog( + title: const Text("Detail Kurir"), + content: SizedBox( + height: Get.height * 0.5, + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 10), + Container( + decoration: const BoxDecoration( + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + blurRadius: 10, color: Colors.grey, spreadRadius: 5) + ], + ), + child: CircleAvatar( + radius: 50, + backgroundImage: const AssetImage('assets/loading.gif'), + backgroundColor: Colors.white, + child: CircleAvatar( + radius: 50.0, + backgroundImage: NetworkImage( + pengirimanModel.kurir!.photo_url ?? + 'https://via.placeholder.com/150'), + backgroundColor: Colors.transparent, + ), + ), + ), + const SizedBox(height: 15), + Container( + decoration: const BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey, + spreadRadius: 1, + blurRadius: 10, + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/loading.gif'), + fit: BoxFit.cover, + ), + color: Colors.white, + ), + width: 200, + height: 200, + child: Image.network( + pengirimanModel.kurir!.kenderaan_url ?? + "https://via.placeholder.com/150", + fit: BoxFit.cover, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: "Rp. " + + AllFunction.thousandsSeperator( + pengirimanModel.biaya!.biayaMinimal!), + // maxLength: 13, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Harga Minimal', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: "Rp. " + + AllFunction.thousandsSeperator( + pengirimanModel.biaya!.biayaMaksimal!), + // maxLength: 13, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Harga Maksimal', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: "Rp. " + + AllFunction.thousandsSeperator( + pengirimanModel.biaya!.biayaPerKilo!), + // maxLength: 13, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Biaya Per Kilometer', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + show_foto_pengiriman() { + Get.bottomSheet( + SingleChildScrollView( + child: Container( + height: Get.height * 0.5, + decoration: const BoxDecoration( + boxShadow: [ + BoxShadow(blurRadius: 10, color: Colors.grey, spreadRadius: 5) + ], + image: DecorationImage( + image: AssetImage('assets/loading.gif'), + fit: BoxFit.cover, + ), + ), + child: Container( + decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(100), + image: DecorationImage( + image: NetworkImage(pengirimanModel.fotoPengiriman ?? + "https://via.placeholder.com/150"), + fit: BoxFit.fill, + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/controller/after_login/pengirim/kirimBarangController.dart b/lib/controller/after_login/pengirim/kirimBarangController.dart index b5fcd16..aa92370 100644 --- a/lib/controller/after_login/pengirim/kirimBarangController.dart +++ b/lib/controller/after_login/pengirim/kirimBarangController.dart @@ -1,4 +1,4 @@ -// ignore_for_file: file_names, non_constant_identifier_names, invalid_use_of_protected_member +// ignore_for_file: file_names, non_constant_identifier_names, invalid_use_of_protected_member, prefer_const_constructors import 'dart:async'; import 'dart:collection'; @@ -28,6 +28,8 @@ import 'package:image_picker/image_picker.dart'; import 'package:location/location.dart'; import 'package:path_provider/path_provider.dart'; +import '../../../widgets/appbar.dart'; + class KirimBarangController extends GetxController { //////// begin of marking delivery location /////// List kelurahan_desa_list = []; //list for kelurahan desa @@ -412,15 +414,19 @@ class KirimBarangController extends GetxController { child: Center( child: Column( children: [ - AppBar( - title: const Text('Pin Lokasi Pengiriman'), - automaticallyImplyLeading: false, - actions: [ - IconButton( - icon: const Icon(Icons.close), - onPressed: () => Get.back(), - ), - ], + PreferredSize( + preferredSize: Size.fromHeight( + MediaQuery.of(context).size.height * 0.08), + child: AppBarWidget( + header: "Pin Lokasi Pengiriman", + autoLeading: false, + actions: [ + IconButton( + icon: const Icon(Icons.close), + onPressed: () => Get.back(), + ), + ], + ), ), const SizedBox(height: 15), SizedBox( @@ -556,7 +562,7 @@ class KirimBarangController extends GetxController { duration: const Duration(seconds: 2), ); } else { - WidgetsBinding.instance?.focusManager.primaryFocus + WidgetsBinding.instance!.focusManager.primaryFocus ?.unfocus(); konfirmKelurahanDesaIndex = _pilihanKelurahanDesa; konfirmMarker = _markerPosition; @@ -579,7 +585,10 @@ class KirimBarangController extends GetxController { style: ElevatedButton.styleFrom( primary: (_pilihanKelurahanDesa == 0) ? Colors.grey - : Colors.blue, + : Color.fromARGB(255, 104, 164, 164), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), ), ), ) @@ -1373,7 +1382,7 @@ class KirimBarangController extends GetxController { ElevatedButton( child: const Text('OK'), onPressed: () { - WidgetsBinding.instance?.focusManager.primaryFocus?.unfocus(); + WidgetsBinding.instance!.focusManager.primaryFocus?.unfocus(); selectedKurirNama = kurirModel.nama!; kurirOutroTextController.text = kurirModel.nama!; @@ -1716,15 +1725,19 @@ class KirimBarangController extends GetxController { child: Center( child: Column( children: [ - AppBar( - title: const Text('Pin Lokasi Permulaan'), - automaticallyImplyLeading: false, - actions: [ - IconButton( - icon: const Icon(Icons.close), - onPressed: () => Get.back(), - ), - ], + PreferredSize( + preferredSize: Size.fromHeight( + MediaQuery.of(context).size.height * 0.08), + child: AppBarWidget( + header: "Pin Lokasi Permulaan", + autoLeading: false, + actions: [ + IconButton( + icon: const Icon(Icons.close), + onPressed: () => Get.back(), + ), + ], + ), ), const SizedBox(height: 15), SizedBox( @@ -1821,26 +1834,26 @@ class KirimBarangController extends GetxController { borderRadius: BorderRadius.circular(10), color: Colors.white, ), - child: ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(10), - bottomRight: Radius.circular(10), - bottomLeft: Radius.circular(10), - ), - child: Obx( - () => GoogleMap( - mapType: - mapTypenya.value ? MapType.normal : MapType.hybrid, - mapToolbarEnabled: true, - rotateGesturesEnabled: true, - myLocationButtonEnabled: true, - polygons: _polygons, - markers: _markers, - // liteModeEnabled: true, - initialCameraPosition: _initialCameraPosition, - onMapCreated: _onBounds, - // onCameraMove: _onCameraMove, + child: SizedBox( + width: 400, + height: 250, + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Obx( + () => GoogleMap( + mapType: mapTypenya.value + ? MapType.normal + : MapType.hybrid, + mapToolbarEnabled: true, + rotateGesturesEnabled: true, + myLocationButtonEnabled: true, + polygons: _polygons, + markers: _markers, + // liteModeEnabled: true, + initialCameraPosition: _initialCameraPosition, + onMapCreated: _onBounds, + // onCameraMove: _onCameraMove, + ), ), ), ), @@ -1856,7 +1869,10 @@ class KirimBarangController extends GetxController { }, child: const Text('Lokasi Sekarang'), style: ElevatedButton.styleFrom( - primary: Colors.blue, + primary: Color.fromARGB(255, 4, 103, 103), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), ), ), const SizedBox( @@ -1873,7 +1889,7 @@ class KirimBarangController extends GetxController { _pilihanKelurahanDesa; } konfirmMarkerLokasiPermulaan = _markerPosition; - WidgetsBinding.instance?.focusManager.primaryFocus + WidgetsBinding.instance!.focusManager.primaryFocus ?.unfocus(); _check_jarak_tempuh(); Get.back(); @@ -1912,7 +1928,10 @@ class KirimBarangController extends GetxController { primary: (_markerPosition == null && konfirmMarkerLokasiPermulaan == null) ? Colors.grey - : Colors.blue, + : Color.fromARGB(255, 104, 164, 164), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), ), ), ], diff --git a/lib/controller/after_login/pengirim/listKurirController.dart b/lib/controller/after_login/pengirim/listKurirController.dart new file mode 100644 index 0000000..91a0322 --- /dev/null +++ b/lib/controller/after_login/pengirim/listKurirController.dart @@ -0,0 +1,37 @@ +// ignore_for_file: file_names + +import 'package:get/get.dart'; + +import '../../../api/pengirimApi.dart'; +import '../../../models/usersModel.dart'; + +class ListKurirController extends GetxController { + RxList kurirModelList = [].obs; + RxInt loadKurir = 0.obs; + + @override + void onReady() { + super.onReady(); + kurirAll(); + } + + kurirAll() async { + loadKurir.value = 0; + kurirModelList.value = []; + Map _data = await PengirimApi.getAllKurir(); + // dev.log(_data.toString()); + + if (_data['status'] == 200) { + if (_data['data'].length > 0) { + kurirModelList.value = + _data['data'].map((e) => KurirModel.fromJson(e)).toList(); + } else { + kurirModelList.value = []; + } + loadKurir.value = 1; + } else { + kurirModelList.value = []; + loadKurir.value = 2; + } + } +} diff --git a/lib/controller/after_login/pengirim/logKirimanController.dart b/lib/controller/after_login/pengirim/logKirimanController.dart index 0834d12..5456810 100644 --- a/lib/controller/after_login/pengirim/logKirimanController.dart +++ b/lib/controller/after_login/pengirim/logKirimanController.dart @@ -1,8 +1,9 @@ -// ignore_for_file: file_names, non_constant_identifier_names +// ignore_for_file: file_names, non_constant_identifier_names, sized_box_for_whitespace import 'dart:developer'; import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_polyline_points/flutter_polyline_points.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:get/get.dart'; @@ -22,13 +23,14 @@ class LogKirimanController extends GetxController { RxBool isPortrait = true.obs; late GoogleMapController mapController; - Set _markers = {}; - Set _polylines = {}; + final Set _markers = {}; + final Set _polylines = {}; List _polylineCoordinates = []; - PolylinePoints _polylinePoints = PolylinePoints(); - String _googleAPiKey = globals.api_key; + final PolylinePoints _polylinePoints = PolylinePoints(); + final String _googleAPiKey = globals.api_key; List? _listLatLng; + double? _distance_travel; // late GoogleMapController mapController; final _initialCameraPosition = const CameraPosition( @@ -59,7 +61,7 @@ class LogKirimanController extends GetxController { checkAllLogKiriman() async { Map _data = await PengirimApi.getLogKiriman(); - log(_data.toString()); + // log(_data.toString()); // await 4 sec widgetLogKiriman.value = const Center( child: CircularProgressIndicator(), @@ -70,7 +72,7 @@ class LogKirimanController extends GetxController { for (var item in _data['data']) { PengirimanModel? _pengirimanModel = PengirimanModel.fromJson(item); - // log(_pengiriman.kurir!.id.toString()); + log(_pengirimanModel.createdAt.toString()); _listWidget.add(_widgetLogKiriman(_pengirimanModel)); // _listWidget.add(_widgetLogKiriman()); @@ -102,8 +104,9 @@ class LogKirimanController extends GetxController { } } - _widgetLogKiriman(PengirimanModel? _pengirimanModel) { - var _createdAtPlus8 = DateTime.parse(_pengirimanModel!.createdAt!) + Widget _widgetLogKiriman(PengirimanModel _pengirimanModel) { + log(_pengirimanModel.kurir.toString()); + var _createdAtPlus8 = DateTime.parse(_pengirimanModel.createdAt!) .add(const Duration(hours: 8)); String _tanggal = DateFormat('dd-MM-yyyy').format(_createdAtPlus8); @@ -112,6 +115,7 @@ class LogKirimanController extends GetxController { String _jam = DateFormat('HH:mm:ss').format(_createdAtPlus8); String _nama_kurir = _pengirimanModel.kurir!.nama!; + // String _nama_kurir = "Nama"; String _status = _pengirimanModel.statusPengiriman!; @@ -132,8 +136,15 @@ class LogKirimanController extends GetxController { children: [ SlidableAction( flex: 2, - onPressed: (context) {}, - backgroundColor: const Color.fromARGB(255, 70, 192, 232), + onPressed: (context) { + Get.offAndToNamed( + '/pengirimIndex/infoPengiriman', + arguments: { + 'pengiriman_model': _pengirimanModel, + }, + ); + }, + backgroundColor: const Color.fromARGB(255, 104, 164, 164), foregroundColor: Colors.white, icon: Icons.info_outline_rounded, label: 'Info', @@ -143,7 +154,7 @@ class LogKirimanController extends GetxController { onPressed: (context) { _lihat_foto_kiriman(context, _foto_pengiriman); }, - backgroundColor: const Color.fromARGB(255, 71, 92, 250), + backgroundColor: const Color.fromARGB(255, 4, 103, 103), foregroundColor: Colors.white, icon: Icons.photo_rounded, label: 'Barang Kiriman', @@ -159,7 +170,7 @@ class LogKirimanController extends GetxController { _lihat_rute_pengiriman( context, _kordinat_pengiriman, _kordinat_permulaan); }, - backgroundColor: Color.fromARGB(255, 242, 78, 23), + backgroundColor: const Color.fromARGB(255, 2, 72, 72), foregroundColor: Colors.white, icon: Icons.maps_home_work_rounded, label: "Rute Pengiriman", @@ -234,7 +245,7 @@ class LogKirimanController extends GetxController { _lihat_foto_kiriman(BuildContext context, String foto_pengiriman) { log(foto_pengiriman); - if (foto_pengiriman != null && foto_pengiriman != "") { + if (foto_pengiriman != "") { Get.dialog( AlertDialog( title: const Text("Foto Pengiriman"), @@ -253,7 +264,7 @@ class LogKirimanController extends GetxController { child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Container( - decoration: BoxDecoration( + decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/loading.gif'), fit: BoxFit.cover, @@ -276,12 +287,12 @@ class LogKirimanController extends GetxController { Get.snackbar( "Info", "Foto Barang Pengiriman Masih Dalam Proses Upload", - icon: Icon( + icon: const Icon( Icons.info_outline_rounded, color: Colors.white, ), - backgroundColor: Color.fromARGB(255, 71, 203, 240), - duration: Duration(seconds: 3), + backgroundColor: const Color.fromARGB(255, 71, 203, 240), + duration: const Duration(seconds: 3), snackPosition: SnackPosition.TOP, ); } @@ -291,6 +302,10 @@ class LogKirimanController extends GetxController { BuildContext context, KordinatPengiriman kordinat_pengiriman, KordinatPermulaan kordinat_permulaan) async { + await EasyLoading.show( + status: 'Loading Peta...', + maskType: EasyLoadingMaskType.black, + ); _markers.clear(); _polylines.clear(); _polylineCoordinates = []; @@ -306,16 +321,16 @@ class LogKirimanController extends GetxController { double.parse(kordinat_permulaan.lat!), double.parse(kordinat_permulaan.lng!), ); - _listLatLng = [ - LatLng( - double.parse(kordinat_permulaan.lat!), - double.parse(kordinat_permulaan.lng!), - ), - LatLng( - double.parse(kordinat_pengiriman.lat!), - double.parse(kordinat_pengiriman.lng!), - ), - ]; + // _listLatLng = [ + // LatLng( + // double.parse(kordinat_permulaan.lat!), + // double.parse(kordinat_permulaan.lng!), + // ), + // LatLng( + // double.parse(kordinat_pengiriman.lat!), + // double.parse(kordinat_pengiriman.lng!), + // ), + // ]; await setPolylines( _latLng_pengiriman, @@ -327,7 +342,7 @@ class LogKirimanController extends GetxController { markerId: const MarkerId("permulaan"), position: LatLng(double.parse(kordinat_permulaan.lat!), double.parse(kordinat_permulaan.lng!)), - infoWindow: InfoWindow( + infoWindow: const InfoWindow( title: "Lokasi Permulaan", ), ), @@ -338,19 +353,19 @@ class LogKirimanController extends GetxController { markerId: const MarkerId("pengiriman"), position: LatLng(double.parse(kordinat_pengiriman.lat!), double.parse(kordinat_pengiriman.lng!)), - infoWindow: InfoWindow( + infoWindow: const InfoWindow( title: "LokasiPengiriman", ), ), ); // await 1 sec - await Future.delayed(Duration(seconds: 1)); + // await Future.delayed(Duration(seconds: 1)); Get.dialog( AlertDialog( content: Container( height: Get.height * 0.5, child: GoogleMap( - mapType: MapType.hybrid, + mapType: MapType.normal, mapToolbarEnabled: true, rotateGesturesEnabled: true, myLocationButtonEnabled: true, @@ -362,8 +377,37 @@ class LogKirimanController extends GetxController { // onCameraMove: _onCameraMove, ), ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + const SizedBox(), + Container( + width: 200, + child: TextFormField( + initialValue: _distance_travel.toString() + " km", + decoration: InputDecoration( + labelText: 'Jarak Pengiriman', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + ), + const SizedBox() + ], + ), + const SizedBox( + height: 10, + ), + ], ), ); + + await EasyLoading.dismiss(); } setPolylines(LatLng latLng_pengiriman, LatLng latLng_permulaan) async { @@ -375,17 +419,21 @@ class LogKirimanController extends GetxController { travelMode: TravelMode.driving, // travelMode: TravelMode.driving, ); + // log(_result.points.toString() + "ini dia"); if (_result.points.isNotEmpty) { // loop through all PointLatLng points and convert them // to a list of LatLng, required by the Polyline - _result.points.forEach((PointLatLng point) { + _listLatLng = [latLng_permulaan]; + for (var point in _result.points) { _polylineCoordinates.add(LatLng(point.latitude, point.longitude)); - }); + _listLatLng!.add(LatLng(point.latitude, point.longitude)); + } + _listLatLng!.add(latLng_pengiriman); Polyline polyline = Polyline( - polylineId: PolylineId("poly"), - color: Color.fromARGB(255, 40, 122, 198), + polylineId: const PolylineId("poly"), + color: const Color.fromARGB(255, 40, 122, 198), points: _polylineCoordinates, width: 3, ); @@ -399,6 +447,7 @@ class LogKirimanController extends GetxController { ); log(distance.toString() + "ini dia"); + _distance_travel = distance; } } diff --git a/lib/controller/after_login/pengirim/pengirimProfileController.dart b/lib/controller/after_login/pengirim/pengirimProfileController.dart new file mode 100644 index 0000000..b5612b7 --- /dev/null +++ b/lib/controller/after_login/pengirim/pengirimProfileController.dart @@ -0,0 +1,33 @@ +// ignore_for_file: file_names + +// ignore: unused_import +import 'dart:developer' as dev; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:get/get.dart'; +import 'package:kurir/api/beforeLoginAPI.dart'; + +class PengirimProfileController extends GetxController { + String headerText = "Profil Pengirim"; + @override + void onInit() { + dev.log("sini on init profile pengirim"); + super.onInit(); + } + + logout() async { + await EasyLoading.show( + status: 'Logout', + maskType: EasyLoadingMaskType.black, + ); + + await BeforeLoginApi.logout(); + await EasyLoading.dismiss(); + Get.offAllNamed( + '/index', + arguments: { + "tap": 0, + "history": [0], + }, + ); + } +} diff --git a/lib/controller/before_login/loginController.dart b/lib/controller/before_login/loginController.dart index 65ffbff..3ec2ff5 100644 --- a/lib/controller/before_login/loginController.dart +++ b/lib/controller/before_login/loginController.dart @@ -209,7 +209,7 @@ class LoginController extends GetxController { items: const [ BottomNavigationBarItem( icon: Icon(Icons.home), - label: 'Home', + label: 'Halaman Utama', ), BottomNavigationBarItem( icon: Icon(Icons.login), @@ -221,7 +221,7 @@ class LoginController extends GetxController { ), ], currentIndex: _indexTap.value, - selectedItemColor: const Color.fromARGB(255, 148, 183, 229), + selectedItemColor: const Color.fromARGB(255, 2, 72, 72), onTap: _onItemTapped, ); } diff --git a/lib/controller/before_login/pendaftaranKurirController.dart b/lib/controller/before_login/pendaftaranKurirController.dart index 323c2b1..2038b3b 100644 --- a/lib/controller/before_login/pendaftaranKurirController.dart +++ b/lib/controller/before_login/pendaftaranKurirController.dart @@ -276,6 +276,12 @@ class PendaftaranKurirController extends GetxController { onPressed: () { Get.back(); }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: const Text("OK"), ), const SizedBox(), @@ -299,6 +305,9 @@ class PendaftaranKurirController extends GetxController { actions: [ ElevatedButton( child: const Text('Tidak'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + ), onPressed: () { Get.back(); }, @@ -306,7 +315,7 @@ class PendaftaranKurirController extends GetxController { ElevatedButton( child: const Text('Ya'), style: ElevatedButton.styleFrom( - primary: Colors.red, + primary: const Color.fromARGB(255, 104, 164, 164), ), onPressed: () { sign_up(); @@ -472,6 +481,9 @@ class PendaftaranKurirController extends GetxController { actions: [ ElevatedButton( child: const Text('Tidak'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 104, 164, 164), + ), onPressed: () { Get.back(); }, @@ -479,7 +491,7 @@ class PendaftaranKurirController extends GetxController { ElevatedButton( child: const Text('Ya'), style: ElevatedButton.styleFrom( - primary: Colors.red, + primary: const Color.fromARGB(255, 2, 72, 72), ), onPressed: () async { await _cek_and_delete(); diff --git a/lib/controller/before_login/pendaftaranPengirimController.dart b/lib/controller/before_login/pendaftaranPengirimController.dart index dc9d5ad..4d1181e 100644 --- a/lib/controller/before_login/pendaftaranPengirimController.dart +++ b/lib/controller/before_login/pendaftaranPengirimController.dart @@ -79,6 +79,10 @@ class PendaftaranPengirimController extends GetxController { onPressed: () { Get.back(); }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + textStyle: const TextStyle(color: Colors.white), + ), child: const Text("OK"), ), const SizedBox(), @@ -225,6 +229,9 @@ class PendaftaranPengirimController extends GetxController { actions: [ ElevatedButton( child: const Text('Tidak'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + ), onPressed: () { Get.back(); }, @@ -232,7 +239,7 @@ class PendaftaranPengirimController extends GetxController { ElevatedButton( child: const Text('Ya'), style: ElevatedButton.styleFrom( - primary: Colors.red, + primary: const Color.fromARGB(255, 104, 164, 164), ), onPressed: () { // log("sini sign up"); @@ -400,6 +407,9 @@ class PendaftaranPengirimController extends GetxController { actions: [ ElevatedButton( child: const Text('Tidak'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 104, 164, 164), + ), onPressed: () { Get.back(); }, @@ -407,7 +417,7 @@ class PendaftaranPengirimController extends GetxController { ElevatedButton( child: const Text('Ya'), style: ElevatedButton.styleFrom( - primary: Colors.red, + primary: const Color.fromARGB(255, 2, 72, 72), ), onPressed: () async { // await _cek_and_delete(); diff --git a/lib/controller/splashController.dart b/lib/controller/splashController.dart index 817d0a7..f6da62a 100644 --- a/lib/controller/splashController.dart +++ b/lib/controller/splashController.dart @@ -1,9 +1,11 @@ // ignore_for_file: file_names -import 'dart:developer'; +import 'dart:developer' as dev; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; +import 'package:kurir/api/notification_api.dart'; +import 'package:socket_io_client/socket_io_client.dart'; class SplashController extends GetxController { final storage = GetStorage(); @@ -11,8 +13,10 @@ class SplashController extends GetxController { @override void onInit() { super.onInit(); + NotificationApi.init(initScheduled: false); + // connectToServer(); Future.delayed(const Duration(milliseconds: 2500), () { - log('SplashController onInit'); + dev.log('SplashController onInit'); // Get.offAllNamed('/index'); // goto to /index with argument tap : 0 final _role = (storage.read('role') != null) ? storage.read('role') : ''; @@ -30,4 +34,48 @@ class SplashController extends GetxController { } }); } + + late Socket socket; + void connectToServer() async { + try { + // Configure socket transports must be sepecified + socket = io('http://192.168.43.125:3001/', { + 'transports': ['websocket'], + 'autoConnect': true, + }); + + // Connect to websocket + socket.connect(); + + // Handle socket events + socket.on('connect', (_) => dev.log('connect asdasdsad: ${socket.id}')); + socket.on('coba2', (_) { + dev.log(_.toString()); + NotificationApi.showNotification( + id: 1, + title: 'Percobaan 1', + body: _['message'], + payload: 'Percobaan 1', + ); + }); + + socket.on('percobaan1', (_) { + NotificationApi.showNotification( + id: 1, + title: 'Percobaan 1', + body: _['message'], + payload: 'Percobaan 1', + ); + }); + + // socket.on('typing', handleTyping); + // socket.on('message', handleMessage); + // socket.on('disconnect', (_) => dev.log('disconnect')); + // socket.on('fromServer', (_) => dev.log(_)); + dev.log(socket.connected.toString() + " connected"); + } catch (e) { + dev.log(e.toString()); + dev.log('tidak connect'); + } + } } diff --git a/lib/function/allFunction.dart b/lib/function/allFunction.dart index b2e8a9a..28f4e06 100644 --- a/lib/function/allFunction.dart +++ b/lib/function/allFunction.dart @@ -67,6 +67,13 @@ class AllFunction { return numbernya.toString(); } + static String thousandSeperatorDouble(double number) { + final formatter = NumberFormat('#,###'); + final numbernya = formatter.format(number); + // log(numbernya + " ini numbernya"); + return numbernya.toString(); + } + static removeComma(String number) { final numbernya = number.replaceAll(RegExp(r','), ''); return numbernya; diff --git a/lib/main.dart b/lib/main.dart index 2cf269a..88a1f33 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,26 +1,104 @@ +import 'dart:async'; import 'dart:io'; +// import 'dart:isolate'; +// import 'dart:developer' as dev; +// import 'dart:math'; + +// import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; +// import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +// import 'package:flutter_background_service/flutter_background_service.dart'; +// import 'package:flutter_background_service_android/flutter_background_service_android.dart'; // import 'package:provider/provider.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; +// import 'package:isolate_handler/isolate_handler.dart'; +// import 'package:kurir/api/notification_api.dart'; import 'package:kurir/routes/routes.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_native_timezone/flutter_native_timezone.dart'; +// import 'package:socket_io_client/socket_io_client.dart'; +import 'package:timezone/data/latest_all.dart' as tz; +import 'package:timezone/timezone.dart' as tz; +// import 'package:worker_manager/worker_manager.dart'; // import 'api/beforeLoginAPI.dart'; +// import 'package:firebase_core/firebase_core.dart'; +// import 'firebase_options.dart'; +// import 'package:firebase_messaging/firebase_messaging.dart'; + +// Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { +// // If you're going to use other Firebase services in the background, such as Firestore, +// // make sure you call `initializeApp` before using other Firebase services. +// await Firebase.initializeApp(); + +// print("Handling a background message: ${message.messageId}"); +// } + void main() async { + WidgetsFlutterBinding.ensureInitialized(); + // await initializeService(); + // await Executor().warmUp(log: true); HttpOverrides.global = MyHttpOverrides(); await GetStorage.init(); + await _configureLocalTimeZone(); + // await Firebase.initializeApp( + // options: DefaultFirebaseOptions.currentPlatform, + // ); + // FirebaseMessaging messaging = FirebaseMessaging.instance; + // NotificationSettings settings = await messaging.requestPermission( + // alert: true, + // announcement: false, + // badge: true, + // carPlay: false, + // criticalAlert: false, + // provisional: false, + // sound: true, + // ); + + // dev.log('User granted permission: ${settings.authorizationStatus}'); + // // FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); + // FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // print('Got a message whilst in the foreground!'); + // print('Message data: ${message.data}'); + + // if (message.notification != null) { + // dev.log('Message also contained a notification: ${message.notification}'); + // } + // }); + + // await AndroidAlarmManager.initialize(); runApp(const MyApp()); + // FlutterBackgroundService().invoke("setAsBackground"); + // FlutterBackgroundService().invoke("setAsForeground"); + // final int helloAlarmID = 0; + // await AndroidAlarmManager.periodic( + // const Duration(minutes: 1), helloAlarmID, printHello); + // startForegroundService(); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. + @override Widget build(BuildContext context) { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + systemNavigationBarColor: Color.fromARGB(255, 2, 72, 72), + statusBarColor: Color.fromARGB(255, 2, 72, 72), + ), + ); return GetMaterialApp( title: 'Flutter Demo', theme: ThemeData( @@ -33,6 +111,21 @@ class MyApp extends StatelessWidget { } } +// // This function happens in the isolate. +// void entryPoint(Map context) { +// // Calling initialize from the entry point with the context is +// // required if communication is desired. It returns a messenger which +// // allows listening and sending information to the main isolate. +// final messenger = HandledIsolate.initialize(context); +// connectToServer(); +// // Triggered every time data is received from the main isolate. +// // messenger.listen((msg) async { +// // // Use a plugin to get some new value to send back to the main isolate. +// // final dir = await getApplicationDocumentsDirectory(); +// // messenger.send(msg + dir.path); +// // }); +// } + class MyHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { @@ -41,3 +134,204 @@ class MyHttpOverrides extends HttpOverrides { (X509Certificate cert, String host, int port) => true; } } + +Future _configureLocalTimeZone() async { + if (kIsWeb || Platform.isLinux) { + return; + } + tz.initializeTimeZones(); + final String? timeZoneName = await FlutterNativeTimezone.getLocalTimezone(); + tz.setLocalLocation(tz.getLocation(timeZoneName!)); +} + +// void printHello() { +// final DateTime now = DateTime.now(); +// final int isolateId = Isolate.current.hashCode; +// dev.log("[$now] Hello, world! isolate=${isolateId} function='$printHello'"); +// NotificationApi.showNotification( +// id: 2, +// title: 'Percobaan 2', +// body: "ini message", +// payload: 'Percobaan 2', +// ); +// // AndroidAlarmManager.c +// } + +// void startForegroundService() async { +// await FlutterForegroundPlugin.setServiceMethodInterval(seconds: 5); +// await FlutterForegroundPlugin.setServiceMethod(globalForegroundService); +// await FlutterForegroundPlugin.startForegroundService( +// holdWakeLock: true, +// onStarted: () { +// dev.log("Foreground on Started"); +// }, +// onStopped: () { +// dev.log("Foreground on Stopped"); +// }, +// title: "Flutter Foreground Service", +// content: "This is Content", +// iconName: "ic_stat_hot_tub", +// ); +// } + +// void globalForegroundService() { +// var random = new Random(); +// NotificationApi.showNotification( +// id: random.nextInt(100), +// title: 'Percobaan 2', +// body: "ini message", +// payload: 'Percobaan 2', +// ); +// dev.log("current datetime is ${DateTime.now()}"); +// } + +// Future initializeService() async { +// final service = FlutterBackgroundService(); +// await service.configure( +// androidConfiguration: AndroidConfiguration( +// // this will executed when app is in foreground or background in separated isolate +// onStart: onStart, + +// // auto start service +// autoStart: true, +// isForegroundMode: true, +// ), +// iosConfiguration: IosConfiguration( +// // auto start service +// autoStart: true, + +// // this will executed when app is in foreground in separated isolate +// onForeground: onStart, + +// // you have to enable background fetch capability on xcode project +// onBackground: onIosBackground, +// ), +// ); +// service.startService(); +// } + +// bool onIosBackground(ServiceInstance service) { +// WidgetsFlutterBinding.ensureInitialized(); +// dev.log('FLUTTER BACKGROUND FETCH'); + +// return true; +// } + +// void onStart(ServiceInstance service) async { +// // Only available for flutter 3.0.0 and later +// // DartPluginRegistrant.ensureInitialized(); + +// // For flutter prior to version 3.0.0 +// // We have to register the plugin manually + +// // SharedPreferences preferences = await SharedPreferences.getInstance(); +// // await preferences.setString("hello", "world"); +// // connectToServer(); +// if (service is AndroidServiceInstance) { +// service.on('setAsForeground').listen((event) { +// // connectToServer(); +// service.setAsForegroundService(); +// // connectToServer(); +// }); + +// service.on('setAsBackground').listen((event) { +// // connectToServer(); +// service.setAsBackgroundService(); +// // connectToServer(); +// }); +// } + +// service.on('stopService').listen((event) { +// service.stopSelf(); +// }); + +// // { +// // if (service is AndroidServiceInstance) { +// // service.setForegroundNotificationInfo( +// // title: "My App Service", +// // content: "Updated at ${DateTime.now()}", +// // ); +// // connectToServer(); +// // } +// // } + +// // bring to foreground +// Timer.periodic(const Duration(seconds: 5), (timer) async { +// // final hello = preferences.getString("hello"); +// dev.log("hello nya"); + +// if (service is AndroidServiceInstance) { +// service.setForegroundNotificationInfo( +// title: "My App Service", +// content: "Updated at ${DateTime.now()}", +// ); +// } + +// /// you can see this log in logcat +// dev.log('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}'); +// var random = new Random(); +// NotificationApi.showNotification( +// id: random.nextInt(100), +// title: 'Percobaan 2', +// body: "ini message", +// payload: 'Percobaan 2', +// ); + +// // test using external plugin +// final deviceInfo = DeviceInfoPlugin(); +// String? device; +// if (Platform.isAndroid) { +// final androidInfo = await deviceInfo.androidInfo; +// device = androidInfo.model; +// } + +// if (Platform.isIOS) { +// final iosInfo = await deviceInfo.iosInfo; +// device = iosInfo.model; +// } + +// service.invoke( +// 'update', +// { +// "current_date": DateTime.now().toIso8601String(), +// "device": device, +// }, +// ); +// }); +// } + +// // late Socket socket; +// void connectToServer() async { +// try { +// late Socket socket; +// // Configure socket transports must be sepecified +// socket = io('http://192.168.43.125:3001/', { +// 'transports': ['websocket'], +// 'autoConnect': true, +// }); + +// // Connect to websocket +// socket.connect(); + +// // Handle socket events +// socket.on('connect', (_) => dev.log('connect asdasdsad: ${socket.id}')); +// socket.on('coba2', (_) => dev.log(_.toString())); +// socket.on('percobaan1', (_) { +// NotificationApi.showNotification( +// id: 1, +// title: 'Percobaan 1', +// body: _['message'], +// payload: 'Percobaan 1', +// ); +// }); + +// // socket.on('typing', handleTyping); +// // socket.on('message', handleMessage); +// // socket.on('disconnect', (_) => dev.log('disconnect')); +// // socket.on('fromServer', (_) => dev.log(_)); +// dev.log(socket.connected.toString() + " connected"); +// } catch (e) { +// dev.log(e.toString()); +// dev.log('tidak connect'); +// } +// } diff --git a/lib/models/pengirimimanModel.dart b/lib/models/pengirimimanModel.dart index d36e8a6..441d6a1 100644 --- a/lib/models/pengirimimanModel.dart +++ b/lib/models/pengirimimanModel.dart @@ -12,7 +12,7 @@ class PengirimanModel { String? alamatPenerima; String? statusPengiriman; KurirModel? kurir; - String? pengirim; + PengirimModel? pengirim; String? createdAt; String? updatedAt; int? iV; @@ -48,7 +48,9 @@ class PengirimanModel { alamatPenerima = json['alamat_penerima']; statusPengiriman = json['status_pengiriman']; kurir = json['kurir'] != null ? KurirModel.fromJson(json['kurir']) : null; - pengirim = json['pengirim']; + pengirim = json['pengirim'] != null + ? PengirimModel.fromJson(json['pengirim']) + : null; createdAt = json['created_at']; updatedAt = json['updated_at']; iV = json['__v']; @@ -74,7 +76,9 @@ class PengirimanModel { if (kurir != null) { data['kurir'] = kurir!.toJson(); } - data['pengirim'] = pengirim; + if (pengirim != null) { + data['pengirim'] = pengirim!.toJson(); + } data['created_at'] = createdAt; data['updated_at'] = updatedAt; data['__v'] = iV; diff --git a/lib/models/usersModel.dart b/lib/models/usersModel.dart index 6393bc4..1a34a71 100644 --- a/lib/models/usersModel.dart +++ b/lib/models/usersModel.dart @@ -57,3 +57,119 @@ class KurirModel { "kenderaan_url": kenderaan_url, }; } + +class Data { + String? sId; + String? email; + String? noTelp; + String? nama; + String? alamat; + String? photoUrl; + String? status; + List? pengirimanBarang; + + Data( + {this.sId, + this.email, + this.noTelp, + this.nama, + this.alamat, + this.photoUrl, + this.status, + this.pengirimanBarang}); + + Data.fromJson(Map json) { + sId = json['_id']; + email = json['email']; + noTelp = json['no_telp']; + nama = json['nama']; + alamat = json['alamat']; + photoUrl = json['photo_url']; + status = json['status']; + pengirimanBarang = json['pengiriman_barang'].cast(); + } + + Map toJson() { + final Map data = {}; + data['_id'] = sId; + data['email'] = email; + data['no_telp'] = noTelp; + data['nama'] = nama; + data['alamat'] = alamat; + data['photo_url'] = photoUrl; + data['status'] = status; + data['pengiriman_barang'] = pengirimanBarang; + return data; + } +} + +class coba { + String? message; + List? data; + + coba({this.message, this.data}); + + coba.fromJson(Map json) { + message = json['message']; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(Data.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + data['message'] = message; + if (this.data != null) { + data['data'] = this.data!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class PengirimModel { + String? sId; + String? email; + String? noTelp; + String? nama; + String? alamat; + String? photoUrl; + String? status; + List? pengirimanBarang; + + PengirimModel( + {this.sId, + this.email, + this.noTelp, + this.nama, + this.alamat, + this.photoUrl, + this.status, + this.pengirimanBarang}); + + PengirimModel.fromJson(Map json) { + sId = json['_id']; + email = json['email']; + noTelp = json['no_telp']; + nama = json['nama']; + alamat = json['alamat']; + photoUrl = json['photo_url']; + status = json['status']; + pengirimanBarang = json['pengiriman_barang'].cast(); + } + + Map toJson() { + final Map data = {}; + data['_id'] = sId; + data['email'] = email; + data['no_telp'] = noTelp; + data['nama'] = nama; + data['alamat'] = alamat; + data['photo_url'] = photoUrl; + data['status'] = status; + data['pengiriman_barang'] = pengirimanBarang; + return data; + } +} diff --git a/lib/pages/after_login/kurir/pengaturanPage.dart b/lib/pages/after_login/kurir/pengaturanPage.dart index 227421c..160052b 100644 --- a/lib/pages/after_login/kurir/pengaturanPage.dart +++ b/lib/pages/after_login/kurir/pengaturanPage.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:kurir/controller/after_login/kurir/pengaturanController.dart'; -import 'package:kurir/widgets/focusToTextFormField.dart'; -import 'package:kurir/widgets/ourContainer.dart'; -import 'package:kurir/widgets/thousandSeparator.dart'; +import '../../../controller/after_login/kurir/pengaturanController.dart'; import '../../../widgets/boxBackgroundDecoration.dart'; +import '../../../widgets/focusToTextFormField.dart'; +import '../../../widgets/ourContainer.dart'; +import '../../../widgets/thousandSeparator.dart'; class PengaturanKurirPage extends GetView { const PengaturanKurirPage({Key? key}) : super(key: key); @@ -45,29 +45,12 @@ class PengaturanKurirPage extends GetView { ), EnsureVisibleWhenFocused( focusNode: controller.minimalBiayaPengirimanFocusNode, - child: TextFormField( - // initialValue: 700.toString(), + child: _PengaturanTextFormField( controller: controller.minimalBiayaPengirimanController, + hintText: 'Minimal Biaya Pengiriman', + labelText: 'Minimal Biaya Pengiriman', focusNode: controller.minimalBiayaPengirimanFocusNode, - keyboardType: TextInputType.number, - maxLength: 6, - inputFormatters: [ThousandsSeparatorInputFormatter()], - decoration: InputDecoration( - // suffix: , - // suffixText: ' / kg', - // put suffixText before prefixText - prefixText: 'Rp . ', - - hintText: 'Minimal Biaya Pengiriman', - labelText: 'Minimal Biaya Pengiriman', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - ), validator: (value) { if (value!.isEmpty) { return 'Minimal Biaya Pengiriman tidak boleh kosong'; @@ -88,33 +71,24 @@ class PengaturanKurirPage extends GetView { ), EnsureVisibleWhenFocused( focusNode: controller.maksimalBiayaPengirimanFocusNode, - child: TextFormField( + child: _PengaturanTextFormField( controller: controller.maksimalBiayaPengirimanController, + hintText: 'Maksimal Biaya Pengiriman', + labelText: 'Maksimal Biaya Pengiriman', focusNode: controller.maksimalBiayaPengirimanFocusNode, - keyboardType: TextInputType.number, - maxLength: 6, - inputFormatters: [ThousandsSeparatorInputFormatter()], - decoration: InputDecoration( - // suffix: , - // suffixText: ' / kg', - // put suffixText before prefixText - prefixText: 'Rp . ', - - hintText: 'Maksimal Biaya Pengiriman', - labelText: 'Maksimal Biaya Pengiriman', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - ), validator: (value) { if (value!.isEmpty) { return 'Maksimal Biaya Pengiriman tidak boleh kosong'; } + + if (controller.removeComma(controller + .maksimalBiayaPengirimanController.text) < + controller.removeComma(value)) { + return 'Maksimal Biaya Pengiriman tidak boleh lebih besar dari Maksimal Biaya Pengiriman'; + } + return null; }, ), @@ -124,31 +98,17 @@ class PengaturanKurirPage extends GetView { ), EnsureVisibleWhenFocused( focusNode: controller.biayaPerKiloFocusNode, - child: TextFormField( + child: _PengaturanTextFormField( controller: controller.biayaPerKiloController, + hintText: 'Biaya Per Kilometer', + labelText: 'Biaya Per Kilometer', focusNode: controller.biayaPerKiloFocusNode, - keyboardType: TextInputType.number, - maxLength: 6, - inputFormatters: [ThousandsSeparatorInputFormatter()], - decoration: InputDecoration( - // suffix: , - suffixText: ' / km', - // put suffixText before prefixText - prefixText: 'Rp . ', - - hintText: 'Biaya Per Kilometer', - labelText: 'Biaya Per Kilometer', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide( - color: Colors.grey, - ), - ), - ), + suffixText: ' / km', validator: (value) { if (value!.isEmpty) { return 'Biaya Per Kilometer tidak boleh kosong'; } + return null; }, ), @@ -157,6 +117,12 @@ class PengaturanKurirPage extends GetView { height: 15, ), ElevatedButton( + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), onPressed: () { // log() if (controller.formKey.currentState!.validate()) { @@ -175,8 +141,8 @@ class PengaturanKurirPage extends GetView { ElevatedButton( child: const Text('Tidak'), style: ElevatedButton.styleFrom( - primary: - Colors.red[400], //background color + primary: const Color.fromARGB(255, 104, + 164, 164), //background color // onPrimary: Colors.black, //ripple color ), onPressed: () { @@ -185,6 +151,11 @@ class PengaturanKurirPage extends GetView { ), ElevatedButton( child: const Text('Ya'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB( + 255, 2, 72, 72), //background color + // onPrimary: Colors.black, //ripple color + ), onPressed: () { controller.simpan(); Navigator.of(context).pop(); @@ -231,3 +202,78 @@ class PengaturanKurirPage extends GetView { ); } } + +class _PengaturanTextFormField extends StatelessWidget { + const _PengaturanTextFormField({ + Key? key, + this.controller, + this.focusNode, + this.hintText, + this.labelText, + this.validator, + this.suffixText, + }) : super(key: key); + + final TextEditingController? controller; + final FocusNode? focusNode; + final String? hintText; + final String? labelText; + final FormFieldValidator? validator; + final String? suffixText; + + @override + Widget build(BuildContext context) { + return TextFormField( + // initialValue: 700.toString(), + controller: controller, + focusNode: focusNode, + keyboardType: TextInputType.number, + maxLength: 6, + inputFormatters: [ThousandsSeparatorInputFormatter()], + decoration: InputDecoration( + // suffix: , + // suffixText: ' / kg', + // put suffixText before prefixText + prefixText: 'Rp . ', + suffixText: suffixText, + hintText: hintText, + labelText: labelText, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 104, 164, 164), + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.red, + width: 1, + ), + ), + ), + validator: validator, + ); + } +} diff --git a/lib/pages/after_login/kurir/pengirimanPage.dart b/lib/pages/after_login/kurir/pengirimanPage.dart index 7b6a2b9..76673f9 100644 --- a/lib/pages/after_login/kurir/pengirimanPage.dart +++ b/lib/pages/after_login/kurir/pengirimanPage.dart @@ -1,26 +1,418 @@ // ignore_for_file: file_names import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; +import 'package:get/get.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import '../../../controller/after_login/kurir/pengirimanController.dart'; +import '../../../models/pengirimimanModel.dart'; +import '../../../widgets/bounce_scroller.dart'; import '../../../widgets/boxBackgroundDecoration.dart'; +import '../../../widgets/load_data.dart'; -class PengirimanKurirPage extends StatelessWidget { +class PengirimanKurirPage extends GetView { const PengirimanKurirPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return const Scaffold( + return Scaffold( // ignore: unnecessary_const - body: const BoxBackgroundDecoration( - child: Center( - child: Text( - 'Pengiriman', - style: TextStyle( - fontSize: 30, - color: Colors.white, - ), - )), + body: BoxBackgroundDecoration( + child: Stack( + children: [ + Container( + alignment: Alignment.center, + width: double.infinity * 0.9, + height: double.infinity, + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox(height: MediaQuery.of(context).size.height * 0.13), + _MainWidget(controller: controller), + ], + ), + ), + ), + const TopSeachInput(), + ], + ), ), ); } } + +class _MainWidget extends StatelessWidget { + const _MainWidget({ + Key? key, + required this.controller, + }) : super(key: key); + + final PengirimanKurirController controller; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + left: MediaQuery.of(context).size.height * 0.03, + right: MediaQuery.of(context).size.height * 0.03), + child: Obx( + () => BounceScrollerWidget( + children: [ + if (controller.loadPengiriman.value == 0) const LoadingDataWidget(), + if (controller.loadPengiriman.value == 1 && + controller.pengirimanModelList.isNotEmpty) + for (var data in controller.pengirimanModelList) + _SlidableWidget(data: data, controller: controller), + if (controller.loadPengiriman.value == 1 && + controller.pengirimanModelList.isEmpty) + Center( + child: const TiadaDataWIdget( + text: "Tiada data pengiriman\ndalam proses pengesahan")), + if (controller.loadPengiriman.value == 2) + const ErrorLoadDataWidget(), + ], + ), + ), + ); + } +} + +class _SlidableWidget extends StatelessWidget { + const _SlidableWidget({ + Key? key, + required this.data, + required this.controller, + }) : super(key: key); + + final PengirimanModel data; + final PengirimanKurirController controller; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Slidable( + key: const ValueKey(1), + startActionPane: ActionPane( + motion: const DrawerMotion(), + extentRatio: 0.90, + // dismissible: DismissiblePane(onDismissed: () {}), + children: [ + SlidableAction( + flex: 5, + onPressed: (context) { + // Get.offAndToNamed( + // '/pengirimIndex/infoPengiriman', + // arguments: { + // 'pengiriman_model': _pengirimanModel, + // }, + // ); + }, + backgroundColor: const Color.fromARGB(255, 104, 164, 164), + foregroundColor: Colors.white, + icon: Icons.check_box, + label: 'Terima Pengiriman', + ), + SlidableAction( + flex: 5, + onPressed: (context) { + controller.lihat_foto_kiriman(context, data.fotoPengiriman!); + }, + backgroundColor: const Color.fromARGB(255, 4, 103, 103), + foregroundColor: Colors.white, + icon: Icons.photo_rounded, + label: 'Barang Kiriman', + ), + ], + ), + endActionPane: ActionPane( + motion: const DrawerMotion(), + extentRatio: 0.5, + children: [ + SlidableAction( + onPressed: (context) { + // _lihat_rute_pengiriman( + // context, _kordinat_pengiriman, _kordinat_permulaan); + }, + backgroundColor: Colors.red, + foregroundColor: Colors.white, + icon: Icons.cancel_rounded, + label: "Batalkan Permintaan\nPengirim", + ), + ], + ), + child: _MainChild(data: data, controller: controller), + ), + ); + } +} + +class _MainChild extends StatelessWidget { + const _MainChild({ + Key? key, + required this.data, + required this.controller, + }) : super(key: key); + + final PengirimanModel data; + final PengirimanKurirController controller; + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: 115, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: const Color.fromARGB(255, 165, 163, 163).withOpacity(0.5), + blurRadius: 10, + spreadRadius: 5, + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 2, + child: Container( + width: 65, + height: 65, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color.fromARGB(255, 165, 163, 163) + .withOpacity(0.5), + blurRadius: 10, + spreadRadius: 5, + ), + ], + image: const DecorationImage( + image: AssetImage('assets/loading.gif'), + fit: BoxFit.fitHeight, + ), + ), + child: CircleAvatar( + radius: 30.0, + backgroundImage: NetworkImage( + data.pengirim!.photoUrl ?? 'https://via.placeholder.com/150', + scale: 0.5, + ), + backgroundColor: Colors.transparent, + ), + ), + ), + Expanded( + flex: 4, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + Text( + controller.timeZoneAdd8(data.createdAt), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + overflow: TextOverflow.ellipsis, + ), + ), + Text( + data.pengirim!.nama!, + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + // Coba(data:data,controller:controller) + _FutureBuilderHargaJarak( + controller: controller, + data: data, + ), + Text( + data.statusPengiriman!, + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + Expanded( + flex: 1, + child: Container( + padding: const EdgeInsets.all(2), + width: 50, + height: 50, + decoration: BoxDecoration( + color: Color.fromARGB(255, 2, 72, 72), + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color.fromARGB(255, 104, 164, 164) + .withOpacity(0.5), + blurRadius: 10, + spreadRadius: 5, + ), + ], + ), + child: IconButton( + onPressed: () { + controller.showMapDialog(context, data); + }, + icon: Icon( + Icons.turn_sharp_right_outlined, + color: Color.fromARGB(255, 199, 214, 234), + ), + ), + ), + ), + ], + ), + ); + } +} + +class TopSeachInput extends StatelessWidget { + const TopSeachInput({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Positioned( + top: MediaQuery.of(context).size.height * 0.05, + right: MediaQuery.of(context).size.width * 0.05, + left: MediaQuery.of(context).size.width * 0.05, + child: SizedBox( + width: double.infinity, + height: 40, + child: TextFormField( + decoration: InputDecoration( + hintText: 'Cari Pengiriman', + hintStyle: const TextStyle( + color: Colors.white, + ), + prefixIcon: const Icon( + Icons.search, + color: Colors.white, + ), + suffixIcon: const Icon( + Icons.filter_list, + color: Colors.white, + ), + filled: true, + fillColor: Colors.transparent, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + style: const TextStyle( + color: Colors.white, + ), + ), + ), + ); + } +} + +class _FutureBuilderHargaJarak extends StatelessWidget { + const _FutureBuilderHargaJarak( + {Key? key, required this.controller, required this.data}) + : super(key: key); + + final PengirimanKurirController controller; + final PengirimanModel data; + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: controller.cekDistance( + LatLng(double.parse(data.kordinatPengiriman!.lat!), + double.parse(data.kordinatPengiriman!.lng!)), + LatLng(double.parse(data.kordinatPermulaan!.lat!), + double.parse(data.kordinatPermulaan!.lng!))), + builder: (context, snapshot) { + if (snapshot.hasData) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + controller.cekHarga(snapshot.data, data.biaya!.biayaMinimal!, + data.biaya!.biayaMaksimal!, data.biaya!.biayaPerKilo!), + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + Text( + snapshot.data.toString() + " km", + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ); + } else if (snapshot.hasError) { + return Text( + "Error mengambil data", + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ); + } else { + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + Color.fromARGB( + 255, + 4, + 103, + 103, + ), + ), + ), + ); + } + }, + ); + } +} diff --git a/lib/pages/after_login/kurir/profilePage.dart b/lib/pages/after_login/kurir/profilePage.dart index be5c24b..12d67d8 100644 --- a/lib/pages/after_login/kurir/profilePage.dart +++ b/lib/pages/after_login/kurir/profilePage.dart @@ -2,7 +2,10 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:kurir/controller/after_login/kurir/profileController.dart'; + +import '../../../controller/after_login/kurir/profileController.dart'; +import '../../../widgets/appbar.dart'; +import '../../../widgets/boxBackgroundDecoration.dart'; class ProfileKurirPage extends GetView { const ProfileKurirPage({Key? key}) : super(key: key); @@ -10,41 +13,54 @@ class ProfileKurirPage extends GetView { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Profile'), - actions: [ - IconButton( - icon: const Icon(Icons.logout_outlined), - onPressed: () { - // log("ini untuk logout"); - // create get alert dialog - Get.dialog(AlertDialog( - title: const Text('Logout'), - content: const Text('Anda yakin ingin logout?'), - actions: [ - ElevatedButton( - child: const Text('Yes'), - onPressed: () { - // log("ini untuk logout"); - Get.back(); - controller.logout(); - }, + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: AppBarWidget( + header: "Halaman Profil", + autoLeading: false, + actions: [ + IconButton( + icon: const Icon(Icons.logout_outlined), + onPressed: () { + // log("ini untuk logout"); + // create get alert dialog + Get.dialog( + AlertDialog( + title: const Text('Logout'), + content: const Text('Anda yakin ingin logout?'), + actions: [ + ElevatedButton( + child: const Text('Yes'), + style: ElevatedButton.styleFrom( + primary: Color.fromARGB( + 255, 104, 164, 164), //background color + // onPrimary: Colors.black, //ripple color + ), + onPressed: () { + // log("ini untuk logout"); + Get.back(); + controller.logout(); + }, + ), + ElevatedButton( + child: const Text('No'), + style: ElevatedButton.styleFrom( + primary: + Color.fromARGB(255, 2, 72, 72), //background color + // onPrimary: Colors.black, //ripple color + ), + onPressed: () { + Get.back(); + }, + ), + ], ), - ElevatedButton( - child: const Text('No'), - style: ElevatedButton.styleFrom( - primary: Colors.red[400], //background color - // onPrimary: Colors.black, //ripple color - ), - onPressed: () { - Get.back(); - }, - ), - ], - )); - }, - ), - ], + ); + }, + ), + ], + ), ), body: WillPopScope( onWillPop: () async { @@ -53,8 +69,10 @@ class ProfileKurirPage extends GetView { ); return false; }, - child: const Center( - child: Text('Profile'), + child: BoxBackgroundDecoration( + child: const Center( + child: Text('Profile'), + ), ), ), ); diff --git a/lib/pages/after_login/pengirim/infoPengirimanPage.dart b/lib/pages/after_login/pengirim/infoPengirimanPage.dart new file mode 100644 index 0000000..e6aeb26 --- /dev/null +++ b/lib/pages/after_login/pengirim/infoPengirimanPage.dart @@ -0,0 +1,290 @@ +// ignore_for_file: file_names, curly_braces_in_flow_control_structures +// ignore: unused_import +import 'dart:developer' as dev; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:kurir/controller/after_login/pengirim/infoPengirimanController.dart'; +import 'package:kurir/widgets/boxBackgroundDecoration.dart'; +import 'package:kurir/widgets/ourContainer.dart'; + +class InfoPengirimanPage extends GetView { + const InfoPengirimanPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + // String _harga_minimal = AllFunction.thousandsSeperator( + // controller.pengirimanModel.biaya!.biayaMinimal!); + return Scaffold( + appBar: AppBar( + title: const Text('Info Pengiriman'), + actions: [ + // create back button + IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () { + Get.offAllNamed( + '/pengirimIndex', + arguments: { + 'tap': 1, + }, + ); + }, + ), + ], + ), + body: WillPopScope( + onWillPop: () async { + Get.offAllNamed( + '/pengirimIndex', + arguments: { + 'tap': 1, + }, + ); + return false; + }, + child: BoxBackgroundDecoration( + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox( + height: 20, + ), + OurContainer( + child: Column( + children: [ + const SizedBox( + height: 10, + ), + GestureDetector( + onTap: () { + controller.show_foto_pengiriman(); + }, + child: Container( + width: 100, + height: 100, + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(100), + boxShadow: const [ + BoxShadow( + color: Colors.grey, + blurRadius: 5, + spreadRadius: 1, + ), + ], + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + image: const DecorationImage( + image: AssetImage( + 'assets/loading.gif', + ), + fit: BoxFit.fill, + ), + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + image: DecorationImage( + image: NetworkImage( + controller.pengirimanModel.fotoPengiriman!, + ), + fit: BoxFit.fill, + ), + ), + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: + controller.pengirimanModel.statusPengiriman, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Status Pengiriman', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: controller.pengirimanModel.namaPenerima, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Nama Penerima', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: + controller.pengirimanModel.noTelponPenerima, + // maxLength: 13, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'No Telpon Penerima', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: controller.pengirimanModel.alamatPenerima, + keyboardType: TextInputType.multiline, + textInputAction: TextInputAction.newline, + // minLines: 1, + maxLines: 4, + decoration: InputDecoration( + labelText: 'Alamat Penerima', + labelStyle: const TextStyle( + color: Colors.blue, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + initialValue: controller.pengirimanModel.kurir!.nama, + // maxLength: 13, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + suffix: GestureDetector( + onTap: () { + // dev.log("message"); + if (controller.loadingMaps.value) + controller.show_kurir_dialog(); + }, + child: const Icon( + Icons.info_outline_rounded, + color: Colors.blue, + ), + ), + labelText: 'Nama Kurir', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + controller: controller.distance_travel_controller, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Jarak Pengiriman', + suffixIcon: GestureDetector( + onTap: () { + if (controller.loadingMaps.value) + controller.show_maps_dialog(); + }, + child: const Icon( + Icons.info_outline_rounded, + color: Colors.blue, + ), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + TextFormField( + readOnly: true, + controller: controller.price_controller, + decoration: InputDecoration( + labelStyle: const TextStyle( + color: Colors.blue, + ), + labelText: 'Harga Pengiriman', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Colors.grey, + ), + ), + ), + ), + const SizedBox( + height: 15, + ), + (controller.pengirimanModel.statusPengiriman == + "Dalam Pengesahan Kurir") + ? Center( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red, + ), + child: const Text("Batalkan Pengiriman"), + onPressed: () {}, + ), + ) + : const SizedBox(), + ], + ), + ), + const SizedBox( + height: 20, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/after_login/pengirim/kirimBarangPage.dart b/lib/pages/after_login/pengirim/kirimBarangPage.dart index a0e7ea3..db3c918 100644 --- a/lib/pages/after_login/pengirim/kirimBarangPage.dart +++ b/lib/pages/after_login/pengirim/kirimBarangPage.dart @@ -35,11 +35,11 @@ class KirimBarangPage extends GetView { width: 80, height: 80, decoration: BoxDecoration( - color: Colors.grey, + color: const Color.fromARGB(255, 199, 214, 234), borderRadius: BorderRadius.circular(100), boxShadow: const [ BoxShadow( - color: Colors.grey, + color: Color.fromARGB(255, 104, 164, 164), blurRadius: 5, spreadRadius: 1, ), @@ -76,7 +76,8 @@ class KirimBarangPage extends GetView { ), ) : const Icon(Icons.add, - color: Colors.white, size: 22), + color: Color.fromARGB(255, 2, 72, 72), + size: 22), Positioned( bottom: 0, right: 0, @@ -87,7 +88,8 @@ class KirimBarangPage extends GetView { width: 40, height: 40, decoration: BoxDecoration( - color: Colors.blue, + color: const Color.fromARGB( + 255, 4, 103, 103), borderRadius: BorderRadius.circular(100), ), @@ -286,6 +288,12 @@ class KirimBarangPage extends GetView { // log("sini pin lokasi"); controller.pin_lokasi(context); }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 104, 164, 164), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: const Text( 'Lokasi Pengiriman', textAlign: TextAlign.center, @@ -307,6 +315,12 @@ class KirimBarangPage extends GetView { // } controller.pin_lokasi_permulaan(context, "awal"); }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 104, 164, 164), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: const Text( 'Lokasi Permulaan', textAlign: TextAlign.center, @@ -319,17 +333,20 @@ class KirimBarangPage extends GetView { child: SizedBox( width: MediaQuery.of(context).size.width * 0.3, child: ElevatedButton( - style: ElevatedButton.styleFrom( - primary: Colors.green, - ), onPressed: () { - WidgetsBinding.instance?.focusManager.primaryFocus + WidgetsBinding.instance!.focusManager.primaryFocus ?.unfocus(); if (controller.formKey.currentState!.validate()) { FocusScope.of(context).unfocus(); controller.konfirmasi_all(context); } }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: const Text( 'Konfirmasi', textAlign: TextAlign.center, diff --git a/lib/pages/after_login/pengirim/listKurirPage.dart b/lib/pages/after_login/pengirim/listKurirPage.dart index 6a66a4e..201b77e 100644 --- a/lib/pages/after_login/pengirim/listKurirPage.dart +++ b/lib/pages/after_login/pengirim/listKurirPage.dart @@ -1,19 +1,99 @@ // ignore_for_file: file_names import 'package:flutter/material.dart'; -import 'package:kurir/widgets/boxBackgroundDecoration.dart'; +import 'package:get/get.dart'; -class ListKurirPage extends StatelessWidget { +import '../../../controller/after_login/pengirim/listKurirController.dart'; +import '../../../models/usersModel.dart'; +import '../../../widgets/bounce_scroller.dart'; +import '../../../widgets/boxBackgroundDecoration.dart'; +import '../../../widgets/load_data.dart'; + +class ListKurirPage extends GetView { const ListKurirPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return const BoxBackgroundDecoration( - child: Center( - child: Text( - 'List Kurir', - style: TextStyle( - fontSize: 30, + return BoxBackgroundDecoration( + child: Stack( + children: [ + Container( + alignment: Alignment.center, + width: double.infinity * 0.9, + height: double.infinity, + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox(height: MediaQuery.of(context).size.height * 0.13), + _MainDetail(controller: controller), + ], + ), + ), + ), + _TopSearchInputField(), + ], + ), + ); + } +} + +class _TopSearchInputField extends StatelessWidget { + const _TopSearchInputField({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Positioned( + top: MediaQuery.of(context).size.height * 0.05, + right: MediaQuery.of(context).size.width * 0.05, + left: MediaQuery.of(context).size.width * 0.05, + child: SizedBox( + width: double.infinity, + height: 40, + child: TextFormField( + decoration: InputDecoration( + hintText: 'Cari Kurir', + hintStyle: const TextStyle( + color: Colors.white, + ), + prefixIcon: const Icon( + Icons.search, + color: Colors.white, + ), + suffixIcon: const Icon( + Icons.filter_list, + color: Colors.white, + ), + filled: true, + fillColor: Colors.transparent, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.white, + width: 1, + ), + ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + style: const TextStyle( color: Colors.white, ), ), @@ -21,3 +101,142 @@ class ListKurirPage extends StatelessWidget { ); } } + +class _MainDetail extends StatelessWidget { + const _MainDetail({ + Key? key, + required this.controller, + }) : super(key: key); + + final ListKurirController controller; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + left: MediaQuery.of(context).size.height * 0.03, + right: MediaQuery.of(context).size.height * 0.03), + child: Obx( + () => BounceScrollerWidget( + children: [ + if (controller.loadKurir.value == 0) const LoadingDataWidget(), + if (controller.loadKurir.value == 1 && + controller.kurirModelList.isNotEmpty) + for (var data in controller.kurirModelList) + _KurirDetailBox(data: data) + else if (controller.loadKurir.value == 1 && + controller.kurirModelList.isEmpty) + const TiadaDataWIdget(text: "Tidak ada data"), + if (controller.loadKurir.value == 2) const ErrorLoadDataWidget(), + ], + ), + ), + ); + } +} + +class _KurirDetailBox extends StatelessWidget { + const _KurirDetailBox({ + Key? key, + required this.data, + }) : super(key: key); + + final KurirModel data; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Container( + width: double.infinity, + height: 90, + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: const Color.fromARGB(255, 165, 163, 163).withOpacity(0.5), + blurRadius: 10, + spreadRadius: 5, + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 2, + child: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: const Color.fromARGB(255, 165, 163, 163) + .withOpacity(0.5), + blurRadius: 10, + spreadRadius: 5, + ), + ], + image: const DecorationImage( + image: AssetImage('assets/loading.gif'), + fit: BoxFit.fitHeight, + ), + ), + child: CircleAvatar( + radius: 30.0, + backgroundImage: NetworkImage( + data.photo_url ?? 'https://via.placeholder.com/150', + scale: 0.5, + ), + backgroundColor: Colors.transparent, + ), + ), + ), + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + Text( + data.nama ?? 'Nama Belum Terisi', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + overflow: TextOverflow.ellipsis, + ), + ), + Text( + data.no_telp ?? 'No Telp Belum Terisi', + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + Text( + data.email ?? 'Email Belum Terisi', + style: const TextStyle( + fontSize: 15, + color: Colors.grey, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + const Expanded( + flex: 1, + child: Text("Rating"), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/after_login/pengirim/logKirimanPage.dart b/lib/pages/after_login/pengirim/logKirimanPage.dart index 2e3934e..88c1c75 100644 --- a/lib/pages/after_login/pengirim/logKirimanPage.dart +++ b/lib/pages/after_login/pengirim/logKirimanPage.dart @@ -51,7 +51,7 @@ class LogKirimanPage extends GetView { child: GestureDetector( child: const Icon( Icons.list_alt_rounded, - color: Colors.blueAccent, + color: Color.fromARGB(255, 4, 103, 103), ), onTap: () {}, ), diff --git a/lib/pages/after_login/pengirim/pengirimProfilePage.dart b/lib/pages/after_login/pengirim/pengirimProfilePage.dart index 151bd29..cbe052e 100644 --- a/lib/pages/after_login/pengirim/pengirimProfilePage.dart +++ b/lib/pages/after_login/pengirim/pengirimProfilePage.dart @@ -1,27 +1,31 @@ // ignore_for_file: file_names +// ignore: unused_import import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:kurir/widgets/boxBackgroundDecoration.dart'; -class PengirimProfilePage extends StatelessWidget { +import '../../../controller/after_login/pengirim/pengirimProfileController.dart'; +import '../../../widgets/appbar.dart'; +import '../../../widgets/boxBackgroundDecoration.dart'; + +class PengirimProfilePage extends GetView { const PengirimProfilePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Pengirim Profile'), - actions: [ - IconButton( - icon: const Icon(Icons.exit_to_app), - onPressed: () { - log("logout"); - }, - ), - ], + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: AppBarWidget( + header: controller.headerText, + autoLeading: true, + actions: [ + HeaderActionButton(controller: controller), + ], + ), ), body: WillPopScope( onWillPop: () async { @@ -33,18 +37,155 @@ class PengirimProfilePage extends StatelessWidget { ); return false; }, - child: const BoxBackgroundDecoration( - child: Center( - child: Text( - 'Pengirim Profile', - style: TextStyle( - fontSize: 30, - color: Colors.white, + child: BoxBackgroundDecoration( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox( + height: 30, ), - ), + Container( + padding: const EdgeInsets.all(3), + width: 150, + height: 150, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + image: const DecorationImage( + image: AssetImage('assets/loading.gif'), + fit: BoxFit.cover, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.3), + blurRadius: 10, + spreadRadius: 5, + ), + ], + ), + ), + const Padding( + padding: + EdgeInsets.only(left: 15, right: 15, top: 15, bottom: 10), + child: Text( + "Nama User", + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + color: Colors.white, + ), + ), + ), + const DetailChild( + icon: Icons.phone_android_outlined, text: "08123456789"), + const DetailChild( + icon: Icons.email_outlined, text: "Karauksii@gmail.com"), + const DetailChild( + icon: Icons.home, + text: + "Jln Industri Kecil Parepare asdasd asdasd asdasda asdas"), + const DetailChild( + icon: Icons.motorcycle_outlined, + text: "3 kali melakukan pengiriman barang"), + ], ), ), ), ); } } + +class DetailChild extends StatelessWidget { + const DetailChild({ + Key? key, + required this.icon, + required this.text, + }) : super(key: key); + + final IconData icon; + final String text; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only( + top: 10, + bottom: 10, + left: MediaQuery.of(context).size.width * 0.15, + right: MediaQuery.of(context).size.width * 0.15, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + icon, + color: Colors.white, + ), + const SizedBox( + width: 25, + ), + Flexible( + child: Text( + text, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + color: Colors.white, + ), + ), + ), + ], + ), + ); + } +} + +class HeaderActionButton extends StatelessWidget { + const HeaderActionButton({ + Key? key, + required this.controller, + }) : super(key: key); + + final PengirimProfileController controller; + + @override + Widget build(BuildContext context) { + return IconButton( + icon: const Icon(Icons.logout_outlined), + onPressed: () { + Get.dialog( + AlertDialog( + title: const Text('Logout'), + content: const Text('Anda yakin ingin logout?'), + actions: [ + ElevatedButton( + child: const Text('Yes'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + ), + onPressed: () { + // log("ini untuk logout"); + Get.back(); + controller.logout(); + }, + ), + ElevatedButton( + child: const Text('No'), + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB( + 255, 104, 164, 164), //background color + // onPrimary: Colors.black, //ripple color + ), + onPressed: () { + Get.back(); + }, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/pages/before_login/daftar.dart b/lib/pages/before_login/daftar.dart index 52aad25..562dc8d 100644 --- a/lib/pages/before_login/daftar.dart +++ b/lib/pages/before_login/daftar.dart @@ -2,9 +2,10 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:kurir/controller/before_login/loginController.dart'; // import 'package:kurir/controller/before_login/indexController.dart'; +import '../../controller/before_login/loginController.dart'; +import '../../widgets/appbar.dart'; import '../../widgets/boxBackgroundDecoration.dart'; import '../../widgets/ourContainer.dart'; @@ -17,8 +18,13 @@ class DaftarPage extends GetView { return WillPopScope( onWillPop: () async => controller.willPopScopeWidget(), child: Scaffold( - appBar: AppBar( - title: const Text('Daftar'), + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: const AppBarWidget( + header: "Halaman Pendaftaran", + autoLeading: true, + ), ), body: BoxBackgroundDecoration( child: SingleChildScrollView( @@ -80,6 +86,12 @@ class DaftarPage extends GetView { Get.offAllNamed('/pendaftaranPengirim'); } }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: const Text('Daftar'), ), ), diff --git a/lib/pages/before_login/index.dart b/lib/pages/before_login/index.dart index 540f90c..f26b4ec 100644 --- a/lib/pages/before_login/index.dart +++ b/lib/pages/before_login/index.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:kurir/controller/before_login/loginController.dart'; // import 'package:kurir/controller/before_login/indexController.dart'; +import '../../widgets/appbar.dart'; import '../../widgets/boxBackgroundDecoration.dart'; // class IndexPage extends GetView { @@ -13,9 +14,13 @@ class IndexPage extends GetView { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Hompage'), - automaticallyImplyLeading: false, + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: const AppBarWidget( + header: "Halaman Utama", + autoLeading: true, + ), ), body: const DoubleBackToCloseApp( child: BoxBackgroundDecoration( diff --git a/lib/pages/before_login/login.dart b/lib/pages/before_login/login.dart index 096c7e0..a814989 100644 --- a/lib/pages/before_login/login.dart +++ b/lib/pages/before_login/login.dart @@ -2,11 +2,12 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:kurir/widgets/focusToTextFormField.dart'; -import 'package:kurir/widgets/ourContainer.dart'; import '../../controller/before_login/loginController.dart'; +import '../../widgets/appbar.dart'; import '../../widgets/boxBackgroundDecoration.dart'; +import '../../widgets/focusToTextFormField.dart'; +import '../../widgets/ourContainer.dart'; class LoginPage extends GetView { const LoginPage({Key? key}) : super(key: key); @@ -16,8 +17,13 @@ class LoginPage extends GetView { return WillPopScope( onWillPop: () async => controller.willPopScopeWidget(), child: Scaffold( - appBar: AppBar( - title: const Text('Login'), + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: const AppBarWidget( + header: "Halaman Login", + autoLeading: true, + ), ), body: BoxBackgroundDecoration( child: SingleChildScrollView( @@ -44,10 +50,38 @@ class LoginPage extends GetView { () => DropdownButtonFormField( decoration: InputDecoration( labelText: 'Login Sebagai', - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( - color: Colors.grey, + color: Color.fromARGB(255, 2, 72, 72), + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 104, 164, 164), + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.red, + width: 1, ), ), ), @@ -79,12 +113,41 @@ class LoginPage extends GetView { hintText: 'Masukkan Username', labelText: 'Username', border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( - color: Colors.grey, + color: Color.fromARGB(255, 2, 72, 72), + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 104, 164, 164), + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.red, + width: 1, ), ), ), + validator: (value) { if (value!.isEmpty) { controller.usernameFocusNode.requestFocus(); @@ -109,9 +172,37 @@ class LoginPage extends GetView { hintText: 'Masukkan Password', labelText: 'Password', border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(30), borderSide: const BorderSide( - color: Colors.grey, + color: Color.fromARGB(255, 2, 72, 72), + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 104, 164, 164), + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Color.fromARGB(255, 2, 72, 72), + width: 1, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(30), + borderSide: const BorderSide( + color: Colors.red, + width: 1, ), ), suffixIcon: IconButton( @@ -153,6 +244,12 @@ class LoginPage extends GetView { controller.login(); } }, + style: ElevatedButton.styleFrom( + primary: const Color.fromARGB(255, 2, 72, 72), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), child: const Text('Login'), ), ), diff --git a/lib/pages/before_login/pendaftaran_kurir.dart b/lib/pages/before_login/pendaftaran_kurir.dart index d105b3b..4f9a06c 100644 --- a/lib/pages/before_login/pendaftaran_kurir.dart +++ b/lib/pages/before_login/pendaftaran_kurir.dart @@ -3,10 +3,11 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:kurir/controller/before_login/pendaftaranKurirController.dart'; -import 'package:kurir/widgets/focusToTextFormField.dart'; +import '../../controller/before_login/pendaftaranKurirController.dart'; +import '../../widgets/appbar.dart'; import '../../widgets/boxBackgroundDecoration.dart'; +import '../../widgets/focusToTextFormField.dart'; import '../../widgets/ourContainer.dart'; // import 'package:image_picker/image_picker.dart'; @@ -20,17 +21,22 @@ class PendaftaranKurirPage extends GetView { return WillPopScope( onWillPop: () => controller.willPopScopeWidget(), child: Scaffold( - appBar: AppBar( - title: const Text('Pendaftaran Kurir'), - actions: [ - IconButton( - icon: const Icon(Icons.info_outline), - onPressed: () { - controller.intro_message(); - // controller.getHttp(); - }, - ), - ], + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: AppBarWidget( + header: "Pendaftaran Kurir", + autoLeading: true, + actions: [ + IconButton( + icon: const Icon(Icons.info_outline), + onPressed: () { + controller.intro_message(); + // controller.getHttp(); + }, + ), + ], + ), ), body: BoxBackgroundDecoration( child: SingleChildScrollView( @@ -650,7 +656,17 @@ class PendaftaranKurirPage extends GetView { ); } }, - child: const Text('Daftar'), + child: const Text( + 'Daftar', + style: + TextStyle(color: Color.fromARGB(255, 2, 72, 72)), + ), + style: ElevatedButton.styleFrom( + primary: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), ), ), SizedBox( diff --git a/lib/pages/before_login/pendaftaran_pengirirm.dart b/lib/pages/before_login/pendaftaran_pengirirm.dart index 99ee40a..de647df 100644 --- a/lib/pages/before_login/pendaftaran_pengirirm.dart +++ b/lib/pages/before_login/pendaftaran_pengirirm.dart @@ -8,6 +8,8 @@ import 'package:kurir/widgets/boxBackgroundDecoration.dart'; import 'package:kurir/widgets/focusToTextFormField.dart'; import 'package:kurir/widgets/ourContainer.dart'; +import '../../widgets/appbar.dart'; + class PendaftaranPengirimPage extends GetView { const PendaftaranPengirimPage({Key? key}) : super(key: key); @@ -16,14 +18,19 @@ class PendaftaranPengirimPage extends GetView { return WillPopScope( onWillPop: () async => controller.willPopScopeWidget(), child: Scaffold( - appBar: AppBar( - title: const Text('Pendaftaran Pengirim'), - actions: [ - IconButton( - onPressed: () => controller.intro_message(), - icon: const Icon(Icons.info_outline), - ), - ], + appBar: PreferredSize( + preferredSize: + Size.fromHeight(MediaQuery.of(context).size.height * 0.08), + child: AppBarWidget( + header: "Pendaftaran Pengirim", + autoLeading: true, + actions: [ + IconButton( + onPressed: () => controller.intro_message(), + icon: const Icon(Icons.info_outline), + ), + ], + ), ), body: BoxBackgroundDecoration( child: SingleChildScrollView( @@ -413,7 +420,17 @@ class PendaftaranPengirimPage extends GetView { ); } }, - child: const Text('Daftar'), + style: ElevatedButton.styleFrom( + primary: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: const Text( + 'Daftar', + style: + TextStyle(color: Color.fromARGB(255, 2, 72, 72)), + ), ), ), SizedBox( diff --git a/lib/routes/routes.dart b/lib/routes/routes.dart index 3ddb3b5..876a071 100644 --- a/lib/routes/routes.dart +++ b/lib/routes/routes.dart @@ -1,13 +1,16 @@ import 'package:flutter/animation.dart'; import 'package:get/get.dart'; import 'package:kurir/binding/beforeEnterBinding.dart'; +import 'package:kurir/binding/infoPengirimanBinding.dart'; import 'package:kurir/binding/kurirIndexBinding.dart'; import 'package:kurir/binding/kurirProfileBinding.dart'; // import 'package:kurir/binding/indexBinding.dart'; import 'package:kurir/binding/pendaftaranKurirBinding.dart'; import 'package:kurir/binding/pengirimIndexBinding.dart'; +import 'package:kurir/binding/pengirimProfileBinding.dart'; import 'package:kurir/pages/after_login/before_enter.dart'; import 'package:kurir/pages/after_login/kurir/profilePage.dart'; +import 'package:kurir/pages/after_login/pengirim/infoPengirimanPage.dart'; import 'package:kurir/pages/after_login/pengirim/pengirimProfilePage.dart'; import 'package:kurir/pages/before_login/daftar.dart'; import 'package:kurir/pages/before_login/login.dart'; @@ -105,13 +108,24 @@ class Routes { binding: PengirimIndexBinding(), transition: Transition.native, transitionDuration: const Duration(seconds: 1), + children: [ + GetPage( + name: '/infoPengiriman', + page: () => const InfoPengirimanPage(), + binding: InfoPengirimanBinding(), + transition: Transition.native, + transitionDuration: const Duration(seconds: 1), + curve: Curves.easeInOut, + ), + GetPage( + name: '/profilePengirim', + page: () => const PengirimProfilePage(), + binding: PengirimProfileBinding(), + transition: Transition.native, + transitionDuration: const Duration(seconds: 1), + ) + ], ), - GetPage( - name: '/profilePengirim', - page: () => const PengirimProfilePage(), - transition: Transition.native, - transitionDuration: const Duration(seconds: 1), - ) ]; } } diff --git a/lib/splashScreen.dart b/lib/splashScreen.dart index a05b76e..271aaf0 100644 --- a/lib/splashScreen.dart +++ b/lib/splashScreen.dart @@ -1,10 +1,98 @@ // ignore_for_file: file_names +// ignore: unused_import +import 'dart:developer' as dev; +// import 'dart:isolate'; +// import 'dart:math'; +// import 'dart:math'; import 'package:flutter/material.dart'; +// import 'package:kurir/api/notification_api.dart'; +// import 'package:socket_io_client/socket_io_client.dart'; -class SplashScreen extends StatelessWidget { +class SplashScreen extends StatefulWidget { const SplashScreen({Key? key}) : super(key: key); + @override + State createState() => _SplashScreenState(); +} + +class _SplashScreenState extends State { + // // @override + // void initState() { + // Workmanager().initialize( + // callbackDispatcher, + // isInDebugMode: true, + // ); + // Workmanager().registerOneOffTask( + // "percobaan1", + // "percobaan1", + // initialDelay: Duration(seconds: 10), + // ); + // Workmanager().registerPeriodicTask( + // "percobaan2", + // "percobaan2", + // frequency: Duration(minutes: 1), + // ); + // Workmanager().registerPeriodicTask( + // "percobaan3", + // "percobaan3", + // frequency: Duration(seconds: 15), + // // initialDelay: Duration(seconds: 15), + // ); + // super.initState(); + // } + + // @override + // void initState() { + // NotificationApi.init(initScheduled: false, context: context); + // connectToServer(); + // dev.log("ini initestatenya"); + // super.initState(); + // } + + // late Socket socket; + // void connectToServer() async { + // try { + // // Configure socket transports must be sepecified + // socket = io('http://192.168.43.125:3001/', { + // 'transports': ['websocket'], + // 'autoConnect': true, + // }); + + // // Connect to websocket + // socket.connect(); + + // // Handle socket events + // socket.on('connect', (_) => dev.log('connect asdasdsad: ${socket.id}')); + // socket.on('coba2', (_) => dev.log(_.toString())); + // socket.on('percobaan1', (_) { + // NotificationApi.showNotification( + // id: 1, + // title: 'Percobaan 1', + // body: _['message'], + // payload: 'Percobaan 1', + // ); + // }); + + // // socket.on('typing', handleTyping); + // // socket.on('message', handleMessage); + // // socket.on('disconnect', (_) => dev.log('disconnect')); + // // socket.on('fromServer', (_) => dev.log(_)); + // dev.log(socket.connected.toString() + " connected"); + // } catch (e) { + // dev.log(e.toString()); + // dev.log('tidak connect'); + // } + // } + + // Cancelable? lastKnownOperation; + + // @override + // void initState() { + // final task = Executor().execute(arg1: 10000, fun1: fib); + // super.initState(); + // } + @override Widget build(BuildContext context) { return Scaffold( @@ -36,3 +124,74 @@ class SplashScreen extends StatelessWidget { ); } } + +// int notif() { +// var random = Random(); +// NotificationApi.showNotification( +// id: random.nextInt(100), +// title: 'Percobaan 1', +// body: 'Percobaan 1', +// payload: 'Percobaan 1', +// ); +// return 1; +// } + +// int fib(int n) { +// if (n < 2) { +// return n; +// } + +// var random = Random(); +// NotificationApi.showNotification( +// id: random.nextInt(100), +// title: 'Percobaan 1', +// body: 'Percobaan 1', +// payload: 'Percobaan 1', +// ); +// // dev.log((fib(n - 2) + fib(n - 1)).toString()); +// return fib(n - 2) + fib(n - 1); +// } + +// void callbackDispatcher() { +// Workmanager().executeTask((task, inputData) async { +// switch (task) { +// case "percobaan1": +// dev.log("ini di percobaan1"); +// NotificationApi.showNotification( +// id: 1, +// title: 'Percobaan 1', +// body: "ini message", +// payload: 'Percobaan 1', +// ); +// Workmanager().( +// "percobaan1", +// "percobaan1", +// initialDelay: Duration(seconds: 10), +// ); +// break; +// case "percobaan2": +// dev.log("ini di percobaan2"); +// NotificationApi.showNotification( +// id: 2, +// title: 'Percobaan 2', +// body: "ini message", +// payload: 'Percobaan 2', +// ); +// break; +// case "percobaan3": +// dev.log("ini di percobaan3"); +// NotificationApi.showNotification( +// id: 3, +// title: 'Percobaan 3', +// body: "ini message", +// payload: 'Percobaan 3', +// ); +// break; +// } + +// return Future.value(true); +// }); +// } + +// The callback function should always be a top-level function. + diff --git a/lib/widgets/appbar.dart b/lib/widgets/appbar.dart new file mode 100644 index 0000000..c54807d --- /dev/null +++ b/lib/widgets/appbar.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class AppBarWidget extends StatelessWidget { + const AppBarWidget({ + Key? key, + required this.header, + required this.autoLeading, + this.actions, + }) : super(key: key); + + final String header; + final bool autoLeading; + final List? actions; + @override + Widget build(BuildContext context) { + return AppBar( + centerTitle: true, + title: Text( + header, + style: TextStyle( + fontSize: MediaQuery.of(context).size.height * 0.03, + fontWeight: FontWeight.bold, + ), + ), + automaticallyImplyLeading: autoLeading, + backgroundColor: const Color.fromARGB(255, 2, 72, 72), + // shape: const RoundedRectangleBorder( + // borderRadius: BorderRadius.vertical( + // bottom: Radius.circular(40), + // ), + // ), + actions: actions, + ); + } +} diff --git a/lib/widgets/bounce_scroller.dart b/lib/widgets/bounce_scroller.dart new file mode 100644 index 0000000..ffce79a --- /dev/null +++ b/lib/widgets/bounce_scroller.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class BounceScrollerWidget extends StatelessWidget { + const BounceScrollerWidget({Key? key, required this.children}) + : super(key: key); + + final List children; + @override + Widget build(BuildContext context) { + return SizedBox( + height: MediaQuery.of(context).size.height * 0.9, + width: double.infinity, + child: ListView( + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + children: children, + ), + ); + } +} diff --git a/lib/widgets/load_data.dart b/lib/widgets/load_data.dart new file mode 100644 index 0000000..76a3490 --- /dev/null +++ b/lib/widgets/load_data.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; + +class ErrorLoadDataWidget extends StatelessWidget { + const ErrorLoadDataWidget({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.05), + child: const Center( + child: Text( + 'Terjadi kesalahan', + style: TextStyle( + color: Colors.white, + fontSize: 20, + ), + ), + ), + ); + } +} + +class TiadaDataWIdget extends StatelessWidget { + const TiadaDataWIdget({ + Key? key, + this.text = 'Tidak ada data', + }) : super(key: key); + + final String text; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.05), + child: Center( + child: Text( + text, + style: TextStyle( + color: Colors.white, + fontSize: 20, + ), + ), + ), + ); + } +} + +class LoadingDataWidget extends StatelessWidget { + const LoadingDataWidget({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.05), + child: const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.white), + ), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 696dd6a..71e1be0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" async: dependency: transitive description: @@ -64,6 +71,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + dbus: + dependency: transitive + description: + name: dbus + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.3" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.4" + device_info_plus_linux: + dependency: transitive + description: + name: device_info_plus_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + device_info_plus_macos: + dependency: transitive + description: + name: device_info_plus_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.3" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0+1" + device_info_plus_web: + dependency: transitive + description: + name: device_info_plus_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + device_info_plus_windows: + dependency: transitive + description: + name: device_info_plus_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" double_back_to_close_app: dependency: "direct main" description: @@ -97,6 +153,34 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_background_service: + dependency: "direct main" + description: + name: flutter_background_service + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + flutter_background_service_android: + dependency: "direct main" + description: + name: flutter_background_service_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + flutter_background_service_ios: + dependency: transitive + description: + name: flutter_background_service_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + flutter_background_service_platform_interface: + dependency: transitive + description: + name: flutter_background_service_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_easyloading: dependency: "direct main" description: @@ -111,6 +195,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.dartlang.org" + source: hosted + version: "9.5.3+1" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.2" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0" + flutter_native_timezone: + dependency: "direct main" + description: + name: flutter_native_timezone + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -373,6 +485,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.5" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" platform: dependency: transitive description: @@ -394,6 +513,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" + rxdart: + dependency: "direct main" + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.26.0" sky_engine: dependency: transitive description: flutter @@ -462,6 +588,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.8" + timezone: + dependency: "direct main" + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.0" typed_data: dependency: transitive description: @@ -546,6 +679,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0+1" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" sdks: - dart: ">=2.16.0-134.5.beta <3.0.0" + dart: ">=2.16.2 <3.0.0" flutter: ">=2.8.0" diff --git a/pubspec.yaml b/pubspec.yaml index 858ff9f..8e054d2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.16.0-134.5.beta <3.0.0" + # sdk: ">=2.16.0-134.5.beta <3.0.0" + sdk: ">=2.16.2 <3.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -59,6 +60,34 @@ dependencies: flutter_polyline_points: url_launcher: ^6.0.1 + flutter_local_notifications: ^9.5.3 + rxdart: ^0.26.0 + timezone: ^0.8.0 + flutter_native_timezone: ^2.0.0 + + flutter_background_service: ^2.1.2 + flutter_background_service_android: ^2.0.2 + device_info_plus: ^3.2.4 + + # flutter_background_service_platform_interface: ^0.0.1 + + # flutter_foreground_task: ^3.7.3 #ini jalan kalau pakai if true + + # workmanager: ^0.4.1 # ini jalan + # background_fetch: ^1.1.0 + # android_alarm_manager_plus: ^2.0.5 + + # collection: ^1.15.0 + # worker_manager: ^4.2.6 + + # flutter_foreground_plugin: ^0.8.0 #ini jalan...tpi kalao close ndak jalan + + # isolate_handler: ^1.0.1 + # firebase_messaging: ^11.4.2 + # firebase_core: ^1.18.0 + # firebase_analytics: ^9.1.10 + + dev_dependencies: flutter_test: sdk: flutter