modify reservation table page, add socket io client for real time data update, modify makanan list page

This commit is contained in:
kicap
2023-08-25 04:21:55 +08:00
parent 6c5bfde828
commit d96a14e062
30 changed files with 726 additions and 165 deletions

View File

@ -62,8 +62,8 @@ class AkunUserView extends StatelessWidget {
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',
child: Image.asset(
'assets/nasi_goreng.jpg',
height: 150,
width: 150,
fit: BoxFit.fill,

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:reza_app/model/makanan_model.dart';
import 'package:stacked/stacked.dart';
import '../../../../../app/themes/app_colors.dart';
@ -8,8 +10,12 @@ import '../../../../widgets/my_white_container.dart';
import './detail_makanan_view_model.dart';
class DetailMakananView extends HookWidget {
const DetailMakananView({Key? key}) : super(key: key);
final MakananModel makananModel;
const DetailMakananView({
Key? key,
required this.makananModel,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final scrollController = useScrollController();
@ -21,7 +27,7 @@ class DetailMakananView extends HookWidget {
return ViewModelBuilder<DetailMakananViewModel>.reactive(
viewModelBuilder: () => DetailMakananViewModel(),
onViewModelReady: (DetailMakananViewModel model) async {
await model.init();
await model.init(makananModel);
},
builder: (
BuildContext context,
@ -127,7 +133,9 @@ class DetailMakananView extends HookWidget {
),
// 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.",
model.isBusy
? 'Loading...'
: model.makananModel!.deskripsiMakanan!,
style: regularTextStyle.copyWith(
fontSize: 13,
color: fontGrey,
@ -184,7 +192,9 @@ class DetailMakananView extends HookWidget {
height: 5,
),
Text(
"Rp. 35.000",
model.isBusy
? 'Loading...'
: 'Rp. ${int.parse(makananModel.hargaMakanan!) + 10000}',
style: boldTextStyle.copyWith(
fontSize: 16,
color: dangerColor,
@ -342,7 +352,9 @@ class SecondWidget extends ViewModelWidget<DetailMakananViewModel> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Burger King Handcrafted Burgers ",
viewModel.isBusy
? 'Loading...'
: viewModel.makananModel!.namaMakanan!,
style: regularTextStyle.copyWith(
fontSize: 17,
),
@ -351,7 +363,9 @@ class SecondWidget extends ViewModelWidget<DetailMakananViewModel> {
height: 10,
),
Text(
"Rp. 25.000",
viewModel.isBusy
? 'Loading...'
: 'Rp .${viewModel.makananModel!.hargaMakanan!}',
style: regularTextStyle.copyWith(
fontSize: 18,
color: dangerColor,
@ -405,37 +419,38 @@ class TopMenuWidget extends ViewModelWidget<DetailMakananViewModel> {
return Stack(
children: [
SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.35,
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',
fit: BoxFit.cover,
),
),
Positioned(
bottom: 10,
right: 10,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 5,
),
// width: 20,
height: 20,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const Center(
child: Text(
'1 / 2',
style: TextStyle(
color: fontGrey,
fontSize: 12,
),
),
),
),
),
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.35,
child: viewModel.isBusy
? const Center(child: CircularProgressIndicator())
: Image.network(
'${dotenv.env['url']}assets/makanan/${viewModel.makananModel!.imgUrl}',
fit: BoxFit.cover,
)),
// Positioned(
// bottom: 10,
// right: 10,
// child: Container(
// padding: const EdgeInsets.symmetric(
// horizontal: 5,
// ),
// // width: 20,
// height: 20,
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(10),
// ),
// child: const Center(
// child: Text(
// '1 / 2',
// style: TextStyle(
// color: fontGrey,
// fontSize: 12,
// ),
// ),
// ),
// ),
// ),
],
);
}

View File

@ -1,10 +1,16 @@
import 'package:reza_app/model/makanan_model.dart';
import '../../../../../app/app.logger.dart';
import '../../../../../app/core/custom_base_view_model.dart';
class DetailMakananViewModel extends CustomBaseViewModel {
final log = getLogger('DetailMakananViewModel');
MakananModel? makananModel;
Future<void> init() async {
Future<void> init(MakananModel makananModel) async {
setBusy(true);
globalVar.backPressed = 'backNormal';
this.makananModel = makananModel;
setBusy(false);
}
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:reza_app/ui/widgets/my_textformfield.dart';
import 'package:reza_app/ui/widgets/my_white_container.dart';
import 'package:stacked/stacked.dart';
@ -147,66 +148,95 @@ class MakananListView extends StatelessWidget {
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,
child: model.isBusy
? const Center(
child: CircularProgressIndicator(),
)
: (model.listMakanan.isEmpty
? const Center(
child: Text('Data Kosong'),
)
: SingleChildScrollView(
child: Wrap(
spacing: 5,
runSpacing: 10,
// alignment: WrapAlignment.spaceAround,
// crossAxisAlignment: WrapCrossAlignment.center,
children: [
for (var i = 0;
i < model.listMakanan.length;
i++)
GestureDetector(
onTap: () => model.goToDetailMakanan(
model.listMakanan[i]),
child: Padding(
padding: const EdgeInsets.only(
left: 10,
// right: 5,
),
child: Container(
width: MediaQuery.of(context)
.size
.width *
0.46,
color: Colors.white,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Image.network(
'${dotenv.env['url']}assets/makanan/${model.listMakanan[i].imgUrl}',
height: 150,
width: double.infinity,
fit: BoxFit.fill,
),
// Image.asset(
// 'assets/nasi_goreng.jpg',
// height: 150,
// width: double.infinity,
// fit: BoxFit.fill,
// ),
const SizedBox(
height: 5,
),
Padding(
padding: const EdgeInsets.only(
left: 5,
),
child: Text(
model.listMakanan[i]
.namaMakanan!,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(
height: 5,
),
Padding(
padding: const EdgeInsets.only(
left: 5,
),
child: Text(
model.listMakanan[i]
.deskripsiMakanan!,
style: const TextStyle(
color: Colors.grey,
),
),
),
const SizedBox(
height: 5,
),
],
),
),
),
),
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,
),
],
),
],
),
),
],
),
),
),
)),
),
],
),

