diff --git a/.env b/.env index fad3a8f..1e1f0fb 100644 --- a/.env +++ b/.env @@ -2,6 +2,12 @@ # 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: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 +# 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' +# url = 'http://192.168.20.232:3001/' +# table_url = 'http://192.168.20.232:3001/table' +# api_url = 'http://192.168.20.232:3001/table' +url = 'https://reza_backend.kicap-karan.com/' +table_url = 'https://reza_backend.kicap-karan.com/table' +api_url = 'https://reza_backend.kicap-karan.com/table' \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8c6fbc8..48cc004 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,10 +1,12 @@ + + (); + + final Map builders = { + DialogType.mejaEditStatusDialogView: (context, request, completer) => + MejaEditStatusDialogView(request: request, completer: completer), + DialogType.addEditMakananTextFormDialogView: + (context, request, completer) => AddEditMakananTextFormDialogView( + request: request, completer: completer), + }; + + dialogService.registerCustomDialogBuilders(builders); +} diff --git a/lib/app/app.locator.dart b/lib/app/app.locator.dart index 97e55c5..f575214 100644 --- a/lib/app/app.locator.dart +++ b/lib/app/app.locator.dart @@ -15,6 +15,7 @@ import 'package:stacked_shared/stacked_shared.dart'; import '../services/global_var.dart'; import '../services/http_services.dart'; import '../services/my_easyloading.dart'; +import '../services/my_socket_io_client.dart'; import '../services/other_function.dart'; final locator = StackedLocator.instance; @@ -36,4 +37,5 @@ Future setupLocator({ locator.registerLazySingleton(() => MyHttpServices()); locator.registerLazySingleton(() => OtherFunction()); locator.registerLazySingleton(() => GlobalVar()); + locator.registerLazySingleton(() => MySocketIoClient()); } diff --git a/lib/main.dart b/lib/main.dart index f85b32f..3a280a2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,14 +1,18 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:stacked_services/stacked_services.dart'; +import 'app/app.dialogs.dart'; import 'app/app.locator.dart'; import 'app/app.router.dart'; import 'app/themes/app_theme.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); + HttpOverrides.global = MyHttpOverrides(); await dotenv.load(fileName: ".env"); await setupAllLocator(); runApp(const MyApp()); @@ -33,7 +37,16 @@ class MyApp extends StatelessWidget { Future setupAllLocator() async { await setupLocator(); - // setupDialogUi(); + setupDialogUi(); // setupBottomsheetUi(); // setupSnackbarUi(); } + +class MyHttpOverrides extends HttpOverrides { + @override + HttpClient createHttpClient(SecurityContext? context) { + return super.createHttpClient(context) + ..badCertificateCallback = + (X509Certificate cert, String host, int port) => true; + } +} diff --git a/lib/model/makanan_model.dart b/lib/model/makanan_model.dart new file mode 100644 index 0000000..7aa740d --- /dev/null +++ b/lib/model/makanan_model.dart @@ -0,0 +1,32 @@ +class MakananModel { + int? idMakanan; + String? namaMakanan; + String? hargaMakanan; + String? deskripsiMakanan; + String? imgUrl; + + MakananModel( + {this.idMakanan, + this.namaMakanan, + this.hargaMakanan, + this.deskripsiMakanan, + this.imgUrl}); + + MakananModel.fromJson(Map json) { + idMakanan = json['id_makanan']; + namaMakanan = json['nama_makanan']; + hargaMakanan = json['harga_makanan']; + deskripsiMakanan = json['deskripsi_makanan']; + imgUrl = json['img_url']; + } + + Map toJson() { + final Map data = {}; + data['id_makanan'] = idMakanan; + data['nama_makanan'] = namaMakanan; + data['harga_makanan'] = hargaMakanan; + data['deskripsi_makanan'] = deskripsiMakanan; + data['img_url'] = imgUrl; + return data; + } +} diff --git a/lib/model/my_model.dart b/lib/model/my_model.dart new file mode 100644 index 0000000..f3a924b --- /dev/null +++ b/lib/model/my_model.dart @@ -0,0 +1,21 @@ +class MyModel { + String? message; + bool? theBool; + dynamic data; + + MyModel({this.message, this.theBool, this.data}); + + MyModel.fromJson(Map json) { + message = json['message']; + theBool = json['bool']; + data = json['data']; + } + + Map toJson() { + final Map data = {}; + data['message'] = message; + data['bool'] = theBool; + data['data'] = this.data; + return data; + } +} diff --git a/lib/model/reservasi_meja_model.dart b/lib/model/reservasi_meja_model.dart new file mode 100644 index 0000000..1ee93ba --- /dev/null +++ b/lib/model/reservasi_meja_model.dart @@ -0,0 +1,36 @@ +class ReservasiMejaModel { + int? idMeja; + int? idUser; + String? status; + String? jamBooking; + String? createdAt; + String? updatedAt; + + ReservasiMejaModel( + {this.idMeja, + this.idUser, + this.status, + this.jamBooking, + this.createdAt, + this.updatedAt}); + + ReservasiMejaModel.fromJson(Map json) { + idMeja = json['id_meja']; + idUser = json['id_user']; + status = json['status']; + jamBooking = json['jam_booking']; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + } + + Map toJson() { + final Map data = {}; + data['id_meja'] = idMeja; + data['id_user'] = idUser; + data['status'] = status; + data['jam_booking'] = jamBooking; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + return data; + } +} diff --git a/lib/model/user_model.dart b/lib/model/user_model.dart new file mode 100644 index 0000000..bc80d32 --- /dev/null +++ b/lib/model/user_model.dart @@ -0,0 +1,44 @@ +class UserModel { + int? idUser; + String? nama; + String? noTelpon; + String? tanggalLahir; + String? jenisKelamin; + String? alamat; + String? createdAt; + String? updatedAt; + + UserModel( + {this.idUser, + this.nama, + this.noTelpon, + this.tanggalLahir, + this.jenisKelamin, + this.alamat, + this.createdAt, + this.updatedAt}); + + UserModel.fromJson(Map json) { + idUser = json['id_user']; + nama = json['nama']; + noTelpon = json['no_telpon']; + tanggalLahir = json['tanggal_lahir']; + jenisKelamin = json['jenis_kelamin']; + alamat = json['alamat']; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + } + + Map toJson() { + final Map data = {}; + data['id_user'] = idUser; + data['nama'] = nama; + data['no_telpon'] = noTelpon; + data['tanggal_lahir'] = tanggalLahir; + data['jenis_kelamin'] = jenisKelamin; + data['alamat'] = alamat; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + return data; + } +} diff --git a/lib/services/http_services.dart b/lib/services/http_services.dart index f2e4da5..67f909e 100644 --- a/lib/services/http_services.dart +++ b/lib/services/http_services.dart @@ -6,7 +6,7 @@ import '../app/app.logger.dart'; class MyHttpServices { final log = getLogger('MyHttpServices'); final _options = BaseOptions( - baseUrl: dotenv.env['api_url']!, + baseUrl: dotenv.env['url']!, connectTimeout: const Duration(seconds: 120), receiveTimeout: const Duration(seconds: 120), ); @@ -20,14 +20,22 @@ class MyHttpServices { Future get(String path) async { try { return await _dio.get(path); - } on DioException { + } on DioException catch (e) { + log.e('error : $e'); rethrow; } } Future postWithFormData(String path, FormData formData) async { try { - return await _dio.post(path, data: formData); + return await _dio.post( + path, + data: formData, + // method="POST" enctype="multipart/form-data"> + options: Options( + contentType: 'multipart/form-data', + ), + ); } on DioException { rethrow; } diff --git a/lib/services/my_easyloading.dart b/lib/services/my_easyloading.dart index 46cb062..98198c9 100644 --- a/lib/services/my_easyloading.dart +++ b/lib/services/my_easyloading.dart @@ -9,7 +9,7 @@ class MyEasyLoading { ); } - dismissLoading() { + dismiss() { EasyLoading.dismiss(); } diff --git a/lib/services/my_socket_io_client.dart b/lib/services/my_socket_io_client.dart new file mode 100644 index 0000000..8689244 --- /dev/null +++ b/lib/services/my_socket_io_client.dart @@ -0,0 +1,48 @@ +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:socket_io_client/socket_io_client.dart'; + +import '../app/app.logger.dart'; + +class MySocketIoClient { + final log = getLogger('MySocketIoClient'); + final String _url = dotenv.env['url']!; + static final MySocketIoClient _instance = MySocketIoClient._internal(); + factory MySocketIoClient() => _instance; + MySocketIoClient._internal(); + + late Socket _socket; + Socket get socket => _socket; + + Future init() async { + try { + _socket = io(_url, { + 'transports': ['websocket'], + 'autoConnect': false, + }); + _socket.connect(); + log.i('socket connected'); + } catch (e) { + log.e('error : $e'); + } + } + + Future emit(String event, dynamic data) async { + _socket.emit(event, data); + } + + Future on(String event, Function(dynamic) callback) async { + _socket.on(event, callback); + } + + Future off(String event) async { + _socket.off(event); + } + + Future disconnect() async { + _socket.disconnect(); + } + + Future connect() async { + _socket.connect(); + } +} diff --git a/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_text_form_dialog/add_edit_makanan_text_form_dialog_view.dart b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_text_form_dialog/add_edit_makanan_text_form_dialog_view.dart new file mode 100644 index 0000000..41c6707 --- /dev/null +++ b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_text_form_dialog/add_edit_makanan_text_form_dialog_view.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:reza_admin/app/themes/app_text.dart'; +import 'package:reza_admin/ui/widgets/my_textformfield.dart'; +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; + +import './add_edit_makanan_text_form_dialog_view_model.dart'; + +class AddEditMakananTextFormDialogView extends StatelessWidget { + final DialogRequest? request; + final Function(DialogResponse)? completer; + + const AddEditMakananTextFormDialogView({ + Key? key, + this.request, + this.completer, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + viewModelBuilder: () => AddEditMakananTextFormDialogViewModel(), + onViewModelReady: (AddEditMakananTextFormDialogViewModel model) async { + await model.init(request!.data); + }, + builder: ( + BuildContext context, + AddEditMakananTextFormDialogViewModel model, + Widget? child, + ) { + return Dialog( + child: Container( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + model.title, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 20), + MyTextFormField( + hintText: model.description, + maxLines: model.maxLines, + controller: model.textEditingController, + keyboardType: model.keyboardType + ? TextInputType.number + : TextInputType.text, + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + completer!(DialogResponse(confirmed: false)); + }, + child: Text( + 'Cancel', + style: boldTextStyle.copyWith(color: Colors.red), + ), + ), + TextButton( + onPressed: () { + if (model.textEditingController.text.isNotEmpty) { + completer!(DialogResponse( + confirmed: true, + data: model.textEditingController.text, + )); + } else { + model.snackbarService.showSnackbar( + message: 'Please fill the form', + title: 'Error', + ); + } + + // completer!(DialogResponse( + // confirmed: true, + // responseData: model.status, + // )); + }, + child: const Text('Save'), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_text_form_dialog/add_edit_makanan_text_form_dialog_view_model.dart b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_text_form_dialog/add_edit_makanan_text_form_dialog_view_model.dart new file mode 100644 index 0000000..5d26d1c --- /dev/null +++ b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_text_form_dialog/add_edit_makanan_text_form_dialog_view_model.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../app/app.logger.dart'; +import '../../../../../../app/core/custom_base_view_model.dart'; + +class AddEditMakananTextFormDialogViewModel extends CustomBaseViewModel { + final log = getLogger('AddEditMakananTextFormDialogViewModel'); + late String title; + late String description; + late int maxLines; + late bool keyboardType; + + TextEditingController textEditingController = TextEditingController(); + + Future init(data) async { + log.i(data); + + title = data['title']; + description = data['description']; + maxLines = data['maxLines']; + keyboardType = data['keyboardType']; + } +} diff --git a/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view.dart b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view.dart index 3715ba6..000dfd7 100644 --- a/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view.dart +++ b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view.dart @@ -35,159 +35,187 @@ class AddEditMakananView extends HookWidget { return true; }, child: 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( - 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: [ - Row( - children: [ - Expanded( - child: RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Ongkos Kirim', - style: boldTextStyle.copyWith( - fontSize: 14, - ), + 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: [ + Row( + children: [ + Expanded( + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Ongkos Kirim', + style: boldTextStyle.copyWith( + fontSize: 14, ), - TextSpan( - text: ' Harga Ongkir Di Sini', - style: boldTextStyle.copyWith( - fontSize: 14, - color: dangerColor, - fontStyle: FontStyle.italic, - ), + ), + TextSpan( + text: ' Rp. 10.000', + style: boldTextStyle.copyWith( + fontSize: 14, + color: dangerColor, + fontStyle: FontStyle.italic, ), - ], - ), + ), + ], ), ), - const SizedBox( - width: 10, - ), - IconButton( - onPressed: () {}, - icon: const Icon( - Icons.edit, - color: dangerColor, - ), - iconSize: 20, - ), - const SizedBox( - width: 10, - ), - ], - ), - const SizedBox( - height: 10, - ), - Text( - "Bisa Dibayar COD sekitar Parepare", - style: regularTextStyle.copyWith( - fontSize: 13, - color: fontGrey, ), + const SizedBox( + width: 10, + ), + // IconButton( + // onPressed: () async { + // String? data = + // await model.addEditDialog( + // title: 'Ongkos Kirim', + // description: 'Harga Ongkir Di Sini', + // keyboardType: true, + // maxLines: 1, + // ); + + // // model.log.i('data: $data'); + // model.hargaOngkir = data; + // model.notifyListeners(); + // }, + // icon: const Icon( + // Icons.edit, + // color: dangerColor, + // ), + // iconSize: 20, + // ), + const SizedBox( + width: 10, + ), + ], + ), + 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: [ - Row( - children: [ - Expanded( - child: Text( - "Deskripsi", - style: boldTextStyle.copyWith( - fontSize: 15, - ), + ), + 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: [ + Row( + children: [ + Expanded( + child: Text( + "Deskripsi", + style: boldTextStyle.copyWith( + fontSize: 15, ), ), - const SizedBox( - width: 10, - ), - IconButton( - onPressed: () {}, - icon: const Icon( - Icons.edit, - color: mainGrey, - ), - iconSize: 20, - ), - const SizedBox( - width: 10, - ), - ], - ), - const SizedBox( - height: 10, - ), - // bikin dummy text tentang nasi goreng - Text( - "Deskripsi Makanan Di Sini", - style: regularTextStyle.copyWith( - fontSize: 13, - color: fontGrey, - fontStyle: FontStyle.italic, ), - textAlign: TextAlign.justify, + const SizedBox( + width: 10, + ), + IconButton( + onPressed: () async { + String? data = + await model.addEditDialog( + title: 'Deskripsi', + description: + 'Deskripsi Makanan Di Sini', + maxLines: 5); + + // model.log.i('data: $data'); + model.deskripsi = data; + model.notifyListeners(); + }, + icon: const Icon( + Icons.edit, + color: mainGrey, + ), + iconSize: 20, + ), + const SizedBox( + width: 10, + ), + ], + ), + const SizedBox( + height: 10, + ), + // bikin dummy text tentang nasi goreng + Text( + model.deskripsi ?? + "Deskripsi Makanan Di Sini", + style: regularTextStyle.copyWith( + fontSize: 13, + color: fontGrey, + fontStyle: FontStyle.italic, ), - ], - ), + textAlign: TextAlign.justify, + ), + ], ), ), - const SizedBox( - height: 20, - ), - ], - ); - }, - ), - TopBarWidget(opacity: opacity), - ], - ), + ), + const SizedBox( + height: 20, + ), + ], + ); + }, + ), + TopBarWidget(opacity: opacity), + ], ), - bottomNavigationBar: Container( + ), + bottomNavigationBar: GestureDetector( + onTap: () { + model.tambahEditMakanan(); + }, + child: Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 10, @@ -220,7 +248,9 @@ class AddEditMakananView extends HookWidget { ), ), ), - )), + ), + ), + ), ); }, ); @@ -351,7 +381,7 @@ class SecondWidget extends ViewModelWidget { children: [ Expanded( child: Text( - "Nama Makanan Di Sini", + viewModel.namaMakanan ?? 'Nama Makanan Di Sini', style: regularTextStyle.copyWith( fontSize: 17, fontStyle: FontStyle.italic, @@ -362,7 +392,16 @@ class SecondWidget extends ViewModelWidget { width: 10, ), IconButton( - onPressed: () {}, + onPressed: () async { + String? data = await viewModel.addEditDialog( + title: 'Nama Makanan', + description: 'Nama Makanan Di Sini', + ); + + // viewModel.log.i('data: $data'); + viewModel.namaMakanan = data; + viewModel.notifyListeners(); + }, icon: const Icon( Icons.edit, color: mainGrey, @@ -392,7 +431,18 @@ class SecondWidget extends ViewModelWidget { width: 10, ), IconButton( - onPressed: () {}, + onPressed: () async { + String? data = await viewModel.addEditDialog( + title: 'Harga Makanan', + description: 'Harga Makanan Di Sini', + keyboardType: true, + maxLines: 1, + ); + + // viewModel.log.i('data: $data'); + viewModel.hargaMakanan = data; + viewModel.notifyListeners(); + }, icon: const Icon( Icons.edit, color: dangerColor, @@ -432,14 +482,19 @@ class TopMenuWidget extends ViewModelWidget { // '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, // ), - child: Center( - child: Text( - 'Add Image', - style: boldTextStyle.copyWith( - fontSize: 20, - ), - ), - ), + child: viewModel.imageBytes != null + ? Image.memory( + viewModel.imageBytes!, + fit: BoxFit.cover, + ) + : Center( + child: Text( + 'Add Image', + style: boldTextStyle.copyWith( + fontSize: 20, + ), + ), + ), ), // Positioned( // bottom: 10, @@ -468,21 +523,24 @@ class TopMenuWidget extends ViewModelWidget { Positioned( bottom: 20, right: 20, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 5, - ), - width: 50, - height: 50, - decoration: BoxDecoration( - color: mainColor, - borderRadius: BorderRadius.circular(10), - ), - child: const Center( - child: Icon( - Icons.camera_alt_outlined, - color: Colors.white, - size: 30, + child: GestureDetector( + onTap: () => viewModel.addImage(), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 5, + ), + width: 50, + height: 50, + decoration: BoxDecoration( + color: mainColor, + borderRadius: BorderRadius.circular(10), + ), + child: const Center( + child: Icon( + Icons.camera_alt_outlined, + color: Colors.white, + size: 30, + ), ), ), ), diff --git a/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view_model.dart b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view_model.dart index eb79feb..791394b 100644 --- a/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view_model.dart +++ b/lib/ui/views/admin_ui/makanan_list/add_edit_makanan/add_edit_makanan_view_model.dart @@ -1,9 +1,105 @@ +import 'dart:typed_data'; + +import 'package:dio/dio.dart'; +import 'package:image_picker/image_picker.dart'; +import '../../../../../app/app.dialogs.dart'; import '../../../../../app/app.logger.dart'; import '../../../../../app/core/custom_base_view_model.dart'; class AddEditMakananViewModel extends CustomBaseViewModel { final log = getLogger('AddMakananViewModel'); + + String? namaMakanan; + String? hargaMakanan; + // String? hargaOngkir; + String? deskripsi; + + String? _imagePath; + final ImagePicker _picker = ImagePicker(); + XFile? imageFile; + Uint8List? imageBytes; + Future init() async { globalVar.backPressed = 'backNormal'; } + + void addImage() async { + try { + final XFile? image = await _picker.pickImage(source: ImageSource.gallery); + if (image != null) { + imageFile = image; + _imagePath = image.path; + imageBytes = await image.readAsBytes(); + + log.i('image path: $_imagePath'); + notifyListeners(); + } + } catch (e) { + log.e(e); + } + } + + Future addEditDialog( + {required String title, + required String description, + int maxLines = 2, + bool keyboardType = false}) async { + var res = await dialogService.showCustomDialog( + variant: DialogType.addEditMakananTextFormDialogView, + data: { + 'title': title, + 'description': description, + 'maxLines': maxLines, + 'keyboardType': keyboardType, + }, + ); + + if (res!.confirmed) { + return res.data; + } else { + return null; + } + } + + tambahEditMakanan() async { + if (namaMakanan == null || + hargaMakanan == null || + // hargaOngkir == null || + deskripsi == null || + imageFile == null) { + await dialogService.showDialog( + title: 'Error', + description: 'Semua field harus diisi', + ); + } else { + easyLoading.customLoading('Tambah Makanan'); + setBusy(true); + try { + var formData = FormData.fromMap({ + 'nama_makanan': namaMakanan, + 'harga_makanan': hargaMakanan, + // 'harga_ongkir': hargaOngkir, + 'deskripsi_makanan': deskripsi, + 'image': await MultipartFile.fromFile(_imagePath!), + }); + + var res = await httpService.postWithFormData('table/makanan', formData); + log.i(res.data); + setBusy(false); + easyLoading.dismiss(); + dialogService.showDialog( + title: 'Berhasil', + description: 'Makanan berhasil ditambahkan', + ); + globalVar.backPressed = 'exitApp'; + navigationService.back(); + navigationService.back(); + } catch (e) { + log.e(e); + } finally { + setBusy(false); + easyLoading.dismiss(); + } + } + } } diff --git a/lib/ui/views/admin_ui/makanan_list/detail_makanan/detail_makanan_view.dart b/lib/ui/views/admin_ui/makanan_list/detail_makanan/detail_makanan_view.dart index 8b9d059..7211b08 100644 --- a/lib/ui/views/admin_ui/makanan_list/detail_makanan/detail_makanan_view.dart +++ b/lib/ui/views/admin_ui/makanan_list/detail_makanan/detail_makanan_view.dart @@ -371,8 +371,8 @@ class TopMenuWidget extends ViewModelWidget { 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', + child: Image.asset( + 'assets/nasi_goreng.jpg', fit: BoxFit.cover, ), ), diff --git a/lib/ui/views/admin_ui/makanan_list/makanan_list_view.dart b/lib/ui/views/admin_ui/makanan_list/makanan_list_view.dart index 4fcb2c1..c259947 100644 --- a/lib/ui/views/admin_ui/makanan_list/makanan_list_view.dart +++ b/lib/ui/views/admin_ui/makanan_list/makanan_list_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:reza_admin/app/app.router.dart'; import 'package:stacked/stacked.dart'; @@ -141,66 +142,94 @@ 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(), + 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, - ), - ], - ), + ], ), - ), - ], - ), - ), - ), + )), ), ], ), diff --git a/lib/ui/views/admin_ui/makanan_list/makanan_list_view_model.dart b/lib/ui/views/admin_ui/makanan_list/makanan_list_view_model.dart index 7c11af3..518e5fc 100644 --- a/lib/ui/views/admin_ui/makanan_list/makanan_list_view_model.dart +++ b/lib/ui/views/admin_ui/makanan_list/makanan_list_view_model.dart @@ -1,11 +1,46 @@ +import 'package:reza_admin/model/makanan_model.dart'; +import 'package:reza_admin/model/my_model.dart'; + +import '../../../../app/app.locator.dart'; import '../../../../app/app.logger.dart'; import '../../../../app/app.router.dart'; import '../../../../app/core/custom_base_view_model.dart'; +import '../../../../services/my_socket_io_client.dart'; class MakananListViewModel extends CustomBaseViewModel { final log = getLogger('MakananListViewModel'); + final socketIoClient = locator(); + List listMakanan = []; Future init() async { globalVar.backPressed = 'exitApp'; + getData(); + socketIoClient.on('makanan_user', (data) { + log.i('data : $data'); + listMakanan.clear(); + getData(); + // webViewController!.reload(); + }); + } + + 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.dismiss(); + setBusy(false); + } } goToDetailMakanan() { diff --git a/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view.dart b/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view.dart index ec583c4..e8b0d54 100644 --- a/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view.dart +++ b/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view.dart @@ -87,9 +87,9 @@ class MejaDetailView extends StatelessWidget { style: regularTextStyle, children: [ TextSpan( - text: 'Tersedia', + text: model.theBool ? 'Tidak Tersedia' : 'Tersedia', style: regularTextStyle.copyWith( - color: Colors.green, + color: model.theBool ? Colors.red : Colors.green, fontWeight: FontWeight.bold, ), ), @@ -145,58 +145,60 @@ class MejaDetailView extends StatelessWidget { ), ), const SizedBox(height: 10), - Expanded( - child: ListView.builder( - itemCount: 2, - shrinkWrap: true, - itemBuilder: (context, index) { - // make the color random between red and blue - const color = Colors.blue; - String pesanStatus = 'Menunggu Pengesahan'; - return Card( - color: color, - child: ListTile( - // leading: CircleAvatar( - // backgroundColor: Colors.white, - // child: Text( - // index.toString(), - // style: regularTextStyle, - // ), - // ), - title: Text( - 'Nama Pemesan', - style: regularTextStyle.copyWith( - fontSize: 18, - color: Colors.white, - fontStyle: FontStyle.italic, - ), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '08:00.00 - 09:00.00', - style: TextStyle( - color: Colors.white, - ), - ), - Text( - pesanStatus, - style: const TextStyle( - color: Colors.white, - ), - ), - ], - ), - trailing: const Icon(Icons.arrow_forward_ios, - color: Colors.white), - onTap: () { - model.log.i('Meja 1'); - }, - ), - ); - }, - ), + const Expanded( + child: SizedBox(), + + // ListView.builder( + // itemCount: 2, + // shrinkWrap: true, + // itemBuilder: (context, index) { + // // make the color random between red and blue + // const color = Colors.blue; + // String pesanStatus = 'Menunggu Pengesahan'; + // return Card( + // color: color, + // child: ListTile( + // // leading: CircleAvatar( + // // backgroundColor: Colors.white, + // // child: Text( + // // index.toString(), + // // style: regularTextStyle, + // // ), + // // ), + // title: Text( + // 'Nama Pemesan', + // style: regularTextStyle.copyWith( + // fontSize: 18, + // color: Colors.white, + // fontStyle: FontStyle.italic, + // ), + // ), + // subtitle: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // const Text( + // '08:00.00 - 09:00.00', + // style: TextStyle( + // color: Colors.white, + // ), + // ), + // Text( + // pesanStatus, + // style: const TextStyle( + // color: Colors.white, + // ), + // ), + // ], + // ), + // trailing: const Icon(Icons.arrow_forward_ios, + // color: Colors.white), + // onTap: () { + // model.log.i('Meja 1'); + // }, + // ), + // ); + // }, + // ), ), ], ), @@ -262,8 +264,12 @@ class MejaDetailView extends StatelessWidget { onTap: () { model.log.i('List'); // model.navigationService.navigateToMakananListView(); - model.navigationService - .navigateToMejaHistoryLogView(mejaId: mejaId); + // model.navigationService + // .navigateToMejaHistoryLogView(mejaId: mejaId); + model.snackbarService.showSnackbar( + message: 'Fitur ini belum tersedia', + title: 'Info', + duration: const Duration(seconds: 2)); }, child: const Column( mainAxisAlignment: MainAxisAlignment.center, @@ -292,6 +298,7 @@ class MejaDetailView extends StatelessWidget { backgroundColor: orangeColor, onPressed: () { // model.navigationService.navigateToAddEditMakananView(); + model.editStatus(); }, // create a add product button child: const Icon( diff --git a/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view_model.dart b/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view_model.dart index 9b7cc1e..ff9605f 100644 --- a/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view_model.dart +++ b/lib/ui/views/admin_ui/meja_list/meja_detail/meja_detail_view_model.dart @@ -1,3 +1,6 @@ +import 'package:reza_admin/model/my_model.dart'; + +import '../../../../../app/app.dialogs.dart'; import '../../../../../app/app.logger.dart'; import '../../../../../app/core/custom_base_view_model.dart'; @@ -6,16 +9,20 @@ class MejaDetailViewModel extends CustomBaseViewModel { late String mejaId; late String namaMeja; + late int idMeja; String? imgAsset; + bool theBool = false; + Future init(String mejaId) async { - log.i('MejaDetailViewModel init'); - log.i('mejaId : $mejaId'); + // log.i('MejaDetailViewModel init'); + // log.i('mejaId : $mejaId'); this.mejaId = mejaId; globalVar.backPressed = 'backNormal'; // seperate the number from the string var number = int.parse(mejaId.replaceAll(RegExp(r'[^0-9]'), '')); + idMeja = number; // log.i('number : $number'); if (number <= 4) { namaMeja = 'Gazebo'; @@ -30,6 +37,35 @@ class MejaDetailViewModel extends CustomBaseViewModel { namaMeja = '$namaMeja $number'; - log.i('imgAsset : $imgAsset'); + // log.i('imgAsset : $imgAsset'); + getData(); + } + + getData() async { + easyLoading.showLoading(); + setBusy(true); + try { + var response = await httpService.get('table/detail/$idMeja'); + // log.i('response : $response'); + MyModel myModel = MyModel.fromJson(response.data); + theBool = myModel.theBool!; + log.i('theBool : $theBool'); + } catch (e) { + log.e('error : $e'); + } finally { + setBusy(false); + easyLoading.dismiss(); + } + } + + editStatus() async { + var res = await dialogService.showCustomDialog( + variant: DialogType.mejaEditStatusDialogView, + data: {'idMeja': idMeja}, + ); + + if (res!.confirmed) { + getData(); + } } } diff --git a/lib/ui/views/admin_ui/meja_list/meja_edit/meja_edit_view.dart b/lib/ui/views/admin_ui/meja_list/meja_edit/meja_edit_view.dart index c28ef77..b5f33a0 100644 --- a/lib/ui/views/admin_ui/meja_list/meja_edit/meja_edit_view.dart +++ b/lib/ui/views/admin_ui/meja_list/meja_edit/meja_edit_view.dart @@ -30,6 +30,7 @@ class MejaEditView extends StatelessWidget { 'backPressed : ${model.globalVar.backPressed} in MejaEditView'); if (model.globalVar.backPressed == 'backNormal') { // model.globalVar.backPressed = 'exitApp'; + // model.globalVar.backPressed = 'backNormal'; return true; } // model.quitApp(context); @@ -44,7 +45,7 @@ class MejaEditView extends StatelessWidget { leading: IconButton( onPressed: () { if (model.globalVar.backPressed == 'backNormal') { - model.globalVar.backPressed = 'exitApp'; + // model.globalVar.backPressed = 'exitApp'; model.navigationService.back(); // return true; } diff --git a/lib/ui/views/admin_ui/meja_list/meja_edit_status_dialog/meja_edit_status_dialog_view.dart b/lib/ui/views/admin_ui/meja_list/meja_edit_status_dialog/meja_edit_status_dialog_view.dart new file mode 100644 index 0000000..81e7a4e --- /dev/null +++ b/lib/ui/views/admin_ui/meja_list/meja_edit_status_dialog/meja_edit_status_dialog_view.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:reza_admin/app/themes/app_colors.dart'; +import 'package:reza_admin/app/themes/app_text.dart'; +import 'package:stacked/stacked.dart'; +import 'package:stacked_services/stacked_services.dart'; + +import './meja_edit_status_dialog_view_model.dart'; + +class MejaEditStatusDialogView extends StatelessWidget { + final DialogRequest? request; + final Function(DialogResponse)? completer; + + const MejaEditStatusDialogView({ + Key? key, + this.request, + this.completer, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ViewModelBuilder.reactive( + viewModelBuilder: () => MejaEditStatusDialogViewModel(), + onViewModelReady: (MejaEditStatusDialogViewModel model) async { + await model.init(request!.data); + }, + builder: ( + BuildContext context, + MejaEditStatusDialogViewModel model, + Widget? child, + ) { + return Dialog( + child: Container( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + 'Edit Status', + style: regularTextStyle, + ), + const SizedBox(height: 20), + DropdownButtonFormField( + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Status', + ), + value: model.status, + onChanged: (String? value) { + model.status = value!; + }, + items: model.statusList.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value, style: regularTextStyle), + ); + }).toList(), + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + completer!(DialogResponse(confirmed: false)); + }, + child: Text( + 'Batal', + style: regularTextStyle.copyWith(color: redColor), + ), + ), + TextButton( + onPressed: () async { + bool res = await model.editStatus(); + if (res) { + completer!(DialogResponse( + confirmed: true, + )); + } else { + completer!(DialogResponse( + confirmed: false, + )); + } + completer!(DialogResponse( + confirmed: true, + // responseData: model.status, + )); + }, + child: Text( + 'Simpan', + style: regularTextStyle.copyWith(color: greenColor), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/ui/views/admin_ui/meja_list/meja_edit_status_dialog/meja_edit_status_dialog_view_model.dart b/lib/ui/views/admin_ui/meja_list/meja_edit_status_dialog/meja_edit_status_dialog_view_model.dart new file mode 100644 index 0000000..1e3b250 --- /dev/null +++ b/lib/ui/views/admin_ui/meja_list/meja_edit_status_dialog/meja_edit_status_dialog_view_model.dart @@ -0,0 +1,39 @@ +import 'package:dio/dio.dart'; + +import '../../../../../app/app.logger.dart'; +import '../../../../../app/core/custom_base_view_model.dart'; + +class MejaEditStatusDialogViewModel extends CustomBaseViewModel { + final log = getLogger('MejaEditStatusDialogViewModel'); + + int? idMeja; + String status = 'Tersedia'; + + List statusList = ['Tersedia', 'Tidak Tersedia']; + + Future init(data) async { + log.i("data : ${data['idMeja']}"); + idMeja = data['idMeja']; + } + + Future editStatus() async { + easyLoading.showLoading(); + setBusy(true); + try { + var formData = FormData.fromMap({ + 'id_meja': idMeja, + 'status': status, + }); + var response = await httpService.postWithFormData( + 'table/reservation/$idMeja', formData); + log.i('response : $response'); + return true; + } catch (e) { + log.e('error : $e'); + return false; + } finally { + setBusy(false); + easyLoading.dismiss(); + } + } +} diff --git a/lib/ui/views/admin_ui/meja_list/meja_list_view.dart b/lib/ui/views/admin_ui/meja_list/meja_list_view.dart index cca9aca..cf31518 100644 --- a/lib/ui/views/admin_ui/meja_list/meja_list_view.dart +++ b/lib/ui/views/admin_ui/meja_list/meja_list_view.dart @@ -55,10 +55,7 @@ class MejaListView extends StatelessWidget { // 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%)'); @@ -101,7 +98,7 @@ class MejaListView extends StatelessWidget { }, onPageFinished: (String url) { model.log.i('Page finished loading: $url'); - model.easyLoading.dismissLoading(); + model.easyLoading.dismiss(); }, gestureNavigationEnabled: true, backgroundColor: const Color(0x00000000), @@ -169,64 +166,89 @@ class MejaListView extends StatelessWidget { height: 15, ), Expanded( - child: ListView.builder( - itemCount: 15, - shrinkWrap: true, - itemBuilder: (context, index) { - // make the color random between red and blue - final color = index % 2 == 0 ? Colors.red : Colors.blue; - String pesanStatus = - index % 2 == 0 ? 'Dibooking' : 'Menunggu Pengesahan'; - return Card( - color: color, - child: ListTile( - leading: CircleAvatar( - backgroundColor: Colors.white, - child: Text( - index.toString(), - style: regularTextStyle, - ), - ), - title: Text( - 'Nama Pemesan', - style: regularTextStyle.copyWith( - fontSize: 18, - color: Colors.white, - fontStyle: FontStyle.italic, - ), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - '08:00.00 - 09:00.00', - style: TextStyle( - color: Colors.white, + child: model.isBusy + ? const Center( + child: CircularProgressIndicator(), + ) + : ListView.builder( + itemCount: model.reservasiMejaList.length, + shrinkWrap: true, + itemBuilder: (context, index) { + // make the color random between red and blue + + final color = + model.reservasiMejaList[index].status == + 'booking' + ? Colors.red + : (model.reservasiMejaList[index].status == + 'Tidak Tersedia' + ? Colors.grey[600] + : Colors.green); + String pesanStatus = model + .reservasiMejaList[index].status! + .toUpperCase(); + return Card( + color: color, + child: ListTile( + leading: CircleAvatar( + backgroundColor: Colors.white, + child: Text( + model.reservasiMejaList[index].idMeja + .toString(), + style: regularTextStyle, + ), ), - ), - Text( - pesanStatus, - style: const TextStyle( - color: Colors.white, + title: Text( + model.userModelList[index] != null + ? model.userModelList[index]!.nama ?? '-' + : '-', + style: regularTextStyle.copyWith( + fontSize: 18, + color: Colors.white, + fontStyle: FontStyle.italic, + ), ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + model.reservasiMejaList[index] + .jamBooking ?? + '', + style: const TextStyle( + color: Colors.white, + ), + ), + Text( + pesanStatus, + style: const TextStyle( + color: Colors.white, + ), + ), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, + color: Colors.white), + onTap: () { + model.log.i('Meja 1'); + }, ), - ], - ), - trailing: const Icon(Icons.arrow_forward_ios, - color: Colors.white), - onTap: () { - model.log.i('Meja 1'); + ); }, ), - ); - }, - ), ), const SizedBox( height: 15, ), ], ), + // floatingActionButton: FloatingActionButton( + // onPressed: () async { + // await model.webViewController!.reload(); + // }, + // backgroundColor: mainColor, + // child: const Icon(Icons.add), + // ), ), ); }, diff --git a/lib/ui/views/admin_ui/meja_list/meja_list_view_model.dart b/lib/ui/views/admin_ui/meja_list/meja_list_view_model.dart index e2548bb..2677921 100644 --- a/lib/ui/views/admin_ui/meja_list/meja_list_view_model.dart +++ b/lib/ui/views/admin_ui/meja_list/meja_list_view_model.dart @@ -1,10 +1,78 @@ +import 'package:reza_admin/app/app.locator.dart'; import 'package:reza_admin/app/app.logger.dart'; +import 'package:reza_admin/model/my_model.dart'; +import 'package:reza_admin/model/reservasi_meja_model.dart'; +import 'package:reza_admin/model/user_model.dart'; +import 'package:webview_flutter/webview_flutter.dart'; import '../../../../app/core/custom_base_view_model.dart'; +import '../../../../services/my_socket_io_client.dart'; class MejaListViewModel extends CustomBaseViewModel { final log = getLogger('MejaListViewModel'); + WebViewController? webViewController; + final socketIoClient = locator(); + + List reservasiMejaList = []; + List userModelList = []; + Future init() async { globalVar.backPressed = 'exitApp'; + socketIoClient.on('table_admin', (data) { + log.i('data : $data'); + getData(); + webViewController!.reload(); + }); + getData(); + } + + getData() async { + setBusy(true); + easyLoading.showLoading(); + try { + var response = await httpService.get('table/detail'); + // log.i('response : ${response.data}'); + MyModel myModel = MyModel.fromJson(response.data); + + if (myModel.data != null) { + for (var item in myModel.data!) { + reservasiMejaList.add(ReservasiMejaModel.fromJson(item)); + } + // log.i('reservasiMejaList : $reservasiMejaList'); + } + + for (var item in reservasiMejaList) { + if (item.idUser != null) { + UserModel? userModel = await getUserDetail(item.idUser!); + userModelList.add(userModel!); + } else { + userModelList.add(null); + } + } + log.i('userModelList : $userModelList'); + } catch (e) { + log.e(e); + } finally { + setBusy(false); + easyLoading.dismiss(); + } + } + + Future getUserDetail(int id) async { + setBusy(true); + easyLoading.showLoading(); + try { + var response = await httpService.get('table/user/$id'); + log.i('response : ${response.data}'); + MyModel myModel = MyModel.fromJson(response.data); + return UserModel.fromJson(myModel.data); + } catch (e) { + log.e(e); + return null; + } finally { + setBusy(false); + easyLoading.dismiss(); + // return null; + } } } diff --git a/lib/ui/views/admin_ui/pesanan_list/pesanan_list_view.dart b/lib/ui/views/admin_ui/pesanan_list/pesanan_list_view.dart index a4ac978..b87b52b 100644 --- a/lib/ui/views/admin_ui/pesanan_list/pesanan_list_view.dart +++ b/lib/ui/views/admin_ui/pesanan_list/pesanan_list_view.dart @@ -131,8 +131,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, 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 2852346..d65d767 100644 --- a/lib/ui/views/login_user/login_user_view_model.dart +++ b/lib/ui/views/login_user/login_user_view_model.dart @@ -20,7 +20,7 @@ class LoginUserViewModel extends CustomBaseViewModel { globalVar.backPressed = 'cantBack'; easyLoading.showLoading(); await Future.delayed(const Duration(seconds: 2)); - easyLoading.dismissLoading(); + easyLoading.dismiss(); setBusy(false); globalVar.backPressed = 'backNormal'; notifyListeners(); diff --git a/lib/ui/views/splash_screen/splash_screen_view_model.dart b/lib/ui/views/splash_screen/splash_screen_view_model.dart index ecdb20f..a0447c2 100644 --- a/lib/ui/views/splash_screen/splash_screen_view_model.dart +++ b/lib/ui/views/splash_screen/splash_screen_view_model.dart @@ -1,9 +1,16 @@ +import 'package:reza_admin/app/app.locator.dart'; + import '../../../app/app.router.dart'; import '../../../app/core/custom_base_view_model.dart'; +import '../../../services/my_socket_io_client.dart'; +// import '../../../services/my_socket_io_client.dart'; class SplashScreenViewModel extends CustomBaseViewModel { + final socketIoClient = locator(); Future init() async { + // MySocketIoClient().init(); + socketIoClient.init(); await Future.delayed(const Duration(seconds: 2)); await navigationService.navigateToLoginUserView(); } diff --git a/pubspec.lock b/pubspec.lock index 77f0635..30842f4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -773,6 +773,22 @@ packages: description: flutter source: sdk version: "0.0.99" + socket_io_client: + dependency: "direct main" + description: + name: socket_io_client + sha256: ede469f3e4c55e8528b4e023bdedbc20832e8811ab9b61679d1ba3ed5f01f23b + url: "https://pub.dev" + source: hosted + version: "2.0.3+1" + socket_io_common: + dependency: transitive + description: + name: socket_io_common + sha256: "2ab92f8ff3ebbd4b353bf4a98bee45cc157e3255464b2f90f66e09c4472047eb" + url: "https://pub.dev" + source: hosted + version: "2.0.3" source_gen: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 09d4a33..1ed9ece 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,6 +55,7 @@ dependencies: flutter_hooks: ^0.19.0 webview_flutter: ^3.0.4 carousel_slider: ^4.2.1 + socket_io_client: dev_dependencies: flutter_test: @@ -91,6 +92,7 @@ flutter: - assets/reza_gazebo.jpeg - assets/reza_meja_1.jpeg - assets/reza_meja_2.jpeg + - assets/nasi_goreng.jpg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware