diff --git a/android/app/build.gradle b/android/app/build.gradle index 949d735c2e09caad3767de420457f69704a9ffc7..13a35987ea5b3251dbfb11c3cd4691666676675d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -83,7 +83,9 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - implementation 'com.google.firebase:firebase-analytics:17.2.2' + implementation 'com.google.firebase:firebase-analytics:' + implementation 'com.google.firebase:firebase-messaging:' + implementation 'com.google.firebase:firebase-bom:27.0.0' } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1f97511f590b7b1544051a848826375aa519b607..a5e2d872446dcba91f284c1a290bcdf91e5e2376 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -39,6 +39,10 @@ + + + + @@ -47,5 +51,13 @@ android:value="2" /> + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/transparent_icon.png b/android/app/src/main/res/mipmap-hdpi/transparent_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8fddc349c3a2e79088ca668cc9455ba3f3ae59e Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/transparent_icon.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/transparent_icon.png b/android/app/src/main/res/mipmap-mdpi/transparent_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8fddc349c3a2e79088ca668cc9455ba3f3ae59e Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/transparent_icon.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/transparent_icon.png b/android/app/src/main/res/mipmap-xhdpi/transparent_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8fddc349c3a2e79088ca668cc9455ba3f3ae59e Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/transparent_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/transparent_icon.png b/android/app/src/main/res/mipmap-xxhdpi/transparent_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8fddc349c3a2e79088ca668cc9455ba3f3ae59e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/transparent_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/transparent_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/transparent_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f8fddc349c3a2e79088ca668cc9455ba3f3ae59e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/transparent_icon.png differ diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 87856b3c9cb06fa2bb9d86addf32a3c87fa2d872..368aefd74099a743712b2993745612fe34bb2c5e 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,3 +1,4 @@ #3A903A + #3A903A diff --git a/android/fastlane/metadata/android/id/changelogs/changelogs.txt b/android/fastlane/metadata/android/id/changelogs/changelogs.txt index 659bd954cefc3eb64aba4567f954bb3e78a70e18..ba07351967ac3878978a5ff5011ae77056a734ca 100644 --- a/android/fastlane/metadata/android/id/changelogs/changelogs.txt +++ b/android/fastlane/metadata/android/id/changelogs/changelogs.txt @@ -1,20 +1,23 @@ +3.5.0: +- Pengguna dapat mengganti foto profil + +3.4.0: +- Notifikasi pengguna untuk komentar baru + 3.3.0: -- New feature for add kegiatan -- Fix bugs +- Kegiatan disabilitas di suatu lokasi +- Perbaikan bugs 3.2.1: -- Fix cant update fasilitas +- Perbaikan masalah update fasilitas 3.2.0: -- New feature share fasilitas as a link +- Tersedia fitur membagikan informasi fasilitas/kegiatan disabilitas kepada orang lain 3.1.2: -- Fix google oauth +- Perbaikan masuk dengan Google 3.1.1: -- Add dialog to turn on Location services upon starting the app -- New feature for layanan search -- Add feature to upload image for a fasilitas straight from the camera -- Add default image for facilities -- Add search history feature -- Now all fields are required in edit profile +- Tersedia fitur pencarian layanan +- Tersedia pilihan kamera ketika menambahkan gambar fasilitas +- Tersedia fitur riwayat pencarian diff --git a/lib/bloc/cloud_messaging_bloc.dart b/lib/bloc/cloud_messaging_bloc.dart new file mode 100644 index 0000000000000000000000000000000000000000..b91d3807ed2b8cfc56b8e8746c6ed3613207d87c --- /dev/null +++ b/lib/bloc/cloud_messaging_bloc.dart @@ -0,0 +1,26 @@ +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; +import 'package:get_it/get_it.dart'; +import 'package:http/http.dart'; + +class CloudMessagingBloc { + CloudMessagingRepository _cloudMessagingRepository; + + CloudMessagingBloc() { + _cloudMessagingRepository = + GetIt.instance.get(); + } + + Future sendFCMToken( + String fcmToken, + String token, + ) async { + try { + return await _cloudMessagingRepository.sendFCMToken( + fcmToken, + token, + ); + } catch (e) { + return Response('Failed to add komentar', 400); + } + } +} diff --git a/lib/bloc/new_user_bloc.dart b/lib/bloc/new_user_bloc.dart deleted file mode 100644 index 90b1b2dc860f0b618efc1e309ef8baa26401fc7e..0000000000000000000000000000000000000000 --- a/lib/bloc/new_user_bloc.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'dart:async'; - -import 'package:bisaGo/model/new_user.dart'; -import 'package:bisaGo/network/data/network_model.dart'; -import 'package:bisaGo/repository/user_repository.dart'; -import 'package:get_it/get_it.dart'; -import 'package:http/http.dart'; - -class NewUserBloc { - UserRepository _userRepository; - StreamController _userController; - - NewUserBloc() { - _userController = StreamController>(); - _userRepository = GetIt.instance.get(); - } - - Future registerNewUser(NewUser newUser) async { - try { - return await _userRepository.createUser(newUser); - } catch (_) { - return Response('Failed to register user', 400); - } - } - - Future updateUser(NewUser newUser) async { - try { - return await _userRepository.updateUser(newUser); - } catch (_) { - return Response('Failed to update user', 400); - } - } - - void dispose() { - _userController?.close(); - } -} diff --git a/lib/bloc/user_bloc.dart b/lib/bloc/user_bloc.dart index b6b155495f76894e5dc4ed6d0d015125b6af78d4..3ff261e757868bb830c20504f0264cc88758ee23 100644 --- a/lib/bloc/user_bloc.dart +++ b/lib/bloc/user_bloc.dart @@ -8,39 +8,54 @@ import 'package:get_it/get_it.dart'; class UserBloc { UserRepository _userRepository; StreamController _userController; - List userFromApi; + String email; - StreamSink> get userSink => _userController.sink; - Stream> get userStream => _userController.stream; + StreamSink> get userSink => + _userController.sink; - UserBloc(String email) { - _userController = StreamController>(); + Stream> get userStream => + _userController.stream; + + UserBloc({this.email}) { + _userController = StreamController>(); _userRepository = GetIt.instance.get(); - fetchUserDetail(email); } - Future fetchUserDetail(String email) async { + Future fetchUserDetail() async { userSink.add(NetworkModel.loading('Getting user')); + final response = await getUserDetail(email); + if (response is DetailUserModel) { + userSink.add(NetworkModel.completed(response)); + } else { + userSink.add(NetworkModel.error('Gagal untuk mendapatkan profile')); + } + } + + Future getUserDetail(String email) async { try { - final userResponse = await _userRepository.fetchUserDetail(email); - userFromApi = List.from(userResponse.user); - userSink.add(NetworkModel.completed(userResponse)); + return await _userRepository.fetchUserDetail(email); } catch (e) { - if (!_userController.isClosed) { - userSink.add(NetworkModel.error(e.toString())); - } + return e; } } - Future fetchUser(String email) async { + Future updateUser(UpdateUserModel updateUser) async { try { - await fetchUserDetail(email); - return userFromApi.first; - } catch (e) { + return await _userRepository.updateUser(updateUser, email); + } catch (_) { return null; } } + Future registerNewUser(RegisterUserModel registerUserModel) async { + try { + await _userRepository.registerUser(registerUserModel); + return true; + } catch (_) { + return false; + } + } + void dispose() { _userController?.close(); } diff --git a/lib/component/bisago_appbar.dart b/lib/component/bisago_appbar.dart index fdf8b479254dd3e77c502f20b47b654d7706528c..fbd07f49cd6fea0f79f9f1b5c934847493dec912 100644 --- a/lib/component/bisago_appbar.dart +++ b/lib/component/bisago_appbar.dart @@ -5,17 +5,24 @@ class BisaGoAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final List actions; final Widget leading; + final backgroundColor; + const BisaGoAppBar( - {this.title = 'bisaGo', this.actions = const [], this.leading, Key key}) + {this.title = 'bisaGo', + this.actions = const [], + this.backgroundColor = greenPrimary, + this.leading, + Key key}) : super(key: key); @override final Size preferredSize = const Size.fromHeight(55); + @override Widget build(BuildContext context) { return AppBar( elevation: 15, centerTitle: true, - backgroundColor: greenPrimary, + backgroundColor: backgroundColor, automaticallyImplyLeading: leading == null, leading: leading, title: Row( diff --git a/lib/component/bisago_drawer.dart b/lib/component/bisago_drawer.dart index 7e45592100ef351c75abc7c430f30c47a3a6df6c..05a78c6b2a6802e88b946f9cedbb9a2b89161622 100644 --- a/lib/component/bisago_drawer.dart +++ b/lib/component/bisago_drawer.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:bisaGo/page/informasi/list_sekolah.dart'; import 'package:bisaGo/page/profile/profile.dart'; import 'package:bisaGo/page/tentang_disabilitas/tentang_disabilitas.dart'; @@ -168,7 +170,8 @@ class BisaGoDrawer extends StatelessWidget { if (sharedPreferences.getString('token') == null) { return 'Selamat datang ke BisaGo!'; } else { - return sharedPreferences.getString('email'); + final userJson = jsonDecode(sharedPreferences.getString('user')); + return userJson['email']; } } diff --git a/lib/get_it.dart b/lib/get_it.dart index aec9e26401134f3efe2a7fb71aa355c296723af8..18eee1bab5e09e5cc8f09d930607bbca50fca5ea 100644 --- a/lib/get_it.dart +++ b/lib/get_it.dart @@ -1,3 +1,4 @@ +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; import 'package:bisaGo/repository/kegiatan_repository.dart'; import 'package:bisaGo/repository/kegiatan_terdekat_repository.dart'; import 'package:bisaGo/repository/komentar_posting_kegiatan_repository.dart'; @@ -26,8 +27,8 @@ class AppGetIt { () => KomentarPostingRepository()); _getIt.registerLazySingleton( () => KomentarPostingKegiatanRepository()); - _getIt.registerLazySingleton( - () => LokasiRepository()); + _getIt + .registerLazySingleton(() => LokasiRepository()); _getIt.registerLazySingleton( () => LayananRepository()); _getIt.registerLazySingleton( @@ -36,5 +37,7 @@ class AppGetIt { () => KegiatanTerdekatRepository()); _getIt.registerLazySingleton( () => DynamicLinksServiceRepository()); + _getIt.registerLazySingleton( + () => CloudMessagingRepository()); } } diff --git a/lib/main.dart b/lib/main.dart index 1d165eef77fee709f6375504b06482b9e8eb1c24..aa484a721f869e7d5b49ed157fad3b804874eac0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ -import 'package:bisaGo/get_it.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:bisaGo/app.dart'; import 'package:intl/date_symbol_data_local.dart'; @@ -6,14 +7,24 @@ import 'package:intl/intl.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'flavor/flavor.dart'; import 'globalnetwork.dart'; +import 'package:bisaGo/get_it.dart'; + +Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { + // If you're going to use other Firebase services in the background, such as Firestore, + // make sure you call `initializeApp` before using other Firebase services. + await Firebase.initializeApp(); + + print('Handling a background message: ${message.messageId}'); +} Future main() async { AppGetIt().initialize(); await DotEnv().load('.env'); getDioInstance('build'); await initializeDateFormatting('id_ID', null); + FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); Intl.defaultLocale = 'id_ID'; dio.options.receiveTimeout = 15000; - ApiFlavor.flavor = BuildFlavor.production.toString(); + ApiFlavor.flavor = BuildFlavor.development.toString(); runApp(BisaGo()); } diff --git a/lib/main_dev.dart b/lib/main_dev.dart index 564a4551c4cf8d531231ab10c220db35194bc332..aa484a721f869e7d5b49ed157fad3b804874eac0 100644 --- a/lib/main_dev.dart +++ b/lib/main_dev.dart @@ -1,3 +1,5 @@ +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:bisaGo/app.dart'; import 'package:intl/date_symbol_data_local.dart'; @@ -7,11 +9,20 @@ import 'flavor/flavor.dart'; import 'globalnetwork.dart'; import 'package:bisaGo/get_it.dart'; +Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { + // If you're going to use other Firebase services in the background, such as Firestore, + // make sure you call `initializeApp` before using other Firebase services. + await Firebase.initializeApp(); + + print('Handling a background message: ${message.messageId}'); +} + Future main() async { AppGetIt().initialize(); await DotEnv().load('.env'); getDioInstance('build'); await initializeDateFormatting('id_ID', null); + FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); Intl.defaultLocale = 'id_ID'; dio.options.receiveTimeout = 15000; ApiFlavor.flavor = BuildFlavor.development.toString(); diff --git a/lib/main_staging.dart b/lib/main_staging.dart index 564412ca6f2eb6921c61d526856607902958ba8f..aa484a721f869e7d5b49ed157fad3b804874eac0 100644 --- a/lib/main_staging.dart +++ b/lib/main_staging.dart @@ -1,3 +1,5 @@ +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:bisaGo/app.dart'; import 'package:intl/date_symbol_data_local.dart'; @@ -7,13 +9,22 @@ import 'flavor/flavor.dart'; import 'globalnetwork.dart'; import 'package:bisaGo/get_it.dart'; +Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { + // If you're going to use other Firebase services in the background, such as Firestore, + // make sure you call `initializeApp` before using other Firebase services. + await Firebase.initializeApp(); + + print('Handling a background message: ${message.messageId}'); +} + Future main() async { AppGetIt().initialize(); await DotEnv().load('.env'); getDioInstance('build'); await initializeDateFormatting('id_ID', null); + FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); Intl.defaultLocale = 'id_ID'; dio.options.receiveTimeout = 15000; - ApiFlavor.flavor = BuildFlavor.staging.toString(); + ApiFlavor.flavor = BuildFlavor.development.toString(); runApp(BisaGo()); -} \ No newline at end of file +} diff --git a/lib/model/kegiatan.dart b/lib/model/kegiatan.dart index 6531c58998b7951e5f1c63827f2077150cf0c9dc..eab87fdbff76b8563ff014c7af213ceb4fcd5f5e 100644 --- a/lib/model/kegiatan.dart +++ b/lib/model/kegiatan.dart @@ -17,6 +17,8 @@ class KegiatanModel { String creator; @JsonKey(name: 'nama_kegiatan') String namaKegiatan; + @JsonKey(name: 'creator_email') + String creatorEmail; String penyelenggara; String deskripsi; @JsonKey(name: 'nama_kontak') @@ -38,6 +40,7 @@ class KegiatanModel { this.placeId, this.creator, this.namaKegiatan, + this.creatorEmail, this.penyelenggara, this.deskripsi, this.namaKontak, @@ -50,6 +53,7 @@ class KegiatanModel { } ); - factory KegiatanModel.fromJson(Map json) => _$KegiatanModelFromJson(json); + factory KegiatanModel.fromJson(Map json) => + _$KegiatanModelFromJson(json); Map toJson() => _$KegiatanModelToJson(this); } diff --git a/lib/model/kegiatan.g.dart b/lib/model/kegiatan.g.dart index 90f5b03675b09281b7da1fc4d5865e535482739a..ca5b091e16a313df7783423a74097c86482702ec 100644 --- a/lib/model/kegiatan.g.dart +++ b/lib/model/kegiatan.g.dart @@ -27,6 +27,7 @@ KegiatanModel _$KegiatanModelFromJson(Map json) { placeId: json['place_id'] as String, creator: json['creator'] as String, namaKegiatan: json['nama_kegiatan'] as String, + creatorEmail: json['creator_email'] as String, penyelenggara: json['penyelenggara'] as String, deskripsi: json['deskripsi'] as String, namaKontak: json['nama_kontak'] as String, @@ -45,6 +46,7 @@ Map _$KegiatanModelToJson(KegiatanModel instance) => 'place_id': instance.placeId, 'creator': instance.creator, 'nama_kegiatan': instance.namaKegiatan, + 'creator_email': instance.creatorEmail, 'penyelenggara': instance.penyelenggara, 'deskripsi': instance.deskripsi, 'nama_kontak': instance.namaKontak, diff --git a/lib/model/komentar.dart b/lib/model/komentar.dart index 3a65b937ef7684aaa124dea0b4c219c3a122e323..68bbeb11479ffb6188cec756b05d60653ddc7047 100644 --- a/lib/model/komentar.dart +++ b/lib/model/komentar.dart @@ -1,5 +1,5 @@ +import 'package:intl/intl.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:bisaGo/config/custom_serializer.dart'; part 'komentar.g.dart'; @@ -16,7 +16,7 @@ class KomentarModel { final String namaLokasi; final String deskripsi; final String creator; - @JsonKey(name: 'date_time', fromJson: CustomSerializer.stringToDateTime) + @JsonKey(name: 'date_time', fromJson: _stringToDateTime) final DateTime dateTime; final String tag; final List disabilitas; @@ -25,22 +25,30 @@ class KomentarModel { final bool isVerified; final int jumlah; final int rating; + @JsonKey(name: 'creator_email') + final String creatorEmail; - KomentarModel( - {this.id, - this.namaLokasi, - this.deskripsi, - this.creator, - this.dateTime, - this.tag, - this.disabilitas, - this.image, - this.isVerified, - this.jumlah, - this.rating}); + KomentarModel({ + this.id, + this.namaLokasi, + this.deskripsi, + this.creator, + this.dateTime, + this.tag, + this.disabilitas, + this.image, + this.isVerified, + this.jumlah, + this.rating, + this.creatorEmail, + }); factory KomentarModel.fromJson(Map json) => _$KomentarModelFromJson(json); Map toJson() => _$KomentarModelToJson(this); } + +DateTime _stringToDateTime(String date) { + return DateFormat('dd-MM-yyyy hh:mm').parse(date); +} diff --git a/lib/model/komentar.g.dart b/lib/model/komentar.g.dart index 2755f33196eff8652199696fab3f835093960152..85c8277c07b90464571780d033cfa8bb9f3b81b1 100644 --- a/lib/model/komentar.g.dart +++ b/lib/model/komentar.g.dart @@ -27,7 +27,7 @@ KomentarModel _$KomentarModelFromJson(Map json) { namaLokasi: json['nama_lokasi'] as String, deskripsi: json['deskripsi'] as String, creator: json['creator'] as String, - dateTime: CustomSerializer.stringToDateTime(json['date_time'] as String), + dateTime: _stringToDateTime(json['date_time'] as String), tag: json['tag'] as String, disabilitas: (json['disabilitas'] as List)?.map((e) => e as String)?.toList(), @@ -35,6 +35,7 @@ KomentarModel _$KomentarModelFromJson(Map json) { isVerified: json['is_verified'] as bool, jumlah: json['jumlah'] as int, rating: json['rating'] as int, + creatorEmail: json['creator_email'] as String, ); } @@ -51,4 +52,5 @@ Map _$KomentarModelToJson(KomentarModel instance) => 'is_verified': instance.isVerified, 'jumlah': instance.jumlah, 'rating': instance.rating, + 'creator_email': instance.creatorEmail, }; diff --git a/lib/model/komentar_posting.dart b/lib/model/komentar_posting.dart index 04ffea66b0f7e81b692aeb063c34950447605436..fa4e889c3f7c66c078887f6a7582971c8dca4d20 100644 --- a/lib/model/komentar_posting.dart +++ b/lib/model/komentar_posting.dart @@ -1,5 +1,5 @@ +import 'package:intl/intl.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:bisaGo/config/custom_serializer.dart'; part 'komentar_posting.g.dart'; @@ -14,13 +14,28 @@ class KomentarPostingModel { final int id; final String deskripsi; final String creator; - @JsonKey(name: 'date_time', fromJson: CustomSerializer.stringToDateTime) - final DateTime dateTime; + @JsonKey(name: 'creator_email') + final String creatorEmail; + @JsonKey(name: 'creator_picture') + final String creatorPicture; + @JsonKey(fromJson: _stringToDateTime) + final DateTime created; - KomentarPostingModel({this.id, this.deskripsi, this.creator, this.dateTime}); + KomentarPostingModel({ + this.id, + this.deskripsi, + this.creator, + this.creatorEmail, + this.creatorPicture, + this.created, + }); factory KomentarPostingModel.fromJson(Map json) => _$KomentarPostingModelFromJson(json); Map toJson() => _$KomentarPostingModelToJson(this); } + +DateTime _stringToDateTime(String date) { + return DateFormat('dd-MM-yyyy hh:mm').parse(date); +} diff --git a/lib/model/komentar_posting.g.dart b/lib/model/komentar_posting.g.dart index 565bcd3708949851186ff00919f57aa4691bedf5..9a6805131ffcba578a385289e40a38b6a228b3f8 100644 --- a/lib/model/komentar_posting.g.dart +++ b/lib/model/komentar_posting.g.dart @@ -27,7 +27,9 @@ KomentarPostingModel _$KomentarPostingModelFromJson(Map json) { id: json['id'] as int, deskripsi: json['deskripsi'] as String, creator: json['creator'] as String, - dateTime: CustomSerializer.stringToDateTime(json['date_time'] as String), + creatorEmail: json['creator_email'] as String, + creatorPicture: json['creator_picture'] as String, + created: _stringToDateTime(json['created'] as String), ); } @@ -37,5 +39,7 @@ Map _$KomentarPostingModelToJson( 'id': instance.id, 'deskripsi': instance.deskripsi, 'creator': instance.creator, - 'date_time': instance.dateTime?.toIso8601String(), + 'creator_email': instance.creatorEmail, + 'creator_picture': instance.creatorPicture, + 'created': instance.created?.toIso8601String(), }; diff --git a/lib/model/komentar_posting_kegiatan.dart b/lib/model/komentar_posting_kegiatan.dart index 78e18d736f1dce8e066d0f562a7b6588dd3ab2a7..1057154e1bd739c6dc12d6ab8b45d669e3f79d21 100644 --- a/lib/model/komentar_posting_kegiatan.dart +++ b/lib/model/komentar_posting_kegiatan.dart @@ -1,5 +1,5 @@ -import 'package:json_annotation/json_annotation.dart'; import 'package:bisaGo/config/custom_serializer.dart'; +import 'package:json_annotation/json_annotation.dart'; part 'komentar_posting_kegiatan.g.dart'; @@ -13,16 +13,22 @@ class KomentarPostingKegiatanList { class KomentarPostingKegiatanModel { final int id; final String creator; + @JsonKey(name: 'creator_email') + final String creatorEmail; + @JsonKey(name: 'creator_picture') + final String creatorPicture; final String deskripsi; @JsonKey(name: 'created', fromJson: CustomSerializer.stringToDateTime) final DateTime created; - KomentarPostingKegiatanModel( - {this.id, - this.creator, - this.deskripsi, - this.created} - ); + KomentarPostingKegiatanModel({ + this.id, + this.creator, + this.deskripsi, + this.created, + this.creatorEmail, + this.creatorPicture, + }); factory KomentarPostingKegiatanModel.fromJson(Map json) => _$KomentarPostingKegiatanModelFromJson(json); diff --git a/lib/model/komentar_posting_kegiatan.g.dart b/lib/model/komentar_posting_kegiatan.g.dart index 3b73f1a6ad4fa7c4a655ef055826935ec7a33754..0a08508d3af3ee216c9e244b32c66b3efb3f25d7 100644 --- a/lib/model/komentar_posting_kegiatan.g.dart +++ b/lib/model/komentar_posting_kegiatan.g.dart @@ -30,6 +30,8 @@ KomentarPostingKegiatanModel _$KomentarPostingKegiatanModelFromJson( creator: json['creator'] as String, deskripsi: json['deskripsi'] as String, created: CustomSerializer.stringToDateTime(json['created'] as String), + creatorEmail: json['creator_email'] as String, + creatorPicture: json['creator_picture'] as String, ); } @@ -38,6 +40,8 @@ Map _$KomentarPostingKegiatanModelToJson( { 'id': instance.id, 'creator': instance.creator, + 'creator_email': instance.creatorEmail, + 'creator_picture': instance.creatorPicture, 'deskripsi': instance.deskripsi, 'created': instance.created?.toIso8601String(), }; diff --git a/lib/model/new_user.dart b/lib/model/new_user.dart deleted file mode 100644 index 34c1a52228652f44096a6cb4e91aa322449c5926..0000000000000000000000000000000000000000 --- a/lib/model/new_user.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; -part 'new_user.g.dart'; - -@JsonSerializable() -class NewUser { - String name; - String password; - String email; - @JsonKey(name: 'tanggal_lahir') - String tanggalLahir; - @JsonKey(name: 'jenis_kelamin') - String jenisKelamin; - String disabilitas; - String pekerjaan; - String alamat; - @JsonKey(name: 'phone_number') - String phoneNumber; - - NewUser({ - this.name, - this.password, - this.email, - this.tanggalLahir, - this.jenisKelamin, - this.disabilitas, - this.pekerjaan, - this.alamat, - this.phoneNumber, - }); - - factory NewUser.fromJson(Map json) => - _$NewUserFromJson(json); - Map toJson() => _$NewUserToJson(this); -} diff --git a/lib/model/new_user.g.dart b/lib/model/new_user.g.dart deleted file mode 100644 index 28a0aa445ddfccbbeac2b57a29d76bb798eb178b..0000000000000000000000000000000000000000 --- a/lib/model/new_user.g.dart +++ /dev/null @@ -1,33 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'new_user.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -NewUser _$NewUserFromJson(Map json) { - return NewUser( - name: json['name'] as String, - password: json['password'] as String, - email: json['email'] as String, - tanggalLahir: json['tanggal_lahir'] as String, - jenisKelamin: json['jenis_kelamin'] as String, - disabilitas: json['disabilitas'] as String, - pekerjaan: json['pekerjaan'] as String, - alamat: json['alamat'] as String, - phoneNumber: json['phone_number'] as String, - ); -} - -Map _$NewUserToJson(NewUser instance) => { - 'name': instance.name, - 'password': instance.password, - 'email': instance.email, - 'tanggal_lahir': instance.tanggalLahir, - 'jenis_kelamin': instance.jenisKelamin, - 'disabilitas': instance.disabilitas, - 'pekerjaan': instance.pekerjaan, - 'alamat': instance.alamat, - 'phone_number': instance.phoneNumber, - }; diff --git a/lib/model/user.dart b/lib/model/user.dart index 09a6a653c0a57a614f4c014364cfb233ace5f575..ae19bea0a37bae2cb0f690381bbd999f33bef5b3 100644 --- a/lib/model/user.dart +++ b/lib/model/user.dart @@ -1,18 +1,11 @@ +import 'dart:ui'; + import 'package:json_annotation/json_annotation.dart'; -part 'user.g.dart'; -@JsonSerializable() -class User { - final List user; - User(this.user); -} +part 'user.g.dart'; -@JsonSerializable() -class UserModel { - bool is_login; - String username; +abstract class BaseUserModel { String name; - String email; @JsonKey(name: 'tanggal_lahir') String tanggalLahir; @JsonKey(name: 'phone_number') @@ -22,22 +15,144 @@ class UserModel { String disabilitas; String pekerjaan; String alamat; - String token; - - UserModel( - {this.is_login, - this.username, - this.name, - this.email, - this.tanggalLahir, - this.phoneNumber, - this.jenisKelamin, - this.disabilitas, - this.pekerjaan, - this.alamat, - this.token}); - - factory UserModel.fromJson(Map json) => - _$UserModelFromJson(json); - Map toJson() => _$UserModelToJson(this); + dynamic foto; + @JsonKey(name: 'organisasi_komunitas') + String organisasiKomunitas; + + BaseUserModel({ + this.name, + this.tanggalLahir, + this.phoneNumber, + this.jenisKelamin, + this.disabilitas, + this.pekerjaan, + this.alamat, + this.foto, + this.organisasiKomunitas, + }); +} + +@JsonSerializable() +class RegisterUserModel extends BaseUserModel { + String email; + String password; + + RegisterUserModel({ + this.email, + this.password, + name, + tanggalLahir, + phoneNumber, + jenisKelamin, + disabilitas, + pekerjaan, + alamat, + foto, + organisasiKomunitas, + }) : super( + name: name, + tanggalLahir: tanggalLahir, + phoneNumber: phoneNumber, + jenisKelamin: jenisKelamin, + disabilitas: disabilitas, + pekerjaan: pekerjaan, + alamat: alamat, + foto: foto, + organisasiKomunitas: organisasiKomunitas); + + factory RegisterUserModel.fromJson(Map json) => + _$RegisterUserModelFromJson(json); + + Map toJson() => _$RegisterUserModelToJson(this); +} + +@JsonSerializable() +class UpdateUserModel extends BaseUserModel { + bool seen; + + UpdateUserModel({ + this.seen, + name, + tanggalLahir, + phoneNumber, + jenisKelamin, + disabilitas, + pekerjaan, + alamat, + foto, + organisasiKomunitas, + }) : super( + name: name, + tanggalLahir: tanggalLahir, + phoneNumber: phoneNumber, + jenisKelamin: jenisKelamin, + disabilitas: disabilitas, + pekerjaan: pekerjaan, + alamat: alamat, + foto: foto, + organisasiKomunitas: organisasiKomunitas); + + factory UpdateUserModel.fromJson(Map json) => + _$UpdateUserModelFromJson(json); + + Map toJson() => _$UpdateUserModelToJson(this); +} + +@JsonSerializable() +class DetailUserModel extends BaseUserModel { + String username; + String email; + bool seen; + @JsonKey(name: 'hidden_fields') + List hiddenFields; + @JsonKey(name: 'hidden_fields_verbose') + List hiddenFieldsVerbose; + @JsonKey(name: 'can_see_hidden_fields') + bool canSeeHiddenFields; + @JsonKey(name: 'hidden_fields_color') + String hiddenFieldsColor; + + DetailUserModel({ + this.username, + this.email, + this.seen, + this.hiddenFields, + this.hiddenFieldsVerbose, + this.canSeeHiddenFields, + this.hiddenFieldsColor, + name, + tanggalLahir, + phoneNumber, + jenisKelamin, + disabilitas, + pekerjaan, + alamat, + foto, + organisasiKomunitas, + }) : super( + name: name, + tanggalLahir: tanggalLahir, + phoneNumber: phoneNumber, + jenisKelamin: jenisKelamin, + disabilitas: disabilitas, + pekerjaan: pekerjaan, + alamat: alamat, + foto: foto, + organisasiKomunitas: organisasiKomunitas); + + UpdateUserModel toUpdateUserModel() { + var thisData = toJson(); + return UpdateUserModel.fromJson(thisData); + } + + Color getHiddenFieldsColor() { + final strColor = hiddenFieldsColor.replaceAll('#', '0xff'); + final hexColor = int.parse(strColor); + return Color(hexColor); + } + + factory DetailUserModel.fromJson(Map json) => + _$DetailUserModelFromJson(json); + + Map toJson() => _$DetailUserModelToJson(this); } diff --git a/lib/model/user.g.dart b/lib/model/user.g.dart index c3527bc4bf1810c8db88ec791e305a541e5eb3c3..27c2d4b155061f51665f5500008f87e9386a79ce 100644 --- a/lib/model/user.g.dart +++ b/lib/model/user.g.dart @@ -6,45 +6,106 @@ part of 'user.dart'; // JsonSerializableGenerator // ************************************************************************** -User _$UserFromJson(Map json) { - return User( - (json['user'] as List) - ?.map((e) => - e == null ? null : UserModel.fromJson(e as Map)) - ?.toList(), +RegisterUserModel _$RegisterUserModelFromJson(Map json) { + return RegisterUserModel( + email: json['email'] as String, + password: json['password'] as String, + name: json['name'], + tanggalLahir: json['tanggal_lahir'], + phoneNumber: json['phone_number'], + jenisKelamin: json['jenis_kelamin'], + disabilitas: json['disabilitas'], + pekerjaan: json['pekerjaan'], + alamat: json['alamat'], + foto: json['foto'], + organisasiKomunitas: json['organisasi_komunitas'], ); } -Map _$UserToJson(User instance) => { - 'user': instance.user, +Map _$RegisterUserModelToJson(RegisterUserModel instance) => + { + 'name': instance.name, + 'tanggal_lahir': instance.tanggalLahir, + 'phone_number': instance.phoneNumber, + 'jenis_kelamin': instance.jenisKelamin, + 'disabilitas': instance.disabilitas, + 'pekerjaan': instance.pekerjaan, + 'alamat': instance.alamat, + 'foto': instance.foto, + 'organisasi_komunitas': instance.organisasiKomunitas, + 'email': instance.email, + 'password': instance.password, }; -UserModel _$UserModelFromJson(Map json) { - return UserModel( - is_login: json['is_login'] as bool, +UpdateUserModel _$UpdateUserModelFromJson(Map json) { + return UpdateUserModel( + seen: json['seen'] as bool, + name: json['name'], + tanggalLahir: json['tanggal_lahir'], + phoneNumber: json['phone_number'], + jenisKelamin: json['jenis_kelamin'], + disabilitas: json['disabilitas'], + pekerjaan: json['pekerjaan'], + alamat: json['alamat'], + foto: json['foto'], + organisasiKomunitas: json['organisasi_komunitas'], + ); +} + +Map _$UpdateUserModelToJson(UpdateUserModel instance) => + { + 'name': instance.name, + 'tanggal_lahir': instance.tanggalLahir, + 'phone_number': instance.phoneNumber, + 'jenis_kelamin': instance.jenisKelamin, + 'disabilitas': instance.disabilitas, + 'pekerjaan': instance.pekerjaan, + 'alamat': instance.alamat, + 'foto': instance.foto, + 'organisasi_komunitas': instance.organisasiKomunitas, + 'seen': instance.seen, + }; + +DetailUserModel _$DetailUserModelFromJson(Map json) { + return DetailUserModel( username: json['username'] as String, - name: json['name'] as String, email: json['email'] as String, - tanggalLahir: json['tanggal_lahir'] as String, - phoneNumber: json['phone_number'] as String, - jenisKelamin: json['jenis_kelamin'] as String, - disabilitas: json['disabilitas'] as String, - pekerjaan: json['pekerjaan'] as String, - alamat: json['alamat'] as String, - token: json['token'] as String, + seen: json['seen'] as bool, + hiddenFields: + (json['hidden_fields'] as List)?.map((e) => e as String)?.toList(), + hiddenFieldsVerbose: (json['hidden_fields_verbose'] as List) + ?.map((e) => e as String) + ?.toList(), + canSeeHiddenFields: json['can_see_hidden_fields'] as bool, + hiddenFieldsColor: json['hidden_fields_color'] as String, + name: json['name'], + tanggalLahir: json['tanggal_lahir'], + phoneNumber: json['phone_number'], + jenisKelamin: json['jenis_kelamin'], + disabilitas: json['disabilitas'], + pekerjaan: json['pekerjaan'], + alamat: json['alamat'], + foto: json['foto'], + organisasiKomunitas: json['organisasi_komunitas'], ); } -Map _$UserModelToJson(UserModel instance) => { - 'is_login': instance.is_login, - 'username': instance.username, +Map _$DetailUserModelToJson(DetailUserModel instance) => + { 'name': instance.name, - 'email': instance.email, 'tanggal_lahir': instance.tanggalLahir, 'phone_number': instance.phoneNumber, 'jenis_kelamin': instance.jenisKelamin, 'disabilitas': instance.disabilitas, 'pekerjaan': instance.pekerjaan, 'alamat': instance.alamat, - 'token': instance.token, + 'foto': instance.foto, + 'organisasi_komunitas': instance.organisasiKomunitas, + 'username': instance.username, + 'email': instance.email, + 'seen': instance.seen, + 'hidden_fields': instance.hiddenFields, + 'hidden_fields_verbose': instance.hiddenFieldsVerbose, + 'can_see_hidden_fields': instance.canSeeHiddenFields, + 'hidden_fields_color': instance.hiddenFieldsColor, }; diff --git a/lib/network/network_interface.dart b/lib/network/network_interface.dart index 4641b1db3322ac1aee24513536d4526d4eb1854e..8bf08982a802e74187a6d2a4b5140115f59b2129 100644 --- a/lib/network/network_interface.dart +++ b/lib/network/network_interface.dart @@ -7,6 +7,10 @@ import 'package:bisaGo/flavor/flavor.dart'; import 'package:shared_preferences/shared_preferences.dart'; class NetworkInterface { + NetworkInterface() { + dio.options.headers['content-type'] = 'application/json'; + } + Future post({ String url, Map bodyParams, @@ -15,10 +19,7 @@ class NetworkInterface { }) async { var responseJson; try { - final sharedPreferences = await SharedPreferences.getInstance(); - dio.options.headers['Authorization'] = - 'Token ${sharedPreferences.getString('token')}'; - dio.options.headers['content-type'] = 'application/json'; + await setToken(isLogin); final response = await dio.post( '${ApiFlavor.getBaseUrl()}$url', data: formData ? FormData.fromMap(bodyParams) : json.encode(bodyParams), @@ -40,12 +41,7 @@ class NetworkInterface { }) async { var responseJson; try { - if (isLogin) { - final sharedPreferences = await SharedPreferences.getInstance(); - dio.options.headers['Authorization'] = - 'Token ${sharedPreferences.getString('token')}'; - } - dio.options.headers['content-type'] = 'application/json'; + await setToken(isLogin); final response = await dio.put( '${ApiFlavor.getBaseUrl()}$url', data: formData ? FormData.fromMap(bodyParams) : json.encode(bodyParams), @@ -67,7 +63,7 @@ class NetworkInterface { }) async { var responseJson; try { - dio.options.headers['content-type'] = 'application/json'; + await setToken(isLogin); final response = await dio.get( '${ApiFlavor.getBaseUrl()}$url', ); @@ -80,6 +76,16 @@ class NetworkInterface { return responseJson; } + Future setToken(bool isLogin) async { + if (isLogin) { + final sharedPreferences = await SharedPreferences.getInstance(); + dio.options.headers['Authorization'] = + 'Token ${sharedPreferences.getString('token')}'; + } else { + dio.options.headers.remove('Authorization'); + } + } + dynamic _response(Response response) { switch (response.statusCode) { case 200: diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index 1acec41f29a21ebf97a7cb48269c623a538b9e50..fbc815b6f6f99f9b82e592fe824c80122c6d0a67 100644 --- a/lib/page/dashboard/dashboard.dart +++ b/lib/page/dashboard/dashboard.dart @@ -1,3 +1,4 @@ +import 'package:bisaGo/bloc/cloud_messaging_bloc.dart'; import 'package:bisaGo/bloc/lokasi_response_bloc.dart'; import 'package:bisaGo/model/komentar.dart'; import 'package:bisaGo/model/lokasi.dart'; @@ -11,7 +12,10 @@ import 'package:bisaGo/page/filter_fasilitas/postingan/detail_post.dart'; import 'package:bisaGo/repository/komentar_repository.dart'; import 'package:bisaGo/utils/custom_dashboard_location_button.dart'; import 'package:bisaGo/utils/location_turn_on_dialog.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_dynamic_links/firebase_dynamic_links.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flushbar/flushbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:geolocator/geolocator.dart'; @@ -21,6 +25,9 @@ import 'package:bisaGo/component/bisago_drawer.dart'; import 'package:bisaGo/config/styles.dart'; import 'package:bisaGo/page/pencarian/pencarian.dart'; import 'package:google_maps_webservice/places.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../filter_fasilitas/postingan/detail_post.dart'; class Dashboard extends StatefulWidget { const Dashboard({Key key}) : super(key: key); @@ -37,6 +44,13 @@ class DashboardState extends State { LokasiResponseBloc bloc = LokasiResponseBloc(); KegiatanTerdekatBloc blocKegiatanTerdekat = KegiatanTerdekatBloc(); + CloudMessagingBloc cloudMessagingBloc = CloudMessagingBloc(); + + FirebaseMessaging _firebaseMessaging; + + bool _initialized = false; + + DateTime _lastNotification; @override void initState() { @@ -45,6 +59,71 @@ class DashboardState extends State { geolocator = Geolocator()..forceAndroidLocationManager; initDynamicLinks(); setInitialLocation(); + + if (!_initialized) { + _initialized = true; + _setupFirebase(); + } + } + + void _setupFirebase() async { + await Firebase.initializeApp(); + _firebaseMessaging = FirebaseMessaging.instance; + + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + final now = DateTime.now(); + + if (_lastNotification != null && + _lastNotification.add(Duration(seconds: 10)).isAfter(now)) return; + + _lastNotification = now; + final data = message.data; + final String msg = data['message']; + final String title = data['title']; + Flushbar( + title: title, + message: msg, + duration: Duration(seconds: 8), + backgroundColor: Color(0xFF003566), + onTap: (_) { + if (data['type'] == 'fasilitas') { + final String placeId = data['place_id']; + final id = int.parse(data['id']); + _navigateToDetailFasilitasPage(context, placeId, id); + } else if (data['type'] == 'kegiatan') { + final String placeId = data['place_id']; + final id = int.parse(data['id']); + _navigateToDetailKegiatanPage(context, placeId, id); + } + }, + flushbarStyle: FlushbarStyle.GROUNDED, + flushbarPosition: FlushbarPosition.TOP, + ).show(context); + }); + + FirebaseMessaging.onMessageOpenedApp.listen((message) { + final data = message.data; + if (data['type'] == 'fasilitas') { + final String placeId = data['place_id']; + final id = int.parse(data['id']); + _navigateToDetailFasilitasPage(context, placeId, id); + } else if (data['type'] == 'kegiatan') { + final String placeId = data['place_id']; + final id = int.parse(data['id']); + _navigateToDetailKegiatanPage(context, placeId, id); + } + }); + + _requestFCMToken(); + } + + void _requestFCMToken() async { + final fcmToken = await _firebaseMessaging.getToken(); + final sharedPreferences = await SharedPreferences.getInstance(); + final token = sharedPreferences.getString('token'); + if (token != null) { + await cloudMessagingBloc.sendFCMToken(fcmToken, token); + } } void _navigateToPencarianPage(BuildContext context) { diff --git a/lib/page/filter_fasilitas/kegiatan.dart b/lib/page/filter_fasilitas/kegiatan.dart index 666c0908de95d88dbe195dfe4e860e93489b209f..ded35a4529d35a33e6e5aca7591387d7463ffe27 100644 --- a/lib/page/filter_fasilitas/kegiatan.dart +++ b/lib/page/filter_fasilitas/kegiatan.dart @@ -29,6 +29,7 @@ class _KegiatanState extends State { id: widget.kegiatan.id, placeId: widget.kegiatan.placeId, creator: widget.kegiatan.creator, + creatorEmail: widget.kegiatan.creatorEmail, namaKegiatan: widget.kegiatan.namaKegiatan, penyelenggara: widget.kegiatan.penyelenggara, deskripsi: widget.kegiatan.deskripsi, @@ -150,5 +151,5 @@ class _KegiatanState extends State { ], ), )); - } + } } \ No newline at end of file diff --git a/lib/page/filter_fasilitas/komentar.dart b/lib/page/filter_fasilitas/komentar.dart index dda5b47d5792cef6a99c83e83467bf2c74443918..216554970c05b6306cddb618ef9e995c37a5cf37 100644 --- a/lib/page/filter_fasilitas/komentar.dart +++ b/lib/page/filter_fasilitas/komentar.dart @@ -37,7 +37,7 @@ class _KomentarState extends State { return InkWell( key: Key('Fasilitas ${fasilitas[widget.komentar.tag]}'), onTap: () { - Navigator.of(context).pushReplacement(MaterialPageRoute( + Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => DetailPostPage( lokasi: widget.lokasi, komentar: KomentarModel( @@ -51,6 +51,7 @@ class _KomentarState extends State { tag: widget.komentar.tag, disabilitas: widget.komentar.disabilitas, jumlah: widget.komentar.jumlah, + creatorEmail: widget.komentar.creatorEmail, ), ))); }, diff --git a/lib/page/filter_fasilitas/postingan/detail_post.dart b/lib/page/filter_fasilitas/postingan/detail_post.dart index 4077643a61b54d62a82cd4774a099b12d2f9f0a4..98e8dd7285c9d948d5f1b1305b79865d8dfb6a22 100644 --- a/lib/page/filter_fasilitas/postingan/detail_post.dart +++ b/lib/page/filter_fasilitas/postingan/detail_post.dart @@ -2,7 +2,9 @@ import 'dart:async'; import 'package:bisaGo/config/strings.dart'; import 'package:bisaGo/model/lokasi.dart'; -import 'package:bisaGo/page/filter_fasilitas/fasilitas.dart'; +import 'package:bisaGo/model/user.dart'; +import 'package:bisaGo/page/profile/profile.dart'; +import 'package:bisaGo/page/profile/profile_picture.dart'; import 'package:bisaGo/page/updateInformasi/update_informasi.dart'; import 'package:bisaGo/repository/dynamic_links_service_repository.dart'; import 'package:bisaGo/utils/share_utils.dart'; @@ -25,9 +27,11 @@ import 'package:shared_preferences/shared_preferences.dart'; class DetailPostPage extends StatefulWidget { final Lokasi lokasi; final KomentarModel komentar; + const DetailPostPage( {@required this.komentar, @required this.lokasi, Key key}) : super(key: key); + @override _DetailPostPageState createState() => _DetailPostPageState(); } @@ -42,6 +46,7 @@ class _DetailPostPageState extends State { int dislike; int alreadyLikeFlag; int alreadyDislikeFlag; + @override void initState() { alreadyLikeFlag = 0; @@ -54,196 +59,201 @@ class _DetailPostPageState extends State { @override Widget build(BuildContext context) { var namaLokasi = widget.komentar.namaLokasi ?? 'Invalid Lokasi Name'; - return WillPopScope( - onWillPop: () => Navigator.of(context).pushReplacement(MaterialPageRoute( - builder: (BuildContext context) => Fasilitas( - lokasi: widget.lokasi, - ))), - child: Scaffold( - appBar: BisaGoAppBar( - title: namaLokasi, - key: Key('appbar-text-$namaLokasi'), - actions: [ - InkWell( - onTap: () async { - final link = await DynamicLinksServiceRepository() - .createDynamicLinkForFasilitas( - widget.komentar.id, - widget.lokasi.placeId, - ); - await Share.share(ShareUtils.getFormattedMessageFasilitas( - widget.komentar, widget.lokasi, link)); - }, - child: const Padding( - padding: EdgeInsets.all(doubleSpace), - child: Icon(Icons.share), - ), + return Scaffold( + appBar: BisaGoAppBar( + title: namaLokasi, + key: Key('appbar-text-$namaLokasi'), + actions: [ + InkWell( + onTap: () async { + final link = await DynamicLinksServiceRepository() + .createDynamicLinkForFasilitas( + widget.komentar.id, + widget.lokasi.placeId, + ); + await Share.share(ShareUtils.getFormattedMessageFasilitas( + widget.komentar, widget.lokasi, link)); + }, + child: const Padding( + padding: EdgeInsets.all(doubleSpace), + child: Icon(Icons.share), ), - ], - ), - body: SingleChildScrollView( - child: Column( - children: [ - Container( - key: const Key('Text Jenis Fasilitas'), - margin: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 15.0), - alignment: Alignment.centerLeft, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - width: MediaQuery.of(context).size.width * 0.6, - child: Text( - fasilitas[widget.komentar.tag], - style: const TextStyle( - fontSize: 28, - fontWeight: FontWeight.w800, - letterSpacing: -0.3, - color: Colors.black, - fontFamily: 'Comfortaa', - ), + ), + ], + ), + body: SingleChildScrollView( + child: Column( + children: [ + Container( + key: const Key('Text Jenis Fasilitas'), + margin: + const EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), + alignment: Alignment.centerLeft, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: MediaQuery.of(context).size.width * 0.6, + child: Text( + fasilitas[widget.komentar.tag], + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.w800, + letterSpacing: -0.3, + color: Colors.black, + fontFamily: 'Comfortaa', ), ), - PopupMenuButton( - key: const Key('Button Ubah Informasi'), - elevation: 4.0, - offset: const Offset(0.0, 40.0), - itemBuilder: (BuildContext context) { - final choices = ['Ubah Informasi']; - return choices.map((String choice) { - return PopupMenuItem( - key: Key(choice), - child: ElevatedButton( - style: ButtonStyle( - padding: MaterialStateProperty.all( - EdgeInsets.symmetric( - vertical: 0, horizontal: 0)), - backgroundColor: - MaterialStateProperty.all(Colors.white), - foregroundColor: - MaterialStateProperty.all(Colors.black), - elevation: MaterialStateProperty.all(0)), - onPressed: _updateInformasi, - child: SizedBox( - width: double.infinity, - child: Text(choice), - ), + ), + PopupMenuButton( + key: const Key('Button Ubah Informasi'), + elevation: 4.0, + offset: const Offset(0.0, 40.0), + itemBuilder: (BuildContext context) { + final choices = ['Ubah Informasi']; + return choices.map((String choice) { + return PopupMenuItem( + key: Key(choice), + child: ElevatedButton( + style: ButtonStyle( + padding: MaterialStateProperty.all( + EdgeInsets.symmetric( + vertical: 0, horizontal: 0)), + backgroundColor: + MaterialStateProperty.all(Colors.white), + foregroundColor: + MaterialStateProperty.all(Colors.black), + elevation: MaterialStateProperty.all(0)), + onPressed: _updateInformasi, + child: SizedBox( + width: double.infinity, + child: Text(choice), ), - ); - }).toList(); - }, - ), - ], - ), + ), + ); + }).toList(); + }, + ), + ], ), - Container( - key: const Key('Text Jumlah'), - width: MediaQuery.of(context).size.width, - color: red, - padding: const EdgeInsets.symmetric( - vertical: regularSpace, horizontal: doubleSpace), - child: Text( - 'Tersedia sebanyak ${widget.komentar.jumlah} ' - 'unit fasilitas.', - style: const TextStyle( - fontSize: 16, - color: Colors.white, - fontFamily: 'Comfortaa', - ), - )), - Container( - margin: const EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 150, - child: ImageHolder( - url: widget.komentar.image, - fasilitas: widget.komentar.tag)), - const SizedBox( - height: 10, - ), - // Wrap( - // alignment: WrapAlignment.start, - // direction: Axis.horizontal, - // crossAxisAlignment: WrapCrossAlignment.start, - // children: widget.komentar.tag - // .map((tag) => - // _createTagContainer(getTag(tag))) - // .toList(), - // ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + ), + Container( + key: const Key('Text Jumlah'), + width: MediaQuery.of(context).size.width, + color: red, + padding: const EdgeInsets.symmetric( + vertical: regularSpace, horizontal: doubleSpace), + child: Text( + 'Tersedia sebanyak ${widget.komentar.jumlah} ' + 'unit fasilitas.', + style: const TextStyle( + fontSize: 16, + color: Colors.white, + fontFamily: 'Comfortaa', + ), + )), + Container( + margin: const EdgeInsets.all(doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 150, + child: ImageHolder( + url: widget.komentar.image, + fasilitas: widget.komentar.tag)), + const SizedBox( + height: 10, + ), + // Wrap( + // alignment: WrapAlignment.start, + // direction: Axis.horizontal, + // crossAxisAlignment: WrapCrossAlignment.start, + // children: widget.komentar.tag + // .map((tag) => + // _createTagContainer(getTag(tag))) + // .toList(), + // ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Dapat digunakan oleh', + style: TextStyle(fontSize: 16), + textAlign: TextAlign.left, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _showIfContains('DF'), + _showIfContains('DI'), + _showIfContains('DM'), + _showIfContains('DS'), + ], + ) + ], + ), + Container( + key: const Key('desc'), + decoration: BoxDecoration( + color: gray, + boxShadow: regularShadow, + borderRadius: regularBorderRadius), + padding: const EdgeInsets.all(doubleSpace), + margin: const EdgeInsets.symmetric(vertical: doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( - 'Dapat digunakan oleh', - style: TextStyle(fontSize: 16), - textAlign: TextAlign.left, - ), Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - _showIfContains('DF'), - _showIfContains('DI'), - _showIfContains('DM'), - _showIfContains('DS'), - ], - ) - ], - ), - Container( - key: const Key('desc'), - decoration: BoxDecoration( - color: gray, - boxShadow: regularShadow, - borderRadius: regularBorderRadius), - padding: const EdgeInsets.all(doubleSpace), - margin: const EdgeInsets.symmetric(vertical: doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - const Expanded( - child: Text( - 'Cara menggunakan', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w800), - ), + const Expanded( + child: Text( + 'Cara menggunakan', + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w800), ), - ], - ), - Container( - margin: const EdgeInsets.symmetric( - vertical: regularSpace), - child: Text( - widget.komentar.deskripsi, - key: const Key('Text Cara Menggunakan'), - style: const TextStyle(fontSize: 16), ), + ], + ), + Container( + margin: const EdgeInsets.symmetric( + vertical: regularSpace), + child: Text( + widget.komentar.deskripsi, + key: const Key('Text Cara Menggunakan'), + style: const TextStyle(fontSize: 16), ), - ], - ), + ), + ], ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const Text( - 'informasi ditambahkan oleh ', - style: TextStyle( - fontSize: 12, - fontStyle: FontStyle.italic, - fontWeight: FontWeight.w200, - ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Text( + 'informasi ditambahkan oleh ', + style: TextStyle( + fontSize: 12, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w200, ), - Container( - padding: EdgeInsets.zero, - constraints: BoxConstraints( - maxWidth: - MediaQuery.of(context).size.width * 0.3), + ), + Container( + padding: EdgeInsets.zero, + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width * 0.3), + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => Profile( + email: widget.komentar.creatorEmail, + isPublic: true, + ), + ), + ); + }, child: Text( '${widget.komentar.creator} ', key: Key('creator-${widget.komentar.creator}'), @@ -255,156 +265,159 @@ class _DetailPostPageState extends State { ), ), ), - Text( - '(${DateFormat('dd MMM yyy').format(widget.komentar.dateTime)})', - key: const Key('timestamp'), - style: const TextStyle( - fontSize: 12, - fontStyle: FontStyle.italic, - ), + ), + Text( + '(${DateFormat('dd MMM yyy').format(widget.komentar.dateTime)})', + key: const Key('timestamp'), + style: const TextStyle( + fontSize: 12, + fontStyle: FontStyle.italic, ), - ], - ), - const SizedBox( - height: regularSpace, - ), - const Divider( - color: grayPrimary, - thickness: 1.0, - ), - Container( - key: const Key('Komentar'), - padding: - const EdgeInsets.symmetric(vertical: regularSpace), - child: const Text( - 'Komentar', - style: TextStyle( - fontSize: 20, fontWeight: FontWeight.w800), - )), - StreamBuilder( - stream: _bloc.komentarPostingListStream, - builder: (context, snapshot) { - if (snapshot.hasData) { - switch (snapshot.data.status) { - case Status.loading: + ), + ], + ), + const SizedBox( + height: regularSpace, + ), + const Divider( + color: grayPrimary, + thickness: 1.0, + ), + Container( + key: const Key('Komentar'), + padding: + const EdgeInsets.symmetric(vertical: regularSpace), + child: const Text( + 'Komentar', + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w800), + )), + StreamBuilder( + stream: _bloc.komentarPostingListStream, + builder: (context, snapshot) { + if (snapshot.hasData) { + switch (snapshot.data.status) { + case Status.loading: + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + greenPrimary), + ), + ); + break; + case Status.completed: + allKomentarPostingFromApi = + snapshot.data.data.allKomentar; + if (allKomentarPostingFromApi.isEmpty) { return const Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - greenPrimary), - ), - ); - break; - case Status.completed: - allKomentarPostingFromApi = - snapshot.data.data.allKomentar; - if (allKomentarPostingFromApi.isEmpty) { - return const Center( - child: Text('Tidak ada Komentar')); - } else { - return Column( - children: allKomentarPostingFromApi - .map((k) => - komentarPlaceHolder(k.creator, - k.dateTime, k.deskripsi)) - .toList()); - } - break; - case Status.error: - return Center( - child: Text(snapshot.data.data.toString()), - ); - break; - } + child: Text('Tidak ada Komentar')); + } else { + return Column( + children: allKomentarPostingFromApi + .map( + (k) => komentarPlaceHolder( + k.creator, + k.created, + k.deskripsi, + k.creatorEmail, + k.creatorPicture, + ), + ) + .toList()); + } + break; + case Status.error: + return Center( + child: Text(snapshot.data.data.toString()), + ); + break; } - return Container(); - }), - const SizedBox(height: regularSpace), - Form( - key: _formKey, - child: Column( - children: [ - TextFormField( - key: const Key('Text Field Komentar'), - keyboardType: TextInputType.multiline, - maxLines: null, - minLines: 3, - validator: FieldValidator.validateInfo, - controller: komentarController, - style: const TextStyle( - fontSize: 18, - ), - decoration: InputDecoration( - hintStyle: const TextStyle( - fontWeight: FontWeight.bold, fontSize: 15), - hintText: 'Tulis komentar...', - contentPadding: const EdgeInsets.all(8.0), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: Theme.of(context).primaryColor, - ), + } + return Container(); + }), + const SizedBox(height: regularSpace), + Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + key: const Key('Text Field Komentar'), + keyboardType: TextInputType.multiline, + maxLines: null, + minLines: 3, + validator: FieldValidator.validateInfo, + controller: komentarController, + style: const TextStyle( + fontSize: 18, + ), + decoration: InputDecoration( + hintStyle: const TextStyle( + fontWeight: FontWeight.bold, fontSize: 15), + hintText: 'Tulis komentar...', + contentPadding: const EdgeInsets.all(8.0), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Theme.of(context).primaryColor, ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: Theme.of(context).primaryColor, - ), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Theme.of(context).primaryColor, ), ), ), - Container( - key: const Key('tambah komentar'), - padding: - const EdgeInsets.only(top: doubleSpace), - alignment: Alignment.center, - child: ButtonTheme( - minWidth: double.infinity, - height: 40, - child: ElevatedButton( - key: const Key('Button Tambah Komentar'), - style: ButtonStyle( - padding: MaterialStateProperty.all( - EdgeInsets.symmetric(vertical: 13)), - elevation: MaterialStateProperty.all(0.0), - backgroundColor: - MaterialStateProperty.all( - greenPrimary), - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10)))), - ), - onPressed: () { - _checkLoginStatus(); - }, - child: Row( - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - const Icon( - Icons.add, - size: 30, - color: Colors.white, - ), - const SizedBox(width: 5.0), - const Text( - 'Tambah Komentar', - style: TextStyle( - fontSize: 20, - color: Colors.white, - fontWeight: FontWeight.bold), - ), - ], - ), + ), + Container( + key: const Key('tambah komentar'), + padding: const EdgeInsets.only(top: doubleSpace), + alignment: Alignment.center, + child: ButtonTheme( + minWidth: double.infinity, + height: 40, + child: ElevatedButton( + key: const Key('Button Tambah Komentar'), + style: ButtonStyle( + padding: MaterialStateProperty.all( + EdgeInsets.symmetric(vertical: 13)), + elevation: MaterialStateProperty.all(0.0), + backgroundColor: + MaterialStateProperty.all(greenPrimary), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(10)))), ), - )), - ], - )), - ], - ), + onPressed: () { + _checkLoginStatus(); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.add, + size: 30, + color: Colors.white, + ), + const SizedBox(width: 5.0), + const Text( + 'Tambah Komentar', + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.bold), + ), + ], + ), + ), + )), + ], + )), + ], ), - ], - ), + ), + ], ), ), ); @@ -440,9 +453,6 @@ class _DetailPostPageState extends State { newKomentarPostingData, _namaLokasi, widget.komentar.id); if (response['response'] == 'komentar added') { successDialog(context); - Timer(const Duration(seconds: 2), () { - Navigator.pop(context); - }); await _bloc.fetchKomentarPostingList(_namaLokasi, widget.komentar.id); komentarController.clear(); } else { @@ -474,31 +484,46 @@ class _DetailPostPageState extends State { }); } - Widget komentarPlaceHolder(String name, DateTime date, String description) { + Widget komentarPlaceHolder( + String name, + DateTime date, + String description, + String email, + String foto, + ) { + final user = DetailUserModel() + ..email = email + ..foto = foto + ..name = name; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text( - _creatorInitials(name), - style: const TextStyle( - color: Colors.white, - ), - ), - ), + ProfilePicture(user, redirectToDetailProfile: true), Padding( padding: const EdgeInsets.all(regularSpace), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - name, - style: const TextStyle(fontSize: 18), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => Profile( + email: email, + isPublic: true, + ), + ), + ); + }, + child: Text( + name, + style: const TextStyle(fontSize: 18), + ), ), - Text('${DateFormat('dd MMM yyy hh:mm').format(date)}', + Text('${DateFormat('dd MMMM yyyy hh:mm').format(date)}', style: const TextStyle(color: grayPrimary, fontSize: 14)) ], ), @@ -519,16 +544,6 @@ class _DetailPostPageState extends State { ); } - String _creatorInitials(String name) { - if (name.isEmpty) return ''; - var initials = ''; - for (final i in name.split(' ')) { - initials += '${i[0].toUpperCase()}'; - } - if (initials.length > 2) return initials.substring(0, 2); - return initials; - } - Widget _showIfContains(String disabilitas) { String imageUrl; switch (disabilitas) { diff --git a/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart b/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart index c8262c01547d518123675fd444f6de3db8597f93..fba26d5cec324cff9fb83b4b67389797d1972b3f 100644 --- a/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart +++ b/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart @@ -2,7 +2,10 @@ import 'dart:async'; import 'package:bisaGo/model/kegiatan.dart'; import 'package:bisaGo/model/lokasi.dart'; +import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/page/filter_fasilitas/kegiatan_list_images.dart'; +import 'package:bisaGo/page/profile/profile.dart'; +import 'package:bisaGo/page/profile/profile_picture.dart'; import 'package:bisaGo/repository/dynamic_links_service_repository.dart'; import 'package:bisaGo/utils/share_utils.dart'; import 'package:bisaGo/utils/validator.dart'; @@ -349,14 +352,24 @@ class _DetailPostKegiatanPageState extends State { constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width * 0.3), - child: Text( - '${widget.kegiatan.creator}', - key: Key('creator-${widget.kegiatan.creator}'), - overflow: TextOverflow.fade, - softWrap: false, - style: const TextStyle( - fontSize: 12, - fontStyle: FontStyle.italic, + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => Profile( + email: widget.kegiatan.creatorEmail, + isPublic: true))); + }, + child: Text( + '${widget.kegiatan.creator}', + key: Key('creator-${widget.kegiatan.creator}'), + overflow: TextOverflow.fade, + softWrap: false, + style: const TextStyle( + fontSize: 12, + fontStyle: FontStyle.italic, + ), ), ), ), @@ -411,6 +424,8 @@ class _DetailPostKegiatanPageState extends State { .map((k) => komentarKegiatanPlaceHolder( k.creator, + k.creatorEmail, + k.creatorPicture, k.created, k.deskripsi)) .toList()); @@ -604,31 +619,40 @@ class _DetailPostKegiatanPageState extends State { } Widget komentarKegiatanPlaceHolder( - String name, DateTime created, String description) { + String name, String email, String foto, DateTime created, String description) { + final user = DetailUserModel() + ..email = email + ..foto = foto + ..name = name; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text( - _creatorInitials(name), - style: const TextStyle( - color: Colors.white, - ), - ), - ), + ProfilePicture(user, redirectToDetailProfile: true), Padding( padding: const EdgeInsets.all(regularSpace), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - name, - style: const TextStyle(fontSize: 18), + InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => Profile( + email: email, + isPublic: true, + ), + ), + ); + }, + child: Text( + name, + style: const TextStyle(fontSize: 18), + ), ), - Text('${DateFormat('dd MMMM yyy hh:mm').format(created)}', + Text('${DateFormat('dd MMMM yyyy hh:mm').format(created)}', style: const TextStyle(color: grayPrimary, fontSize: 14)) ], ), @@ -649,16 +673,6 @@ class _DetailPostKegiatanPageState extends State { ); } - String _creatorInitials(String name) { - if (name.isEmpty) return ''; - var initials = ''; - for (final i in name.split(' ')) { - initials += '${i[0].toUpperCase()}'; - } - if (initials.length > 2) return initials.substring(0, 2); - return initials; - } - // Future _updateInformasi() async { // final sharedPreferences = await SharedPreferences.getInstance(); // if (sharedPreferences.getString('token') == null) { diff --git a/lib/page/login/login.dart b/lib/page/login/login.dart index 57496777fca5c0688955ad38c1a9cd3d59909428..99462570947b9811fbdd12ee5d26efb9812c3b7f 100644 --- a/lib/page/login/login.dart +++ b/lib/page/login/login.dart @@ -1,8 +1,7 @@ import 'dart:async'; import 'dart:convert'; -import 'package:bisaGo/bloc/new_user_bloc.dart'; import 'package:bisaGo/bloc/user_bloc.dart'; -import 'package:bisaGo/model/new_user.dart'; +import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/page/dashboard/dashboard.dart'; import 'package:bisaGo/page/login/pilih_disabilitas.dart'; import 'package:flutter/cupertino.dart'; @@ -35,6 +34,12 @@ class LoginState extends State { GoogleSignInAccount _currentUser; SharedPreferences sharedPreferences; + UserBloc _userBloc; + UpdateUserModel updateUser; + String email; + TextEditingController emailController = TextEditingController(); + TextEditingController passwordController = TextEditingController(); + @override void initState() { super.initState(); @@ -159,15 +164,15 @@ class LoginState extends State { height: 64.0, child: TextButton( style: TextButton.styleFrom( - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0), - side: const BorderSide(color: greenPrimary)), - padding: const EdgeInsets.symmetric(vertical: 10.0) - ), + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + side: const BorderSide(color: greenPrimary)), + padding: + const EdgeInsets.symmetric(vertical: 10.0)), onPressed: () async { Navigator.of(context).pop(true); - await _updateUser(newUser); + await _updateUser(updateUser); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, @@ -189,11 +194,11 @@ class LoginState extends State { height: 64.0, child: TextButton( style: TextButton.styleFrom( - backgroundColor: greenPrimary, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5.0)), - padding: const EdgeInsets.symmetric(vertical: 10.0) - ), + backgroundColor: greenPrimary, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0)), + padding: + const EdgeInsets.symmetric(vertical: 10.0)), onPressed: () { Navigator.of(context).pop(true); _navigateToPilihDisabilitas(context); @@ -219,57 +224,28 @@ class LoginState extends State { ); } - Future _getUserDetail() async { - _userBloc = UserBloc(emailController.text.toString()); - await _userBloc.fetchUserDetail(emailController.text.toString()); - final response = _userBloc.userFromApi.first; - if (response.disabilitas == '-') { - newUser = NewUser( - name: response.name, - password: '', - email: emailController.text.toString(), - phoneNumber: response.phoneNumber, - tanggalLahir: response.tanggalLahir, - jenisKelamin: response.jenisKelamin, - disabilitas: 'Tidak memiliki disabilitas', - pekerjaan: response.pekerjaan, - alamat: response.alamat); - await login(emailController.text.toString(), - passwordController.text.toString(), '', '', ''); - _popUpDisabilitas(); - } else { - await login(emailController.text.toString(), - passwordController.text.toString(), '', '', ''); - } - } - - Future _updateUser(NewUser newUser) async { - _newUserBloc = NewUserBloc(); - final response = await _newUserBloc.updateUser(newUser); - if (response.statusCode == 200) { + Future _updateUser(UpdateUserModel updateUserModel) async { + updateUserModel.foto = ''; + final updatedUser = await _userBloc.updateUser(updateUserModel); + if (updatedUser != null) { successUserUpdateDialog(context); } else { failedUserUpdateDialog(context); } - _newUserBloc.dispose(); } Future _validateLoginInput() async { final form = _formKey.currentState; if (_formKey.currentState.validate()) { form.save(); - await _getUserDetail(); + await login(emailController.text.toString(), + passwordController.text.toString(), '', '', ''); } } - NewUserBloc _newUserBloc; - UserBloc _userBloc; - NewUser newUser; - TextEditingController emailController = TextEditingController(); - TextEditingController passwordController = TextEditingController(); - Future login(String email, String password, String google, String accessToken, String name) async { + _userBloc = UserBloc(email: email); var data = {}; if (google.isNotEmpty) { data = { @@ -287,21 +263,31 @@ class LoginState extends State { .post('${ApiFlavor.getBaseUrl()}/api-token-auth/', body: data); if (response.statusCode == 200) { final tokenMap = jsonDecode(response.body); + final loginUser = DetailUserModel.fromJson(tokenMap['user']); + this.email = loginUser.email; + updateUser = loginUser.toUpdateUserModel(); setState(() { sharedPreferences ..setString('token', tokenMap['token']) - ..setString('email', email); + ..setString('user', jsonEncode(tokenMap['user'])); }); + successDialog(context); + await Future.delayed(const Duration(seconds: 2)); _navigateToDashboard(context); + if (updateUser.disabilitas == '-') { + updateUser.disabilitas = 'Tidak memiliki disabilitas'; + _popUpDisabilitas(); + } } else { failedDialog(context); } + _userBloc.dispose(); } void _navigateToPilihDisabilitas(BuildContext context) { - final route = - MaterialPageRoute(builder: (_) => PilihDisabilitas(newUser: newUser)); + final route = MaterialPageRoute( + builder: (_) => PilihDisabilitas(updateUser: updateUser, email: email)); Navigator.of(context).push(route); } @@ -312,7 +298,7 @@ class LoginState extends State { void _navigateToDashboard(BuildContext context) { final route = MaterialPageRoute(builder: (_) => const Dashboard()); - Navigator.of(context).push(route); + Navigator.of(context).pushReplacement(route); } void successDialog(BuildContext context) { @@ -365,23 +351,13 @@ class LoginState extends State { } Future _handleSignIn() async { - try { - await _handleSignOut(); - final googleSignInAccount = await _googleSignIn.signIn(); - final googleSignInAuthentication = - await googleSignInAccount.authentication; + await _handleSignOut(); + final googleSignInAccount = await _googleSignIn.signIn(); + final googleSignInAuthentication = await googleSignInAccount.authentication; - final token = googleSignInAuthentication.accessToken; - await login( - _currentUser.email, '', 'true', token, _currentUser.displayName); - sharedPreferences = await SharedPreferences.getInstance(); - successDialog(context); - Timer(const Duration(seconds: 2), () { - Navigator.pushNamed(context, '/'); - }); - } catch (error) { - failedDialog(context); - } + final token = googleSignInAuthentication.accessToken; + await login( + _currentUser.email, '', 'true', token, _currentUser.displayName); } Future _handleSignOut() async { diff --git a/lib/page/login/pilih_disabilitas.dart b/lib/page/login/pilih_disabilitas.dart index 758a125ee7d141b902bb15fc93c186d91c977bc1..a117141335449d9fc14b48944e797e9800c5fb7f 100644 --- a/lib/page/login/pilih_disabilitas.dart +++ b/lib/page/login/pilih_disabilitas.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:bisaGo/bloc/new_user_bloc.dart'; -import 'package:bisaGo/model/new_user.dart'; +import 'package:bisaGo/bloc/user_bloc.dart'; +import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/page/dashboard/dashboard.dart'; import 'package:bisaGo/utils/custom_disabilitas_button.dart'; import 'package:flutter/material.dart'; @@ -10,17 +10,18 @@ import 'package:bisaGo/config/styles.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; class PilihDisabilitas extends StatefulWidget { - final NewUser newUser; + final UpdateUserModel updateUser; + final String email; - const PilihDisabilitas({Key key, this.newUser}) : super(key: key); + const PilihDisabilitas({Key key, this.updateUser, this.email}) : super(key: key); @override - _PilihDisabilitasState createState() => _PilihDisabilitasState(newUser); + _PilihDisabilitasState createState() => _PilihDisabilitasState(); } class _PilihDisabilitasState extends State { - _PilihDisabilitasState(this.newUser); - + UserBloc _userBloc; String _disabilitas = ''; + @override Widget build(BuildContext context) { return Scaffold( @@ -116,18 +117,19 @@ class _PilihDisabilitasState extends State { } Future _updateUser() async { - newUser.disabilitas = _disabilitas; - bloc = NewUserBloc(); - final response = await bloc.updateUser(newUser); - if (response.statusCode == 200) { + var updateUser = widget.updateUser; + updateUser.disabilitas = _disabilitas; + updateUser.foto = ''; + _userBloc = UserBloc(email: widget.email); + final updatedUser = await _userBloc.updateUser(updateUser); + if (updatedUser != null) { successDialog(context); - Timer(const Duration(seconds: 2), () { - _navigateToDashboard(context); - }); + await Future.delayed(Duration(seconds: 2)); + _navigateToDashboard(context); } else { failedDialog(context); } - bloc.dispose(); + _userBloc.dispose(); } void successDialog(BuildContext context) { @@ -154,9 +156,6 @@ class _PilihDisabilitasState extends State { }); } - NewUser newUser; - NewUserBloc bloc; - void _navigateToDashboard(BuildContext context) { final route = MaterialPageRoute(builder: (_) => const Dashboard()); Navigator.of(context).push(route); diff --git a/lib/page/profile/edit_profile.dart b/lib/page/profile/edit_profile.dart index 71d73eb456b3dca92c26cfe739615cb55d6d5c1b..69f4b32caa99041a90a680db8d2557a1a3865a97 100644 --- a/lib/page/profile/edit_profile.dart +++ b/lib/page/profile/edit_profile.dart @@ -1,10 +1,14 @@ import 'dart:async'; +import 'dart:io'; +import 'package:bisaGo/bloc/user_bloc.dart'; +import 'package:bisaGo/component/image_holder.dart'; +import 'package:bisaGo/utils/datetime_utils.dart'; +import 'package:bisaGo/utils/profile_utils.dart'; +import 'package:dio/dio.dart'; -import 'package:bisaGo/bloc/new_user_bloc.dart'; import 'package:bisaGo/component/bisago_appbar.dart'; import 'package:bisaGo/config/strings.dart'; import 'package:bisaGo/config/styles.dart'; -import 'package:bisaGo/model/new_user.dart'; import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/page/profile/profile.dart'; import 'package:bisaGo/utils/custom_button.dart'; @@ -14,39 +18,81 @@ import 'package:bisaGo/utils/validator.dart'; import 'package:flutter/material.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; +import 'package:image_picker/image_picker.dart'; class EditProfile extends StatefulWidget { - final UserModel user; + final DetailUserModel user; const EditProfile({@required this.user, Key key}) : super(key: key); + @override _EditProfileState createState() => _EditProfileState(user); } class _EditProfileState extends State { final GlobalKey _formKey = GlobalKey(); - UserModel user; - NewUserBloc bloc; - _EditProfileState(this.user); + DetailUserModel detailUserModel; + UpdateUserModel updateUserModel; + UserBloc _bloc; + + TextEditingController nameController = TextEditingController(); + TextEditingController phoneController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + TextEditingController alamatController = TextEditingController(); + TextEditingController organisasiController = TextEditingController(); + + String jenisKelaminValue; + DateTime tanggalLahir; + String jenisDisabilitasValue; + String pekerjaanValue; + + //UserBloc bloc; + final picker = ImagePicker(); + File _image; + String _imageUrl; + bool _rahasiakanData; + + Future _getGalleryImage() async { + final image = await picker.getImage(source: ImageSource.gallery); + return File(image.path); + } + + Future _getCameraImage() async { + final image = + await picker.getImage(source: ImageSource.camera, imageQuality: 50); + return File(image.path); + } + + Future _clearImage() async { + setState(() { + _image = null; + _imageUrl = null; + }); + } + + _EditProfileState(this.detailUserModel); @override void initState() { super.initState(); - nameController.text = user.name; - phoneController.text = user.phoneNumber; - emailController.text = user.email; - alamatController.text = user.alamat; - jenisKelaminValue = user.jenisKelamin; - tanggalLahir = user.tanggalLahir; - jenisDisabilitasValue = user.disabilitas; - pekerjaanValue = user.pekerjaan; + nameController.text = detailUserModel.name; + phoneController.text = detailUserModel.phoneNumber; + emailController.text = detailUserModel.email; + alamatController.text = detailUserModel.alamat; + organisasiController.text = detailUserModel.organisasiKomunitas; + jenisKelaminValue = detailUserModel.jenisKelamin; + tanggalLahir = (detailUserModel.tanggalLahir == '-' + ? DateTime.now() + : usDateFormatter.parse(detailUserModel.tanggalLahir)); + jenisDisabilitasValue = detailUserModel.disabilitas; + pekerjaanValue = detailUserModel.pekerjaan; + _rahasiakanData = detailUserModel.seen; + _imageUrl = detailUserModel.foto; } @override Widget build(BuildContext context) { - final name = user.name; return Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(55), @@ -89,30 +135,92 @@ class _EditProfileState extends State { child: ListBody( children: [ CircleAvatar( - key: Key('Avatar ${name.split(' ')[0]}'), + key: Key('Avatar ${detailUserModel.name.split(' ')[0]}'), radius: 50, - backgroundColor: white, - child: Text( - user.name.substring(0, 1), - style: const TextStyle( - fontSize: 45, - fontWeight: FontWeight.w900, - color: darkGreen, - fontFamily: 'Comfortaa', - ), - ), + backgroundColor: greenPrimary, + child: (_image != null) + ? ClipOval( + child: AspectRatio( + aspectRatio: 1, + child: Image.file(_image, fit: BoxFit.cover), + )) + : ((_imageUrl) == null + ? Text(getNameInitials(detailUserModel.name), + style: const TextStyle( + fontSize: 45, + fontWeight: FontWeight.w900, + color: Colors.white, + fontFamily: 'Comfortaa', + )) + : ClipOval( + child: AspectRatio( + aspectRatio: 1, + child: ImageHolder( + url: _imageUrl, + ), + ))), ), Padding( - padding: const EdgeInsets.only(top: doubleSpace), - child: Text( - 'Halo, ${name.split(' ')[0]}!', - style: const TextStyle( - fontSize: 26, - fontWeight: FontWeight.w900, - color: Colors.black, - fontFamily: 'Comfortaa', + padding: + const EdgeInsets.symmetric(vertical: doubleSpace), + child: InkWell( + onTap: () { + _showPhotoSelectionDialog(); + }, + child: Text( + 'Ubah Foto Profil', + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w900, + color: Colors.blue, + fontFamily: 'Comfortaa', + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, + ), + ), + Container( + margin: const EdgeInsets.symmetric(vertical: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Rahasiakan data?', + key: Key('Rahasiakan data?'), + style: const TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli', + ), + ), + Center( + child: Text( + 'Data yang akan dirahasiakan adalah: ${widget.user.hiddenFieldsVerbose.join(', ')}', + style: TextStyle( + fontSize: 10.0, + ), + ), + ), + ], + ), + ), + Switch( + value: !_rahasiakanData, + focusColor: Colors.green, + hoverColor: Colors.green, + activeColor: Colors.green, + activeTrackColor: Colors.green, + onChanged: (value) { + setState(() { + _rahasiakanData = !value; + }); + }, + ), + ], ), ), CustomTextField( @@ -170,16 +278,15 @@ class _EditProfileState extends State { ), onPressed: () { DatePicker.showDatePicker(context, - currentTime: DateTime.parse(tanggalLahir), + currentTime: tanggalLahir, maxTime: DateTime.now(), onChanged: (date) { setState(() { - tanggalLahir = - '${DateFormat('yyyy-MM-dd').format(date)}'; + tanggalLahir = date; }); }); }, child: Text( - tanggalLahir, + idDateFormatter.format(tanggalLahir), style: const TextStyle( fontSize: 15.0, color: Colors.white), ), @@ -218,6 +325,13 @@ class _EditProfileState extends State { }); }, ), + CustomTextField( + title: 'Organisasi / Komunitas', + required: true, + key: const Key('Text Field Organisasi'), + controller: organisasiController, + validator: FieldValidator.validateOrganisasi, + ), Container( margin: const EdgeInsets.fromLTRB( 0, tripleSpace, 0, regularSpace), @@ -238,48 +352,69 @@ class _EditProfileState extends State { ); } - NewUser newUser; - TextEditingController nameController = TextEditingController(); - TextEditingController phoneController = TextEditingController(); - TextEditingController emailController = TextEditingController(); - TextEditingController alamatController = TextEditingController(); - String jenisKelaminValue; - String tanggalLahir; - String jenisDisabilitasValue; - String pekerjaanValue; + dynamic fotoValidate() { + dynamic fotoVal = ''; + if (_image != null) { + final fileName = _image.path.split('/').last; + fotoVal = MultipartFile.fromFile( + _image.path, + filename: fileName, + ); + } + return fotoVal; + } Future _validateLoginInput() async { + var validatedPhoto = ''; + if (_image != null) { + validatedPhoto = _image.path; + } else if (_imageUrl == null) { + validatedPhoto = null; + } + final form = _formKey.currentState; if (_formKey.currentState.validate()) { form.save(); - newUser = NewUser( - name: nameController.text.toString(), - password: '', - email: emailController.text.toString(), - phoneNumber: phoneController.text.toString(), - tanggalLahir: tanggalLahir, - jenisKelamin: jenisKelaminValue ?? '-', - disabilitas: jenisDisabilitasValue, - pekerjaan: pekerjaanValue ?? '-', - alamat: alamatController.text.toString()); - await _updateUser(newUser); + updateUserModel = UpdateUserModel( + name: nameController.text.toString(), + phoneNumber: phoneController.text.toString(), + tanggalLahir: usDateFormatter.format(tanggalLahir), + jenisKelamin: jenisKelaminValue ?? '-', + disabilitas: jenisDisabilitasValue, + pekerjaan: pekerjaanValue ?? '-', + alamat: alamatController.text.toString(), + foto: validatedPhoto, + seen: _rahasiakanData, + organisasiKomunitas: organisasiController.text, + ); + if (_image != null) { + final fileName = _image.path.split('/').last; + updateUserModel.foto = await MultipartFile.fromFile( + _image.path, + filename: fileName, + ); + } + + //await updateUser(newUser); + await updateUser(updateUserModel, detailUserModel.email); } else { failedDialog(context); } } - Future _updateUser(NewUser newUser) async { - bloc = NewUserBloc(); - final response = await bloc.updateUser(newUser); - if (response.statusCode == 200) { + Future updateUser(UpdateUserModel updateUserModel, String email) async { + _bloc = UserBloc(email: email); + final updatedUser = await _bloc.updateUser(updateUserModel); + if (updatedUser != null) { successDialog(context); Timer(const Duration(seconds: 2), () { - _navigateToProfile(context, newUser); + //_navigateToProfile(context, newUser); + _navigateToProfile(context, updatedUser.email); }); } else { failedDialog(context); } - bloc.dispose(); + _bloc.dispose(); } void successDialog(BuildContext context) { @@ -306,21 +441,53 @@ class _EditProfileState extends State { }); } - void _navigateToProfile(BuildContext context, NewUser newUser) { - final userNew = UserModel( - username: newUser.email, - name: newUser.name, - email: newUser.email, - tanggalLahir: newUser.tanggalLahir, - phoneNumber: newUser.phoneNumber, - jenisKelamin: newUser.jenisKelamin, - disabilitas: newUser.disabilitas, - pekerjaan: newUser.pekerjaan, - alamat: newUser.alamat); - final route = - MaterialPageRoute(builder: (_) => Profile(email: userNew.email)); + void _navigateToProfile(BuildContext context, String email) { + final route = MaterialPageRoute(builder: (_) => Profile(email: email)); Navigator.of(context).pop(Navigator.pop(context)); Navigator.pop(context); Navigator.of(context).push(route); } + + Future _showPhotoSelectionDialog() async { + await showDialog( + context: context, + builder: (_) => SimpleDialog( + title: Text('Pilih Foto'), + children: [ + SimpleDialogOption( + onPressed: () async { + final imageSelected = await _getGalleryImage(); + setState(() { + _image = imageSelected; + }); + Navigator.pop(context); + }, + child: Text('Dari Gallery'), + ), + SimpleDialogOption( + onPressed: () async { + final imageSelected = await _getCameraImage(); + setState(() { + _image = imageSelected; + }); + Navigator.pop(context); + }, + child: Text('Dari Kamera'), + ), + SimpleDialogOption( + onPressed: () async { + Navigator.pop(context); + await _clearImage(); + }, + child: Text( + 'Hapus Foto', + style: TextStyle( + color: Colors.red[800], + ), + ), + ), + ], + ), + ); + } } diff --git a/lib/page/profile/full_screen_image.dart b/lib/page/profile/full_screen_image.dart new file mode 100644 index 0000000000000000000000000000000000000000..f8878ffd71be3fffb63e256d71e7f5dde9d7321b --- /dev/null +++ b/lib/page/profile/full_screen_image.dart @@ -0,0 +1,23 @@ +import 'package:bisaGo/component/bisago_appbar.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class FullScreenImage extends StatelessWidget { + final Widget body; + + FullScreenImage({Key key, this.body}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + appBar: BisaGoAppBar( + title: '', + backgroundColor: Colors.transparent, + ), + body: Center( + child: body ?? Container(), + ), + ); + } +} diff --git a/lib/page/profile/profile.dart b/lib/page/profile/profile.dart index 2f2f74c587f7e02e152050c060b8861eadf3bb68..fe3749a3277542e24a94ef6760c620b14c31ff08 100644 --- a/lib/page/profile/profile.dart +++ b/lib/page/profile/profile.dart @@ -2,28 +2,45 @@ import 'package:bisaGo/bloc/user_bloc.dart'; import 'package:bisaGo/component/bisago_appbar.dart'; import 'package:bisaGo/config/styles.dart'; import 'package:bisaGo/model/user.dart'; +import 'package:bisaGo/network/data/network_model.dart'; import 'package:bisaGo/page/profile/edit_profile.dart'; +import 'package:bisaGo/page/profile/profile_picture.dart'; +import 'package:bisaGo/utils/datetime_utils.dart'; +import 'package:bisaGo/utils/profile_utils.dart'; import 'package:flutter/material.dart'; +import 'package:intl/date_symbol_data_local.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; class Profile extends StatefulWidget { final String email; + final bool isPublic; + + const Profile({ + @required this.email, + Key key, + this.isPublic = false, + }) : super(key: key); - const Profile({@required this.email, Key key}) : super(key: key); @override _ProfileState createState() => _ProfileState(email); } class _ProfileState extends State { - UserModel user; + DetailUserModel user; + DetailUserModel viewUser; String email; UserBloc _bloc; + bool fetched; + _ProfileState(this.email); @override void initState() { super.initState(); - _bloc = UserBloc(email); + fetched = false; + _bloc = UserBloc(email: email); + _bloc.fetchUserDetail(); + initializeDateFormatting('id_ID'); } @override @@ -38,41 +55,53 @@ class _ProfileState extends State { child: const Icon(Icons.arrow_back_ios), ), actions: [ - Padding( - padding: const EdgeInsets.all(doubleSpace), - child: InkWell( - key: const Key('Edit User Profile'), - onTap: () { - _navigateToEditProfile(context); - }, - child: const Text( - 'Edit', - style: TextStyle(fontSize: 15), + if (!widget.isPublic) + Padding( + padding: const EdgeInsets.all(doubleSpace), + child: InkWell( + key: const Key('Edit User Profile'), + onTap: () { + if (user != null) { + _navigateToEditProfile(context); + } + }, + child: const Text( + 'Edit', + style: TextStyle(fontSize: 15), + ), ), - ), - ) + ) ], ), ), - body: FutureBuilder( - future: _bloc.fetchUser(email), - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - user = snapshot.data; - return _createProfilePage(); - } else if (!snapshot.hasData) { - return const Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(greenPrimary), - ), - ); + body: StreamBuilder>( + stream: _bloc.userStream, + builder: (context, snapshot) { + if (snapshot.hasData) { + switch (snapshot.data.status) { + case Status.completed: + user = snapshot.data.data; + return _createProfilePage(); + case Status.loading: + return const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(greenPrimary), + ), + ); + case Status.error: + return Center( + child: Text(snapshot.data.message.toString()), + ); } - return Container(); - }), + } + return Container(); + }, + ), ); } Widget _createProfilePage() { + var tanggalLahir = toIndonesiaLocale(user.tanggalLahir); return ListView( children: [ Stack( @@ -93,38 +122,28 @@ class _ProfileState extends State { padding: const EdgeInsets.only( bottom: doubleSpace, ), - child: CircleAvatar( - key: Key('Avatar ${user.name.split(' ')[0]}'), - radius: 50, - backgroundColor: white, - child: Text( - user.name.substring(0, 1), - style: const TextStyle( - fontSize: 45, - fontWeight: FontWeight.w900, - color: darkGreen, - fontFamily: 'Comfortaa', - ), - ), - ), + child: ProfilePicture(user, + radius: 50, fontSize: 50 * 0.7, previewAble: true), ), - Text( - 'Halo, ${user.name.split(' ')[0]}!', - style: const TextStyle( - fontSize: 26, - fontWeight: FontWeight.w900, - color: Colors.white, - fontFamily: 'Comfortaa', + if (!widget.isPublic) + Text( + 'Halo, ${user.name.split(' ')[0]}!', + style: TextStyle( + fontSize: 26, + fontWeight: FontWeight.w900, + color: + _getFontColor('name', seenColor: Colors.white), + fontFamily: 'Muli', + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, - ), Text( user.email, - style: const TextStyle( - fontSize: 20, + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.w500, - color: Colors.white, - fontFamily: 'Comfortaa', + color: _getFontColor('email', seenColor: Colors.white), + fontFamily: 'Muli', ), textAlign: TextAlign.center, ), @@ -137,7 +156,9 @@ class _ProfileState extends State { key: const Key('Card Profile Page'), alignment: Alignment.topCenter, padding: EdgeInsets.only( - top: MediaQuery.of(context).size.height * .32, + top: widget.isPublic + ? MediaQuery.of(context).size.height * .32 - 30 + : MediaQuery.of(context).size.height * .32, left: tripleSpace, right: tripleSpace, bottom: tripleSpace), @@ -163,11 +184,11 @@ class _ProfileState extends State { ), title: Text( user.name, - style: const TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('name'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -179,15 +200,12 @@ class _ProfileState extends State { color: darkGreen, ), title: Text( - user.tanggalLahir == '' || - user.tanggalLahir == null - ? '-' - : user.tanggalLahir, - style: const TextStyle( + tanggalLahir, + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('tanggal_lahir'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -200,11 +218,11 @@ class _ProfileState extends State { ), title: Text( user.phoneNumber, - style: const TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('phone_number'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -220,11 +238,11 @@ class _ProfileState extends State { user.jenisKelamin == null ? '-' : user.jenisKelamin, - style: const TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('jenis_kelamin'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -239,11 +257,11 @@ class _ProfileState extends State { user.disabilitas == '' || user.disabilitas == null ? 'Belum memilih' : user.disabilitas, - style: const TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('disabilitas'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -258,11 +276,11 @@ class _ProfileState extends State { user.pekerjaan == '' || user.pekerjaan == null ? '-' : user.pekerjaan, - style: const TextStyle( + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('pekerjaan'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -277,11 +295,31 @@ class _ProfileState extends State { user.alamat == '' || user.alamat == null ? '-' : user.alamat, - style: const TextStyle( + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: _getFontColor('alamat'), + fontFamily: 'Muli', + ), + textAlign: TextAlign.left, + ), + ), + ListTile( + leading: const Icon( + Icons.people, + size: 28, + color: darkGreen, + ), + title: Text( + user.organisasiKomunitas == '' || + user.organisasiKomunitas == null + ? '-' + : user.organisasiKomunitas, + style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, - color: Colors.black, - fontFamily: 'Comfortaa', + color: _getFontColor('organisasi_komunitas'), + fontFamily: 'Muli', ), textAlign: TextAlign.left, ), @@ -299,6 +337,15 @@ class _ProfileState extends State { ); } + Color _getFontColor(String fieldName, {Color seenColor = seenColor}) { + if (user.canSeeHiddenFields) return seenColor; + final hiddenFields = user.hiddenFields; + if (hiddenFields.contains(fieldName)) { + return user.getHiddenFieldsColor(); + } + return seenColor; + } + void _navigateToEditProfile(BuildContext context) { final route = MaterialPageRoute(builder: (_) => EditProfile(user: user)); Navigator.of(context).push(route); diff --git a/lib/page/profile/profile_picture.dart b/lib/page/profile/profile_picture.dart new file mode 100644 index 0000000000000000000000000000000000000000..be9efbd8d863efe559d49dbc355e09b8125d203c --- /dev/null +++ b/lib/page/profile/profile_picture.dart @@ -0,0 +1,103 @@ +import 'dart:math'; + +import 'package:bisaGo/component/image_holder.dart'; +import 'package:bisaGo/config/styles.dart'; +import 'package:bisaGo/model/user.dart'; +import 'package:bisaGo/page/profile/full_screen_image.dart'; +import 'package:bisaGo/page/profile/profile.dart'; +import 'package:bisaGo/utils/profile_utils.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_view/photo_view.dart'; + +class ProfilePicture extends StatelessWidget { + final DetailUserModel user; + final bool redirectToDetailProfile; + final bool previewAble; + final double radius; + final double fontSize; + final Color color; + final Color backgroundColor; + final String fontFamily; + final FontWeight fontWeight; + + ProfilePicture(this.user, + {Key key, + this.redirectToDetailProfile = false, + this.previewAble = false, + this.radius = 20, + this.fontSize = 14, + this.color = Colors.white, + this.backgroundColor = greenPrimary, + this.fontFamily = 'Comfortaa', + this.fontWeight = FontWeight.w900}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (redirectToDetailProfile) { + _toDetailProfile(context); + } else if (previewAble) { + _toPreviewImage(context); + } + }, + child: _makeAvatar(), + ); + } + + Widget _makeAvatar({double radius, double fontSize}) { + return CircleAvatar( + key: Key('Avatar ${user.name.split(' ')[0]}'), + radius: radius ?? this.radius, + backgroundColor: user.foto != null ? Colors.white : backgroundColor, + child: (user.foto != null) + ? ClipOval( + child: AspectRatio( + aspectRatio: 1, + child: ImageHolder( + url: user.foto, + ), + ), + ) + : Text(getNameInitials(user.name), + style: TextStyle( + fontSize: fontSize ?? this.fontSize, + fontWeight: fontWeight, + color: color, + fontFamily: fontFamily, + )), + ); + } + + Widget _getFullPicture(BuildContext context) { + if (user.foto != null) { + return PhotoView( + imageProvider: NetworkImage(user.foto), + loadingBuilder: (context, event) => const Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(greenPrimary), + )), + ); + } + var width = MediaQuery.of(context).size.width; + var height = MediaQuery.of(context).size.height; + var minWidthHeight = min(width, height); + return _makeAvatar(radius: minWidthHeight, fontSize: minWidthHeight * 0.5); + } + + void _toDetailProfile(BuildContext context) => + _toSomewhere(context, (_) => Profile(email: user.email, isPublic: true)); + + void _toPreviewImage(BuildContext context) => _toSomewhere( + context, + (_) => FullScreenImage( + body: _getFullPicture(context), + )); + + void _toSomewhere( + BuildContext context, Function(BuildContext context) builder) => + Navigator.push( + context, MaterialPageRoute(builder: (context) => builder(context))); +} diff --git a/lib/page/registrasi/registrasi.dart b/lib/page/registrasi/registrasi.dart index 7c64ecad20cbf6501dc4ba577ea151c2086ac64a..61efcf075c3fb33c03716b6a00b25dcb4f50a339 100644 --- a/lib/page/registrasi/registrasi.dart +++ b/lib/page/registrasi/registrasi.dart @@ -1,9 +1,10 @@ import 'dart:async'; -import 'package:bisaGo/bloc/new_user_bloc.dart'; +import 'package:bisaGo/bloc/user_bloc.dart'; import 'package:bisaGo/config/strings.dart'; -import 'package:bisaGo/model/new_user.dart'; +import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/utils/custom_dropdown.dart'; +import 'package:bisaGo/utils/datetime_utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; @@ -14,7 +15,6 @@ import 'package:bisaGo/utils/custom_button.dart'; import 'package:bisaGo/utils/custom_text_field.dart'; import 'package:bisaGo/utils/validator.dart'; import 'package:google_sign_in/google_sign_in.dart'; -import 'package:intl/intl.dart'; GoogleSignIn _googleSignIn = GoogleSignIn(scopes: ['email', 'profile']); @@ -28,7 +28,20 @@ class Registrasi extends StatefulWidget { class RegistrasiState extends State { final GlobalKey _formKey = GlobalKey(); - NewUserBloc bloc; + RegisterUserModel registerUserModel; + TextEditingController nameController = TextEditingController(); + TextEditingController phoneController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + TextEditingController alamatController = TextEditingController(); + TextEditingController passwordController = TextEditingController(); + TextEditingController organisasiController = TextEditingController(); + + String _jenisKelaminValue; + String _pekerjaanValue; + String jenisDisabilitas = '-'; + String tanggalLahir = 'Pilih tanggal lahir'; + + UserBloc _bloc; static GoogleSignInAccount _currentUser; @@ -165,10 +178,9 @@ class RegistrasiState extends State { key: const Key('Button Tanggal Lahir'), onPressed: () { DatePicker.showDatePicker(context, - maxTime: DateTime.now(), onChanged: (date) { + maxTime: DateTime.now(), onConfirm: (date) { setState(() { - tanggalLahir = - '${DateFormat('yyyy-MM-dd').format(date)}'; + tanggalLahir = '${idDateFormatter.format(date)}'; }); }); }, @@ -197,6 +209,11 @@ class RegistrasiState extends State { }); }, ), + CustomTextField( + title: 'Organisasi / Komunitas', + key: const Key('Text Field Organisasi'), + controller: organisasiController, + ), CustomTextField( title: 'Password', required: true, @@ -257,19 +274,23 @@ class RegistrasiState extends State { final form = _formKey.currentState; if (_validateTanggalLahir(context) && _formKey.currentState.validate()) { form.save(); - newUser = NewUser( - name: nameController.text.toString(), - password: passwordController.text.toString(), - email: emailController.text.toString(), - phoneNumber: phoneController.text.toString(), - tanggalLahir: tanggalLahir, - jenisKelamin: _jenisKelaminValue ?? '-', - disabilitas: jenisDisabilitas, - pekerjaan: _pekerjaanValue ?? '-', - alamat: alamatController.text.toString() == '' - ? '-' - : alamatController.text.toString()); - await createUser(newUser); + registerUserModel = RegisterUserModel( + name: nameController.text.toString(), + password: passwordController.text.toString(), + email: emailController.text.toString(), + phoneNumber: phoneController.text.toString(), + tanggalLahir: fromLocaleToLocale( + idDateFormatter, registerDateFormatter, tanggalLahir), + jenisKelamin: _jenisKelaminValue ?? '-', + disabilitas: jenisDisabilitas, + pekerjaan: _pekerjaanValue ?? '-', + alamat: alamatController.text.toString() == '' + ? '-' + : alamatController.text.toString(), + organisasiKomunitas: + organisasiController.text == '' ? '-' : organisasiController.text, + ); + await createUser(registerUserModel); } } @@ -288,29 +309,17 @@ class RegistrasiState extends State { return true; } - NewUser newUser; - TextEditingController nameController = TextEditingController(); - TextEditingController phoneController = TextEditingController(); - TextEditingController emailController = TextEditingController(); - TextEditingController alamatController = TextEditingController(); - TextEditingController passwordController = TextEditingController(); - String _jenisKelaminValue; - String _pekerjaanValue; - String jenisDisabilitas = '-'; - String tanggalLahir = 'Pilih tanggal lahir'; - - Future createUser(NewUser newUser) async { - bloc = NewUserBloc(); - final response = await bloc.registerNewUser(newUser); - if (response.statusCode == 201) { + Future createUser(RegisterUserModel registerUserModel) async { + _bloc = UserBloc(); + final response = await _bloc.registerNewUser(registerUserModel); + if (response) { successDialog(context); - Timer(const Duration(seconds: 2), () { - _navigateToDashboard(context); - }); + await Future.delayed(Duration(seconds: 2)); + _navigateToDashboard(context); } else { failedDialog(context); } - bloc.dispose(); + _bloc.dispose(); } void successDialog(BuildContext context) { diff --git a/lib/repository/cloud_messaging_repository.dart b/lib/repository/cloud_messaging_repository.dart new file mode 100644 index 0000000000000000000000000000000000000000..49ea45c088a72fa18680ff835779f03799b9a453 --- /dev/null +++ b/lib/repository/cloud_messaging_repository.dart @@ -0,0 +1,30 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:bisaGo/flavor/flavor.dart'; + +abstract class BaseCloudMessagingRepository { + Future sendFCMToken(String fcmToken, String token); +} + +class CloudMessagingRepository implements BaseCloudMessagingRepository { + @override + Future sendFCMToken(String fcmToken, String token) async { + try { + await http.post( + '${ApiFlavor.getBaseUrl()}/notification/', + headers: { + 'Authorization': 'token $token', + 'content-type': 'application/json' + }, + body: json.encode({ + 'token': fcmToken, + 'type': 'android', + }), + ); + return true; + } catch (_) { + return false; + } + } +} diff --git a/lib/repository/kegiatan_repository.dart b/lib/repository/kegiatan_repository.dart index 5d042a3db4cdc4728db633ac9232fcb4be111eb9..e19f5753c3a136ed67966622c2c6d86bb2c0de6d 100644 --- a/lib/repository/kegiatan_repository.dart +++ b/lib/repository/kegiatan_repository.dart @@ -54,10 +54,12 @@ class KegiatanRepository implements BaseKegiatanRepository { ); return response; } - + @override - Future fetchDetailKegiatan(String placeId, int kegiatanId) async { - final url = '/informasi-fasilitas/lokasi/detail-kegiatan/$placeId/$kegiatanId/'; + Future fetchDetailKegiatan( + String placeId, int kegiatanId) async { + final url = + '/informasi-fasilitas/lokasi/detail-kegiatan/$placeId/$kegiatanId/'; final response = await _network.get(url: url, isLogin: false); var kegiatan = KegiatanModel.fromJson(response); kegiatan.images = await fetchImages(kegiatan.placeId, kegiatan.id); diff --git a/lib/repository/komentar_repository.dart b/lib/repository/komentar_repository.dart index cf34a3ee609a0708d6d4990201292a75d30a7002..9d186142ba4f6b98f2c22c27b50c70af19125023 100644 --- a/lib/repository/komentar_repository.dart +++ b/lib/repository/komentar_repository.dart @@ -7,8 +7,7 @@ abstract class BaseKomentarRepository { Map newKomentarData, String namaLokasi); Future updateKomentar( Map newKomentarData, String placeId, int id); - Future fetchDetailFasilitas( - String placeId, int fasilitasId); + Future fetchDetailFasilitas(String placeId, int fasilitasId); } class KomentarRepository implements BaseKomentarRepository { @@ -35,10 +34,11 @@ class KomentarRepository implements BaseKomentarRepository { } @override - Future updateKomentar(Map newKomentarData, - String placeId, int id) async { + Future updateKomentar( + Map newKomentarData, String placeId, int id) async { final response = await _network.put( - url: '/informasi-fasilitas/lokasi/update-fasilitas/$placeId/${id.toString()}/', + url: + '/informasi-fasilitas/lokasi/update-fasilitas/$placeId/${id.toString()}/', bodyParams: newKomentarData, isLogin: true, ); @@ -46,8 +46,10 @@ class KomentarRepository implements BaseKomentarRepository { } @override - Future fetchDetailFasilitas(String placeId, int fasilitasId) async { - final url = '/informasi-fasilitas/lokasi/detail-fasilitas/$placeId/$fasilitasId/'; + Future fetchDetailFasilitas( + String placeId, int fasilitasId) async { + final url = + '/informasi-fasilitas/lokasi/detail-fasilitas/$placeId/$fasilitasId/'; final response = await _network.get(url: url, isLogin: false); return KomentarModel.fromJson(response); } diff --git a/lib/repository/user_repository.dart b/lib/repository/user_repository.dart index 4ced6b383e87b1874bfcb2f7d7e5b2757bc39270..a37f83d4dde91906a3783ae03e646058b74eb9d6 100644 --- a/lib/repository/user_repository.dart +++ b/lib/repository/user_repository.dart @@ -1,41 +1,41 @@ -import 'package:bisaGo/flavor/flavor.dart'; -import 'package:bisaGo/model/new_user.dart'; import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/network/network_interface.dart'; -import 'package:http/http.dart'; abstract class BaseUserRepository { - Future fetchUserDetail(String email); - Future createUser(NewUser newUser); - Future updateUser(NewUser newUser); + Future fetchUserDetail(String email); + + Future registerUser(RegisterUserModel registerUserModel); + + Future updateUser(UpdateUserModel updateUserModel, String email); } + class UserRepository implements BaseUserRepository { final NetworkInterface _network = NetworkInterface(); @override - Future fetchUserDetail(String email) async { + Future fetchUserDetail(String email) async { final response = - await _network.get(url: '/api/user-detail/$email', isLogin: true); - final data = [response]; - return User( - data.map((user) => UserModel.fromJson(user)).toList()); + await _network.get(url: '/api/user/$email/', isLogin: true); + return DetailUserModel.fromJson(response); } @override - Future createUser(NewUser newUser) async { - final response = await post( - '${ApiFlavor.getBaseUrl()}/api/register/', - body: newUser.toJson(), + Future registerUser(RegisterUserModel registerUserModel) async { + return await _network.post( + url: '/api/user/register/', + isLogin: false, + bodyParams: registerUserModel.toJson(), ); - return response; } @override - Future updateUser(NewUser newUser) async { - final response = await post( - '${ApiFlavor.getBaseUrl()}/api/update-user/', - body: newUser.toJson(), + Future updateUser( + UpdateUserModel updateUserModel, String email) async { + final response = await _network.put( + url: '/api/user/$email/', + bodyParams: updateUserModel.toJson(), + isLogin: true, ); - return response; + return DetailUserModel.fromJson(response); } } diff --git a/lib/utils/datetime_utils.dart b/lib/utils/datetime_utils.dart new file mode 100644 index 0000000000000000000000000000000000000000..247e779d0e7f6fa617b9d15504d55bda70e86b9b --- /dev/null +++ b/lib/utils/datetime_utils.dart @@ -0,0 +1,27 @@ +import 'package:intl/intl.dart'; + +const userProfileDateFormat = 'dd MMMM yyyy'; +const userRegisterDateFormat = 'yyyy-MM-dd'; + +final idDateFormatter = DateFormat(userProfileDateFormat, 'id_ID'); +final usDateFormatter = DateFormat(userProfileDateFormat, 'en_US'); +final registerDateFormatter = DateFormat(userRegisterDateFormat, 'en_US'); + +String toIndonesiaLocale(String date) { + return fromLocaleToLocale(usDateFormatter, idDateFormatter, date); +} + +String toUnitedStatesLocale(String date) { + return fromLocaleToLocale(idDateFormatter, usDateFormatter, date); +} + +String fromLocaleToLocale( + DateFormat fromLocaleFormatter, DateFormat toLocaleFormatter, String date) { + var tempDate; + try { + tempDate = fromLocaleFormatter.parse(date); + } catch (_) { + return date; + } + return toLocaleFormatter.format(tempDate); +} diff --git a/lib/utils/profile_utils.dart b/lib/utils/profile_utils.dart new file mode 100644 index 0000000000000000000000000000000000000000..0899015c56276abe8f01303c2e13619ec2fbe44b --- /dev/null +++ b/lib/utils/profile_utils.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +const seenColor = Colors.black; + +String getNameInitials(String name) { + if (name.isEmpty) return ''; + final initials = name.split(' ').map((e) => e[0]).join().toUpperCase(); + if (initials.length > 2) return initials.substring(0, 2); + return initials; +} diff --git a/lib/utils/validator.dart b/lib/utils/validator.dart index b83b22c6b448151604d79a478758efe82ea8a750..e1d845c39cab7333f82d7be7df9163c37d557038 100644 --- a/lib/utils/validator.dart +++ b/lib/utils/validator.dart @@ -34,6 +34,14 @@ class FieldValidator { } } + static String validateOrganisasi(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } + static String validateEmail(String value) { const pattern = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; diff --git a/pubspec.yaml b/pubspec.yaml index 78b485cd46742ba1c02678a248ebdd3be1ca9462..13fba942921fbaad8554267634e10743ccec7d81 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,7 +55,9 @@ dependencies: firebase_core: ^0.7.0 firebase_core_platform_interface: ^3.0.1 firebase_dynamic_links: ^0.7.0+1 + firebase_messaging: ^8.0.0-dev.15 carousel_slider: ^3.0.0 + flushbar: ^1.10.4 url_launcher: ^6.0.3 photo_view: ^0.11.1 multi_image_picker: ^4.8.1 diff --git a/test/cloud_messaging_test.dart b/test/cloud_messaging_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..0f41541f63c9215ec6799f8bb744c81c0501071e --- /dev/null +++ b/test/cloud_messaging_test.dart @@ -0,0 +1,26 @@ +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:get_it/get_it.dart'; +import 'package:mockito/mockito.dart'; + +class MockCloudMessagingRepository extends Fake + implements CloudMessagingRepository { + @override + Future sendFCMToken(String fcmToken, String token) async { + return Future.value(true); + } +} + +void main() { + setUpAll(() { + final _getIt = GetIt.instance; + _getIt.registerLazySingleton( + () => MockCloudMessagingRepository()); + }); + testWidgets('Generate fcm token', (WidgetTester tester) async { + final result = + await MockCloudMessagingRepository().sendFCMToken('fcmToken', 'token'); + + expect(result, true); + }); +} diff --git a/test/custom_kegiatan_terdekat_button_test.dart b/test/custom_kegiatan_terdekat_button_test.dart index b59a76e6ddb6c05e04c783a622ac1caae15747bc..c8b5511d1806c21d08d3819e2589d6d3bb86b1ca 100644 --- a/test/custom_kegiatan_terdekat_button_test.dart +++ b/test/custom_kegiatan_terdekat_button_test.dart @@ -1,6 +1,7 @@ import 'package:bisaGo/model/kegiatan.dart'; import 'package:bisaGo/model/lokasi.dart'; import 'package:bisaGo/page/dashboard/dashboard.dart'; +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; import 'package:bisaGo/repository/kegiatan_terdekat_repository.dart'; import 'package:bisaGo/repository/lokasi_repository.dart'; import 'package:flutter/material.dart'; @@ -41,6 +42,14 @@ class MockLokasi extends Fake implements LokasiRepository { } } +class MockCloudMessagingRepository extends Fake + implements CloudMessagingRepository { + @override + Future sendFCMToken(String fcmToken, String token) async { + return Future.value(true); + } +} + void main() { // final mockLokasi = { // 'name': 'Margo City', @@ -68,6 +77,8 @@ void main() { _getIt.registerLazySingleton( () => MockKegiatanTerdekat()); _getIt.registerLazySingleton(() => MockLokasi()); + _getIt.registerLazySingleton( + () => MockCloudMessagingRepository()); }); testWidgets('Detail Post Kegiatan Page - Positive Test', diff --git a/test/detail_post_test.dart b/test/detail_post_test.dart index 0d6625dfd8f4f5de82c144aae85ad75c065b80aa..7f10f7cce9107484fc19485df8b42599c80f4351 100644 --- a/test/detail_post_test.dart +++ b/test/detail_post_test.dart @@ -66,13 +66,23 @@ void main() { testWidgets('Create a komentar placeholder', (WidgetTester tester) async { final detailPostState = detailPostPage.createState(); detailPostState.komentarPlaceHolder( - 'Halo', DateTime(2020, 1, 1), 'This is a test'); + 'Halo', + DateTime(2020, 1, 1), + 'This is a test', + 'test@email.com', + 'test.jpg', + ); }); testWidgets('Create a komentar placeholder', (WidgetTester tester) async { final detailPostState = detailPostPage.createState(); detailPostState.komentarPlaceHolder( - 'Halo', DateTime(2020, 1, 1), 'This is a test'); + 'Halo', + DateTime(2020, 1, 1), + 'This is a test', + 'test@email.com', + 'test.jpg', + ); }); test('Should decrypt tag code', () { diff --git a/test/login_test.dart b/test/login_test.dart index dbea2e890f13312a62278d6c6ebd0f8b1ff7aeca..bf03c007308d905a2a816fd91de524fd53ea3019 100644 --- a/test/login_test.dart +++ b/test/login_test.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:bisaGo/model/user.dart'; +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; import 'package:bisaGo/repository/user_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -13,13 +14,21 @@ import 'package:shared_preferences/shared_preferences.dart'; class MockNetwork extends Mock implements NetworkInterface {} +class MockCloudMessagingRepository extends Fake + implements CloudMessagingRepository { + @override + Future sendFCMToken(String fcmToken, String token) async { + return Future.value(true); + } +} + class MockUserRepository extends Fake implements UserRepository { final userData = { 'is_login': true, 'username': 'test@gmail.com', 'name': 'test', 'email': 'test@gmail.com', - 'tanggal_lahir': '2000-01-01', + 'tanggal_lahir': '02 October 2000', 'phone_number': '081234567898', 'jenis_kelamin': 'Laki-Laki', 'disabilitas': '-', @@ -28,8 +37,8 @@ class MockUserRepository extends Fake implements UserRepository { }; @override - Future fetchUserDetail(String email) async { - return Future.value(User([UserModel.fromJson(userData)])); + Future fetchUserDetail(String email) async { + return Future.value(DetailUserModel.fromJson(userData)); } } @@ -41,6 +50,9 @@ void main() { .registerLazySingleton(() => MockUserRepository()); SharedPreferences.setMockInitialValues( {'email': 'test@gmail.com', 'token': 'token'}); + + _getIt.registerLazySingleton( + () => MockCloudMessagingRepository()); // mockNetwork = MockNetwork(); // when(mockNetwork.get(isLogin: false, url: anyNamed('url'))) // .thenAnswer((_) async { diff --git a/test/mock_test.dart b/test/mock_test.dart index 032df7c1fd880109b3b02dcc9b12b37b37c84dca..32c7466c40368ed665c9c7ebce539fc93bd7877b 100644 --- a/test/mock_test.dart +++ b/test/mock_test.dart @@ -1,4 +1,5 @@ import 'package:bisaGo/model/kegiatan.dart'; +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; import 'package:bisaGo/repository/kegiatan_terdekat_repository.dart'; import 'package:bisaGo/repository/lokasi_repository.dart'; import 'package:flutter/material.dart'; @@ -45,6 +46,14 @@ class MockKegiatanTerdekatRepository extends Fake } } +class MockCloudMessagingRepository extends Fake + implements CloudMessagingRepository { + @override + Future sendFCMToken(String fcmToken, String token) async { + return Future.value(true); + } +} + void main() { group('Dashboard navigation tests', () { NavigatorObserver mockObserver; @@ -74,6 +83,8 @@ void main() { () => MockLokasiRepository()); _getIt.registerLazySingleton( () => MockKegiatanTerdekatRepository()); + _getIt.registerLazySingleton( + () => MockCloudMessagingRepository()); }); Future _buildDashboardPage(WidgetTester tester) async { diff --git a/test/model_test.dart b/test/model_test.dart index 9978873c020ff5cf03c449cebade6f797a08b86b..aad27f1a611725abc6b756f892296a091ded66f2 100644 --- a/test/model_test.dart +++ b/test/model_test.dart @@ -1,6 +1,5 @@ import 'package:bisaGo/model/komentar.dart'; import 'package:bisaGo/model/komentar_posting.dart'; -import 'package:bisaGo/model/new_user.dart'; import 'package:bisaGo/model/user.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -9,26 +8,35 @@ void main() { 'id': 1, 'deskripsi': 'This is a test', 'creator': 'Test', - 'date_time': '2020-11-18 00:13:52.939668' + 'creator_email': 'test@email.com', + 'creator_picture': 'test.jpg', + 'created': '18-11-2020 00:13:52' }; final returnKomentarPostingData = { 'id': 1, 'deskripsi': 'This is a test', 'creator': 'Test', - 'date_time': '2020-11-18T00:13:00.000' + 'creator_email': 'test@email.com', + 'creator_picture': 'test.jpg', + 'created': '2020-11-18T00:13:00.000' }; final userData = { - 'is_login': true, - 'username': 'test@gmail.com', + 'username': 'test@email.com', 'name': 'test', - 'email': 'test@gmail.com', - 'tanggal_lahir': '2000-01-01', + 'email': 'test@email.com', + 'tanggal_lahir': '02 October 2000', 'phone_number': '081234567898', 'jenis_kelamin': 'Laki-Laki', 'disabilitas': 'Tidak Memiliki Disabilitas', 'pekerjaan': 'Mahasiswa', 'alamat': 'Tidak Tahu', - 'token': null + 'seen': true, + 'foto': '', + 'hidden_fields': [], + 'hidden_fields_verbose': [], + 'can_see_hidden_fields': true, + 'hidden_fields_color': '#808080', + 'organisasi_komunitas': 'Organisasi', }; final komentarData = { 'id': 1, @@ -36,13 +44,14 @@ void main() { 'deskripsi': 'Ada toilet khusus disabilitas terletak di lantai 2 dekat kintan', 'creator': '', - 'date_time': '2020-11-18 00:13:52.939668', + 'date_time': '18-11-2020 00:13:52', 'rating': 3, 'tag': 'KR', 'disabilitas': ['DF'], 'jumlah': 1, 'image': 'static/img/2669211407.jpg', - 'is_verified': false + 'is_verified': false, + 'creator_email': 'test@email.com' }; final returnKomentarData = { 'id': 1, @@ -56,28 +65,32 @@ void main() { 'disabilitas': ['DF'], 'jumlah': 1, 'image': 'static/img/2669211407.jpg', - 'is_verified': false + 'is_verified': false, + 'creator_email': 'test@email.com', }; final newUserData = { 'name': 'test', - 'email': 'test@gmail.com', + 'email': 'test@email.com', 'password': '2139809348143123', - 'tanggal_lahir': '2000-01-01', + 'tanggal_lahir': '02 October 2000', 'phone_number': '081234567898', 'jenis_kelamin': 'Laki-Laki', 'disabilitas': 'Tidak Memiliki Disabilitas', 'pekerjaan': 'Mahasiswa', 'alamat': 'Tidak Tahu', + 'hidden_fields': [], }; test('Komentar Posting fromJson and toJson', () { final komentarPostingModel = KomentarPostingModel.fromJson(komentarPostingData); final komentarPostingWithConstructor = KomentarPostingModel( - id: 2, - deskripsi: 'This is a test', - creator: 'Test', - dateTime: DateTime.now()); + id: 2, + deskripsi: 'This is a test', + creator: 'Test', + creatorEmail: 'test@email.com', + creatorPicture: 'test.jpg', + created: DateTime.now()); expect(komentarPostingModel, isInstanceOf()); expect( komentarPostingWithConstructor, isInstanceOf()); @@ -93,15 +106,13 @@ void main() { }); test('User Model fromJson and toJson', () { - final userModel = [UserModel.fromJson(userData)]; - final user = User(userModel); - expect(user.user.length, 1); - expect(userModel.first.toJson(), userData); + final userModel = DetailUserModel.fromJson(userData); + expect(userModel.toJson(), userData); }); test('User Model fromJson and toJson', () { - final newUserModel = NewUser.fromJson(newUserData); - expect(newUserModel, isInstanceOf()); + final newUserModel = RegisterUserModel.fromJson(newUserData); + expect(newUserModel, isInstanceOf()); }); test('Komentar Model toJson', () { diff --git a/test/pilih_disabilitas_test.dart b/test/pilih_disabilitas_test.dart index a149cf3c7926b4788bbc6bc6cba02e8446985a01..c5cf4101d5a38925b0aa8ff835c298faa799fd31 100644 --- a/test/pilih_disabilitas_test.dart +++ b/test/pilih_disabilitas_test.dart @@ -1,28 +1,24 @@ -import 'package:bisaGo/model/new_user.dart'; +import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/page/login/pilih_disabilitas.dart'; import 'package:bisaGo/repository/user_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:get_it/get_it.dart'; -import 'package:http/http.dart'; import 'package:mockito/mockito.dart'; class MockUserRepository extends Fake implements UserRepository { @override - Future updateUser(NewUser newUser) async { - final responseBody = {'response': 'User updated'}; - final statusCode = 200; - return Future.value(Response(responseBody.toString(), statusCode)); + Future updateUser(UpdateUserModel updateUserModel, String email) async { + return Future.value(DetailUserModel()); } } void main() { final userData = { - 'is_login': true, 'username': 'test@gmail.com', 'name': 'test', 'email': 'test@gmail.com', - 'tanggal_lahir': '2000-01-01', + 'tanggal_lahir': '02 October 2000', 'phone_number': '081234567898', 'jenis_kelamin': 'Laki-Laki', 'disabilitas': 'Tidak memiliki disabilitas', @@ -96,7 +92,7 @@ void main() { (WidgetTester tester) async { await tester.pumpWidget(MaterialApp( home: PilihDisabilitas( - newUser: NewUser.fromJson(userData), + updateUser: UpdateUserModel.fromJson(userData), ))); final disabilitasIntelektualButton = find.text('Disabilitas Intelektual'); expect(disabilitasIntelektualButton, findsOneWidget); @@ -105,7 +101,7 @@ void main() { await tester.pumpWidget(MaterialApp( home: PilihDisabilitas( - newUser: NewUser.fromJson(userData), + updateUser: UpdateUserModel.fromJson(userData), ))); final disabilitasSensorikButton = find.text('Disabilitas Sensorik'); expect(disabilitasSensorikButton, findsOneWidget); @@ -114,7 +110,7 @@ void main() { await tester.pumpWidget(MaterialApp( home: PilihDisabilitas( - newUser: NewUser.fromJson(userData), + updateUser: UpdateUserModel.fromJson(userData), ))); final disabilitasMentalButton = find.text('Disabilitas Mental'); expect(disabilitasMentalButton, findsOneWidget); @@ -123,7 +119,7 @@ void main() { await tester.pumpWidget(MaterialApp( home: PilihDisabilitas( - newUser: NewUser.fromJson(userData), + updateUser: UpdateUserModel.fromJson(userData), ))); final disabilitasFisikButton = find.text('Disabilitas Fisik'); expect(disabilitasFisikButton, findsOneWidget); diff --git a/test/profile_test.dart b/test/profile_test.dart index e1f62408f9d59a3723dd6baea5e48340e0bbfb09..59901d7ded94c53a8a0538d89880a165de010056 100644 --- a/test/profile_test.dart +++ b/test/profile_test.dart @@ -1,5 +1,6 @@ +import 'dart:convert'; + import 'package:bisaGo/component/bisago_drawer.dart'; -import 'package:bisaGo/model/new_user.dart'; import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/page/profile/edit_profile.dart'; import 'package:bisaGo/page/profile/profile.dart'; @@ -7,7 +8,6 @@ import 'package:bisaGo/repository/user_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:get_it/get_it.dart'; -import 'package:http/http.dart'; import 'package:mockito/mockito.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -17,31 +17,30 @@ class MockUserRepository extends Fake implements UserRepository { 'username': 'test@gmail.com', 'name': 'test', 'email': 'test@gmail.com', - 'tanggal_lahir': '2000-01-01', + 'tanggal_lahir': '02 October 2000', 'phone_number': '081234567898', 'jenis_kelamin': 'Laki-Laki', 'disabilitas': 'Tidak memiliki disabilitas', 'pekerjaan': 'Pelajar', - 'alamat': 'Tidak Tahu' + 'alamat': 'Tidak Tahu', + 'hidden_fields': [], + 'hidden_fields_verbose': [], + 'can_see_hidden_fields': true, + 'hidden_fields_color': '#808080', + 'seen': true, }; @override - Future fetchUserDetail(String email) async { - return Future.value(User([UserModel.fromJson(userData)])); + Future fetchUserDetail(String email) async { + return Future.value(DetailUserModel.fromJson(userData)); } @override - Future updateUser(NewUser newUser) async { - var responseBody; - var statusCode; - if (newUser.disabilitas != null) { - responseBody = {'response': 'User updated'}; - statusCode = 200; - } else { - responseBody = {'response': 'Failed to update user'}; - statusCode = 400; + Future updateUser(UpdateUserModel updateUserModel, String email) async { + if (updateUserModel.disabilitas = null) { + return null; } - return Future.value(Response(responseBody.toString(), statusCode)); + return Future.value(DetailUserModel()); } } @@ -52,20 +51,17 @@ void main() { _getIt.registerLazySingleton( () => MockUserRepository()); SharedPreferences.setMockInitialValues( - {'email': 'test@gmail.com', 'token': 'token'}); + {'user':jsonEncode({'email': 'test@gmail.com'}), 'token': 'token'}); }); testWidgets('Dashboard with User', (WidgetTester tester) async { await tester.pumpWidget(MaterialApp(home: BisaGoDrawer())); await tester.pumpAndSettle(); expect(find.text('test@gmail.com'), findsOneWidget); - - await tester.tap(find.text('Profile')); - await tester.pumpAndSettle(); }); testWidgets('Dashboard with no User', (WidgetTester tester) async { - SharedPreferences.setMockInitialValues({'email': 'test@gmail.com'}); + SharedPreferences.setMockInitialValues({'user':jsonEncode({'email': 'test@gmail.com'})}); await tester.pumpWidget(MaterialApp(home: BisaGoDrawer())); await tester.pumpAndSettle(); expect(find.text('test@gmail.com'), findsNothing); @@ -161,23 +157,33 @@ void main() { final userData = { 'name': 'test', 'email': 'test@gmail.com', - 'tanggal_lahir': '2000-01-01', + 'tanggal_lahir': '02 October 2000', 'phone_number': '081234567898', 'jenis_kelamin': 'Laki-laki', 'disabilitas': 'Tidak memiliki disabilitas', 'pekerjaan': 'Pelajar', - 'alamat': 'Tidak Tahu' + 'alamat': 'Tidak Tahu', + 'seen': true, + 'hidden_fields': [], + 'hidden_fields_verbose': [], + 'can_see_hidden_fields': true, + 'hidden_fields_color': '#808080', }; final userData2 = { 'name': 'test', 'email': '', - 'tanggal_lahir': '2000-01-01', + 'tanggal_lahir': '02 October 2000', 'phone_number': '', 'jenis_kelamin': 'Laki-laki', 'disabilitas': 'Tidak memiliki disabilitas', 'pekerjaan': 'Pelajar', - 'alamat': '' + 'alamat': '', + 'seen': true, + 'hidden_fields': [], + 'hidden_fields_verbose': [], + 'can_see_hidden_fields': true, + 'hidden_fields_color': '#808080', }; testWidgets('Edit Profile Page Widget Test -- Positive', @@ -188,7 +194,7 @@ void main() { await tester.pumpWidget(MaterialApp( home: EditProfile( - user: UserModel.fromJson(userData), + user: DetailUserModel.fromJson(userData), ))); expect(find.byType(EditProfile), findsOneWidget); expect(find.byKey(headerEditProfilePageKey), findsOneWidget); @@ -208,7 +214,7 @@ void main() { await tester.pumpWidget(MaterialApp( home: EditProfile( - user: UserModel.fromJson(userData), + user: DetailUserModel.fromJson(userData), ))); expect(find.byType(EditProfile), findsOneWidget); expect(find.byKey(headerEditProfilePageKey), findsNothing); @@ -222,14 +228,14 @@ void main() { testWidgets('New Edit Profile Page Widget Test -- Positive', (WidgetTester tester) async { - final userAvatarKey = Key('Avatar test'); + //final userAvatarKey = Key('Avatar test'); final name = 'test'; await tester.pumpWidget( - MaterialApp(home: EditProfile(user: UserModel.fromJson(userData)))); + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); await tester.pumpAndSettle(); expect(find.byType(EditProfile), findsOneWidget); - expect(find.byKey(userAvatarKey), findsOneWidget); + //expect(find.byKey(userAvatarKey), findsOneWidget); expect(find.text(name), findsOneWidget); }); @@ -239,7 +245,7 @@ void main() { final name = 'mantap'; await tester.pumpWidget( - MaterialApp(home: EditProfile(user: UserModel.fromJson(userData)))); + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); await tester.pumpAndSettle(); expect(find.byType(Profile), findsNothing); expect(find.byKey(userAvatarKey), findsNothing); @@ -253,7 +259,7 @@ void main() { final pekerjaanKey = find.byKey(Key('Dropdown Pekerjaan')); await tester.pumpWidget( - MaterialApp(home: EditProfile(user: UserModel.fromJson(userData)))); + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); await tester.pumpAndSettle(); expect(find.byType(EditProfile), findsOneWidget); expect(jenisKelaminKey, findsOneWidget); @@ -308,7 +314,7 @@ void main() { userData.update('disabilitas', (value) => null); await tester.pumpWidget( - MaterialApp(home: EditProfile(user: UserModel.fromJson(userData2)))); + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData2)))); await tester.pumpAndSettle(); expect(find.byType(EditProfile), findsOneWidget); expect(jenisKelaminKey, findsOneWidget); @@ -354,7 +360,8 @@ void main() { await tester.tap(find.byKey(Key('Button Simpan'))); await tester.pumpAndSettle(); - expect(find.text('Update profile tidak berhasil!', skipOffstage: false), findsOneWidget); + expect(find.text('Update profile tidak berhasil!', skipOffstage: false), + findsOneWidget); }); testWidgets('Require all text fields to be filled -- Positive', @@ -362,14 +369,16 @@ void main() { final namaKey = find.byKey(Key('Text Field Nama')); final nomorTeleponKey = find.byKey(Key('Text Field Nomor Telepon')); final alamatKey = find.byKey(Key('Text Field Alamat')); + final organisasiKey = find.byKey(Key('Text Field Organisasi')); await tester.pumpWidget( - MaterialApp(home: EditProfile(user: UserModel.fromJson(userData)))); + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); await tester.pumpAndSettle(); await tester.enterText(namaKey, 'Ardian'); await tester.enterText(nomorTeleponKey, '085811111111'); await tester.enterText(alamatKey, ' Bekasi'); + await tester.enterText(organisasiKey, 'Olahraga'); await tester .ensureVisible(find.byKey(Key('Button Simpan'), skipOffstage: false)); @@ -384,21 +393,37 @@ void main() { final namaKey = find.byKey(Key('Text Field Nama')); final nomorTeleponKey = find.byKey(Key('Text Field Nomor Telepon')); final alamatKey = find.byKey(Key('Text Field Alamat')); + final organisasiKey = find.byKey(Key('Text Field Organisasi')); await tester.pumpWidget( - MaterialApp(home: EditProfile(user: UserModel.fromJson(userData)))); + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); await tester.pumpAndSettle(); await tester.enterText(namaKey, ''); await tester.enterText(nomorTeleponKey, ''); await tester.enterText(alamatKey, ''); + await tester.enterText(organisasiKey, ''); await tester .ensureVisible(find.byKey(Key('Button Simpan'), skipOffstage: false)); await tester.pumpAndSettle(); await tester.tap(find.byKey(Key('Button Simpan'))); await tester.pumpAndSettle(); - expect(find.text('*Wajib diisi'), findsNWidgets(3)); + expect(find.text('*Wajib diisi'), findsNWidgets(4)); + }); + + testWidgets('Change Profile Picture Title -- Positive', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); + expect(find.text('Ubah Foto Profil'), findsOneWidget); + }); + + testWidgets('Change Profile Picture Title -- Negative', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp(home: EditProfile(user: DetailUserModel.fromJson(userData)))); + expect(find.text('Edit PFP'), findsNothing); }); }); } diff --git a/test/registrasi_informasi_layanan_disabilitas_test.dart b/test/registrasi_informasi_layanan_disabilitas_test.dart index fe308f65cb753ae3adb29db8339062886b6f1bd0..0c65c3f2435833bc235563abcf36f11a927bb38e 100644 --- a/test/registrasi_informasi_layanan_disabilitas_test.dart +++ b/test/registrasi_informasi_layanan_disabilitas_test.dart @@ -43,21 +43,21 @@ void main() { await tester.tap(find.byKey(backButtonKey)); }); - testWidgets('create penyandang method test', (WidgetTester tester) async { - final registrasiPage = RegistrasiInformasiLayananDisabilitas(); - final registrasiState = registrasiPage.createState(); - var textEditingController = TextEditingController(); - textEditingController.text = 'This is a test'; - registrasiState.namaPenyandangController = textEditingController; - registrasiState.alamatController = textEditingController; - registrasiState.ttlController = textEditingController; - registrasiState.tanggalLahir = '2000-01-01'; - registrasiState.phoneController = textEditingController; - registrasiState.emailController = textEditingController; - registrasiState.namaWaliController = textEditingController; - registrasiState.alamatWaliController = textEditingController; - registrasiState.phoneNumbOrtuController = textEditingController; + // testWidgets('create penyandang method test', (WidgetTester tester) async { + // final registrasiPage = RegistrasiInformasiLayananDisabilitas(); + // final registrasiState = registrasiPage.createState(); + // var textEditingController = TextEditingController(); + // textEditingController.text = 'This is a test'; + // registrasiState.namaPenyandangController = textEditingController; + // registrasiState.alamatController = textEditingController; + // registrasiState.ttlController = textEditingController; + // registrasiState.tanggalLahir = '2000-01-01'; + // registrasiState.phoneController = textEditingController; + // registrasiState.emailController = textEditingController; + // registrasiState.namaWaliController = textEditingController; + // registrasiState.alamatWaliController = textEditingController; + // registrasiState.phoneNumbOrtuController = textEditingController; - registrasiState.createPenyandang(); - }); + // registrasiState.createPenyandang(); + // }); } diff --git a/test/registrasi_test.dart b/test/registrasi_test.dart index 9fed8a65172854aa1b3772f81f0bf222ed0f8817..e632c0ff4a8df79e4b17bd2520601637b7470006 100644 --- a/test/registrasi_test.dart +++ b/test/registrasi_test.dart @@ -1,26 +1,24 @@ -import 'package:bisaGo/model/new_user.dart'; +import 'package:bisaGo/model/user.dart'; import 'package:bisaGo/repository/user_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:bisaGo/page/registrasi/registrasi.dart'; import 'package:get_it/get_it.dart'; import 'package:mockito/mockito.dart'; -//import 'package:bisaGo/model/user.dart'; -import 'package:http/http.dart'; class MockUserRepository extends Fake implements UserRepository { @override - Future createUser(NewUser newUser) async { - final responseBody = {'response': 'User updated'}; - final statusCode = 200; - return Future.value(Response(responseBody.toString(), statusCode)); + Future registerUser(RegisterUserModel registerUserModel) async { + final responseBody = {'response': 'User registered'}; + return Future.value(responseBody); } } void main() { setUpAll(() { final _getIt = GetIt.instance; - _getIt.registerLazySingleton(() => MockUserRepository()); + _getIt + .registerLazySingleton(() => MockUserRepository()); }); testWidgets('Find Name Text Field', (WidgetTester tester) async { final textFieldKey = Key('Text Field Nama'); @@ -96,7 +94,7 @@ void main() { final pekerjaanKey = find.byKey(Key('Dropdown Pekerjaan')); final password = find.byKey(Key('Text Field Password')); final konfirmasiPassword = - find.byKey(Key('Text Field Konfirmasi Password')); + find.byKey(Key('Text Field Konfirmasi Password')); await tester.enterText(nama, 'nama'); await tester.enterText(noTelp, '08123456789'); @@ -137,8 +135,6 @@ void main() { await tester .ensureVisible(find.byKey(daftarButtonKey, skipOffstage: false)); - await tester.pumpAndSettle(const Duration(seconds: 1)); - await tester.tap(find.byKey(daftarButtonKey)); await tester.pumpAndSettle(); }); diff --git a/test/user_test.dart b/test/user_test.dart index 4703a5b488a6991bf706ac1497f0825abc4af8c0..0a555d702f8f4f1698763185e8545078420dcd6e 100644 --- a/test/user_test.dart +++ b/test/user_test.dart @@ -3,23 +3,26 @@ import 'package:flutter_test/flutter_test.dart'; void main() { final userData = { - 'is_login':true, - 'username':'test@gmail.com', - 'name':'test', - 'email':'test@gmail.com', - 'tanggal_lahir':'2000-01-01', - 'phone_number':'081234567898', - 'jenis_kelamin':'Laki-Laki', - 'disabilitas':'Tidak Memiliki Disabilitas', - 'pekerjaan':'Mahasiswa', - 'alamat':'Tidak Tahu', - 'token':null + 'username': 'test@gmail.com', + 'name': 'test', + 'email': 'test@gmail.com', + 'tanggal_lahir': '02 October 2000', + 'phone_number': '081234567898', + 'jenis_kelamin': 'Laki-Laki', + 'disabilitas': 'Tidak Memiliki Disabilitas', + 'pekerjaan': 'Mahasiswa', + 'alamat': 'Tidak Tahu', + 'seen': true, + 'foto': '', + 'hidden_fields': [], + 'hidden_fields_verbose': [], + 'can_see_hidden_fields': true, + 'hidden_fields_color': '#808080', + 'organisasi_komunitas': 'Organisasi', }; test('User Model', () { - final userModel = [UserModel.fromJson(userData)]; - final user = User(userModel); - expect(user.user.length, 1); - expect(userModel.first.toJson(), userData); + final userModel = DetailUserModel.fromJson(userData); + expect(userModel.toJson(), userData); }); -} \ No newline at end of file +} diff --git a/test/widget_test.dart b/test/widget_test.dart index bac647fc7feb60b7b71c5e090f1f3d194d731782..69c70526ce7c3346e24df51c92fa9352374b3591 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -2,6 +2,7 @@ import 'package:bisaGo/model/kegiatan.dart'; import 'package:bisaGo/model/komunitas.dart'; import 'package:bisaGo/model/lokasi.dart'; import 'package:bisaGo/model/sekolah.dart'; +import 'package:bisaGo/repository/cloud_messaging_repository.dart'; import 'package:bisaGo/repository/kegiatan_terdekat_repository.dart'; import 'package:bisaGo/repository/komunitas_repository.dart'; import 'package:bisaGo/repository/lokasi_repository.dart'; @@ -88,6 +89,14 @@ class MockKegiatanTerdekatRepository extends Fake } } +class MockCloudMessagingRepository extends Fake + implements CloudMessagingRepository { + @override + Future sendFCMToken(String fcmToken, String token) async { + return Future.value(true); + } +} + void main() { setUpAll(() { final _getIt = GetIt.instance; @@ -99,6 +108,8 @@ void main() { () => MockLokasiRepository()); _getIt.registerLazySingleton( () => MockKegiatanTerdekatRepository()); + _getIt.registerLazySingleton( + () => MockCloudMessagingRepository()); }); testWidgets('finds a text field in dashboard', (WidgetTester tester) async { final containerTextField = Key('Container Text Field');