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 7e0e18fb45ff626a6fc56cfea115918375278066..ea7ae76cd2a169db2a144e3e9eb4badb211784af 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -33,6 +33,10 @@ + + + + @@ -41,5 +45,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..62642395e589bde6ebeb5ad92577e10f4b0287b8 100644 --- a/android/fastlane/metadata/android/id/changelogs/changelogs.txt +++ b/android/fastlane/metadata/android/id/changelogs/changelogs.txt @@ -1,20 +1,20 @@ +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/config/custom_serializer.dart b/lib/config/custom_serializer.dart index 00ed551485c6ffcbb5d0b4b99156a5d29c1d383b..458c5a40085be5818e9619941d34b67cc150f7da 100644 --- a/lib/config/custom_serializer.dart +++ b/lib/config/custom_serializer.dart @@ -2,6 +2,6 @@ import 'package:intl/intl.dart'; class CustomSerializer { static DateTime stringToDateTime(String date) { - return DateFormat('yyyy-MM-dd hh:mm').parse(date); + return DateFormat('dd-MM-yyyy hh:mm').parse(date); } } 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/komentar_posting.dart b/lib/model/komentar_posting.dart index 04ffea66b0f7e81b692aeb063c34950447605436..465d0691b5f2d76f3325ed7e36af878d9473bc63 100644 --- a/lib/model/komentar_posting.dart +++ b/lib/model/komentar_posting.dart @@ -14,10 +14,15 @@ class KomentarPostingModel { final int id; final String deskripsi; final String creator; - @JsonKey(name: 'date_time', fromJson: CustomSerializer.stringToDateTime) - final DateTime dateTime; + @JsonKey(fromJson: CustomSerializer.stringToDateTime) + final DateTime created; - KomentarPostingModel({this.id, this.deskripsi, this.creator, this.dateTime}); + KomentarPostingModel({ + this.id, + this.deskripsi, + this.creator, + this.created, + }); factory KomentarPostingModel.fromJson(Map json) => _$KomentarPostingModelFromJson(json); diff --git a/lib/model/komentar_posting.g.dart b/lib/model/komentar_posting.g.dart index 565bcd3708949851186ff00919f57aa4691bedf5..0670572063c1797746975910dbcc6828422dff10 100644 --- a/lib/model/komentar_posting.g.dart +++ b/lib/model/komentar_posting.g.dart @@ -27,7 +27,7 @@ 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), + created: CustomSerializer.stringToDateTime(json['created'] as String), ); } @@ -37,5 +37,5 @@ Map _$KomentarPostingModelToJson( 'id': instance.id, 'deskripsi': instance.deskripsi, 'creator': instance.creator, - 'date_time': instance.dateTime?.toIso8601String(), + 'created': instance.created?.toIso8601String(), }; diff --git a/lib/model/komentar_posting_kegiatan.dart b/lib/model/komentar_posting_kegiatan.dart index 78e18d736f1dce8e066d0f562a7b6588dd3ab2a7..4f668c1b42c5e5259644469eef0d122e332b7df4 100644 --- a/lib/model/komentar_posting_kegiatan.dart +++ b/lib/model/komentar_posting_kegiatan.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_kegiatan.g.dart'; @@ -14,18 +14,18 @@ class KomentarPostingKegiatanModel { final int id; final String creator; final String deskripsi; - @JsonKey(name: 'created', fromJson: CustomSerializer.stringToDateTime) + @JsonKey(name: 'created', fromJson: _stringToDateTime) final DateTime created; KomentarPostingKegiatanModel( - {this.id, - this.creator, - this.deskripsi, - this.created} - ); + {this.id, this.creator, this.deskripsi, this.created}); factory KomentarPostingKegiatanModel.fromJson(Map json) => _$KomentarPostingKegiatanModelFromJson(json); Map toJson() => _$KomentarPostingKegiatanModelToJson(this); } + +DateTime _stringToDateTime(String date) { + return DateFormat('yyy-MM-dd hh:mm').parse(date); +} diff --git a/lib/model/komentar_posting_kegiatan.g.dart b/lib/model/komentar_posting_kegiatan.g.dart index 3b73f1a6ad4fa7c4a655ef055826935ec7a33754..49596213e4df2955e63cdc26d289aab9d0e37af3 100644 --- a/lib/model/komentar_posting_kegiatan.g.dart +++ b/lib/model/komentar_posting_kegiatan.g.dart @@ -29,7 +29,7 @@ KomentarPostingKegiatanModel _$KomentarPostingKegiatanModelFromJson( id: json['id'] as int, creator: json['creator'] as String, deskripsi: json['deskripsi'] as String, - created: CustomSerializer.stringToDateTime(json['created'] as String), + created: _stringToDateTime(json['created'] as String), ); } diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index 8e70ad4b6701d65f787ae760644f32541446f775..f6915b4dd5290abd37f74c2d49b7e62340fe2fa0 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) { @@ -368,20 +447,20 @@ class DashboardState extends State { ..name = namaLokasi; final fasilitasRoute = MaterialPageRoute( builder: (BuildContext context) => DetailPostKegiatanPage( - lokasi: lokasi, - kegiatan: KegiatanModel( - id: kegiatan.id, - placeId: lokasi.placeId, - creator: kegiatan.creator, - namaKegiatan: kegiatan.namaKegiatan, - penyelenggara: kegiatan.penyelenggara, - narahubung: kegiatan.narahubung, - deskripsi: kegiatan.deskripsi, - timeStart: kegiatan.timeStart, - timeEnd: kegiatan.timeEnd, - image: kegiatan.image, - ), - )); + lokasi: lokasi, + kegiatan: KegiatanModel( + id: kegiatan.id, + placeId: lokasi.placeId, + creator: kegiatan.creator, + namaKegiatan: kegiatan.namaKegiatan, + penyelenggara: kegiatan.penyelenggara, + narahubung: kegiatan.narahubung, + deskripsi: kegiatan.deskripsi, + timeStart: kegiatan.timeStart, + timeEnd: kegiatan.timeEnd, + image: kegiatan.image, + ), + )); await Navigator.of(context).push(fasilitasRoute); } diff --git a/lib/page/filter_fasilitas/kegiatan.dart b/lib/page/filter_fasilitas/kegiatan.dart index d66844303731fed78a616cb41ff20511a7cc3121..ef3c723ed8d307f91a464bec41ae8596ef5c1fce 100644 --- a/lib/page/filter_fasilitas/kegiatan.dart +++ b/lib/page/filter_fasilitas/kegiatan.dart @@ -17,29 +17,27 @@ class Kegiatan extends StatefulWidget { } class _KegiatanState extends State { - @override Widget build(BuildContext context) { return InkWell( key: Key(widget.kegiatan.namaKegiatan), onTap: () { - Navigator.of(context).pushReplacement(MaterialPageRoute( + Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => DetailPostKegiatanPage( - lokasi: widget.lokasi, - kegiatan: KegiatanModel( - id: widget.kegiatan.id, - placeId: widget.kegiatan.placeId, - creator: widget.kegiatan.creator, - namaKegiatan: widget.kegiatan.namaKegiatan, - penyelenggara: widget.kegiatan.penyelenggara, - narahubung: widget.kegiatan.narahubung, - deskripsi: widget.kegiatan.deskripsi, - timeStart: widget.kegiatan.timeStart, - timeEnd: widget.kegiatan.timeEnd, - image: widget.kegiatan.image, - ), - ) - )); + lokasi: widget.lokasi, + kegiatan: KegiatanModel( + id: widget.kegiatan.id, + placeId: widget.kegiatan.placeId, + creator: widget.kegiatan.creator, + namaKegiatan: widget.kegiatan.namaKegiatan, + penyelenggara: widget.kegiatan.penyelenggara, + narahubung: widget.kegiatan.narahubung, + deskripsi: widget.kegiatan.deskripsi, + timeStart: widget.kegiatan.timeStart, + timeEnd: widget.kegiatan.timeEnd, + image: widget.kegiatan.image, + ), + ))); }, child: Container( margin: const EdgeInsets.only(bottom: regularSpace), @@ -72,59 +70,68 @@ class _KegiatanState extends State { ), ), Container( - margin: const EdgeInsets.only(bottom: regularSpace), - child: SizedBox( - width: MediaQuery.of(context).size.width, - height: 160, - child: CarouselSlider( - options: CarouselOptions( - aspectRatio: 1.0, - enlargeCenterPage: true, - enableInfiniteScroll: false, - initialPage: 0, - autoPlay: true, - ), - items: widget.kegiatan.image.map((item) => Container( - child: Container( - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(20)), - child: Stack( - children: [ - Image.network(item, fit: BoxFit.cover, width: 1000.0), - Positioned( - bottom: 0.0, - left: 0.0, - right: 0.0, + margin: const EdgeInsets.only(bottom: regularSpace), + child: SizedBox( + width: MediaQuery.of(context).size.width, + height: 160, + child: CarouselSlider( + options: CarouselOptions( + aspectRatio: 1.0, + enlargeCenterPage: true, + enableInfiniteScroll: false, + initialPage: 0, + autoPlay: true, + ), + items: widget.kegiatan.image + .map((item) => Container( child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromARGB(200, 0, 0, 0), - Color.fromARGB(0, 0, 0, 0) - ], - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - ), - ), - padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), - child: Text( - '#${widget.kegiatan.image.indexOf(item)+1}', - style: TextStyle( - color: Colors.white, - fontSize: 20.0, - fontWeight: FontWeight.bold, - ), - ), + child: ClipRRect( + borderRadius: BorderRadius.all( + Radius.circular(20)), + child: Stack( + children: [ + Image.network(item, + fit: BoxFit.cover, + width: 1000.0), + Positioned( + bottom: 0.0, + left: 0.0, + right: 0.0, + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromARGB( + 200, 0, 0, 0), + Color.fromARGB( + 0, 0, 0, 0) + ], + begin: Alignment + .bottomCenter, + end: Alignment.topCenter, + ), + ), + padding: EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 20.0), + child: Text( + '#${widget.kegiatan.image.indexOf(item) + 1}', + style: TextStyle( + color: Colors.white, + fontSize: 20.0, + fontWeight: + FontWeight.bold, + ), + ), + ), + ), + ], + )), ), - ), - ], - ) - ), - ), - )).toList(), - ), - ) - ), + )) + .toList(), + ), + )), Row( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.end, @@ -148,5 +155,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..d7c53f2b905f61fb21f2d74e2b6fe9f430e37524 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( diff --git a/lib/page/filter_fasilitas/postingan/detail_post.dart b/lib/page/filter_fasilitas/postingan/detail_post.dart index af1d54df43a22cda93b3b70940ed03bd93f8eec6..c8abdb50b5d317bb103f02c43cf47885772e5156 100644 --- a/lib/page/filter_fasilitas/postingan/detail_post.dart +++ b/lib/page/filter_fasilitas/postingan/detail_post.dart @@ -2,7 +2,6 @@ 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/page/updateInformasi/update_informasi.dart'; import 'package:bisaGo/repository/dynamic_links_service_repository.dart'; import 'package:bisaGo/utils/share_utils.dart'; @@ -54,357 +53,345 @@ 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), ), - ), - ], - ), - ), - 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), + margin: const EdgeInsets.symmetric( + vertical: regularSpace), child: Text( - '${widget.komentar.creator} ', - key: Key('creator-${widget.komentar.creator}'), - overflow: TextOverflow.fade, - softWrap: false, - style: const TextStyle( - fontSize: 12, - fontStyle: FontStyle.italic, - ), + widget.komentar.deskripsi, + key: const Key('Text Cara Menggunakan'), + style: const TextStyle(fontSize: 16), ), ), - Text( - '(${DateFormat('dd MMM yyy').format(widget.komentar.dateTime)})', - key: const Key('timestamp'), + ], + ), + ), + 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), + child: Text( + '${widget.komentar.creator} ', + key: Key('creator-${widget.komentar.creator}'), + overflow: TextOverflow.fade, + softWrap: false, 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: + ), + 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: + 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)) + .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 +427,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 { @@ -498,7 +482,7 @@ class _DetailPostPageState extends State { name, style: const TextStyle(fontSize: 18), ), - Text('${DateFormat('dd MMMM yyy hh:mm').format(date)}', + Text('${DateFormat('dd MMMM yyyy hh:mm').format(date)}', style: const TextStyle(color: grayPrimary, fontSize: 14)) ], ), diff --git a/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart b/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart index fbc07c0cc10c94679c0adace288298a43bc3babc..2054000f53e0d4c3670db062138143d13ca3e917 100644 --- a/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart +++ b/lib/page/filter_fasilitas/postingan/detail_post_kegiatan.dart @@ -19,8 +19,6 @@ import 'package:bisaGo/page/login/login.dart'; import 'package:share/share.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import '../fasilitas.dart'; - class DetailPostKegiatanPage extends StatefulWidget { final Lokasi lokasi; final KegiatanModel kegiatan; // ganti model x // sudah @@ -48,436 +46,422 @@ class _DetailPostKegiatanPageState extends State { @override Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () => Navigator.of(context).pushReplacement(MaterialPageRoute( - builder: (BuildContext context) => Fasilitas( - lokasi: widget.lokasi, - ))), - child: Scaffold( - appBar: BisaGoAppBar( - title: widget.lokasi.name, - key: Key('appbar-text-${widget.kegiatan.placeId}'), - actions: [ - InkWell( - onTap: () async { - final link = await DynamicLinksServiceRepository() - .createDynamicLinkForKegiatan( - widget.kegiatan.id, - widget.lokasi.placeId, - ); - await Share.share(ShareUtils.getFormattedMessageKegiatan( - widget.kegiatan, widget.lokasi, link)); - }, - child: const Padding( - padding: EdgeInsets.all(doubleSpace), - child: Icon(Icons.share), - ), + return Scaffold( + appBar: BisaGoAppBar( + title: widget.lokasi.name, + key: Key('appbar-text-${widget.kegiatan.placeId}'), + actions: [ + InkWell( + onTap: () async { + final link = await DynamicLinksServiceRepository() + .createDynamicLinkForKegiatan( + widget.kegiatan.id, + widget.lokasi.placeId, + ); + await Share.share(ShareUtils.getFormattedMessageKegiatan( + widget.kegiatan, widget.lokasi, link)); + }, + child: const Padding( + padding: EdgeInsets.all(doubleSpace), + child: Icon(Icons.share), ), - ], - ), - body: SingleChildScrollView( - child: Column( - children: [ - Container( - key: const Key('Text Judul Kegiatan'), - 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, - // ganti alias tambahan - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: regularSpace), - Text( - widget.kegiatan - .namaKegiatan, // ganti nama kegiatan // sudah - style: const TextStyle( - fontSize: 30, - fontWeight: FontWeight.w800, - letterSpacing: 0.3, - fontFamily: 'Muli', - // color: Colors.black, - // fontFamily: 'Comfortaa', - ), + ), + ], + ), + body: SingleChildScrollView( + child: Column( + children: [ + Container( + key: const Key('Text Judul Kegiatan'), + 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, + // ganti alias tambahan + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: regularSpace), + Text( + widget.kegiatan + .namaKegiatan, // ganti nama kegiatan // sudah + style: const TextStyle( + fontSize: 30, + fontWeight: FontWeight.w800, + letterSpacing: 0.3, + fontFamily: 'Muli', + // color: Colors.black, + // fontFamily: 'Comfortaa', ), - Text( - 'oleh ${widget.kegiatan.penyelenggara}', // ganti format ${nama penyelenggara} // sudah - style: TextStyle(fontSize: 16), - textAlign: TextAlign.left, - ) - ], - ), + ), + Text( + 'oleh ${widget.kegiatan.penyelenggara}', // ganti format ${nama penyelenggara} // sudah + style: TextStyle(fontSize: 16), + textAlign: TextAlign.left, + ) + ], ), - // 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(); - // }, - // ), - ], - ), + ), + // 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(); + // }, + // ), + ], ), - Container( - margin: const EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: MediaQuery.of(context).size.width, - height: 160, - child: CarouselSlider( - options: CarouselOptions( - aspectRatio: 1.0, - enlargeCenterPage: true, - enableInfiniteScroll: false, - initialPage: 0, - autoPlay: true, - ), - items: widget.kegiatan.image - .map((item) => Container( - child: Container( - child: ClipRRect( - borderRadius: BorderRadius.all( - Radius.circular(20)), - child: Stack( - children: [ - Image.network(item, - fit: BoxFit.cover, - width: 1000.0), - Positioned( - bottom: 0.0, - left: 0.0, - right: 0.0, - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - Color.fromARGB( - 200, 0, 0, 0), - Color.fromARGB(0, 0, 0, 0) - ], - begin: - Alignment.bottomCenter, - end: Alignment.topCenter, - ), + ), + Container( + margin: const EdgeInsets.all(doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width, + height: 160, + child: CarouselSlider( + options: CarouselOptions( + aspectRatio: 1.0, + enlargeCenterPage: true, + enableInfiniteScroll: false, + initialPage: 0, + autoPlay: true, + ), + items: widget.kegiatan.image + .map((item) => Container( + child: Container( + child: ClipRRect( + borderRadius: + BorderRadius.all(Radius.circular(20)), + child: Stack( + children: [ + Image.network(item, + fit: BoxFit.cover, width: 1000.0), + Positioned( + bottom: 0.0, + left: 0.0, + right: 0.0, + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + Color.fromARGB( + 200, 0, 0, 0), + Color.fromARGB(0, 0, 0, 0) + ], + begin: Alignment.bottomCenter, + end: Alignment.topCenter, ), - padding: EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 20.0), - child: Text( - '#${widget.kegiatan.image.indexOf(item) + 1}', - style: TextStyle( - color: Colors.white, - fontSize: 20.0, - fontWeight: FontWeight.bold, - ), + ), + padding: EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 20.0), + child: Text( + '#${widget.kegiatan.image.indexOf(item) + 1}', + style: TextStyle( + color: Colors.white, + fontSize: 20.0, + fontWeight: FontWeight.bold, ), ), ), - ], - )), - ), - )) - .toList(), - ), - ), - const SizedBox( - height: 10, - ), - 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), - // ), - // ), - // ], - // ), - // Container( - // margin: const EdgeInsets.symmetric( - // vertical: regularSpace - // ), - // ganti alias tambahan - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - // mainAxisAlignment: - // MainAxisAlignment.center, - children: [ - const Icon( - Icons.access_time, - size: 20, - color: Colors.green, - ), - const SizedBox(width: 7.0), - const Text( - 'Senin, 3 Mei 2021', // ganti format widget.x.tanggalpelaksanaan - style: TextStyle(fontSize: 16), - key: Key('Text Waktu Pelaksanaan'), - ), - ], - ), - SizedBox(height: 40), - Text( - widget.kegiatan - .deskripsi, // ganti format widget.x.deskripsi kegiatan // sudah - style: const TextStyle(fontSize: 16), - key: const Key('Text Deskripsi Kegiatan'), - ), - SizedBox(height: 40), - Row( - // mainAxisAlignment: - // MainAxisAlignment.center, - children: [ - const Icon( - Icons.call, - size: 20, - color: Colors.green, - ), - const SizedBox(width: 7.0), - Text( - widget.kegiatan - .narahubung, // ganti format narahubung // sudah - style: TextStyle(fontSize: 16), - key: Key('Text Narahubung'), - ), - ], - ), - ], - ), - // ), - // ], - // ), + ), + ], + )), + ), + )) + .toList(), ), - 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), - child: Text( - widget.kegiatan - .creator, // ganti format ${widget.x.creator} // sudah - key: Key( - 'Creator info kegiatan'), // ganti format key creator-${widget.x.creator} - overflow: TextOverflow.fade, - softWrap: false, - style: const TextStyle( - fontSize: 12, - fontStyle: FontStyle.italic, + ), + const SizedBox( + height: 10, + ), + 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), + // ), + // ), + // ], + // ), + // Container( + // margin: const EdgeInsets.symmetric( + // vertical: regularSpace + // ), + // ganti alias tambahan + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + // mainAxisAlignment: + // MainAxisAlignment.center, + children: [ + const Icon( + Icons.access_time, + size: 20, + color: Colors.green, ), - ), + const SizedBox(width: 7.0), + const Text( + 'Senin, 3 Mei 2021', // ganti format widget.x.tanggalpelaksanaan + style: TextStyle(fontSize: 16), + key: Key('Text Waktu Pelaksanaan'), + ), + ], ), + SizedBox(height: 40), Text( - '22 April 2021', - // '(${DateFormat('dd MMM yyy').format(widget.kegiatan.dateTime)})', // ganti format (${DateFormat('dd MMM yyy').format(widget.x.dateTime)}) - key: const Key('timestamp'), + widget.kegiatan + .deskripsi, // ganti format widget.x.deskripsi kegiatan // sudah + style: const TextStyle(fontSize: 16), + key: const Key('Text Deskripsi Kegiatan'), + ), + SizedBox(height: 40), + Row( + // mainAxisAlignment: + // MainAxisAlignment.center, + children: [ + const Icon( + Icons.call, + size: 20, + color: Colors.green, + ), + const SizedBox(width: 7.0), + Text( + widget.kegiatan + .narahubung, // ganti format narahubung // sudah + style: TextStyle(fontSize: 16), + key: Key('Text Narahubung'), + ), + ], + ), + ], + ), + // ), + // ], + // ), + ), + 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), + child: Text( + widget.kegiatan + .creator, // ganti format ${widget.x.creator} // sudah + key: Key( + 'Creator info kegiatan'), // ganti format key creator-${widget.x.creator} + overflow: TextOverflow.fade, + softWrap: false, 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), ), + Text( + '22 April 2021', + // '(${DateFormat('dd MMM yyy').format(widget.kegiatan.dateTime)})', // ganti format (${DateFormat('dd MMM yyy').format(widget.x.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.komentarPostingKegiatanListStream, - builder: (context, snapshot) { - if (snapshot.hasData) { - switch (snapshot.data.status) { - case Status.loading: + ), + StreamBuilder( + stream: _bloc.komentarPostingKegiatanListStream, + 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: + allKomentarPositngKegiatanFromApi = snapshot + .data + .data + .allKomentarKegiatan; // kalo error, brarti allKegiatan + if (allKomentarPositngKegiatanFromApi.isEmpty) { return const Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - greenPrimary), - ), - ); - break; - case Status.completed: - allKomentarPositngKegiatanFromApi = snapshot - .data - .data - .allKomentarKegiatan; // kalo error, brarti allKegiatan - if (allKomentarPositngKegiatanFromApi.isEmpty) { - return const Center( - child: Text('Tidak ada komentar')); - } else { - return Column( - children: - allKomentarPositngKegiatanFromApi - .map((k) => - komentarKegiatanPlaceHolder( - k.creator, - k.created, - 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: allKomentarPositngKegiatanFromApi + .map((k) => + komentarKegiatanPlaceHolder( + k.creator, + k.created, + k.deskripsi)) + .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: komentarKegiatanController, - 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: komentarKegiatanController, + 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), + ), + ], + ), + ), + )), + ], + )), + ], ), - ], - ), + ), + ], ), ), ); @@ -513,9 +497,6 @@ class _DetailPostKegiatanPageState extends State { if (response['response'] == 'komentar kegiatan added') { successDialog(context); - Timer(const Duration(seconds: 2), () { - Navigator.pop(context); - }); await _bloc.fetchKomentarPostingKegiatanList( _placeId, widget.kegiatan.id); // ganti widget.x.id // sudah komentarKegiatanController.clear(); diff --git a/lib/page/login/login.dart b/lib/page/login/login.dart index 57496777fca5c0688955ad38c1a9cd3d59909428..67aaa2e980ca1d42832abc94dc95d84899e26ea8 100644 --- a/lib/page/login/login.dart +++ b/lib/page/login/login.dart @@ -1,10 +1,13 @@ import 'dart:async'; import 'dart:convert'; +import 'package:bisaGo/bloc/cloud_messaging_bloc.dart'; 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/page/dashboard/dashboard.dart'; import 'package:bisaGo/page/login/pilih_disabilitas.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -35,6 +38,10 @@ class LoginState extends State { GoogleSignInAccount _currentUser; SharedPreferences sharedPreferences; + FirebaseMessaging _firebaseMessaging; + + CloudMessagingBloc cloudMessagingBloc = CloudMessagingBloc(); + @override void initState() { super.initState(); @@ -159,12 +166,12 @@ 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); @@ -189,11 +196,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); @@ -292,6 +299,8 @@ class LoginState extends State { ..setString('token', tokenMap['token']) ..setString('email', email); }); + await _requestFCMToken(); + successDialog(context); _navigateToDashboard(context); } else { @@ -384,6 +393,19 @@ class LoginState extends State { } } + Future _requestFCMToken() async { + await Firebase.initializeApp(); + + _firebaseMessaging = FirebaseMessaging.instance; + + final fcmToken = await _firebaseMessaging.getToken(); + final sharedPreferences = await SharedPreferences.getInstance(); + final token = sharedPreferences.getString('token'); + if (token != null) { + await cloudMessagingBloc.sendFCMToken(fcmToken, token); + } + } + Future _handleSignOut() async { await _googleSignIn.signOut(); } 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 e8fdb53b8e26f78aca55f1d35bd76f11e30d7f0e..b1f969ac6488ffd7c84c331106fe6cf519abfed3 100644 --- a/lib/repository/kegiatan_repository.dart +++ b/lib/repository/kegiatan_repository.dart @@ -55,10 +55,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.image = await fetchImages(kegiatan.placeId, kegiatan.id); diff --git a/lib/repository/user_repository.dart b/lib/repository/user_repository.dart index 4ced6b383e87b1874bfcb2f7d7e5b2757bc39270..dd7caf0331ae1e354aeaf8a7c858dcf1da0e0a4c 100644 --- a/lib/repository/user_repository.dart +++ b/lib/repository/user_repository.dart @@ -9,13 +9,14 @@ abstract class BaseUserRepository { Future createUser(NewUser newUser); Future updateUser(NewUser newUser); } + class UserRepository implements BaseUserRepository { final NetworkInterface _network = NetworkInterface(); @override Future fetchUserDetail(String email) async { final response = - await _network.get(url: '/api/user-detail/$email', isLogin: true); + await _network.get(url: '/api/user/$email/', isLogin: true); final data = [response]; return User( data.map((user) => UserModel.fromJson(user)).toList()); diff --git a/pubspec.yaml b/pubspec.yaml index 59f1b2ba4576ab45e87141c318a48e53234659c3..14d76cf29aa08394cbe0c21b3489b74b438129b7 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 dev_dependencies: flutter_test: 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/login_test.dart b/test/login_test.dart index dbea2e890f13312a62278d6c6ebd0f8b1ff7aeca..2573a52272127c220f0064b2cdad3c9bd1c2be90 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,6 +14,14 @@ 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, @@ -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..cece1d5f14ee3f674c967fefd1a81701d772245d 100644 --- a/test/model_test.dart +++ b/test/model_test.dart @@ -9,13 +9,13 @@ void main() { 'id': 1, 'deskripsi': 'This is a test', 'creator': 'Test', - 'date_time': '2020-11-18 00:13:52.939668' + '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' + 'created': '2020-11-18T00:13:00.000' }; final userData = { 'is_login': true, @@ -36,7 +36,7 @@ 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'], @@ -77,7 +77,7 @@ void main() { id: 2, deskripsi: 'This is a test', creator: 'Test', - dateTime: DateTime.now()); + created: DateTime.now()); expect(komentarPostingModel, isInstanceOf()); expect( komentarPostingWithConstructor, isInstanceOf()); 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');