diff --git a/.env b/.env index c89c34d..fad3a8f 100644 --- a/.env +++ b/.env @@ -2,5 +2,6 @@ # api_url = 'https://panti-asuhan.s-keytech.com/api/' # # url = 'http://172.29.85.181/panti_asuhan2/' # # api_url = 'http://172.29.85.181/panti_asuhan2/api/' -url = 'http://20.20.20.25/panti_asuhan2/' -api_url = 'http://20.20.20.25/panti_asuhan2/api/' \ No newline at end of file +url = 'http://20.20.20.25:3001/' +table_url = 'http://20.20.20.25:3001/table' +api_url = 'http://20.20.20.25:3001/table' \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3ddb0b2..61ce643 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,7 +2,9 @@ + android:icon="@mipmap/ic_launcher" + android:usesCleartextTraffic="true" + > { splashScreenView, loginUserView, @@ -53,6 +60,8 @@ class Routes { inputInformasiDiriView, userIndexTrackingView, detailMakananView, + mejaDetailView, + keranjangSayaView, }; } @@ -86,54 +95,76 @@ class StackedRouter extends _i1.RouterBase { Routes.detailMakananView, page: _i8.DetailMakananView, ), + _i1.RouteDef( + Routes.mejaDetailView, + page: _i9.MejaDetailView, + ), + _i1.RouteDef( + Routes.keranjangSayaView, + page: _i10.KeranjangSayaView, + ), ]; final _pagesMap = { _i2.SplashScreenView: (data) { - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => const _i2.SplashScreenView(), settings: data, ); }, _i3.LoginUserView: (data) { - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => const _i3.LoginUserView(), settings: data, ); }, _i4.MasukanNoHpView: (data) { - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => const _i4.MasukanNoHpView(), settings: data, ); }, _i5.VerifikasiNoHpView: (data) { - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => const _i5.VerifikasiNoHpView(), settings: data, ); }, _i6.InputInformasiDiriView: (data) { final args = data.getArgs(nullOk: false); - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => _i6.InputInformasiDiriView(key: args.key, noHp: args.noHp), settings: data, ); }, _i7.UserIndexTrackingView: (data) { - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => const _i7.UserIndexTrackingView(), settings: data, fullscreenDialog: true, ); }, _i8.DetailMakananView: (data) { - return _i9.MaterialPageRoute( + return _i11.MaterialPageRoute( builder: (context) => const _i8.DetailMakananView(), settings: data, ); }, + _i9.MejaDetailView: (data) { + final args = data.getArgs(nullOk: false); + return _i11.MaterialPageRoute( + builder: (context) => + _i9.MejaDetailView(key: args.key, mejaId: args.mejaId), + settings: data, + ); + }, + _i10.KeranjangSayaView: (data) { + return _i11.MaterialPageRoute( + builder: (context) => const _i10.KeranjangSayaView(), + settings: data, + ); + }, }; @override @@ -148,7 +179,7 @@ class InputInformasiDiriViewArguments { required this.noHp, }); - final _i9.Key? key; + final _i11.Key? key; final String noHp; @@ -169,6 +200,33 @@ class InputInformasiDiriViewArguments { } } +class MejaDetailViewArguments { + const MejaDetailViewArguments({ + this.key, + required this.mejaId, + }); + + final _i11.Key? key; + + final String mejaId; + + @override + String toString() { + return '{"key": "$key", "mejaId": "$mejaId"}'; + } + + @override + bool operator ==(covariant MejaDetailViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.mejaId == mejaId; + } + + @override + int get hashCode { + return key.hashCode ^ mejaId.hashCode; + } +} + class UserIndexTrackingViewRoutes { static const reservasiMejaView = ''; @@ -190,44 +248,44 @@ class UserIndexTrackingViewRouter extends _i1.RouterBase { final _routes = <_i1.RouteDef>[ _i1.RouteDef( UserIndexTrackingViewRoutes.reservasiMejaView, - page: _i10.ReservasiMejaView, + page: _i12.ReservasiMejaView, ), _i1.RouteDef( UserIndexTrackingViewRoutes.makananListView, - page: _i11.MakananListView, + page: _i13.MakananListView, ), _i1.RouteDef( UserIndexTrackingViewRoutes.pesananListView, - page: _i12.PesananListView, + page: _i14.PesananListView, ), _i1.RouteDef( UserIndexTrackingViewRoutes.akunUserView, - page: _i13.AkunUserView, + page: _i15.AkunUserView, ), ]; final _pagesMap = { - _i10.ReservasiMejaView: (data) { - return _i9.MaterialPageRoute( - builder: (context) => const _i10.ReservasiMejaView(), + _i12.ReservasiMejaView: (data) { + return _i11.MaterialPageRoute( + builder: (context) => const _i12.ReservasiMejaView(), settings: data, ); }, - _i11.MakananListView: (data) { - return _i9.MaterialPageRoute( - builder: (context) => const _i11.MakananListView(), + _i13.MakananListView: (data) { + return _i11.MaterialPageRoute( + builder: (context) => const _i13.MakananListView(), settings: data, ); }, - _i12.PesananListView: (data) { - return _i9.MaterialPageRoute( - builder: (context) => const _i12.PesananListView(), + _i14.PesananListView: (data) { + return _i11.MaterialPageRoute( + builder: (context) => const _i14.PesananListView(), settings: data, ); }, - _i13.AkunUserView: (data) { - return _i9.MaterialPageRoute( - builder: (context) => const _i13.AkunUserView(), + _i15.AkunUserView: (data) { + return _i11.MaterialPageRoute( + builder: (context) => const _i15.AkunUserView(), settings: data, ); }, @@ -239,7 +297,7 @@ class UserIndexTrackingViewRouter extends _i1.RouterBase { Map get pagesMap => _pagesMap; } -extension NavigatorStateExtension on _i14.NavigationService { +extension NavigatorStateExtension on _i16.NavigationService { Future navigateToSplashScreenView([ int? routerId, bool preventDuplicates = true, @@ -297,7 +355,7 @@ extension NavigatorStateExtension on _i14.NavigationService { } Future navigateToInputInformasiDiriView({ - _i9.Key? key, + _i11.Key? key, required String noHp, int? routerId, bool preventDuplicates = true, @@ -341,6 +399,37 @@ extension NavigatorStateExtension on _i14.NavigationService { transition: transition); } + Future navigateToMejaDetailView({ + _i11.Key? key, + required String mejaId, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.mejaDetailView, + arguments: MejaDetailViewArguments(key: key, mejaId: mejaId), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToKeranjangSayaView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return navigateTo(Routes.keranjangSayaView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + Future navigateToNestedReservasiMejaViewInUserIndexTrackingViewRouter([ int? routerId, @@ -455,7 +544,7 @@ extension NavigatorStateExtension on _i14.NavigationService { } Future replaceWithInputInformasiDiriView({ - _i9.Key? key, + _i11.Key? key, required String noHp, int? routerId, bool preventDuplicates = true, @@ -499,6 +588,37 @@ extension NavigatorStateExtension on _i14.NavigationService { transition: transition); } + Future replaceWithMejaDetailView({ + _i11.Key? key, + required String mejaId, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.mejaDetailView, + arguments: MejaDetailViewArguments(key: key, mejaId: mejaId), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithKeranjangSayaView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return replaceWith(Routes.keranjangSayaView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + Future replaceWithNestedReservasiMejaViewInUserIndexTrackingViewRouter([ int? routerId, diff --git a/lib/app/core/custom_base_view_model.dart b/lib/app/core/custom_base_view_model.dart index 8b99696..16e7b40 100755 --- a/lib/app/core/custom_base_view_model.dart +++ b/lib/app/core/custom_base_view_model.dart @@ -16,7 +16,7 @@ class CustomBaseViewModel extends BaseViewModel { final easyLoading = locator(); final httpService = locator(); - bool backPressed = true; + // late bool backPressed; void back() { navigationService.back(); diff --git a/lib/services/my_easyloading.dart b/lib/services/my_easyloading.dart index 46cb062..c1eb253 100644 --- a/lib/services/my_easyloading.dart +++ b/lib/services/my_easyloading.dart @@ -1,6 +1,8 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; class MyEasyLoading { + int backPressed = 1; + showLoading() { EasyLoading.show( status: 'loading...', diff --git a/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view.dart b/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view.dart index 590ac4c..a7335ae 100644 --- a/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view.dart +++ b/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view.dart @@ -40,7 +40,7 @@ class InputInformasiDiriView extends StatelessWidget { ), body: WillPopScope( onWillPop: () async { - if (model.backPressed) { + if (model.easyLoading.backPressed == 1) { model.navigationService.navigateToMasukanNoHpView(); } return false; diff --git a/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view_model.dart b/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view_model.dart index a1316ba..d567933 100644 --- a/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view_model.dart +++ b/lib/ui/views/daftar_user_ui/input_informasi_diri/input_informasi_diri_view_model.dart @@ -33,13 +33,13 @@ class InputInformasiDiriViewModel extends CustomBaseViewModel { } goToLogin() async { - backPressed = false; + easyLoading.backPressed = 0; easyLoading.customLoading("Mendaftarkan Akun Anda"); await Future.delayed(const Duration(seconds: 2)); easyLoading.customLoading("Ke Halaman Login"); await Future.delayed(const Duration(seconds: 2)); easyLoading.dismissLoading(); - backPressed = true; + easyLoading.backPressed = 1; notifyListeners(); await navigationService.navigateToLoginUserView(); } diff --git a/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view.dart b/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view.dart index b3c5a51..09b0c57 100644 --- a/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view.dart +++ b/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view.dart @@ -36,7 +36,7 @@ class MasukanNoHpView extends StatelessWidget { ), body: WillPopScope( onWillPop: () async { - if (model.backPressed) { + if (model.easyLoading.backPressed == 1) { model.navigationService.navigateToLoginUserView(); } return false; diff --git a/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view_model.dart b/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view_model.dart index 2fa3089..663397b 100644 --- a/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view_model.dart +++ b/lib/ui/views/daftar_user_ui/masukan_no_hp/masukan_no_hp_view_model.dart @@ -16,9 +16,9 @@ class MasukanNoHpViewModel extends CustomBaseViewModel { selanjutnya() async { _easyloading.customLoading("Menghantar Kode OTP \nke WhatsApp Anda"); - backPressed = false; + easyLoading.backPressed = 0; await Future.delayed(const Duration(seconds: 3)); - backPressed = true; + easyLoading.backPressed = 1; notifyListeners(); _easyloading.dismissLoading(); await navigationService.navigateToVerifikasiNoHpView(); diff --git a/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view.dart b/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view.dart index d3f618d..b313885 100644 --- a/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view.dart +++ b/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view.dart @@ -36,7 +36,7 @@ class VerifikasiNoHpView extends StatelessWidget { ), body: WillPopScope( onWillPop: () async { - if (model.backPressed) { + if (model.easyLoading.backPressed == 1) { model.back(); } return false; diff --git a/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view_model.dart b/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view_model.dart index 80014ca..37f598c 100644 --- a/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view_model.dart +++ b/lib/ui/views/daftar_user_ui/verifikasi_no_hp/verifikasi_no_hp_view_model.dart @@ -9,11 +9,11 @@ class VerifikasiNoHpViewModel extends CustomBaseViewModel { Future init() async {} goToInputInformasiDiri() async { - backPressed = false; + easyLoading.backPressed = 0; easyLoading.customLoading("Ke Halaman Input Informasi Diri"); await Future.delayed(const Duration(seconds: 3)); easyLoading.dismissLoading(); - backPressed = true; + easyLoading.backPressed = 1; notifyListeners(); await navigationService.navigateToInputInformasiDiriView( noHp: "082293246583", diff --git a/lib/ui/views/login_user/login_user_view.dart b/lib/ui/views/login_user/login_user_view.dart index 31c8324..aaa3c96 100644 --- a/lib/ui/views/login_user/login_user_view.dart +++ b/lib/ui/views/login_user/login_user_view.dart @@ -23,7 +23,7 @@ class LoginUserView extends StatelessWidget { return Scaffold( body: WillPopScope( onWillPop: () async { - if (model.backPressed) { + if (model.easyLoading.backPressed == 1) { // model.back(); model.quitApp(context); } diff --git a/lib/ui/views/login_user/login_user_view_model.dart b/lib/ui/views/login_user/login_user_view_model.dart index 7488f0b..91a9c16 100644 --- a/lib/ui/views/login_user/login_user_view_model.dart +++ b/lib/ui/views/login_user/login_user_view_model.dart @@ -17,12 +17,12 @@ class LoginUserViewModel extends CustomBaseViewModel { login() async { setBusy(true); - backPressed = false; + easyLoading.backPressed = 0; easyLoading.showLoading(); - await Future.delayed(const Duration(seconds: 2)); + await Future.delayed(const Duration(seconds: 5)); easyLoading.dismissLoading(); setBusy(false); - backPressed = true; + easyLoading.backPressed = 1; notifyListeners(); await navigationService.navigateToUserIndexTrackingView(); } diff --git a/lib/ui/views/meja_detail/meja_detail_view.dart b/lib/ui/views/meja_detail/meja_detail_view.dart new file mode 100644 index 0000000..28ad637 --- /dev/null +++ b/lib/ui/views/meja_detail/meja_detail_view.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:reza_app/app/app.router.dart'; +import 'package:reza_app/app/themes/app_colors.dart'; +import 'package:reza_app/app/themes/app_text.dart'; +import 'package:stacked/stacked.dart'; + +import './meja_detail_view_model.dart'; + +class MejaDetailView extends StatelessWidget { + final String mejaId; + + const MejaDetailView({ + Key? key, + required this.mejaId, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + viewModelBuilder: () => MejaDetailViewModel(), + onViewModelReady: (MejaDetailViewModel model) async { + await model.init(mejaId); + }, + builder: ( + BuildContext context, + MejaDetailViewModel model, + Widget? child, + ) { + return Scaffold( + appBar: AppBar( + title: const Text('MejaDetailView', + style: TextStyle(color: Colors.white)), + backgroundColor: mainColor, + leading: IconButton( + onPressed: () => model.navigationService.popUntil((route) => + route.settings.name == Routes.userIndexTrackingView), + icon: const Icon(Icons.arrow_back, color: Colors.white), + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: 250, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: model.imgAsset == null + ? const Center(child: CircularProgressIndicator()) + : Image.asset(model.imgAsset!, fit: BoxFit.cover), + ), + ), + const SizedBox(height: 5), + Text( + model.namaMeja, + style: const TextStyle( + fontSize: 20, + // fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 10), + RichText( + text: TextSpan( + text: 'Status : ', + style: regularTextStyle, + children: [ + TextSpan( + text: 'Tersedia', + style: regularTextStyle.copyWith( + color: Colors.green, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + RichText( + text: TextSpan( + text: 'Kapasitas : ', + style: regularTextStyle, + children: [ + TextSpan( + text: 'Maksimal 8 Orang', + style: regularTextStyle.copyWith( + color: Colors.green, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + RichText( + text: TextSpan( + text: 'Lokasi : ', + style: regularTextStyle, + children: [ + TextSpan( + text: 'Luar Ruangan', + style: regularTextStyle.copyWith( + color: Colors.green, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + RichText( + text: TextSpan( + text: 'Harga : ', + style: regularTextStyle, + children: [ + TextSpan( + text: 'Rp. 20.000', + style: regularTextStyle.copyWith( + color: Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () {}, + label: const Text('Pesan'), + icon: const Icon(Icons.add_shopping_cart), + backgroundColor: mainColor, + ), + floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling, + floatingActionButtonLocation: + FloatingActionButtonLocation.centerFloat, + ); + }, + ); + } +} diff --git a/lib/ui/views/meja_detail/meja_detail_view_model.dart b/lib/ui/views/meja_detail/meja_detail_view_model.dart new file mode 100644 index 0000000..bce3c3b --- /dev/null +++ b/lib/ui/views/meja_detail/meja_detail_view_model.dart @@ -0,0 +1,35 @@ +import '../../../app/app.logger.dart'; +import '../../../app/core/custom_base_view_model.dart'; + +class MejaDetailViewModel extends CustomBaseViewModel { + final log = getLogger('MejaDetailViewModel'); + + late String mejaId; + late String namaMeja; + + String? imgAsset; + + Future init(String mejaId) async { + log.i('MejaDetailViewModel init'); + log.i('mejaId : $mejaId'); + this.mejaId = mejaId; + easyLoading.backPressed = 3; + // seperate the number from the string + var number = int.parse(mejaId.replaceAll(RegExp(r'[^0-9]'), '')); + // log.i('number : $number'); + if (number <= 4) { + namaMeja = 'Gazebo'; + imgAsset = 'assets/reza_gazebo.jpeg'; + } else if (number >= 5 && number <= 12) { + namaMeja = 'Meja'; + imgAsset = 'assets/reza_meja_1.jpeg'; + } else if (number >= 13 && number <= 22) { + namaMeja = 'Meja'; + imgAsset = 'assets/reza_meja_2.jpeg'; + } + + namaMeja = '$namaMeja $number'; + + log.i('imgAsset : $imgAsset'); + } +} diff --git a/lib/ui/views/user_ui/akun_user/akun_user_view.dart b/lib/ui/views/user_ui/akun_user/akun_user_view.dart index 3eaa2a0..d21e99f 100644 --- a/lib/ui/views/user_ui/akun_user/akun_user_view.dart +++ b/lib/ui/views/user_ui/akun_user/akun_user_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; +import '../../../../app/themes/app_colors.dart'; +import '../../../../app/themes/app_text.dart'; import './akun_user_view_model.dart'; class AkunUserView extends StatelessWidget { @@ -18,10 +20,110 @@ class AkunUserView extends StatelessWidget { AkunUserViewModel model, Widget? child, ) { - return const Scaffold( - body: Center( - child: Text( - 'AkunUserView', + return Scaffold( + appBar: AppBar( + title: Text( + 'Akun Saya', + style: boldTextStyle.copyWith(color: fontGrey, fontSize: 16), + ), + // transparent + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + actions: [ + IconButton( + onPressed: () {}, + icon: const Icon( + Icons.logout_outlined, + color: fontGrey, + ), + ), + ], + ), + backgroundColor: backgroundColor, + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + // create a circle avatar 150x150 that contain the image + Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(150), + child: Image.network( + 'https://a.cdn-hotels.com/gdcs/production0/d1513/35c1c89e-408c-4449-9abe-f109068f40c0.jpg?impolicy=fcrop&w=800&h=533&q=medium', + height: 150, + width: 150, + fit: BoxFit.fill, + errorBuilder: (context, error, stackTrace) { + return const Icon(Icons.error); + }, + ), + ), + ), + const SizedBox(height: 10), + Row( + children: [ + const Text('Nama'), + const Expanded(child: SizedBox(width: 10)), + Text( + 'Reza', + style: regularTextStyle.copyWith( + color: fontGrey, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 10), + const Icon( + Icons.arrow_forward_ios, + color: fontGrey, + size: 15, + ), + ], + ), + const SizedBox(height: 20), + Row( + children: [ + const Text('Jenis Kelamin'), + const Expanded(child: SizedBox(width: 10)), + Text( + 'Laki-laki', + style: regularTextStyle.copyWith( + color: fontGrey, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 10), + const Icon( + Icons.arrow_forward_ios, + color: fontGrey, + size: 15, + ), + ], + ), + const SizedBox(height: 20), + Row( + children: [ + const Text('Tanggal Lahir'), + const Expanded(child: SizedBox(width: 10)), + Text( + '12-12-1999', + style: regularTextStyle.copyWith( + color: fontGrey, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 10), + const Icon( + Icons.arrow_forward_ios, + color: fontGrey, + size: 15, + ), + ], + ), + ], ), ), ); diff --git a/lib/ui/views/user_ui/akun_user/akun_user_view_model.dart b/lib/ui/views/user_ui/akun_user/akun_user_view_model.dart index c84d20c..3005729 100644 --- a/lib/ui/views/user_ui/akun_user/akun_user_view_model.dart +++ b/lib/ui/views/user_ui/akun_user/akun_user_view_model.dart @@ -1,5 +1,7 @@ import 'package:reza_app/app/core/custom_base_view_model.dart'; class AkunUserViewModel extends CustomBaseViewModel { - Future init() async {} + Future init() async { + easyLoading.backPressed = 2; + } } diff --git a/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view.dart b/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view.dart index c4dbd9b..ef28730 100644 --- a/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view.dart +++ b/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view.dart @@ -29,79 +29,181 @@ class DetailMakananView extends HookWidget { Widget? child, ) { return Scaffold( - backgroundColor: backgroundColor, - body: SizedBox( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - child: Stack( - children: [ - ListView.builder( - controller: scrollController, - itemCount: 1, - itemBuilder: (context, index) { - return Column( + backgroundColor: backgroundColor, + body: SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + child: Stack( + children: [ + ListView.builder( + controller: scrollController, + itemCount: 1, + itemBuilder: (context, index) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: MediaQuery.of(context).padding.top, + ), + const TopMenuWidget(), + const SecondWidget(), + const SizedBox( + height: 10, + ), + MyWhiteContainer( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Ongkos Kirim', + style: boldTextStyle.copyWith( + fontSize: 14, + ), + ), + TextSpan( + text: ' Rp. 10.000', + style: boldTextStyle.copyWith( + fontSize: 14, + color: dangerColor, + ), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + Text( + "Bisa Dibayar COD sekitar Parepare", + style: regularTextStyle.copyWith( + fontSize: 13, + color: fontGrey, + ), + ), + ], + ), + ), + ), + const SizedBox( + height: 10, + ), + MyWhiteContainer( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Deskripsi", + style: boldTextStyle.copyWith( + fontSize: 15, + ), + ), + const SizedBox( + height: 10, + ), + // bikin dummy text tentang nasi goreng + Text( + "Nasi goreng adalah makanan yang terbuat dari nasi yang digoreng dan diaduk dalam minyak goreng atau margarin, biasanya ditambah kecap manis, bawang merah, bawang putih, daging ayam, telur, dan bumbu-bumbu lainnya. Nasi goreng sering dianggap sebagai makanan nasional Indonesia. Nasi goreng dapat ditemukan di seluruh Indonesia, dari restoran pinggir jalan, warung, hingga hotel bintang lima dan restoran mewah.", + style: regularTextStyle.copyWith( + fontSize: 13, + color: fontGrey, + ), + textAlign: TextAlign.justify, + ), + ], + ), + ), + ), + const SizedBox( + height: 20, + ), + ], + ); + }, + ), + TopBarWidget(opacity: opacity), + ], + ), + ), + bottomNavigationBar: Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + width: MediaQuery.of(context).size.width, + height: 70, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 5, + spreadRadius: 5, + ), + ], + ), + child: Row( + children: [ + Expanded( + child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - height: MediaQuery.of(context).padding.top, + Text( + "Total Harga", + style: regularTextStyle.copyWith( + fontSize: 14, + color: fontGrey, + ), ), - const TopMenuWidget(), - const SecondWidget(), const SizedBox( - height: 10, + height: 5, ), - MyWhiteContainer( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Ongkos Kirim', - style: boldTextStyle.copyWith( - fontSize: 14, - ), - ), - TextSpan( - text: ' Rp. 10.000', - style: boldTextStyle.copyWith( - fontSize: 14, - color: dangerColor, - ), - ), - ], - ), - ), - const SizedBox( - height: 10, - ), - Text( - "Bisa Dibayar COD sekitar Parepare", - style: regularTextStyle.copyWith( - fontSize: 13, - color: fontGrey, - ), - ), - ], - ), + Text( + "Rp. 35.000", + style: boldTextStyle.copyWith( + fontSize: 16, + color: dangerColor, ), ), ], - ); - }, - ), - TopBarWidget(opacity: opacity), - ], - ), - ), - ); + ), + ), + Expanded( + child: Container( + height: 40, + decoration: BoxDecoration( + color: dangerColor, + borderRadius: BorderRadius.circular(10), + ), + child: Center( + child: Text( + "Pesan Sekarang", + style: boldTextStyle.copyWith( + fontSize: 16, + color: Colors.white, + ), + ), + ), + ), + ), + ], + ), + )); }, ); } diff --git a/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view_model.dart b/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view_model.dart index 0896e46..51f212d 100644 --- a/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view_model.dart +++ b/lib/ui/views/user_ui/makanan_list/detail_makanan/detail_makanan_view_model.dart @@ -4,5 +4,7 @@ import '../../../../../app/core/custom_base_view_model.dart'; class DetailMakananViewModel extends CustomBaseViewModel { final log = getLogger('DetailMakananViewModel'); - Future init() async {} + Future init() async { + easyLoading.backPressed = 3; + } } diff --git a/lib/ui/views/user_ui/makanan_list/makanan_list_view.dart b/lib/ui/views/user_ui/makanan_list/makanan_list_view.dart index 3b6ed43..2661c4b 100644 --- a/lib/ui/views/user_ui/makanan_list/makanan_list_view.dart +++ b/lib/ui/views/user_ui/makanan_list/makanan_list_view.dart @@ -22,178 +22,215 @@ class MakananListView extends StatelessWidget { Widget? child, ) { return Scaffold( - backgroundColor: backgroundColor, - body: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // get the top height of the notification bar - SizedBox( - height: MediaQuery.of(context).padding.top, - ), - MyWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: IconButton( - onPressed: () => model.back(), - icon: const Icon(Icons.arrow_back), - ), - ), - const SizedBox( - width: 10, - ), - Expanded( - flex: 10, - child: MyTextFormField( - // controller: model.searchController, - hintText: 'Cari Makanan', - suffixIcon: IconButton( - onPressed: () {}, - icon: const Icon(Icons.search), - ), - ), - ), - Expanded( - flex: 1, - child: IconButton( - onPressed: () {}, - icon: const Icon(Icons.filter_list), - ), - ), - TextButton( - onPressed: () {}, - child: const Text('Filter'), - ), - ], + backgroundColor: backgroundColor, + body: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // get the top height of the notification bar + SizedBox( + height: MediaQuery.of(context).padding.top, ), - ), - const SizedBox( - height: 5, - ), - MyWhiteContainer( - child: IntrinsicHeight( + MyWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( - child: TextButton( - onPressed: () {}, - child: const Text('Terbaru'), + flex: 2, + child: IconButton( + onPressed: () => model.back(), + icon: const Icon(Icons.arrow_back), ), ), - const VerticalDivider( - color: mainGrey, - thickness: 1, + const SizedBox( + width: 10, ), Expanded( - child: TextButton( - onPressed: () {}, - child: const Text( - 'Terlaris', - style: TextStyle( - color: mainGrey, - ), + flex: 10, + child: MyTextFormField( + // controller: model.searchController, + hintText: 'Cari Makanan', + suffixIcon: IconButton( + onPressed: () {}, + icon: const Icon(Icons.search), ), ), ), - const VerticalDivider( - color: Colors.grey, - thickness: 1, - ), Expanded( - child: TextButton( + flex: 1, + child: IconButton( onPressed: () {}, - child: const Row( - children: [ - Text( - 'Harga', - style: TextStyle( - color: mainGrey, - ), - ), - Icon( - Icons.arrow_drop_down, - color: mainGrey, - ), - ], - ), + icon: const Icon(Icons.filter_list), ), ), + TextButton( + onPressed: () {}, + child: const Text('Filter'), + ), ], ), ), - ), - const SizedBox( - height: 10, - ), - Expanded( - child: Center( - child: SingleChildScrollView( - child: Wrap( - spacing: 10, - runSpacing: 10, + const SizedBox( + height: 5, + ), + MyWhiteContainer( + child: IntrinsicHeight( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - for (var i = 0; i < 10; i++) - GestureDetector( - onTap: () => model.goToDetailMakanan(), - child: Container( - width: MediaQuery.of(context).size.width * 0.46, - color: Colors.white, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.network( - 'https://a.cdn-hotels.com/gdcs/production0/d1513/35c1c89e-408c-4449-9abe-f109068f40c0.jpg?impolicy=fcrop&w=800&h=533&q=medium', - height: 150, - width: double.infinity, - fit: BoxFit.fill, - ), - const SizedBox( - height: 5, - ), - const Padding( - padding: EdgeInsets.only( - left: 5, - ), - child: Text( - 'Product Name', - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox( - height: 5, - ), - const Padding( - padding: EdgeInsets.only( - left: 5, - ), - child: Text( - 'Rp. 100.000', - style: TextStyle( - color: Colors.grey, - ), - ), - ), - const SizedBox( - height: 5, - ), - ], + Expanded( + child: TextButton( + onPressed: () {}, + child: const Text('Terbaru'), + ), + ), + const VerticalDivider( + color: mainGrey, + thickness: 1, + ), + Expanded( + child: TextButton( + onPressed: () {}, + child: const Text( + 'Terlaris', + style: TextStyle( + color: mainGrey, ), ), ), + ), + const VerticalDivider( + color: Colors.grey, + thickness: 1, + ), + Expanded( + child: TextButton( + onPressed: () {}, + child: const Row( + children: [ + Text( + 'Harga', + style: TextStyle( + color: mainGrey, + ), + ), + Icon( + Icons.arrow_drop_down, + color: mainGrey, + ), + ], + ), + ), + ), ], ), ), ), + const SizedBox( + height: 10, + ), + Expanded( + child: Center( + child: SingleChildScrollView( + child: Wrap( + spacing: 10, + runSpacing: 10, + children: [ + for (var i = 0; i < 10; i++) + GestureDetector( + onTap: () => model.goToDetailMakanan(), + child: Container( + width: MediaQuery.of(context).size.width * 0.46, + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.network( + 'https://a.cdn-hotels.com/gdcs/production0/d1513/35c1c89e-408c-4449-9abe-f109068f40c0.jpg?impolicy=fcrop&w=800&h=533&q=medium', + height: 150, + width: double.infinity, + fit: BoxFit.fill, + ), + const SizedBox( + height: 5, + ), + const Padding( + padding: EdgeInsets.only( + left: 5, + ), + child: Text( + 'Product Name', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + const SizedBox( + height: 5, + ), + const Padding( + padding: EdgeInsets.only( + left: 5, + ), + child: Text( + 'Rp. 100.000', + style: TextStyle( + color: Colors.grey, + ), + ), + ), + const SizedBox( + height: 5, + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + // create a shopping cart icon with a badge containing the number of items + child: Container( + margin: const EdgeInsets.only(right: 10), + child: Stack( + children: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.shopping_cart_outlined, + color: Colors.white), + iconSize: 30, + ), + Positioned( + top: 5, + right: 5, + child: Container( + width: 20, + height: 20, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + child: const Center( + child: Text( + '9', + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ), + ), + ], + ), ), - ], - ), - ); + )); }, ); } diff --git a/lib/ui/views/user_ui/makanan_list/makanan_list_view_model.dart b/lib/ui/views/user_ui/makanan_list/makanan_list_view_model.dart index 347d15b..0cd330d 100644 --- a/lib/ui/views/user_ui/makanan_list/makanan_list_view_model.dart +++ b/lib/ui/views/user_ui/makanan_list/makanan_list_view_model.dart @@ -4,7 +4,9 @@ import '../../../../app/core/custom_base_view_model.dart'; class MakananListViewModel extends CustomBaseViewModel { final log = getLogger('MakananListViewModel'); - Future init() async {} + Future init() async { + easyLoading.backPressed = 2; + } goToDetailMakanan() { log.i('goToDetailMakanan'); diff --git a/lib/ui/views/user_ui/pesanan_list/keranjang_saya/keranjang_saya_view.dart b/lib/ui/views/user_ui/pesanan_list/keranjang_saya/keranjang_saya_view.dart new file mode 100644 index 0000000..3338823 --- /dev/null +++ b/lib/ui/views/user_ui/pesanan_list/keranjang_saya/keranjang_saya_view.dart @@ -0,0 +1,172 @@ +import 'package:flutter/material.dart'; +import 'package:stacked/stacked.dart'; + +import '../../../../../app/themes/app_colors.dart'; +import '../../../../../app/themes/app_text.dart'; +import '../../../../widgets/my_white_container.dart'; +import './keranjang_saya_view_model.dart'; + +class KeranjangSayaView extends StatelessWidget { + const KeranjangSayaView({super.key}); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + viewModelBuilder: () => KeranjangSayaViewModel(), + onViewModelReady: (KeranjangSayaViewModel model) async { + await model.init(); + }, + builder: ( + BuildContext context, + KeranjangSayaViewModel model, + Widget? child, + ) { + return Scaffold( + appBar: AppBar( + title: const Text('Keranjang Saya', + style: TextStyle(color: Colors.white)), + backgroundColor: mainColor, + iconTheme: const IconThemeData(color: Colors.white), + ), + body: Column( + children: [ + const SizedBox(height: 15), + Expanded( + child: ListView.builder( + itemCount: 10, + shrinkWrap: true, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: MyWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // create a checkbox + Checkbox( + // check if the value is true or false + value: false, + // if true change the value to false + onChanged: (bool? value) { + // model.changeIsCheck(value!); + }, + ), + const SizedBox(width: 10), + // create a container 100x100 that contain the image + Container( + width: 100, + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + 'https://a.cdn-hotels.com/gdcs/production0/d1513/35c1c89e-408c-4449-9abe-f109068f40c0.jpg?impolicy=fcrop&w=800&h=533&q=medium', + height: 150, + width: double.infinity, + fit: BoxFit.fill, + errorBuilder: (context, error, stackTrace) { + return const Icon(Icons.error); + }, + ), + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Product Name ', + style: regularTextStyle.copyWith( + fontSize: 16), + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 5), + Text( + 'Rp. 100.000', + style: boldTextStyle.copyWith( + color: redColor), + ), + const SizedBox(height: 5), + // create a row that contain minus button, value, and plus button + Row( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + // create a button minus + GestureDetector( + onTap: () {}, + child: Container( + width: 25, + height: 25, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(5), + color: stockColor, + ), + child: const Icon( + Icons.remove, + color: mainGrey, + ), + ), + ), + const SizedBox(width: 10), + // create a text that contain value + Text( + '1', + style: regularTextStyle.copyWith( + fontSize: 16, + ), + ), + const SizedBox(width: 10), + // create a button plus + GestureDetector( + onTap: () {}, + child: Container( + width: 25, + height: 25, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(5), + color: stockColor, + ), + child: const Icon( + Icons.add, + color: mainGrey, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + }, + ), + ), + const SizedBox(height: 15), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + // create a shopping cart icon with a badge containing the number of items + child: const Icon( + Icons.shopping_cart_outlined, + color: Colors.white, + ), + )); + }, + ); + } +} diff --git a/lib/ui/views/user_ui/pesanan_list/keranjang_saya/keranjang_saya_view_model.dart b/lib/ui/views/user_ui/pesanan_list/keranjang_saya/keranjang_saya_view_model.dart new file mode 100644 index 0000000..9150cef --- /dev/null +++ b/lib/ui/views/user_ui/pesanan_list/keranjang_saya/keranjang_saya_view_model.dart @@ -0,0 +1,10 @@ +import 'package:reza_app/app/core/custom_base_view_model.dart'; + +import '../../../../../app/app.logger.dart'; + +class KeranjangSayaViewModel extends CustomBaseViewModel { + final log = getLogger('KeranjangSayaViewModel'); + Future init() async { + easyLoading.backPressed = 3; + } +} diff --git a/lib/ui/views/user_ui/pesanan_list/pesanan_list_view.dart b/lib/ui/views/user_ui/pesanan_list/pesanan_list_view.dart index 0dd3a13..15abd6e 100644 --- a/lib/ui/views/user_ui/pesanan_list/pesanan_list_view.dart +++ b/lib/ui/views/user_ui/pesanan_list/pesanan_list_view.dart @@ -1,4 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:reza_app/app/app.router.dart'; +import 'package:reza_app/app/themes/app_colors.dart'; +import 'package:reza_app/app/themes/app_text.dart'; +import 'package:reza_app/ui/widgets/my_white_container.dart'; import 'package:stacked/stacked.dart'; import './pesanan_list_view_model.dart'; @@ -18,12 +22,287 @@ class PesananListView extends StatelessWidget { PesananListViewModel model, Widget? child, ) { - return const Scaffold( - body: Center( - child: Text( - 'PesananListView', + return Scaffold( + appBar: AppBar( + title: Text( + 'List Pesanan', + style: boldTextStyle.copyWith(color: Colors.white), ), + backgroundColor: mainColor, + automaticallyImplyLeading: false, + actions: [ + // create a shopping cart icon with a badge containing the number of items + Container( + margin: const EdgeInsets.only(right: 10), + child: Stack( + children: [ + IconButton( + onPressed: () { + model.navigationService.navigateToKeranjangSayaView(); + }, + icon: const Icon(Icons.shopping_cart_outlined, + color: Colors.white), + ), + Positioned( + top: 5, + right: 5, + child: Container( + width: 20, + height: 20, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + child: const Center( + child: Text( + '9', + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ), + ), + ], + ), + ), + ], ), + backgroundColor: backgroundColor, + body: Column( + children: [ + MyWhiteContainer( + child: IntrinsicHeight( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: TextButton( + onPressed: () {}, + child: const Text('Dikemas'), + ), + ), + const VerticalDivider( + color: mainGrey, + thickness: 1, + ), + Expanded( + child: TextButton( + onPressed: () {}, + child: const Text( + 'Dikirim', + style: TextStyle( + color: mainGrey, + ), + ), + ), + ), + const VerticalDivider( + color: Colors.grey, + thickness: 1, + ), + Expanded( + child: TextButton( + onPressed: () {}, + child: const Text( + 'Selesai', + style: TextStyle( + color: mainGrey, + ), + ), + ), + ), + ], + ), + ), + ), + const SizedBox( + height: 15, + ), + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: 10, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: MyWhiteContainer( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + ), + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 100, + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.network( + 'https://a.cdn-hotels.com/gdcs/production0/d1513/35c1c89e-408c-4449-9abe-f109068f40c0.jpg?impolicy=fcrop&w=800&h=533&q=medium', + height: 100, + width: double.infinity, + fit: BoxFit.fill, + errorBuilder: + (context, error, stackTrace) { + return const Icon(Icons.error); + }, + ), + ), + ), + const SizedBox( + width: 20, + ), + Expanded( + child: IntrinsicHeight( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + 'Nama Makanan', + style: regularTextStyle.copyWith( + fontSize: 17, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox( + height: 5, + ), + Align( + alignment: Alignment.centerRight, + child: Text( + 'x 1', + style: regularTextStyle.copyWith( + color: mainGrey, + fontSize: 17, + ), + ), + ), + const SizedBox( + height: 5, + ), + Align( + alignment: Alignment.centerRight, + child: Text( + 'Rp. 100.000', + style: regularTextStyle.copyWith( + color: redColor, + fontSize: 17, + ), + ), + ), + ], + ), + ), + ) + ], + ), + const SizedBox( + height: 10, + ), + Center( + child: Text( + 'Tampilkan Produk Lain', + style: regularTextStyle.copyWith( + color: mainGrey, + ), + ), + ), + const SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + const Text( + '3 Item', + style: regularTextStyle, + ), + const Expanded(child: SizedBox()), + RichText( + text: TextSpan( + text: 'Total Pesanan: ', + style: regularTextStyle, + children: [ + TextSpan( + text: 'Rp. 300.000', + style: regularTextStyle.copyWith( + color: redColor, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 15, + ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + // lorry icon + const Icon( + Icons.local_shipping_outlined, + color: mainColor, + ), + const SizedBox( + width: 5, + ), + Text( + 'Pesanan telah sampai', + style: regularTextStyle.copyWith( + color: mainColor, + ), + ), + + const Expanded(child: SizedBox()), + const Icon( + Icons.arrow_forward_ios, + color: mainGrey, + size: 15, + ), + ], + ), + ], + ), + ), + ), + ); + }, + ), + ), + ], + ), + // floatingActionButton: FloatingActionButton.extended( + // onPressed: () {}, + // label: Text( + // 'Pesan', + // style: boldTextStyle.copyWith(color: Colors.white), + // ), + // icon: const Icon( + // Icons.shopping_cart, + // color: Colors.white, + // ), + // backgroundColor: mainColor, + // ), ); }, ); diff --git a/lib/ui/views/user_ui/pesanan_list/pesanan_list_view_model.dart b/lib/ui/views/user_ui/pesanan_list/pesanan_list_view_model.dart index e60a9d3..5d9df0f 100644 --- a/lib/ui/views/user_ui/pesanan_list/pesanan_list_view_model.dart +++ b/lib/ui/views/user_ui/pesanan_list/pesanan_list_view_model.dart @@ -1,5 +1,7 @@ import 'package:reza_app/app/core/custom_base_view_model.dart'; class PesananListViewModel extends CustomBaseViewModel { - Future init() async {} + Future init() async { + easyLoading.backPressed = 2; + } } diff --git a/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view.dart b/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view.dart index 581aad5..80506c5 100644 --- a/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view.dart +++ b/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view.dart @@ -1,6 +1,11 @@ +import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:reza_app/app/themes/app_colors.dart'; import 'package:stacked/stacked.dart'; +import 'package:webview_flutter/webview_flutter.dart'; +import '../../meja_detail/meja_detail_view.dart'; import './reservasi_meja_view_model.dart'; class ReservasiMejaView extends StatelessWidget { @@ -18,11 +23,183 @@ class ReservasiMejaView extends StatelessWidget { ReservasiMejaViewModel model, Widget? child, ) { - return const Scaffold( - body: Center( - child: Text( - 'ReservasiMejaView', - ), + return Scaffold( + appBar: AppBar( + title: const Text('RESERVASI MEJA', + style: TextStyle(color: Colors.white)), + backgroundColor: mainColor, + automaticallyImplyLeading: false, + actions: [ + // create a shopping cart icon with a badge containing the number of items + Container( + margin: const EdgeInsets.only(right: 10), + child: Stack( + children: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.shopping_cart_outlined, + color: Colors.white), + ), + Positioned( + top: 5, + right: 5, + child: Container( + width: 20, + height: 20, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + child: const Center( + child: Text( + '9', + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + body: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 20, + ), + CarouselSlider.builder( + itemCount: model.imagePaths.length, + itemBuilder: (BuildContext context, int index, int realIndex) { + return SizedBox( + width: MediaQuery.of(context) + .size + .width, // Set the width to full width + child: Image.asset( + model.imagePaths[index], + fit: BoxFit.cover, + ), + ); + }, + options: CarouselOptions( + autoPlay: true, + aspectRatio: 2.0, + enlargeCenterPage: true, + ), + ), + Expanded( + child: WebView( + initialUrl: dotenv.env['table_url'], + // initialUrl: 'http://172.29.85.181/parkir/user', + // initialUrl: 'https://rekam-medis.airlangga-it.com/', + javascriptMode: JavascriptMode.unrestricted, + onWebViewCreated: (WebViewController webViewController) { + // _controller.complete(webViewController); + // model.controllerCompleter.future + // .then((value) => model.webViewController = value); + // model.controllerCompleter.complete(webViewController); + }, + onProgress: (int progress) { + model.log.i('WebView is loading (progress : $progress%)'); + }, + // javascriptChannels: { + // _toasterJavascriptChannel(context), + // }, + javascriptChannels: { + JavascriptChannel( + name: 'messageHandler', + onMessageReceived: (JavascriptMessage message) async { + // model.log.i('messageHandler : ${message.message}'); + model.easyLoading.backPressed = 1; + model.notifyListeners(); + model.log.i( + 'backPressed : ${model.easyLoading.backPressed}'); + String mejaId = message.message; + model.navigationService.navigateToView( + MejaDetailView( + mejaId: mejaId, + ), + ); + }, + ), + JavascriptChannel( + name: 'messageHandler1', + onMessageReceived: (JavascriptMessage message) async { + // String no_telpon = message.message; + // dev.i('no_telpon : $no_telpon'); + // await launchUrl(Uri.parse('tel:$no_telpon')); + }, + ), + }, + navigationDelegate: (NavigationRequest request) async { + // if (request.url.startsWith('https://www.youtube.com/')) { + // dev.log('blocking navigation to $request}'); + // return NavigationDecision.prevent; + // } + // check if request.url has 'nrm' + + return NavigationDecision.navigate; + }, + onPageStarted: (String url) { + model.log.i('Page started loading: $url'); + }, + onPageFinished: (String url) { + model.log.i('Page finished loading: $url'); + }, + gestureNavigationEnabled: true, + backgroundColor: const Color(0x00000000), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + // create 3 circle color + Container( + width: 20, + height: 20, + decoration: const BoxDecoration( + color: Color.fromRGBO(223, 216, 214, 1), + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 5), + const Text('Tersedia'), + const SizedBox(width: 10), + + Container( + width: 20, + height: 20, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 5), + const Text('Tidak Tersedia'), + + const SizedBox(width: 10), + Container( + width: 20, + height: 20, + decoration: const BoxDecoration( + color: Colors.blue, + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 5), + const Text('Dipesan'), + const SizedBox(width: 10), + ], + ), + ), + ], ), ); }, diff --git a/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view_model.dart b/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view_model.dart index b950afd..97161d9 100644 --- a/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view_model.dart +++ b/lib/ui/views/user_ui/reservasi_meja/reservasi_meja_view_model.dart @@ -1,5 +1,18 @@ -import 'package:reza_app/app/core/custom_base_view_model.dart'; +import 'dart:async'; + +import '../../../../app/app.logger.dart'; +import '../../../../app/core/custom_base_view_model.dart'; class ReservasiMejaViewModel extends CustomBaseViewModel { - Future init() async {} + final log = getLogger('ReservasiMejaViewModel'); + + List imagePaths = [ + 'assets/reza_gazebo.jpeg', + 'assets/reza_meja_1.jpeg', + 'assets/reza_meja_2.jpeg', + ]; + + Future init() async { + easyLoading.backPressed = 2; + } } diff --git a/lib/ui/views/user_ui/user_index_tracking/user_index_tracking_view_model.dart b/lib/ui/views/user_ui/user_index_tracking/user_index_tracking_view_model.dart index b004240..c31e14f 100644 --- a/lib/ui/views/user_ui/user_index_tracking/user_index_tracking_view_model.dart +++ b/lib/ui/views/user_ui/user_index_tracking/user_index_tracking_view_model.dart @@ -1,6 +1,7 @@ import 'package:back_button_interceptor/back_button_interceptor.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:reza_app/services/my_easyloading.dart'; import 'package:stacked/stacked.dart'; import 'package:stacked_services/stacked_services.dart'; @@ -12,18 +13,38 @@ import '../../../../app/themes/app_colors.dart'; class UserIndexTrackingViewModel extends IndexTrackingViewModel { final log = getLogger('UserIndexTrackingViewModel'); final navigationService = locator(); - bool backPressed = true; + final easyLoading = locator(); + // late bool backPressed; Future init() async { BackButtonInterceptor.add(myInterceptor); + // backPressed = easyLoading.backPressed; + easyLoading.backPressed = 2; } bool myInterceptor(bool stopDefaultButtonEvent, RouteInfo info) { // print("BACK BUTTON!"); // Do some stuff. - if (backPressed) { + log.i('myInterceptor : ${easyLoading.backPressed}'); + + if (easyLoading.backPressed == 2) { quitApp(null); } + if (easyLoading.backPressed == 3) { + // easyLoading.backPressed = 2; + // notifyListeners(); + // navigationService.back(); + easyLoading.backPressed = 2; + return false; + } + + if (easyLoading.backPressed == 1) { + // easyLoading.backPressed = 2; + // notifyListeners(); + // navigationService.back(); + return false; + } + return true; } @@ -75,7 +96,7 @@ class UserIndexTrackingViewModel extends IndexTrackingViewModel { } quitApp(BuildContext? context) { - backPressed = false; + easyLoading.backPressed = 0; showDialog( context: context ?? StackedService.navigatorKey!.currentContext!, builder: (BuildContext context) { @@ -85,7 +106,7 @@ class UserIndexTrackingViewModel extends IndexTrackingViewModel { actions: [ TextButton( onPressed: () { - backPressed = true; + easyLoading.backPressed = 2; Navigator.of(context).pop(false); }, child: const Text('Batal'), diff --git a/pubspec.lock b/pubspec.lock index 97f6e66..8c756b3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.6.1" + carousel_slider: + dependency: "direct main" + description: + name: carousel_slider + sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42" + url: "https://pub.dev" + source: hosted + version: "4.2.1" characters: dependency: transitive description: @@ -949,6 +957,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + sha256: "392c1d83b70fe2495de3ea2c84531268d5b8de2de3f01086a53334d8b6030a88" + url: "https://pub.dev" + source: hosted + version: "3.0.4" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "8b3b2450e98876c70bfcead876d9390573b34b9418c19e28168b74f6cb252dbd" + url: "https://pub.dev" + source: hosted + version: "2.10.4" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "812165e4e34ca677bdfbfa58c01e33b27fd03ab5fa75b70832d4b7d4ca1fa8cf" + url: "https://pub.dev" + source: hosted + version: "1.9.5" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: a5364369c758892aa487cbf59ea41d9edd10f9d9baf06a94e80f1bd1b4c7bbc0 + url: "https://pub.dev" + source: hosted + version: "2.9.5" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d62ddd3..e326879 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -53,6 +53,8 @@ dependencies: otp_text_field: ^1.1.3 back_button_interceptor: ^6.0.2 flutter_hooks: ^0.19.0 + webview_flutter: ^3.0.4 + carousel_slider: ^4.2.1 dev_dependencies: flutter_test: @@ -83,6 +85,9 @@ flutter: assets: - .env - assets/logo.png + - assets/reza_gazebo.jpeg + - assets/reza_meja_1.jpeg + - assets/reza_meja_2.jpeg # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see