added shoping and pesanan page

This commit is contained in:
kicap
2023-08-09 17:07:54 +08:00
parent 4350e3503e
commit 696c52efeb
34 changed files with 1564 additions and 288 deletions

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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();

View File

@ -36,7 +36,7 @@ class VerifikasiNoHpView extends StatelessWidget {
),
body: WillPopScope(
onWillPop: () async {
if (model.backPressed) {
if (model.easyLoading.backPressed == 1) {
model.back();
}
return false;

View File

@ -9,11 +9,11 @@ class VerifikasiNoHpViewModel extends CustomBaseViewModel {
Future<void> 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",

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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<MejaDetailViewModel>.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,
);
},
);
}
}

View File

@ -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<void> 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');
}
}

View File

@ -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,
),
],
),
],
),
),
);

View File

@ -1,5 +1,7 @@
import 'package:reza_app/app/core/custom_base_view_model.dart';
class AkunUserViewModel extends CustomBaseViewModel {
Future<void> init() async {}
Future<void> init() async {
easyLoading.backPressed = 2;
}
}

View File

@ -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,
),
),
),
),
),
],
),
));
},
);
}

View File

@ -4,5 +4,7 @@ import '../../../../../app/core/custom_base_view_model.dart';
class DetailMakananViewModel extends CustomBaseViewModel {
final log = getLogger('DetailMakananViewModel');
Future<void> init() async {}
Future<void> init() async {
easyLoading.backPressed = 3;
}
}

View File

@ -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,
),
),
),
),
),
],
),
),
],
),
);
));
},
);
}

View File

@ -4,7 +4,9 @@ import '../../../../app/core/custom_base_view_model.dart';
class MakananListViewModel extends CustomBaseViewModel {
final log = getLogger('MakananListViewModel');
Future<void> init() async {}
Future<void> init() async {
easyLoading.backPressed = 2;
}
goToDetailMakanan() {
log.i('goToDetailMakanan');

View File

@ -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<KeranjangSayaViewModel>.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,
),
));
},
);
}
}

View File

@ -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<void> init() async {
easyLoading.backPressed = 3;
}
}

View File

@ -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,
// ),
);
},
);

View File

@ -1,5 +1,7 @@
import 'package:reza_app/app/core/custom_base_view_model.dart';
class PesananListViewModel extends CustomBaseViewModel {
Future<void> init() async {}
Future<void> init() async {
easyLoading.backPressed = 2;
}
}

View File

@ -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: <JavascriptChannel>{
// _toasterJavascriptChannel(context),
// },
javascriptChannels: <JavascriptChannel>{
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),
],
),
),
],
),
);
},

View File

@ -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<void> init() async {}
final log = getLogger('ReservasiMejaViewModel');
List<String> imagePaths = [
'assets/reza_gazebo.jpeg',
'assets/reza_meja_1.jpeg',
'assets/reza_meja_2.jpeg',
];
Future<void> init() async {
easyLoading.backPressed = 2;
}
}

View File

@ -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<NavigationService>();
bool backPressed = true;
final easyLoading = locator<MyEasyLoading>();
// late bool backPressed;
Future<void> 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'),