View File

@ -1,15 +1,50 @@
import '../../../../app/app.locator.dart';
import '../../../../app/app.logger.dart';
import '../../../../app/app.router.dart';
import '../../../../app/core/custom_base_view_model.dart';
import '../../../../model/makanan_model.dart';
import '../../../../model/my_model.dart';
import '../../../../services/my_socket_io_client.dart';
class MakananListViewModel extends CustomBaseViewModel {
final log = getLogger('MakananListViewModel');
final socketIoClient = locator<MySocketIoClient>();
List<MakananModel> listMakanan = [];
Future<void> init() async {
globalVar.backPressed = 'exitApp';
getData();
socketIoClient.on('makanan_user', (data) {
log.i('data : $data');
listMakanan.clear();
getData();
// webViewController!.reload();
});
}
goToDetailMakanan() {
getData() async {
setBusy(true);
easyLoading.showLoading();
try {
var res = await httpService.get('table/makanan');
MyModel myModel = MyModel.fromJson(res.data);
if (myModel.data.length > 0) {
for (var item in myModel.data) {
listMakanan.add(MakananModel.fromJson(item));
}
}
log.i(listMakanan);
} catch (e) {
log.e(e.toString());
} finally {
easyLoading.dismissLoading();
setBusy(false);
}
}
goToDetailMakanan(MakananModel makananModel) {
log.i('goToDetailMakanan');
navigationService.navigateTo(Routes.detailMakananView);
navigationService.navigateTo(Routes.detailMakananView,
arguments: DetailMakananViewArguments(makananModel: makananModel));
}
}

View File

@ -72,8 +72,8 @@ class KeranjangSayaView extends StatelessWidget {
),
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',
child: Image.asset(
'assets/nasi_goreng.jpg',
height: 150,
width: double.infinity,
fit: BoxFit.fill,

View File

@ -157,8 +157,8 @@ class PesananListView extends StatelessWidget {
),
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',
child: Image.asset(
'assets/nasi_goreng.jpg',
height: 100,
width: double.infinity,
fit: BoxFit.fill,

View File

@ -104,16 +104,14 @@ class ReservasiMejaView extends StatelessWidget {
),
),
Expanded(
// child: SizedBox(),
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);
model.webViewController = webViewController;
},
onProgress: (int progress) {
// model.log.i('WebView is loading (progress : $progress%)');
@ -196,19 +194,19 @@ class ReservasiMejaView extends StatelessWidget {
),
),
const SizedBox(width: 5),
const Text('Tidak Tersedia'),
const Text('Dibooking'),
const SizedBox(width: 10),
Container(
width: 20,
height: 20,
decoration: const BoxDecoration(
color: Colors.blue,
color: Colors.grey,
shape: BoxShape.circle,
),
),
const SizedBox(width: 5),
const Text('Dipesan'),
const Text('Tidak Tersedia'),
const SizedBox(width: 10),
],
),

View File

@ -1,10 +1,16 @@
import 'dart:async';
import 'package:webview_flutter/webview_flutter.dart';
import '../../../../app/app.locator.dart';
import '../../../../app/app.logger.dart';
import '../../../../app/core/custom_base_view_model.dart';
import '../../../../services/my_socket_io_client.dart';
class ReservasiMejaViewModel extends CustomBaseViewModel {
final log = getLogger('ReservasiMejaViewModel');
WebViewController? webViewController;
final socketIoClient = locator<MySocketIoClient>();
List<String> imagePaths = [
'assets/reza_gazebo.jpeg',
@ -14,5 +20,10 @@ class ReservasiMejaViewModel extends CustomBaseViewModel {
Future<void> init() async {
globalVar.backPressed = 'exitApp';
socketIoClient.on('table_admin', (data) {
log.i('data : $data');
// getData();
webViewController!.reload();
});
}
}