complete admin, mandor and user page

This commit is contained in:
kicap
2023-11-03 23:24:23 +08:00
parent 4cc9967ab8
commit 8eacfa6dee
41 changed files with 1335 additions and 492 deletions

4
.env
View File

@ -1,2 +1,2 @@
url = 'http://20.20.20.25/perumahan_backend/' url = 'https://my_localhost.kicap-karan.com/perumahan_backend/'
api_url = 'http://20.20.20.25/perumahan_backend/api/' api_url = 'https://my_localhost.kicap-karan.com/perumahan_backend/index.php/api/'

View File

@ -1,25 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application <application android:label="perumahan_bew" android:name="${applicationName}" android:usesCleartextTraffic="true" android:icon="@mipmap/ic_launcher">
android:label="perumahan_bew" <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
android:name="${applicationName}"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
@ -27,8 +13,22 @@
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data <meta-data android:name="flutterEmbedding" android:value="2" />
android:name="flutterEmbedding"
android:value="2" />
</application> </application>
<queries>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
<!-- If your app checks for call support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="tel" />
</intent>
<!-- If your application checks for inAppBrowserView launch mode support -->
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
</manifest> </manifest>

View File

@ -1,4 +1,5 @@
import 'package:perumahan_bew/ui/views/play_video_dialog/play_video_dialog_view.dart'; import 'package:perumahan_bew/ui/views/play_video_dialog/play_video_dialog_view.dart';
import 'package:perumahan_bew/ui/views/user_index/user_list_pembangunan/user_list_pembangunan_page/user_list_pembangunan_page_view.dart';
import 'package:stacked_services/stacked_services.dart'; import 'package:stacked_services/stacked_services.dart';
import 'package:stacked/stacked_annotations.dart'; import 'package:stacked/stacked_annotations.dart';
@ -18,7 +19,6 @@ import '../ui/views/pengembang_index/pengembang_profil/pengembang_profil_view.da
import '../ui/views/pengembang_index/perumahan_detail/perumahan_detail_view.dart'; import '../ui/views/pengembang_index/perumahan_detail/perumahan_detail_view.dart';
import '../ui/views/splash_screen/splash_screen_view.dart'; import '../ui/views/splash_screen/splash_screen_view.dart';
import '../ui/views/tambah_lihat_progress_bottom_sheet/tambah_lihat_progress_bottom_sheet_view.dart'; import '../ui/views/tambah_lihat_progress_bottom_sheet/tambah_lihat_progress_bottom_sheet_view.dart';
import '../ui/views/user_index/user_home/user_home_view.dart';
import '../ui/views/user_index/user_index_view.dart'; import '../ui/views/user_index/user_index_view.dart';
import '../ui/views/user_index/user_list_pembangunan/user_list_pembangunan_view.dart'; import '../ui/views/user_index/user_list_pembangunan/user_list_pembangunan_view.dart';
import '../ui/views/user_index/user_profile/user_profile_view.dart'; import '../ui/views/user_index/user_profile/user_profile_view.dart';
@ -30,9 +30,9 @@ import '../ui/views/user_index/user_profile/user_profile_view.dart';
MaterialRoute( MaterialRoute(
page: UserIndexView, page: UserIndexView,
children: [ children: [
MaterialRoute(page: UserHomeView, initial: true), MaterialRoute(page: UserListPembangunanView, initial: true),
MaterialRoute(page: UserProfileView), MaterialRoute(page: UserProfileView),
MaterialRoute(page: UserListPembangunanView), MaterialRoute(page: UserListPembangunanPageView),
], ],
), ),
// dibawah untuk admin // dibawah untuk admin
@ -60,7 +60,6 @@ import '../ui/views/user_index/user_profile/user_profile_view.dart';
LazySingleton(classType: SnackbarService), LazySingleton(classType: SnackbarService),
LazySingleton(classType: BottomSheetService), LazySingleton(classType: BottomSheetService),
// //
LazySingleton(classType: UserHomeView),
LazySingleton(classType: PengembangHomeView), LazySingleton(classType: PengembangHomeView),
LazySingleton(classType: MyEasyLoading), LazySingleton(classType: MyEasyLoading),
LazySingleton(classType: MyHttpServices), LazySingleton(classType: MyHttpServices),

View File

@ -18,7 +18,6 @@ import '../services/my_easyloading.dart';
import '../services/other_function.dart'; import '../services/other_function.dart';
import '../services/shared_prefs.dart'; import '../services/shared_prefs.dart';
import '../ui/views/pengembang_index/pengembang_home/pengembang_home_view.dart'; import '../ui/views/pengembang_index/pengembang_home/pengembang_home_view.dart';
import '../ui/views/user_index/user_home/user_home_view.dart';
final locator = StackedLocator.instance; final locator = StackedLocator.instance;
@ -35,7 +34,6 @@ Future<void> setupLocator({
locator.registerLazySingleton(() => DialogService()); locator.registerLazySingleton(() => DialogService());
locator.registerLazySingleton(() => SnackbarService()); locator.registerLazySingleton(() => SnackbarService());
locator.registerLazySingleton(() => BottomSheetService()); locator.registerLazySingleton(() => BottomSheetService());
locator.registerLazySingleton(() => const UserHomeView());
locator.registerLazySingleton(() => const PengembangHomeView()); locator.registerLazySingleton(() => const PengembangHomeView());
locator.registerLazySingleton(() => MyEasyLoading()); locator.registerLazySingleton(() => MyEasyLoading());
locator.registerLazySingleton(() => MyHttpServices()); locator.registerLazySingleton(() => MyHttpServices());

View File

@ -25,11 +25,11 @@ import 'package:perumahan_bew/ui/views/pengembang_index/perumahan_detail/perumah
as _i6; as _i6;
import 'package:perumahan_bew/ui/views/splash_screen/splash_screen_view.dart' import 'package:perumahan_bew/ui/views/splash_screen/splash_screen_view.dart'
as _i2; as _i2;
import 'package:perumahan_bew/ui/views/user_index/user_home/user_home_view.dart'
as _i9;
import 'package:perumahan_bew/ui/views/user_index/user_index_view.dart' as _i4; import 'package:perumahan_bew/ui/views/user_index/user_index_view.dart' as _i4;
import 'package:perumahan_bew/ui/views/user_index/user_list_pembangunan/user_list_pembangunan_view.dart' import 'package:perumahan_bew/ui/views/user_index/user_list_pembangunan/user_list_pembangunan_page/user_list_pembangunan_page_view.dart'
as _i11; as _i11;
import 'package:perumahan_bew/ui/views/user_index/user_list_pembangunan/user_list_pembangunan_view.dart'
as _i9;
import 'package:perumahan_bew/ui/views/user_index/user_profile/user_profile_view.dart' import 'package:perumahan_bew/ui/views/user_index/user_profile/user_profile_view.dart'
as _i10; as _i10;
import 'package:stacked/stacked.dart' as _i1; import 'package:stacked/stacked.dart' as _i1;
@ -162,39 +162,39 @@ class PerumahanDetailViewArguments {
} }
class UserIndexViewRoutes { class UserIndexViewRoutes {
static const userHomeView = ''; static const userListPembangunanView = '';
static const userProfileView = 'user-profile-view'; static const userProfileView = 'user-profile-view';
static const userListPembangunanView = 'user-list-pembangunan-view'; static const userListPembangunanPageView = 'user-list-pembangunan-page-view';
static const all = <String>{ static const all = <String>{
userHomeView,
userProfileView,
userListPembangunanView, userListPembangunanView,
userProfileView,
userListPembangunanPageView,
}; };
} }
class UserIndexViewRouter extends _i1.RouterBase { class UserIndexViewRouter extends _i1.RouterBase {
final _routes = <_i1.RouteDef>[ final _routes = <_i1.RouteDef>[
_i1.RouteDef( _i1.RouteDef(
UserIndexViewRoutes.userHomeView, UserIndexViewRoutes.userListPembangunanView,
page: _i9.UserHomeView, page: _i9.UserListPembangunanView,
), ),
_i1.RouteDef( _i1.RouteDef(
UserIndexViewRoutes.userProfileView, UserIndexViewRoutes.userProfileView,
page: _i10.UserProfileView, page: _i10.UserProfileView,
), ),
_i1.RouteDef( _i1.RouteDef(
UserIndexViewRoutes.userListPembangunanView, UserIndexViewRoutes.userListPembangunanPageView,
page: _i11.UserListPembangunanView, page: _i11.UserListPembangunanPageView,
), ),
]; ];
final _pagesMap = <Type, _i1.StackedRouteFactory>{ final _pagesMap = <Type, _i1.StackedRouteFactory>{
_i9.UserHomeView: (data) { _i9.UserListPembangunanView: (data) {
return _i8.MaterialPageRoute<dynamic>( return _i8.MaterialPageRoute<dynamic>(
builder: (context) => const _i9.UserHomeView(), builder: (context) => const _i9.UserListPembangunanView(),
settings: data, settings: data,
); );
}, },
@ -204,9 +204,9 @@ class UserIndexViewRouter extends _i1.RouterBase {
settings: data, settings: data,
); );
}, },
_i11.UserListPembangunanView: (data) { _i11.UserListPembangunanPageView: (data) {
return _i8.MaterialPageRoute<dynamic>( return _i8.MaterialPageRoute<dynamic>(
builder: (context) => const _i11.UserListPembangunanView(), builder: (context) => const _i11.UserListPembangunanPageView(),
settings: data, settings: data,
); );
}, },
@ -450,14 +450,14 @@ extension NavigatorStateExtension on _i16.NavigationService {
transition: transition); transition: transition);
} }
Future<dynamic> navigateToNestedUserHomeViewInUserIndexViewRouter([ Future<dynamic> navigateToNestedUserListPembangunanViewInUserIndexViewRouter([
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
Map<String, String>? parameters, Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)? Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition, transition,
]) async { ]) async {
return navigateTo<dynamic>(UserIndexViewRoutes.userHomeView, return navigateTo<dynamic>(UserIndexViewRoutes.userListPembangunanView,
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -478,14 +478,15 @@ extension NavigatorStateExtension on _i16.NavigationService {
transition: transition); transition: transition);
} }
Future<dynamic> navigateToNestedUserListPembangunanViewInUserIndexViewRouter([ Future<dynamic>
navigateToNestedUserListPembangunanPageViewInUserIndexViewRouter([
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
Map<String, String>? parameters, Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)? Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition, transition,
]) async { ]) async {
return navigateTo<dynamic>(UserIndexViewRoutes.userListPembangunanView, return navigateTo<dynamic>(UserIndexViewRoutes.userListPembangunanPageView,
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -701,14 +702,15 @@ extension NavigatorStateExtension on _i16.NavigationService {
transition: transition); transition: transition);
} }
Future<dynamic> replaceWithNestedUserHomeViewInUserIndexViewRouter([ Future<dynamic>
replaceWithNestedUserListPembangunanViewInUserIndexViewRouter([
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
Map<String, String>? parameters, Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)? Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition, transition,
]) async { ]) async {
return replaceWith<dynamic>(UserIndexViewRoutes.userHomeView, return replaceWith<dynamic>(UserIndexViewRoutes.userListPembangunanView,
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -730,14 +732,14 @@ extension NavigatorStateExtension on _i16.NavigationService {
} }
Future<dynamic> Future<dynamic>
replaceWithNestedUserListPembangunanViewInUserIndexViewRouter([ replaceWithNestedUserListPembangunanPageViewInUserIndexViewRouter([
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
Map<String, String>? parameters, Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)? Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition, transition,
]) async { ]) async {
return replaceWith<dynamic>(UserIndexViewRoutes.userListPembangunanView, return replaceWith<dynamic>(UserIndexViewRoutes.userListPembangunanPageView,
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,

View File

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart';
@ -13,6 +14,7 @@ import 'app/themes/app_theme.dart';
Future main() async { Future main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
HttpOverrides.global = MyHttpOverrides();
await dotenv.load(fileName: ".env"); await dotenv.load(fileName: ".env");
await setupAllLocator(); await setupAllLocator();
runApp(const MyApp()); runApp(const MyApp());
@ -41,3 +43,12 @@ Future<void> setupAllLocator() async {
setupBottomSheetUi(); setupBottomSheetUi();
// setupSnackbarUi(); // setupSnackbarUi();
} }
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}

View File

@ -84,6 +84,7 @@ class ProgressModel {
String? nama; String? nama;
String? noTelpon; String? noTelpon;
int? no; int? no;
String? type;
ProgressModel( ProgressModel(
{this.idProgress, {this.idProgress,
@ -94,7 +95,8 @@ class ProgressModel {
this.idMandor, this.idMandor,
this.nama, this.nama,
this.noTelpon, this.noTelpon,
this.no}); this.no,
this.type});
ProgressModel.fromJson(Map<String, dynamic> json) { ProgressModel.fromJson(Map<String, dynamic> json) {
idProgress = json['id_progress']; idProgress = json['id_progress'];
@ -106,6 +108,7 @@ class ProgressModel {
nama = json['nama']; nama = json['nama'];
noTelpon = json['no_telpon']; noTelpon = json['no_telpon'];
no = json['no']; no = json['no'];
type = json['type'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -119,6 +122,29 @@ class ProgressModel {
data['nama'] = nama; data['nama'] = nama;
data['no_telpon'] = noTelpon; data['no_telpon'] = noTelpon;
data['no'] = no; data['no'] = no;
data['type'] = type;
return data;
}
}
class MandorModel {
String? idMandor;
String? nama;
String? noTelpon;
MandorModel({this.idMandor, this.nama, this.noTelpon});
MandorModel.fromJson(Map<String, dynamic> json) {
idMandor = json['id_mandor'];
nama = json['nama'];
noTelpon = json['no_telpon'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id_mandor'] = idMandor;
data['nama'] = nama;
data['no_telpon'] = noTelpon;
return data; return data;
} }
} }

View File

@ -36,6 +36,18 @@ class MandorTrackingIndexView extends StatelessWidget {
backgroundColor: mainColor, backgroundColor: mainColor,
elevation: 0, elevation: 0,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
actions: [
// create logout button
IconButton(
onPressed: () {
model.logout();
},
icon: const Icon(
Icons.logout,
color: Colors.white,
),
),
],
), ),
body: ExtendedNavigator( body: ExtendedNavigator(
navigatorKey: StackedService.nestedNavigationKey(4), navigatorKey: StackedService.nestedNavigationKey(4),

View File

@ -5,10 +5,14 @@ import 'package:stacked_services/stacked_services.dart';
import '../../../app/app.locator.dart'; import '../../../app/app.locator.dart';
import '../../../app/app.logger.dart'; import '../../../app/app.logger.dart';
import '../../../app/app.router.dart'; import '../../../app/app.router.dart';
import '../../../services/shared_prefs.dart';
class MandorTrackingIndexViewModel extends IndexTrackingViewModel { class MandorTrackingIndexViewModel extends IndexTrackingViewModel {
final log = getLogger('MandorTrackingIndexViewModel'); final log = getLogger('MandorTrackingIndexViewModel');
final _navigationService = locator<NavigationService>(); final _navigationService = locator<NavigationService>();
final _mySharedPrefs = locator<MySharedPrefs>();
final _dialogService = locator<DialogService>();
final _snackbarService = locator<SnackbarService>();
final _bottomNavBarList = [ final _bottomNavBarList = [
{'name': 'List', 'icon': Icons.list_alt_rounded, 'header': 'List Pemilik'}, {'name': 'List', 'icon': Icons.list_alt_rounded, 'header': 'List Pemilik'},
@ -43,4 +47,26 @@ class MandorTrackingIndexViewModel extends IndexTrackingViewModel {
id: 4, id: 4,
); );
} }
logout() {
_dialogService
.showConfirmationDialog(
title: 'Logout',
description: 'Apakah Anda yakin ingin logout?',
cancelTitle: 'Batal',
confirmationTitle: 'Logout',
)
.then((value) async {
if (value!.confirmed) {
await _mySharedPrefs.clear();
_navigationService.clearStackAndShow(Routes.loginScreenView);
_snackbarService.showSnackbar(
message: 'Logout berhasil',
duration: const Duration(seconds: 2),
);
}
});
// await _mySharedPrefs.clear();
// _navigationService.clearStackAndShow(Routes.loginScreenView);
}
} }

View File

@ -92,7 +92,8 @@ class ListPemilikView extends StatelessWidget {
return Card( return Card(
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
model.log.i('Card $index tapped'); model.checkProgress(
model.listProgress[index]);
}, },
child: ListTile( child: ListTile(
title: Text( title: Text(

View File

@ -1,3 +1,4 @@
import '../../../../app/app.bottomsheets.dart';
import '../../../../app/app.logger.dart'; import '../../../../app/app.logger.dart';
import '../../../../app/core/custom_base_view_model.dart'; import '../../../../app/core/custom_base_view_model.dart';
import '../../../../model/my_response_model.dart'; import '../../../../model/my_response_model.dart';
@ -49,4 +50,15 @@ class ListPemilikViewModel extends CustomBaseViewModel {
setBusy(false); setBusy(false);
} }
} }
checkProgress(ProgressModel progressModel) async {
await bottomSheetService.showCustomSheet(
variant: BottomSheetType.tambahLihatProgressBottomSheetView,
title: 'Lihat Progress',
data: {
'idPerumahan': progressModel.idRumah,
'progressModel': progressModel,
},
);
}
} }

View File

@ -31,52 +31,81 @@ class PengembangHomeView extends StatelessWidget {
} }
return false; return false;
}, },
child: WebView( child: SafeArea(
// initialUrl: 'http://192.168.43.125/rekam-medis', child: SizedBox(
initialUrl: model.url, height: MediaQuery.of(context).size.height,
javascriptMode: JavascriptMode.unrestricted, child: Column(
onWebViewCreated: (WebViewController webViewController) { mainAxisSize: MainAxisSize.min,
// _controller.complete(webViewController); children: [
model.webViewControllerCompleter.future if (model.progress < 1)
.then((value) => model.webVIewcontroller = value); Center(
model.webViewControllerCompleter.complete(webViewController); child: LinearProgressIndicator(
}, value: model.progress,
onProgress: (int progress) { ),
double progressDouble = progress / 100; ),
LinearProgressIndicator( Expanded(
value: progressDouble, child: Visibility(
); visible: model.status,
// model.myEasyLoading.showProgress(progressDouble, "Loading Denah"); child: WebView(
}, // initialUrl: 'http://192.168.43.125/rekam-medis',
// javascriptChannels: <JavascriptChannel>{ initialUrl: model.url,
// _toasterJavascriptChannel(context), javascriptMode: JavascriptMode.unrestricted,
// }, onWebViewCreated:
javascriptChannels: <JavascriptChannel>{ (WebViewController webViewController) {
JavascriptChannel( // _controller.complete(webViewController);
name: 'messageHandler', model.webViewControllerCompleter.future.then(
onMessageReceived: (JavascriptMessage message) { (value) => model.webVIewcontroller = value);
model.log.d(message.message); model.webViewControllerCompleter
// var data = JsonDecoder().convert(message.message); .complete(webViewController);
// model.log.d(data['status']); },
model.goToDetail(message.message); onProgress: (int progress) {
double progressDouble = progress / 100;
model.progress = progressDouble;
model.log.d('progress: $progressDouble');
if (progressDouble == 1) {
model.status = true;
}
model.notifyListeners();
// LinearProgressIndicator(
// value: progressDouble,
// );
// model.myEasyLoading.showProgress(progressDouble, "Loading Denah");
},
// javascriptChannels: <JavascriptChannel>{
// _toasterJavascriptChannel(context),
// },
javascriptChannels: <JavascriptChannel>{
JavascriptChannel(
name: 'messageHandler',
onMessageReceived: (JavascriptMessage message) {
model.log.d(message.message);
// var data = JsonDecoder().convert(message.message);
// model.log.d(data['status']);
model.goToDetail(message.message);
// dev.i("message from the web view=\"${message.message}\""); // dev.i("message from the web view=\"${message.message}\"");
// if (message.message == "coba") { // if (message.message == "coba") {
// dev.i("sini untuk coba"); // dev.i("sini untuk coba");
// controller.runJavascript("coba22('heheheh')"); // controller.runJavascript("coba22('heheheh')");
// } // }
}, },
),
},
// navigationDelegate: (NavigationRequest request) async {},
onPageStarted: (String url) {},
onPageFinished: (String url) {
// dev.i('Page finished loading: $url');
model.easyLoading.dismiss();
},
gestureNavigationEnabled: true,
backgroundColor: const Color(0x00000000),
),
),
),
],
), ),
}, ),
// navigationDelegate: (NavigationRequest request) async {},
onPageStarted: (String url) {},
onPageFinished: (String url) {
// dev.i('Page finished loading: $url');
model.easyLoading.dismiss();
},
gestureNavigationEnabled: true,
backgroundColor: const Color(0x00000000),
), ),
), ),
); );

View File

@ -15,12 +15,18 @@ class PengembangHomeViewModel extends CustomBaseViewModel {
late String url; late String url;
late String level; late String level;
bool status = true;
double progress = 0;
late WebViewController webVIewcontroller; late WebViewController webVIewcontroller;
final Completer<WebViewController> webViewControllerCompleter = final Completer<WebViewController> webViewControllerCompleter =
Completer<WebViewController>(); Completer<WebViewController>();
Future<void> init() async { Future<void> init() async {
// Future.delayed(const Duration(milliseconds: 1), () {
// status = false;
// notifyListeners();
// });
globalVar.backPressed = "exitApp"; globalVar.backPressed = "exitApp";
url = dotenv.env['url']!; url = dotenv.env['url']!;
log.d(url); log.d(url);

View File

@ -38,6 +38,18 @@ class PengembangIndexView extends StatelessWidget {
backgroundColor: mainColor, backgroundColor: mainColor,
elevation: 0, elevation: 0,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
actions: [
// create logout button
IconButton(
onPressed: () {
model.logout();
},
icon: const Icon(
Icons.logout,
color: Colors.white,
),
),
],
), ),
body: ExtendedNavigator( body: ExtendedNavigator(
navigatorKey: StackedService.nestedNavigationKey(3), navigatorKey: StackedService.nestedNavigationKey(3),

View File

@ -5,10 +5,14 @@ import 'package:stacked_services/stacked_services.dart';
import '../../../app/app.locator.dart'; import '../../../app/app.locator.dart';
import '../../../app/app.logger.dart'; import '../../../app/app.logger.dart';
import '../../../app/app.router.dart'; import '../../../app/app.router.dart';
import '../../../services/shared_prefs.dart';
class PengembangIndexViewModel extends IndexTrackingViewModel { class PengembangIndexViewModel extends IndexTrackingViewModel {
final log = getLogger('PengembangIndexViewModel'); final log = getLogger('PengembangIndexViewModel');
final _navigationService = locator<NavigationService>(); final _navigationService = locator<NavigationService>();
final _dialogService = locator<DialogService>();
final _mySharedPrefs = locator<MySharedPrefs>();
final _snackbarService = locator<SnackbarService>();
final _bottomNavBarList = [ final _bottomNavBarList = [
{'name': 'List', 'icon': Icons.list_alt_rounded, 'header': 'List Pemilik'}, {'name': 'List', 'icon': Icons.list_alt_rounded, 'header': 'List Pemilik'},
@ -43,4 +47,26 @@ class PengembangIndexViewModel extends IndexTrackingViewModel {
id: 3, id: 3,
); );
} }
logout() {
_dialogService
.showConfirmationDialog(
title: 'Logout',
description: 'Apakah Anda yakin ingin logout?',
cancelTitle: 'Batal',
confirmationTitle: 'Logout',
)
.then((value) async {
if (value!.confirmed) {
await _mySharedPrefs.clear();
_navigationService.clearStackAndShow(Routes.loginScreenView);
_snackbarService.showSnackbar(
message: 'Logout berhasil',
duration: const Duration(seconds: 2),
);
}
});
// await _mySharedPrefs.clear();
// _navigationService.clearStackAndShow(Routes.loginScreenView);
}
} }

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart'; import 'package:stacked/stacked.dart';
import '../../../../app/themes/app_colors.dart';
import '../../../../app/themes/app_text.dart';
import './pengembang_profil_view_model.dart'; import './pengembang_profil_view_model.dart';
class PengembangProfilView extends StatelessWidget { class PengembangProfilView extends StatelessWidget {
@ -18,10 +20,126 @@ class PengembangProfilView extends StatelessWidget {
PengembangProfilViewModel model, PengembangProfilViewModel model,
Widget? child, Widget? child,
) { ) {
return const Scaffold( return Scaffold(
body: Center( body: SafeArea(
child: Text( child: Stack(
'PengembangProfilView', children: [
Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Stack(
children: [
const CircleAvatar(
radius: 50,
backgroundColor: fontParagraphColor,
// child: model.imageBytes == null
// ? const Icon(
// Icons.person,
// size: 50,
// color: Colors.white,
// )
// : ClipRRect(
// borderRadius: BorderRadius.circular(50),
// child: Image.memory(
// model.imageBytes!,
// width: 100,
// height: 100,
// fit: BoxFit.cover,
// ),
// ),
child: Icon(
Icons.person,
size: 50,
color: Colors.white,
),
),
Positioned(
bottom: 0,
right: 0,
child: CircleAvatar(
radius: 15,
backgroundColor: mainColor,
child: IconButton(
onPressed: () {
// model.addImage();
},
icon: const Icon(
Icons.add,
color: backgroundColor,
size: 15,
)),
),
),
],
),
),
if (model.level == 'Mandor' &&
model.mandorModel != null &&
!model.isBusy)
Column(
children: [
const SizedBox(height: 20),
_FirstDetail(
text: model.mandorModel!.nama!,
icon: Icons.person,
),
const SizedBox(height: 20),
_FirstDetail(
text: model.mandorModel!.noTelpon!,
icon: Icons.phone,
),
],
),
if (model.level != null && model.level == 'Admin')
const Column(
children: [
SizedBox(height: 20),
_FirstDetail(
text: 'Admin',
icon: Icons.person,
),
SizedBox(height: 20),
_FirstDetail(
text:
'Perumahan Mutiara Alga, Kecamatan Suppa, Kabupaten Pinrang, Sulawesi Selatan, 91131',
icon: Icons.phone,
),
],
),
if (model.isBusy)
const Column(
children: [
SizedBox(height: 20),
Center(child: CircularProgressIndicator()),
],
),
],
),
),
// create rounded edit button at top right
Positioned(
top: 20,
right: 20,
child: CircleAvatar(
radius: 20,
backgroundColor: mainColor,
child: IconButton(
onPressed: () {},
icon: const Icon(
Icons.edit,
color: backgroundColor,
size: 15,
),
),
),
),
],
), ),
), ),
); );
@ -29,3 +147,56 @@ class PengembangProfilView extends StatelessWidget {
); );
} }
} }
class _FirstDetail extends StatelessWidget {
const _FirstDetail({
Key? key,
required this.text,
required this.icon,
}) : super(key: key);
final String text;
final IconData icon;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(
icon,
color: mainColor,
size: 40,
),
const SizedBox(
width: 20,
),
Expanded(
child: Text(
text,
style: regularTextStyle.copyWith(
fontSize: 15,
color: mainGrey,
),
),
),
// created edit button
// Expanded(
// child: Align(
// alignment: Alignment.centerRight,
// child: IconButton(
// onPressed: () {},
// icon: const Icon(
// Icons.edit,
// color: mainColor,
// ),
// ),
// ),
// ),
],
),
);
}
}

View File

@ -1,5 +1,37 @@
import 'package:perumahan_bew/app/core/custom_base_view_model.dart'; import 'package:perumahan_bew/model/my_response_model.dart';
import 'package:perumahan_bew/model/rumah_model.dart';
import '../../../../app/app.logger.dart';
import '../../../../app/core/custom_base_view_model.dart';
class PengembangProfilViewModel extends CustomBaseViewModel { class PengembangProfilViewModel extends CustomBaseViewModel {
Future<void> init() async {} final log = getLogger('PengembangProfilViewModel');
String? level;
String? id;
MandorModel? mandorModel;
Future<void> init() async {
level = await mySharedPrefs.getString('level');
id = await mySharedPrefs.getString('id');
log.i('level: $level');
if (level == 'Mandor') {
await getData();
}
notifyListeners();
}
getData() async {
setBusy(true);
try {
var response = await httpService.get('mandor?id=$id');
MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data);
mandorModel = MandorModel.fromJson(myResponseModel.data);
log.i('mandorModel: ${mandorModel!.nama}');
} catch (e) {
log.e('Error: $e');
} finally {
setBusy(false);
}
}
} }

View File

@ -24,6 +24,9 @@ class PerumahanDetailView extends StatelessWidget {
) { ) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
iconTheme: const IconThemeData(
color: backgroundColor,
),
title: Text( title: Text(
'Perumahan Blok ${model.blok} , No. ${model.idRumah}', 'Perumahan Blok ${model.blok} , No. ${model.idRumah}',
style: const TextStyle( style: const TextStyle(
@ -34,15 +37,7 @@ class PerumahanDetailView extends StatelessWidget {
backgroundColor: mainColor, backgroundColor: mainColor,
elevation: 0, elevation: 0,
), ),
body: WillPopScope( body: SafeArea(
onWillPop: () async {
if (model.globalVar.backPressed == 'exitApp') {
// model.back();
return true;
// model.quitApp(context);
}
return false;
},
child: Stack( child: Stack(
children: [ children: [
Padding( Padding(
@ -190,7 +185,8 @@ class PerumahanDetailView extends StatelessWidget {
return Card( return Card(
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
model.log.i('Card $index tapped'); model.checkProgress(
model.progressModel![index]);
}, },
child: ListTile( child: ListTile(
title: Text( title: Text(
@ -245,6 +241,70 @@ class PerumahanDetailView extends StatelessWidget {
), ),
), ),
), ),
// create whatsapp button
Positioned(
top: model.level == 'Mandor' ? 80 : 15,
right: 15,
child: Container(
alignment: Alignment.center,
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: greenColor,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 7,
offset: const Offset(0, 3),
),
],
),
child: IconButton(
onPressed: () {
model.openWhatsapp();
},
icon: const Icon(
Icons.chat_outlined,
color: Colors.white,
size: 30,
),
),
),
),
// create call button
Positioned(
top: model.level == 'Mandor' ? 145 : 80,
right: 15,
child: Container(
alignment: Alignment.center,
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: mainColor,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 7,
offset: const Offset(0, 3),
),
],
),
child: IconButton(
onPressed: () {
model.call();
},
icon: const Icon(
Icons.call_outlined,
color: Colors.white,
size: 30,
),
),
),
),
], ],
), ),
), ),

View File

@ -1,3 +1,5 @@
import 'package:url_launcher/url_launcher.dart';
import '../../../../app/app.bottomsheets.dart'; import '../../../../app/app.bottomsheets.dart';
import '../../../../app/app.logger.dart'; import '../../../../app/app.logger.dart';
import '../../../../app/app.router.dart'; import '../../../../app/app.router.dart';
@ -60,7 +62,9 @@ class PerumahanDetailViewModel extends CustomBaseViewModel {
var res = await bottomSheetService.showCustomSheet( var res = await bottomSheetService.showCustomSheet(
variant: BottomSheetType.tambahLihatProgressBottomSheetView, variant: BottomSheetType.tambahLihatProgressBottomSheetView,
title: 'Form Tambah Progress', title: 'Form Tambah Progress',
data: idPerumahan, data: {
'idPerumahan': idPerumahan,
},
); );
if (res!.confirmed) { if (res!.confirmed) {
@ -72,4 +76,37 @@ class PerumahanDetailViewModel extends CustomBaseViewModel {
await getData(); await getData();
} }
} }
checkProgress(ProgressModel progressModel) async {
await bottomSheetService.showCustomSheet(
variant: BottomSheetType.tambahLihatProgressBottomSheetView,
title: 'Lihat Progress',
data: {
'idPerumahan': idPerumahan,
'progressModel': progressModel,
},
);
}
openWhatsapp() async {
// open whatsapp using url
String noTelpon = rumahModel!.noTelpon!;
// convert the number to international format
noTelpon = noTelpon.replaceAll(RegExp(r'[^0-9]'), '');
noTelpon = '62${noTelpon.substring(1)}';
log.i('no_telpon: $noTelpon');
final url = Uri.parse('https://wa.me/$noTelpon');
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
}
call() async {
final Uri callUri = Uri(scheme: 'tel', path: rumahModel!.noTelpon!);
if (!await launchUrl(callUri)) {
throw 'Could not launch ${callUri.toString()}';
}
}
} }

View File

@ -21,7 +21,7 @@ class PlayVideoDialogView extends StatelessWidget {
return ViewModelBuilder<PlayVideoDialogViewModel>.reactive( return ViewModelBuilder<PlayVideoDialogViewModel>.reactive(
viewModelBuilder: () => PlayVideoDialogViewModel(), viewModelBuilder: () => PlayVideoDialogViewModel(),
onViewModelReady: (PlayVideoDialogViewModel model) async { onViewModelReady: (PlayVideoDialogViewModel model) async {
await model.init(); await model.init(request!.data);
}, },
builder: ( builder: (
BuildContext context, BuildContext context,
@ -34,50 +34,58 @@ class PlayVideoDialogView extends StatelessWidget {
// height: 450, // height: 450,
padding: const EdgeInsets.all(15), padding: const EdgeInsets.all(15),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: model.status != null
mainAxisSize: MainAxisSize.min, ? Column(
children: [ mainAxisSize: MainAxisSize.min,
AspectRatio( children: [
aspectRatio: 16 / 11, AspectRatio(
child: NativeVideoPlayerView( aspectRatio: 16 / 11,
onViewReady: (controller) async { child: NativeVideoPlayerView(
final videoSource = await VideoSource.init( onViewReady: (controller) async {
path: request!.data.toString(), final videoSource = await VideoSource.init(
type: VideoSourceType.file, path: model.status == 'file'
); ? model.path!
await controller.loadVideoSource(videoSource); : model.url!,
model.nativeVideoPlayerController = controller; type: model.status == 'file'
model.notifyListeners(); ? VideoSourceType.file
model.nativeVideoPlayerController!.play(); : VideoSourceType.network,
// loop video );
model.nativeVideoPlayerController!.onPlaybackEnded await controller.loadVideoSource(videoSource);
.addListener(() { model.nativeVideoPlayerController = controller;
model.nativeVideoPlayerController!.seekTo(0); model.notifyListeners();
model.nativeVideoPlayerController!.play(); model.nativeVideoPlayerController!.play();
}); // loop video
}, model.nativeVideoPlayerController!
), .onPlaybackEnded
), .addListener(() {
const SizedBox(height: 20), model.nativeVideoPlayerController!.seekTo(0);
// create button to play video model.nativeVideoPlayerController!.play();
SizedBox( });
width: 150, },
child: MyButton( ),
onPressed: () { ),
model.playVideo = !model.playVideo; const SizedBox(height: 20),
if (model.playVideo) { // create button to play video
model.nativeVideoPlayerController!.play(); SizedBox(
} else { width: 150,
model.nativeVideoPlayerController!.pause(); child: MyButton(
} onPressed: () {
model.notifyListeners(); model.playVideo = !model.playVideo;
}, if (model.playVideo) {
text: model.playVideo ? 'Pause' : 'Play', model.nativeVideoPlayerController!.play();
), } else {
), model.nativeVideoPlayerController!.pause();
], }
), model.notifyListeners();
), },
text: model.playVideo ? 'Pause' : 'Play',
),
),
],
)
: const Center(
child: CircularProgressIndicator(),
)),
), ),
); );
}, },

View File

@ -4,5 +4,14 @@ import 'package:perumahan_bew/app/core/custom_base_view_model.dart';
class PlayVideoDialogViewModel extends CustomBaseViewModel { class PlayVideoDialogViewModel extends CustomBaseViewModel {
NativeVideoPlayerController? nativeVideoPlayerController; NativeVideoPlayerController? nativeVideoPlayerController;
bool playVideo = true; bool playVideo = true;
Future<void> init() async {}
String? status;
String? url;
String? path;
Future<void> init(data) async {
status = data['status'];
url = data['url'];
path = data['path'];
}
} }

View File

@ -47,7 +47,7 @@ class SplashScreenView extends StatelessWidget {
), ),
const Expanded(child: SizedBox()), const Expanded(child: SizedBox()),
Text( Text(
'Jl. Raya Mutiara Alga No. 1, \nKec. Ciputat, Kota Tangerang Selatan, \nBanten 15412', 'Kecamatan Suppa, \nKabupaten Pinrang,\nSulawesi Selatan,91131',
style: regularTextStyle.copyWith( style: regularTextStyle.copyWith(
color: backgroundColor, color: backgroundColor,
fontSize: 12, fontSize: 12,

View File

@ -1,10 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:native_video_player/native_video_player.dart'; import 'package:native_video_player/native_video_player.dart';
import 'package:perumahan_bew/app/themes/app_text.dart'; import 'package:perumahan_bew/app/themes/app_text.dart';
import 'package:perumahan_bew/ui/widgets/my_button.dart'; import 'package:perumahan_bew/ui/widgets/my_button.dart';
import 'package:perumahan_bew/ui/widgets/my_textformfield.dart'; import 'package:perumahan_bew/ui/widgets/my_textformfield.dart';
import 'package:stacked/stacked.dart'; import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart'; import 'package:stacked_services/stacked_services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:validatorless/validatorless.dart'; import 'package:validatorless/validatorless.dart';
import '../../../app/themes/app_colors.dart'; import '../../../app/themes/app_colors.dart';
@ -70,7 +72,7 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
children: [ children: [
Center( Center(
child: Text( child: Text(
'${request!.title!} ${request!.data.toString().toUpperCase()}', '${request!.title!} ${request!.data['idPerumahan'].toString().toUpperCase()}',
style: boldTextStyle, style: boldTextStyle,
), ),
), ),
@ -94,8 +96,8 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
borderRadius: borderRadius:
BorderRadius.circular(10), BorderRadius.circular(10),
child: GestureDetector( child: GestureDetector(
onTap: () => onTap: () => model.showImage(
model.showImage(context), context, 'file', null),
child: Image.memory( child: Image.memory(
model.imageVideoBytes!, model.imageVideoBytes!,
fit: BoxFit.fill, fit: BoxFit.fill,
@ -139,30 +141,123 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
), ),
), ),
)) ))
: const Icon( : (model.progressModel != null
Icons.credit_card_rounded, ? (model.imageVideoType == 'image'
color: Colors.white, ? ClipRRect(
size: 50, borderRadius:
), BorderRadius.circular(10),
child: GestureDetector(
onTap: () => model.showImage(
context,
'network',
dotenv.env['url']! +
model.progressModel!
.img!),
child: Image.network(
dotenv.env['url']! +
model.progressModel!
.img!,
fit: BoxFit.fill,
)),
)
: ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: AspectRatio(
aspectRatio: 16 / 11,
child: NativeVideoPlayerView(
onViewReady:
(controller) async {
final videoSource =
await VideoSource.init(
path: dotenv.env['url']! +
model.progressModel!
.img!,
type: VideoSourceType
.network,
);
await controller
.loadVideoSource(
videoSource);
model.nativeVideoPlayerController =
controller;
model.notifyListeners();
model
.nativeVideoPlayerController!
.play();
// loop video
model
.nativeVideoPlayerController!
.onPlaybackEnded
.addListener(() {
model
.nativeVideoPlayerController!
.seekTo(0);
model
.nativeVideoPlayerController!
.play();
});
},
),
),
))
: const Icon(
Icons.credit_card_rounded,
color: Colors.white,
size: 50,
)),
), ),
Positioned( if (model.progressModel == null)
bottom: 0, Positioned(
right: 0, bottom: 0,
child: CircleAvatar( right: 0,
radius: 15, child: CircleAvatar(
backgroundColor: sixthGrey, radius: 15,
child: IconButton( backgroundColor: sixthGrey,
onPressed: () { child: IconButton(
model.pilihImageVideo(); onPressed: () {
}, model.pilihImageVideo();
icon: const Icon( },
Icons.add, icon: const Icon(
color: backgroundColor3, Icons.add,
size: 15, color: backgroundColor3,
size: 15,
),
),
),
),
if (model.imageVideoType == 'video')
Positioned(
bottom: 0,
left: 0,
top: 0,
right: 0,
child: Container(
alignment: Alignment.center,
child: CircleAvatar(
radius: 15,
backgroundColor: sixthGrey,
child: IconButton(
onPressed: () {
if (model.progressModel != null) {
model.playVideo(
'network',
dotenv.env['url']! +
model.progressModel!.img!);
} else {
model.playVideo(
'file', model.imageVideoPath);
}
},
icon: const Icon(
Icons.play_arrow,
color: backgroundColor3,
size: 15,
),
),
), ),
), ),
), ),
),
], ],
), ),
), ),
@ -174,54 +269,140 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
controller: model.ketController, controller: model.ketController,
validator: validator:
Validatorless.required('Keterangan harus diisi'), Validatorless.required('Keterangan harus diisi'),
readOnly: model.progressModel != null,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Center( if (model.progressModel != null)
child: SizedBox( MyTextFormField(
width: 250, labelText: 'Waktu',
child: MyButton( controller: model.waktuController,
text: 'Tambah Progress', readOnly: true,
onPressed: () { ),
if (model.imageVideoBytes == null) { if (model.progressModel == null)
model.snackbarService.showSnackbar( Center(
message: 'Gambar/video harus diisi', child: SizedBox(
); width: 250,
model.pilihImageVideo(); child: MyButton(
return; text: 'Tambah Progress',
} onPressed: () {
if (model.imageVideoBytes == null) {
model.snackbarService.showSnackbar(
message: 'Gambar/video harus diisi',
);
model.pilihImageVideo();
return;
}
if (model.globalKey.currentState!.validate()) { if (model.globalKey.currentState!.validate()) {
model.dialogService model.dialogService
.showDialog( .showDialog(
title: 'Tambah Progress', title: 'Tambah Progress',
description: 'Apakah anda yakin?', description: 'Apakah anda yakin?',
buttonTitle: 'Ya', buttonTitle: 'Ya',
cancelTitle: 'Tidak', cancelTitle: 'Tidak',
) )
.then((value) async { .then((value) async {
if (value!.confirmed) { if (value!.confirmed) {
// stop playing video // stop playing video
model.nativeVideoPlayerController?.pause(); model.nativeVideoPlayerController
model.nativeVideoPlayerController ?.pause();
?.removeListener(() { model.nativeVideoPlayerController
// model.nativeVideoPlayerController?.dispose(); ?.removeListener(() {
// model.nativeVideoPlayerController?.dispose();
model.nativeVideoPlayerController =
null;
});
model.nativeVideoPlayerController = null; model.nativeVideoPlayerController = null;
});
model.nativeVideoPlayerController = null;
// add progress // add progress
bool res = await model.tambahProgress(); bool res = await model.tambahProgress();
model.log.i('res: $res'); model.log.i('res: $res');
completer!(SheetResponse( completer!(SheetResponse(
confirmed: true, confirmed: true,
)); ));
} }
}); });
} }
}, },
),
), ),
), ),
), if (model.level == 'Pemilik Rumah' &&
model.mandorModel != null)
Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 20),
MyTextFormField(
labelText: 'Mandor',
controller: model.mandorController,
readOnly: true,
),
const SizedBox(height: 20),
MyTextFormField(
labelText: 'No. Telp Mandor',
controller: model.noHpController,
readOnly: true,
),
const SizedBox(height: 20),
// create row with 2 rounded icon , one is chat whatsapp , one is call
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
radius: 15,
backgroundColor: greenColor,
child: IconButton(
onPressed: () async {
// model.openWhatsapp();
String noTelpon =
model.noHpController!.text;
// convert the number to international format
noTelpon = noTelpon.replaceAll(
RegExp(r'[^0-9]'), '');
noTelpon = '62${noTelpon.substring(1)}';
// log.i('no_telpon: $noTelpon');
final url =
Uri.parse('https://wa.me/$noTelpon');
if (!await launchUrl(url)) {
throw Exception(
'Could not launch $url');
}
},
icon: const Icon(
Icons.chat,
color: backgroundColor3,
size: 15,
),
),
),
const SizedBox(width: 20),
CircleAvatar(
radius: 15,
backgroundColor: mainColor,
child: IconButton(
onPressed: () async {
// model.callPhone();
final Uri callUri = Uri(
scheme: 'tel',
path: model.noHpController!.text);
if (!await launchUrl(callUri)) {
throw 'Could not launch ${callUri.toString()}';
}
},
icon: const Icon(
Icons.call,
color: backgroundColor3,
size: 15,
),
),
),
],
),
],
),
], ],
), ),
), ),

View File

@ -5,22 +5,31 @@ import 'package:easy_image_viewer/easy_image_viewer.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:native_video_player/native_video_player.dart'; import 'package:native_video_player/native_video_player.dart';
import 'package:perumahan_bew/model/rumah_model.dart';
import '../../../app/app.dialogs.dart'; import '../../../app/app.dialogs.dart';
import '../../../app/app.logger.dart'; import '../../../app/app.logger.dart';
import '../../../app/core/custom_base_view_model.dart'; import '../../../app/core/custom_base_view_model.dart';
import '../../../app/themes/app_colors.dart'; import '../../../app/themes/app_colors.dart';
import '../../../model/my_response_model.dart';
class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel { class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
final log = getLogger('TambahLihatProgressBottomSheetViewModel'); final log = getLogger('TambahLihatProgressBottomSheetViewModel');
NativeVideoPlayerController? nativeVideoPlayerController; NativeVideoPlayerController? nativeVideoPlayerController;
String? level;
MandorModel? mandorModel;
TextEditingController? mandorController = TextEditingController();
TextEditingController? noHpController = TextEditingController();
String? idPerumahan; String? idPerumahan;
ProgressModel? progressModel;
// form variable // form variable
final globalKey = GlobalKey<FormState>(); final globalKey = GlobalKey<FormState>();
TextEditingController? ketController = TextEditingController(); TextEditingController? ketController = TextEditingController();
TextEditingController? waktuController = TextEditingController();
// image video variable // image video variable
// image picker // image picker
@ -29,9 +38,40 @@ class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
XFile? imageVideoFile; XFile? imageVideoFile;
Uint8List? imageVideoBytes; Uint8List? imageVideoBytes;
String? imageVideoType; String? imageVideoType;
Future<void> init(String data) async { Future<void> init(data) async {
globalVar.backPressed = "exitApp"; globalVar.backPressed = "exitApp";
idPerumahan = data; idPerumahan = data['idPerumahan'];
// log.i(data['progressModel']);
if (data['progressModel'] != null) {
progressModel = data['progressModel'];
ketController!.text = progressModel!.ket!;
waktuController!.text = progressModel!.createdAt!;
log.i('type: ${progressModel!.type}');
imageVideoType = progressModel!.type;
}
level = await mySharedPrefs.getString('level');
if (level == 'Pemilik Rumah') {
await getData();
}
}
getData() async {
setBusy(true);
try {
var response =
await httpService.get('mandor?id=${progressModel!.idMandor}');
MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data);
mandorModel = MandorModel.fromJson(myResponseModel.data);
log.i('mandorModel: ${mandorModel!.nama}');
mandorController!.text = mandorModel!.nama!;
noHpController!.text = mandorModel!.noTelpon!;
} catch (e) {
log.e('Error: $e');
} finally {
setBusy(false);
}
} }
addImage(String type) async { addImage(String type) async {
@ -79,13 +119,20 @@ class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
}); });
} }
playVideo() async { playVideo(String status, String? url) async {
// play video by imageVideoPath // play video by imageVideoPath
log.i('play video');
log.i(status);
log.i(url);
await dialogService.showCustomDialog( await dialogService.showCustomDialog(
variant: DialogType.playVideoDialogView, variant: DialogType.playVideoDialogView,
title: 'Video', title: 'Video',
data: imageVideoPath, data: {
'status': status,
'url': url,
'path': imageVideoPath,
},
); );
} }
@ -117,13 +164,20 @@ class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
} }
} }
showImage(BuildContext context) async { showImage(BuildContext context, String status, String? url) async {
log.i(status);
log.i(url);
showImageViewer( showImageViewer(
context, context,
Image.memory( status == 'file'
imageVideoBytes!, ? Image.memory(
fit: BoxFit.fill, imageVideoBytes!,
).image, fit: BoxFit.fill,
).image
: Image.network(
url!,
fit: BoxFit.fill,
).image,
swipeDismissible: true, swipeDismissible: true,
doubleTapZoomable: true, doubleTapZoomable: true,
); );

View File

@ -1,69 +0,0 @@
import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:webview_flutter/webview_flutter.dart';
import './user_home_view_model.dart';
class UserHomeView extends StatelessWidget {
const UserHomeView({super.key});
@override
Widget build(BuildContext context) {
return ViewModelBuilder<UserHomeViewModel>.nonReactive(
viewModelBuilder: () => UserHomeViewModel(),
onViewModelReady: (UserHomeViewModel model) async {
await model.init();
},
disposeViewModel: false,
fireOnViewModelReadyOnce: true,
builder: (
BuildContext context,
UserHomeViewModel model,
Widget? child,
) {
return Scaffold(
body: WebView(
// initialUrl: 'http://192.168.43.125/rekam-medis',
initialUrl: 'http://20.20.20.25/perumahan',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
// _controller.complete(webViewController);
model.webViewControllerCompleter.future
.then((value) => model.webVIewcontroller = value);
model.webViewControllerCompleter.complete(webViewController);
},
onProgress: (int progress) {
double progressDouble = progress / 100;
model.myEasyLoading.showProgress(progressDouble, "Loading Denah");
},
// javascriptChannels: <JavascriptChannel>{
// _toasterJavascriptChannel(context),
// },
javascriptChannels: <JavascriptChannel>{
JavascriptChannel(
name: 'messageHandler',
onMessageReceived: (JavascriptMessage message) {
model.log.d(message.message);
// dev.i("message from the web view=\"${message.message}\"");
// if (message.message == "coba") {
// dev.i("sini untuk coba");
// controller.runJavascript("coba22('heheheh')");
// }
},
),
},
// navigationDelegate: (NavigationRequest request) async {},
onPageStarted: (String url) {},
onPageFinished: (String url) {
// dev.i('Page finished loading: $url');
model.myEasyLoading.dismissLoading();
},
gestureNavigationEnabled: true,
backgroundColor: const Color(0x00000000),
),
);
},
);
}
}

View File

@ -1,25 +0,0 @@
import 'dart:async';
import 'dart:io';
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_easyloading.dart';
class UserHomeViewModel extends CustomBaseViewModel {
final log = getLogger('UserHomeViewModel');
final _myEasyLoading = locator<MyEasyLoading>();
get myEasyLoading => _myEasyLoading;
late WebViewController webVIewcontroller;
final Completer<WebViewController> webViewControllerCompleter =
Completer<WebViewController>();
Future<void> init() async {
if (Platform.isAndroid) {
WebView.platform = SurfaceAndroidWebView();
}
}
}

View File

@ -38,10 +38,22 @@ class UserIndexView extends StatelessWidget {
backgroundColor: mainColor, backgroundColor: mainColor,
elevation: 0, elevation: 0,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
actions: [
// create logout button
IconButton(
onPressed: () {
model.logout();
},
icon: const Icon(
Icons.logout,
color: Colors.white,
),
),
],
), ),
// extendBody: true, // extendBody: true,
body: ExtendedNavigator( body: ExtendedNavigator(
navigatorKey: StackedService.nestedNavigationKey(2), navigatorKey: StackedService.nestedNavigationKey(7),
router: UserIndexViewRouter(), router: UserIndexViewRouter(),
), ),
bottomNavigationBar: StylishBottomBar( bottomNavigationBar: StylishBottomBar(

View File

@ -5,10 +5,14 @@ import 'package:stacked_services/stacked_services.dart';
import '../../../app/app.locator.dart'; import '../../../app/app.locator.dart';
import '../../../app/app.logger.dart'; import '../../../app/app.logger.dart';
import '../../../app/app.router.dart'; import '../../../app/app.router.dart';
import '../../../services/shared_prefs.dart';
class UserIndexViewModel extends IndexTrackingViewModel { class UserIndexViewModel extends IndexTrackingViewModel {
final log = getLogger('UserIndexViewModel'); final log = getLogger('UserIndexViewModel');
final _navigationService = locator<NavigationService>(); final _navigationService = locator<NavigationService>();
final _dialogService = locator<DialogService>();
final _mySharedPrefs = locator<MySharedPrefs>();
final _snackbarService = locator<SnackbarService>();
final _bottomNavBarList = [ final _bottomNavBarList = [
{ {
@ -16,22 +20,18 @@ class UserIndexViewModel extends IndexTrackingViewModel {
'icon': Icons.list_alt_rounded, 'icon': Icons.list_alt_rounded,
'header': 'List Perumahan' 'header': 'List Perumahan'
}, },
{'name': 'Denah', 'icon': Icons.home_outlined, 'header': 'Denah Perumahan'},
{'name': 'Profil', 'icon': Icons.person_outline, 'header': 'Profil'}, {'name': 'Profil', 'icon': Icons.person_outline, 'header': 'Profil'},
]; ];
List<Map<String, dynamic>> get bottomNavBarList => _bottomNavBarList; List<Map<String, dynamic>> get bottomNavBarList => _bottomNavBarList;
final List<String> _views = [ final List<String> _views = [
UserIndexViewRoutes.userListPembangunanView, UserIndexViewRoutes.userListPembangunanPageView,
UserIndexViewRoutes.userHomeView,
UserIndexViewRoutes.userProfileView, UserIndexViewRoutes.userProfileView,
]; ];
String header = 'Denah Perumahan'; String header = 'Denah Perumahan';
Future<void> init() async { Future<void> init() async {}
setIndex(1);
}
void handleNavigation(int index) { void handleNavigation(int index) {
log.d("handleNavigation: $index"); log.d("handleNavigation: $index");
@ -43,7 +43,29 @@ class UserIndexViewModel extends IndexTrackingViewModel {
header = _bottomNavBarList[index]['header'] as String; header = _bottomNavBarList[index]['header'] as String;
_navigationService.navigateTo( _navigationService.navigateTo(
_views[index], _views[index],
id: 2, id: 7,
); );
} }
logout() {
_dialogService
.showConfirmationDialog(
title: 'Logout',
description: 'Apakah Anda yakin ingin logout?',
cancelTitle: 'Batal',
confirmationTitle: 'Logout',
)
.then((value) async {
if (value!.confirmed) {
await _mySharedPrefs.clear();
_navigationService.clearStackAndShow(Routes.loginScreenView);
_snackbarService.showSnackbar(
message: 'Logout berhasil',
duration: const Duration(seconds: 2),
);
}
});
// await _mySharedPrefs.clear();
// _navigationService.clearStackAndShow(Routes.loginScreenView);
}
} }

View File

@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:perumahan_bew/ui/views/user_index/user_list_pembangunan/user_list_pembangunan_view.dart';
import 'package:stacked/stacked.dart';
import './user_list_pembangunan_page_view_model.dart';
class UserListPembangunanPageView extends StatelessWidget {
const UserListPembangunanPageView({super.key});
@override
Widget build(BuildContext context) {
return ViewModelBuilder<UserListPembangunanPageViewModel>.nonReactive(
viewModelBuilder: () => UserListPembangunanPageViewModel(),
onViewModelReady: (UserListPembangunanPageViewModel model) async {
await model.init();
},
builder: (
BuildContext context,
UserListPembangunanPageViewModel model,
Widget? child,
) {
return const UserListPembangunanView();
},
);
}
}

View File

@ -0,0 +1,5 @@
import 'package:perumahan_bew/app/core/custom_base_view_model.dart';
class UserListPembangunanPageViewModel extends CustomBaseViewModel {
Future<void> init() async {}
}

View File

@ -25,24 +25,14 @@ class UserListPembangunanView extends StatelessWidget {
body: Column( body: Column(
children: [ children: [
const SizedBox(height: 20), const SizedBox(height: 20),
const Padding( Padding(
padding: EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row( child: MyTopWidget(
mainAxisAlignment: MainAxisAlignment.spaceBetween, icon: Icons.list_alt_outlined,
children: [ title: 'Pembangunan',
MyTopWidget( subtitle:
icon: Icons.list_alt_outlined, '${model.listProgress != null ? model.listProgress!.length : 0} Progress',
title: 'Pembangunan', // lastUpdate: '31/02/15 - 10.00 am',
subtitle: '15 kali',
// lastUpdate: '31/02/15 - 10.00 am',
),
MyTopWidget(
icon: Icons.home,
title: 'Progress',
subtitle: '76 %',
// lastUpdate: '31/02/15 - 10.00 am',
),
],
), ),
), ),
const SizedBox(height: 25), const SizedBox(height: 25),
@ -63,27 +53,47 @@ class UserListPembangunanView extends StatelessWidget {
], ],
), ),
// create a listview with 20 dummy data on card and scrollable // create a listview with 20 dummy data on card and scrollable
child: ListView.builder( child: model.isBusy
padding: const EdgeInsets.symmetric( ? const Center(child: CircularProgressIndicator())
horizontal: 10, vertical: 10), : model.status == false
itemCount: 20, ? const Center(child: Text('Error Loading Data'))
itemBuilder: (context, index) { : model.listProgress!.isEmpty
return Card( ? const Center(child: Text('Data Kosong'))
child: GestureDetector( : ListView.builder(
onTap: () { padding: const EdgeInsets.symmetric(
model.log.i('Card $index tapped'); horizontal: 10, vertical: 10),
}, itemCount: model.listProgress!.length,
child: ListTile( itemBuilder: (context, index) {
title: Text('1/02/15 - 10.00 am', return Card(
style: boldTextStyle.copyWith( child: ListTile(
fontSize: 13, color: mainColor)), title: Text(
subtitle: Text('Progress $index'), model.listProgress![index]
trailing: Text('Pembangunan $index'), .createdAt!,
), style: boldTextStyle.copyWith(
), fontSize: 13,
); color: mainColor,
}, ),
)), ),
subtitle: Text(model
.listProgress![index].ket!),
// create icon show
trailing: CircleAvatar(
backgroundColor: mainColor,
child: IconButton(
icon: const Icon(
Icons.list_alt_outlined,
color: backgroundColor,
),
onPressed: () {
model.checkProgress(model
.listProgress![index]);
},
),
),
),
);
},
)),
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),

View File

@ -1,8 +1,52 @@
import 'package:perumahan_bew/app/core/custom_base_view_model.dart'; import 'package:perumahan_bew/model/rumah_model.dart';
import '../../../../app/app.bottomsheets.dart';
import '../../../../app/app.logger.dart'; import '../../../../app/app.logger.dart';
import '../../../../app/core/custom_base_view_model.dart';
import '../../../../model/my_response_model.dart';
class UserListPembangunanViewModel extends CustomBaseViewModel { class UserListPembangunanViewModel extends CustomBaseViewModel {
final log = getLogger('UserListPembangunanViewModel'); final log = getLogger('UserListPembangunanViewModel');
Future<void> init() async {} bool status = false;
RumahDetailModel? rumahDetailModel;
RumahModel? rumahModel;
List<ProgressModel>? listProgress;
Future<void> init() async {
String idRumah = await mySharedPrefs.getString('id') ?? '';
if (idRumah.isNotEmpty) {
await getData(idRumah);
}
}
getData(String idRumah) async {
setBusy(true);
try {
var response = await httpService.get('rumah?id=$idRumah');
MyResponseModel myResponse = MyResponseModel.fromJson(response.data);
// log.i(myResponse.toJson());
RumahDetailModel rumahDetailModel =
RumahDetailModel.fromJson(myResponse.data);
listProgress = rumahDetailModel.progressModel;
status = true;
} catch (e) {
status = false;
log.e(e);
} finally {
setBusy(false);
}
}
checkProgress(ProgressModel progressModel) async {
await bottomSheetService.showCustomSheet(
variant: BottomSheetType.tambahLihatProgressBottomSheetView,
title: 'Lihat Progress',
data: {
'idPerumahan': progressModel.idRumah,
'progressModel': progressModel,
},
);
}
} }

View File

@ -21,99 +21,118 @@ class UserProfileView extends StatelessWidget {
Widget? child, Widget? child,
) { ) {
return Scaffold( return Scaffold(
body: Stack( body: SafeArea(
children: [ child: Padding(
Column( padding: const EdgeInsets.all(20),
child: Stack(
children: [ children: [
const SizedBox( Column(
height: 25, children: [
), // create a rounded container
// create a rounded container Center(
Center( child: Stack(
child: Container(
width: 150,
height: 150,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: const NetworkImage(
'http://kicap-karan.com/assets/img/me.jpg',
),
fit: BoxFit.cover,
onError: (exception, stackTrace) {
model.log.e('Error: $exception');
},
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 7,
offset: const Offset(0, 3),
),
],
),
),
),
const SizedBox(
height: 15,
),
Center(
child: Text(
'Kicap Karan',
style: boldTextStyle.copyWith(
fontSize: 18,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 10),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
for (var i = 0; i < 10; i++) const _DetailChild(), const CircleAvatar(
radius: 50,
backgroundColor: fontParagraphColor,
// child: model.imageBytes == null
// ? const Icon(
// Icons.person,
// size: 50,
// color: Colors.white,
// )
// : ClipRRect(
// borderRadius: BorderRadius.circular(50),
// child: Image.memory(
// model.imageBytes!,
// width: 100,
// height: 100,
// fit: BoxFit.cover,
// ),
// ),
child: Icon(
Icons.person,
size: 50,
color: Colors.white,
),
),
Positioned(
bottom: 0,
right: 0,
child: CircleAvatar(
radius: 15,
backgroundColor: mainColor,
child: IconButton(
onPressed: () {
// model.addImage();
},
icon: const Icon(
Icons.add,
color: fontColor,
size: 15,
)),
),
),
], ],
), ),
), ),
), if (!model.isBusy &&
model.status == true &&
model.rumahModel != null)
Expanded(
child: Column(
children: [
const SizedBox(
height: 15,
),
_DetailChild(
text: model.rumahModel!.pemilik!,
icon: Icons.person,
),
_DetailChild(
text: model.rumahModel!.tanggalPembelian!,
icon: Icons.calendar_today_outlined,
),
_DetailChild(
text: "Rp. ${model.rumahModel!.harga!}",
icon: Icons.attach_money_outlined,
),
_DetailChild(
text: 'Rp. ${model.rumahModel!.cicilan!}',
icon: Icons.money_outlined,
),
],
),
),
if (model.isBusy)
const Expanded(
child: Center(
child: CircularProgressIndicator(),
),
),
],
), ),
const SizedBox( // create rounded button with edit on top right
height: 15, Positioned(
top: 0,
right: 0,
child: CircleAvatar(
radius: 15,
backgroundColor: mainColor,
child: IconButton(
onPressed: () {
// model.addImage();
},
icon: const Icon(
Icons.edit,
color: fontColor,
size: 15,
)),
),
), ),
], ],
), ),
Positioned( ),
top: 15,
right: 65,
child: IconButton(
onPressed: () {
model.log.i('Edit Profile');
},
icon: const Icon(
Icons.edit,
color: mainColor,
size: 30,
),
),
),
Positioned(
top: 15,
right: 15,
child: IconButton(
onPressed: () {
model.log.i('Logout');
model.logout();
},
icon: const Icon(
Icons.logout,
color: mainColor,
size: 30,
),
)),
],
), ),
); );
}, },
@ -124,8 +143,13 @@ class UserProfileView extends StatelessWidget {
class _DetailChild extends StatelessWidget { class _DetailChild extends StatelessWidget {
const _DetailChild({ const _DetailChild({
Key? key, Key? key,
required this.text,
required this.icon,
}) : super(key: key); }) : super(key: key);
final String text;
final IconData icon;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
@ -133,8 +157,8 @@ class _DetailChild extends StatelessWidget {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
const Icon( Icon(
Icons.maps_home_work_outlined, icon,
color: mainColor, color: mainColor,
size: 40, size: 40,
), ),
@ -142,7 +166,7 @@ class _DetailChild extends StatelessWidget {
width: 20, width: 20,
), ),
Text( Text(
'Jln 2, Blok C, No 2', text,
style: regularTextStyle.copyWith( style: regularTextStyle.copyWith(
fontSize: 15, fontSize: 15,
color: mainGrey, color: mainGrey,

View File

@ -1,11 +1,43 @@
import 'package:perumahan_bew/app/core/custom_base_view_model.dart'; import 'package:perumahan_bew/app/core/custom_base_view_model.dart';
import '../../../../app/app.logger.dart'; import '../../../../app/app.logger.dart';
import '../../../../model/my_response_model.dart';
import '../../../../model/rumah_model.dart';
class UserProfileViewModel extends CustomBaseViewModel { class UserProfileViewModel extends CustomBaseViewModel {
final log = getLogger('UserProfileViewModel'); final log = getLogger('UserProfileViewModel');
RumahDetailModel? rumahDetailModel;
RumahModel? rumahModel;
bool status = false;
String? idRumah;
Future<void> init() async {} Future<void> init() async {
idRumah = await mySharedPrefs.getString('id') ?? '';
if (idRumah != '') {
await getData();
}
// await getData();
}
getData() async {
setBusy(true);
try {
var response = await httpService.get('rumah?id=$idRumah');
MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data);
// log.i('myResponseModel: ${myResponseModel.data}');
rumahDetailModel = RumahDetailModel.fromJson(myResponseModel.data);
rumahModel = rumahDetailModel!.rumahModel;
// rumahModel = RumahModel.fromJson(myResponseModel.data);
log.i('rumahModel: ${rumahModel!.toJson()}');
status = true;
} catch (e) {
log.e('Error: $e');
status = false;
} finally {
setBusy(false);
}
}
logout() { logout() {
log.i('logout'); log.i('logout');

View File

@ -7,9 +7,13 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h> #include <file_selector_linux/file_selector_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar); file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
} }

View File

@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux file_selector_linux
url_launcher_linux
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@ -6,13 +6,13 @@ import FlutterMacOS
import Foundation import Foundation
import file_selector_macos import file_selector_macos
import location
import path_provider_foundation import path_provider_foundation
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
} }

View File

@ -512,30 +512,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
location:
dependency: "direct main"
description:
name: location
sha256: "9051959f6f2ccadd887b28b66e9cbbcc25b6838e37cf9e894c421ccc0ebf80b5"
url: "https://pub.dev"
source: hosted
version: "4.4.0"
location_platform_interface:
dependency: transitive
description:
name: location_platform_interface
sha256: "62eeaf1658e92e4459b727f55a3c328eccbac8ba043fa6d262ac5286ad48384c"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
location_web:
dependency: transitive
description:
name: location_web
sha256: "6c08c408a040534c0269c4ff9fe17eebb5a36dea16512fbaf116b9c8bc21545b"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
logger: logger:
dependency: transitive dependency: transitive
description: description:
@ -949,6 +925,70 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.2.2"
url_launcher:
dependency: "direct main"
description:
name: url_launcher
sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
url: "https://pub.dev"
source: hosted
version: "6.1.14"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def"
url: "https://pub.dev"
source: hosted
version: "6.2.0"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a"
url: "https://pub.dev"
source: hosted
version: "6.2.0"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
url: "https://pub.dev"
source: hosted
version: "3.1.0"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2
url: "https://pub.dev"
source: hosted
version: "2.0.19"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
validatorless: validatorless:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -42,7 +42,7 @@ dependencies:
path_provider: ^2.0.9 path_provider: ^2.0.9
dio: dio:
flutter_easyloading: flutter_easyloading:
location: ^4.4.0 # location: ^4.4.0
# flutter_inappwebview: # flutter_inappwebview:
webview_flutter: ^3.0.4 webview_flutter: ^3.0.4
google_fonts: google_fonts:
@ -54,6 +54,7 @@ dependencies:
omni_datetime_picker: omni_datetime_picker:
easy_image_viewer: easy_image_viewer:
native_video_player: native_video_player:
url_launcher:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -7,8 +7,11 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <file_selector_windows/file_selector_windows.h> #include <file_selector_windows/file_selector_windows.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSelectorWindowsRegisterWithRegistrar( FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows")); registry->GetRegistrarForPlugin("FileSelectorWindows"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
} }

View File

@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows file_selector_windows
url_launcher_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST