diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index c6ecbd36fa33b864b07cb429b7d1423584d69228..912b854c4574c3639ef25db48c64e24dc393f674 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"sqflite","dependencies":[]}]} \ No newline at end of file +{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"google_maps_flutter","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"share","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}]} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a1b47e53bf30b0552bf6204186dc275a0899c63b..2b568ae0522e62b82625124faa5e548b557c4c7d 100644 --- a/.gitignore +++ b/.gitignore @@ -291,3 +291,9 @@ modules.xml tests.output .flutter-plugins-dependencies + +android/app/upload.keystore + +android/key_fastlane.json + +android/key.properties diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index da9a47c7190313948d82edb935b54ebcdf895416..fbd6615a2ec21b9bd6fb852fee1d523ee96c427d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ before_script: - echo flutter.sdk=/sdk/flutter > android/local.properties - flutter pub get -image: michael09/flutter:latest +image: michael09/flutter:28-1.12.13_hotfix.9 Lint: stage: lint diff --git a/README.md b/README.md index 6c0f425d264c9e29e46a7929166d7d3cb77bf6c3..3d8e061da9a275b2ed93782d2258f4f94d6341e7 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,4 @@ flutter pub run build_runner build ## Passing Data with BLoC Udah ada contohnya di /bloc (implementasi di screen nya ada di page/pencarian/pencarian.dart) -Bisa baca [disini]https://itnext.io/flutter-handling-your-network-api-calls-like-a-boss-936eef296547 sebagai panduannya \ No newline at end of file +Bisa baca [disini](https://itnext.io/flutter-handling-your-network-api-calls-like-a-boss-936eef296547) sebagai panduannya \ No newline at end of file diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index e8895216fd3c0c3af4c4522334775f41b7deb42e..7ce47463d1b3c98baee08f1b6cd5b5fe5c375ddc 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,2 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 +gradle.user.home= +java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index eac51190b63296f719b720b468a0f4f39846afba..eb2158e9d70ae3c745d949a68ce173cb3b07e959 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -5,4 +5,5 @@ --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> </manifest> diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6782f488f66280a2a535ddcd63842c11e2fdde0b..89609546dd0757236591949bbfd84bfe93e67a66 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,9 @@ In most cases you can leave this as-is, but you if you want to provide additional functionality it is fine to subclass or reimplement FlutterApplication and put your custom class here. --> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <application android:name="io.flutter.app.FlutterApplication" android:label="ppl_disabilitas" diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml index 38838990d69858f983edbee6e8acf5a32c10ef0a..eb2158e9d70ae3c745d949a68ce173cb3b07e959 100644 --- a/android/app/src/profile/AndroidManifest.xml +++ b/android/app/src/profile/AndroidManifest.xml @@ -4,4 +4,6 @@ to allow setting breakpoints, to provide hot reload, etc. --> <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> </manifest> diff --git a/assets/logo/google.png b/assets/logo/google.png new file mode 100644 index 0000000000000000000000000000000000000000..2ef869d64c542bfa652312d35e2fea1757456558 Binary files /dev/null and b/assets/logo/google.png differ diff --git a/assets/logo/google.svg b/assets/logo/google.svg new file mode 100644 index 0000000000000000000000000000000000000000..7f1d5e497be41367280aece388d69ab4c999aab1 --- /dev/null +++ b/assets/logo/google.svg @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/"> + <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/"> + <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/"> + <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/"> + <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/"> + <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/"> + <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/"> + <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/"> +]> +<svg version="1.1" id="Livello_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 533.5 544.3" + style="enable-background:new 0 0 533.5 544.3;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#4285F4;} + .st1{fill:#34A853;} + .st2{fill:#FBBC04;} + .st3{fill:#EA4335;} +</style> +<metadata> + <sfw xmlns="&ns_sfw;"> + <slices></slices> + <sliceSourceBounds bottomLeftOrigin="true" height="544.3" width="533.5" x="0.1" y="110.1"></sliceSourceBounds> + </sfw> +</metadata> +<g> + <path class="st0" d="M533.5,278.4c0-18.5-1.5-37.1-4.7-55.3H272.1v104.8h147c-6.1,33.8-25.7,63.7-54.4,82.7v68h87.7 + C503.9,431.2,533.5,361.2,533.5,278.4z"/> + <path class="st1" d="M272.1,544.3c73.4,0,135.3-24.1,180.4-65.7l-87.7-68c-24.4,16.6-55.9,26-92.6,26c-71,0-131.2-47.9-152.8-112.3 + H28.9v70.1C75.1,486.3,169.2,544.3,272.1,544.3z"/> + <path class="st2" d="M119.3,324.3c-11.4-33.8-11.4-70.4,0-104.2V150H28.9c-38.6,76.9-38.6,167.5,0,244.4L119.3,324.3z"/> + <path class="st3" d="M272.1,107.7c38.8-0.6,76.3,14,104.4,40.8l0,0l77.7-77.7C405,24.6,339.7-0.8,272.1,0C169.2,0,75.1,58,28.9,150 + l90.4,70.1C140.8,155.6,201.1,107.7,272.1,107.7z"/> +</g> +</svg> diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index a59339f96fd8e242ff675f7614e9e0694560cf00..cabde0c6aab2c1ee612e96a4065549e071e9235f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -41,5 +41,12 @@ </array> <key>UIViewControllerBasedStatusBarAppearance</key> <false/> + <!-- image picker --> + <key>NSPhotoLibraryUsageDescription</key> + <string>Need to upload image</string> + <key>NSCameraUsageDescription</key> + <string>Need to upload image</string> + <key>NSMicrophoneUsageDescription</key> + <string>Need to upload image</string> </dict> </plist> diff --git a/lib/app.dart b/lib/app.dart index f113fe88a70914aec0e9f1176f7ddb2f2df22978..8ac4d9e9562d9502a4267791cbafa5cd8ea7c32f 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; -//import 'package:ppl_disabilitas/page/filter & fasilitas/fasilitas.dart'; class BisaGo extends StatelessWidget { @override @@ -9,9 +9,11 @@ class BisaGo extends StatelessWidget { title: 'bisaGo', theme: ThemeData( fontFamily: 'Muli', + primaryColor: greenPrimary, backgroundColor: Colors.white, ), home: Dashboard(), + //home:AddLokasi(), ); } } diff --git a/lib/bloc/KomentarBloc.dart b/lib/bloc/KomentarBloc.dart index db892c69738827c844017b6fac56c0621cd2cadd..0e98647f7509444ebde5124847ed5dc1221590d5 100644 --- a/lib/bloc/KomentarBloc.dart +++ b/lib/bloc/KomentarBloc.dart @@ -7,23 +7,26 @@ import 'package:ppl_disabilitas/repository/KomentarRepository.dart'; class KomentarBloc { KomentarRepository _komentarRepository; StreamController _komentarListController; + List<KomentarModel> allKomentarFromApi; StreamSink<NetworkModel<KomentarList>> get komentarListSink => _komentarListController.sink; Stream<NetworkModel<KomentarList>> get komentarListStream => _komentarListController.stream; - KomentarBloc() { + KomentarBloc(String namaLokasi) { _komentarListController = StreamController<NetworkModel<KomentarList>>(); _komentarRepository = KomentarRepository(); - fetchKomentarList(); + fetchKomentarList(namaLokasi); } - fetchKomentarList() async { + fetchKomentarList(String namaLokasi) async { komentarListSink.add(NetworkModel.loading('Getting Komentar')); try { KomentarList komentarListResponse = - await _komentarRepository.fetchKomentar(); + await _komentarRepository.fetchKomentar(namaLokasi); + allKomentarFromApi = List.from(komentarListResponse.allKomentar); + komentarListSink.add(NetworkModel.completed(komentarListResponse)); } catch (e) { komentarListSink.add(NetworkModel.error(e.toString())); @@ -31,6 +34,39 @@ class KomentarBloc { } } + filterKomentarList(String tag, bool value, List<KomentarModel> currentList) { + if (value) { + for (var komentar in allKomentarFromApi) { + if (komentar.tag.contains(tag)) { + currentList.add(komentar); + } + } + } else { + currentList.removeWhere((komentar) => komentar.tag.contains(tag)); + } + komentarListSink.add(NetworkModel.completed(KomentarList(currentList))); + } + + sortKomentarList(int option, List<KomentarModel> currentList) { + if (option == 0) { + currentList.sort((next_komentar, prev_komentar) => + prev_komentar.date_time.compareTo(next_komentar.date_time)); + } else if (option == 1) { + currentList.sort((next_komentar, prev_komentar) => + (prev_komentar.like + prev_komentar.dislike) + .compareTo(next_komentar.like + next_komentar.dislike)); + } else if (option == 2) { + currentList.sort((next_komentar, prev_komentar) => + prev_komentar.like.compareTo(next_komentar.like)); + } + komentarListSink.add(NetworkModel.completed(KomentarList(currentList))); + } + + resetKomentarList() { + komentarListSink + .add(NetworkModel.completed(KomentarList(allKomentarFromApi))); + } + dispose() { _komentarListController?.close(); } diff --git a/lib/bloc/LokasiResponseBloc.dart b/lib/bloc/LokasiResponseBloc.dart index ace530a114d6116a017ba7c6d80bd1236d755ec0..401a8a05d2ce032e86ec7e3908de9a52de44f005 100644 --- a/lib/bloc/LokasiResponseBloc.dart +++ b/lib/bloc/LokasiResponseBloc.dart @@ -31,7 +31,7 @@ class LokasiResponseBloc { fetchLokasiList() async { lokasiListSink.add(NetworkModel.loading('Getting Locations')); try { - LokasiListResponse lokasiListResponse = + final lokasiListResponse = await _lokasiRepository.fetchLokasi(); lokasiListSink.add(NetworkModel.completed(lokasiListResponse)); } catch (e) { @@ -42,7 +42,7 @@ class LokasiResponseBloc { fetchRecentSearch() async { recentSearchSink.add(NetworkModel.loading('Getting Recent Search')); try { - LokasiListResponse recentSearchData = await _lokasiRepository.fetchRecentSearch(); + final recentSearchData = await _lokasiRepository.fetchRecentSearch(); recentSearchSink.add(NetworkModel.completed(recentSearchData)); } catch (e) { recentSearchSink.add(NetworkModel.error(e.toString())); diff --git a/lib/bloc/SekolahBloc.dart b/lib/bloc/SekolahBloc.dart new file mode 100644 index 0000000000000000000000000000000000000000..423a78f4c44f92652ce7bee0d2e83012854bd2d1 --- /dev/null +++ b/lib/bloc/SekolahBloc.dart @@ -0,0 +1,83 @@ +import 'dart:async'; + +import 'package:ppl_disabilitas/model/sekolah.dart'; +import 'package:ppl_disabilitas/network/data/network_model.dart'; +import 'package:ppl_disabilitas/repository/SekolahRepository.dart'; + +class SekolahBloc { + SekolahRepository _sekolahRepository; + StreamController _sekolahListController; + List<SekolahModel> allSekolahFromApi; + + StreamSink<NetworkModel<SekolahList>> get sekolahListSink => + _sekolahListController.sink; + Stream<NetworkModel<SekolahList>> get sekolahListStream => + _sekolahListController.stream; + + SekolahBloc() { + _sekolahListController = StreamController<NetworkModel<SekolahList>>(); + _sekolahRepository = SekolahRepository(); + fetchSekolahList(); + } + + fetchSekolahList() async { + sekolahListSink.add(NetworkModel.loading('Getting Sekolah')); + try { + SekolahList sekolahListResponse = await _sekolahRepository.fetchSekolah(); + allSekolahFromApi = List.from(sekolahListResponse.allSekolah); + sekolahListSink.add(NetworkModel.completed(sekolahListResponse)); + } catch (e) { + sekolahListSink.add(NetworkModel.error(e.toString())); + print("$e"); + } + } + + filterbyKecamatan( + String kecamatan, bool value, List<SekolahModel> currentList) { + if (value) { + for (var sekolah in allSekolahFromApi) { + if (sekolah.alamat.toLowerCase().contains(kecamatan.toLowerCase())) { + currentList.add(sekolah); + } + } + } else { + currentList.removeWhere((sekolah) => + sekolah.alamat.toLowerCase().contains(kecamatan.toLowerCase())); + } + sekolahListSink.add(NetworkModel.completed(SekolahList(currentList))); + } + + filterbyKategoriSekolah( + String kategori, bool val, List<SekolahModel> currentList) { + if (val) { + for (var sekolah in allSekolahFromApi) { + if (sekolah.jenis_sekolah.contains(kategori)) { + currentList.add(sekolah); + } + } + } else { + currentList.removeWhere((sekolah) => + sekolah.jenis_sekolah.contains(kategori)); + } + sekolahListSink.add(NetworkModel.completed(SekolahList(currentList))); + } + + filterbyTingkatSekolah( + String tingkatSekolah, bool val, List<SekolahModel> currentList) { + if (val) { + for (var sekolah in allSekolahFromApi) { + if (sekolah.name.toLowerCase().startsWith(tingkatSekolah.toLowerCase())) { + currentList.add(sekolah); + } + } + } else { + currentList.removeWhere((sekolah) => + sekolah.name.toLowerCase().startsWith(tingkatSekolah.toLowerCase())); + } + sekolahListSink.add(NetworkModel.completed(SekolahList(currentList))); + } + + dispose() { + _sekolahListController?.close(); + } +} diff --git a/lib/component/ImageHolder.dart b/lib/component/ImageHolder.dart index 30f329d9a93541441498150b2622e4fb40b52743..ca0dbd0a813e3ed781ee5c1beb6fb5521e65e532 100644 --- a/lib/component/ImageHolder.dart +++ b/lib/component/ImageHolder.dart @@ -16,10 +16,7 @@ class ImageHolder extends StatelessWidget { placeholder: (context, _) => const Center(child: CircularProgressIndicator()), errorWidget: (context, url, error) => Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('assets/images/margocity.png'), - fit: BoxFit.scaleDown)), + child: Center(child: Text('Failed to load images'),), ), ); } diff --git a/lib/component/bisago_appbar.dart b/lib/component/bisago_appbar.dart index e32af12651aae7289ffd82946141b165098d1465..2ad2fcf7ee2cb75bd5f46a80b98a869c2977a00b 100644 --- a/lib/component/bisago_appbar.dart +++ b/lib/component/bisago_appbar.dart @@ -2,8 +2,10 @@ import 'package:flutter/material.dart'; import 'package:ppl_disabilitas/config/styles.dart'; class BisaGoAppBar extends StatelessWidget implements PreferredSizeWidget { + final String title; + BisaGoAppBar({this.title = 'bisaGo', Key key}) : super(key: key); @override - final Size preferredSize = Size.fromHeight(55); + final Size preferredSize = const Size.fromHeight(55); @override Widget build(BuildContext context) { return AppBar( @@ -14,15 +16,16 @@ class BisaGoAppBar extends StatelessWidget implements PreferredSizeWidget { mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: <Widget>[ - Padding(padding: EdgeInsets.all(doubleSpace), - child: Text( - "bisaGo", - style: TextStyle( - fontSize: 25, - fontFamily: 'Comfortaa', - fontWeight: FontWeight.w800), - ),) - + Padding( + padding: EdgeInsets.all(doubleSpace), + child: Text( + title, + style: TextStyle( + fontSize: 25, + fontFamily: 'Comfortaa', + fontWeight: FontWeight.w800), + ), + ) ], ), ); diff --git a/lib/component/bisago_drawer.dart b/lib/component/bisago_drawer.dart index ff510da5af717d496172b48488b38676caca3778..e46799e21515813befb9d1621e69fe7a78c855e8 100644 --- a/lib/component/bisago_drawer.dart +++ b/lib/component/bisago_drawer.dart @@ -1,21 +1,23 @@ import 'package:flutter/material.dart'; import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/page/login/login.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class BisaGoDrawer extends StatelessWidget { final List<Map<String, dynamic>> drawerList = [ {'title': 'Beranda', 'icon': Icons.home}, {'title': 'Riwayat Pencarian', 'icon': Icons.history}, {'title': 'Tentang Aplikasi', 'icon': Icons.info}, - {'title': 'Log out', 'icon': Icons.keyboard_backspace} + {'title': 'Login', 'icon': Icons.keyboard_backspace} ]; @override Widget build(BuildContext context) { - List<Widget> menus = drawerList.map((menu) { + final menus = drawerList.map((menu) { return _createListTile( context: context, icon: menu['icon'], title: menu['title']); }).toList(); - List<Widget> drawerItem = [ + final drawerItem = [ Container( height: 130, child: DrawerHeader( @@ -24,10 +26,14 @@ class BisaGoDrawer extends StatelessWidget { ), child: Row( children: <Widget>[ - FloatingActionButton( - backgroundColor: Colors.white, - elevation: 0, - onPressed: () => {}, + SizedBox( + width: 40, + child: FloatingActionButton( + heroTag: null, + backgroundColor: Colors.white, + elevation: 0, + onPressed: () => {}, + ), ), Padding( padding: EdgeInsets.all(doubleSpace), @@ -52,6 +58,7 @@ class BisaGoDrawer extends StatelessWidget { menus.forEach((menu) { drawerItem.add(menu); }); + return Theme( data: Theme.of(context).copyWith( canvasColor: greenPrimary, @@ -63,6 +70,43 @@ class BisaGoDrawer extends StatelessWidget { } Widget _createListTile({BuildContext context, IconData icon, String title}) { + if (title == 'Login') { + return Container( + child: FutureBuilder( + future: changeLoginDrawer(), + builder: (BuildContext context, AsyncSnapshot<String> snapshot) { + if (snapshot.hasData) { + return Container( + child: ListTile( + leading: Icon( + icon, + color: Colors.white, + size: 30, + ), + title: Text( + snapshot.data, + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontFamily: 'Muli', + ), + ), + onTap: () async { + await checkLoginStatus(context); + }, + ), + decoration: BoxDecoration( + color: greenPrimary, + border: Border( + bottom: BorderSide(color: Colors.white), + ), + ), + ); + } + return Container(); + }), + ); + } return Container( child: ListTile( leading: Icon( @@ -78,9 +122,7 @@ class BisaGoDrawer extends StatelessWidget { fontFamily: 'Muli', ), ), - onTap: () { - Navigator.pop(context); - }, + onTap: () {}, ), decoration: BoxDecoration( color: greenPrimary, @@ -90,4 +132,29 @@ class BisaGoDrawer extends StatelessWidget { ), ); } + + Future<String> changeLoginDrawer() async { + SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); + if (sharedPreferences.getString("token") == null) { + return 'Login'; + } else { + return 'Logout'; + } + } + + checkLoginStatus(BuildContext context) async { + SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); + if (sharedPreferences.getString("token") == null) { + _navigateToLoginPage(context); + } else { + print('okeee'); + await sharedPreferences.clear(); + await Navigator.pushNamed(context, '/'); + } + } + + void _navigateToLoginPage(BuildContext context) { + final route = MaterialPageRoute(builder: (_) => Login()); + Navigator.of(context).push(route); + } } diff --git a/lib/component/informasi_sekolah_appbar.dart b/lib/component/informasi_sekolah_appbar.dart new file mode 100644 index 0000000000000000000000000000000000000000..7d3208d8368da07e8bc378c9ff9205b1fa5057d5 --- /dev/null +++ b/lib/component/informasi_sekolah_appbar.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; + +class InformasiSekolahAppBar extends StatelessWidget implements PreferredSizeWidget { + @override + final Size preferredSize = Size.fromHeight(55); + @override + Widget build(BuildContext context) { + return AppBar( + elevation: 15, + centerTitle: true, + backgroundColor: greenPrimary, + leading: IconButton( + icon: Icon(Icons.arrow_back_ios, size: 20), + key: Key('Back Icon Key'), + onPressed: () => Navigator.pop(context, 'Take me back')), + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Padding(padding: EdgeInsets.all(doubleSpace), + child: Text( + "Informasi Sekolah", + style: TextStyle( + fontSize: 25, + fontFamily: 'Comfortaa', + fontWeight: FontWeight.w800), + ),) + + ], + ), + ); + } +} diff --git a/lib/config/custom_serializer.dart b/lib/config/custom_serializer.dart index 3c7dc1f59c5c53a3186f967ea52b376bed2b0f72..c26aa604613b0ccbaccbf416b6273e98bbe306b7 100644 --- a/lib/config/custom_serializer.dart +++ b/lib/config/custom_serializer.dart @@ -1,3 +1,5 @@ +import 'package:intl/intl.dart'; + class CustomSerializer { - static DateTime stringToDateTime(String date) => DateTime.parse(date); + static DateTime stringToDateTime(String date) => DateFormat("yyyy-MM-dd hh:mm:ss").parse(date); } diff --git a/lib/config/strings.dart b/lib/config/strings.dart index 0162847de9bfef0804b5b982a287419cc9838126..053d730b7b92f344c4a2cd4ac9da458bdd07a24f 100644 --- a/lib/config/strings.dart +++ b/lib/config/strings.dart @@ -1,8 +1,8 @@ // Frequently used strings are stored here // No hardcoding string view files. Store here. -final String devBaseURL = "poipole.herokuapp.com"; -final String baseURL = "poipole.herokuapp.com"; +const String devBaseURL = "poipole.herokuapp.com"; +const String baseURL = "poipole.herokuapp.com"; String key = ""; String csrf = ""; String sessionId = ""; @@ -13,4 +13,24 @@ setKey(String newKey) { setSessionId(String newSessionId) { sessionId = newSessionId; +} + +final tags = { + 'KR': 'kursiroda', + 'LF': 'liftdisabilitas', + 'TD': 'toiletdisabilitas', + 'MM': 'masjid', + 'GB': 'guidingblock', + 'BM': 'bidangmiring', + 'CP': 'temandisabilitas', + 'JI': 'jurubahasaisyarat', + 'TN': 'tongkatdisabilitasnetra', + 'KD': 'kursiumumdisabilitas', + 'PK': 'tempatparkirdisabilitas', + 'RT': 'runningtext', + 'TB': 'tempatparkirbiasa' +}; + +getTag(String tag) { + return tags[tag]; } \ No newline at end of file diff --git a/lib/config/styles.dart b/lib/config/styles.dart index aac8a3981d60533fabc4e7f790ab1510680049d9..4bcb0f0f244128a3a1c7066b249f756833c957ad 100644 --- a/lib/config/styles.dart +++ b/lib/config/styles.dart @@ -1,18 +1,20 @@ import 'package:flutter/material.dart'; -final Color greenPrimary = Color(0xff3A903A); -final Color greenPale = Color(0xff4FBA4F); -final Color redPrimary = Color(0xffC60000); +const Color white = Color(0xffFFFFFF); +const Color greenPrimary = Color(0xff3A903A); +const Color greenPale = Color(0xff4FBA4F); +const Color redPrimary = Color(0xffC60000); +const Color grayPrimary = Color(0xff645C5C); -final double superSmallSpace = 4.0; -final double smallSpace = 4.0; -final double regularSpace = 8.0; -final double regularBiggerSpace = 12.0; -final double doubleSpace = 16.0; -final double tripleSpace = 32.0; -final double spaceFourty = 45.0; -final double quartetSpace = 64.0; -final double spaceFourtyEight = 48.0; +const double superSmallSpace = 2.0; +const double smallSpace = 4.0; +const double regularSpace = 8.0; +const double regularBiggerSpace = 12.0; +const double doubleSpace = 16.0; +const double tripleSpace = 32.0; +const double spaceFourty = 45.0; +const double quartetSpace = 64.0; +const double spaceFourtyEight = 48.0; final List<BoxShadow> regularShadow = [ BoxShadow( diff --git a/lib/globalnetwork.dart b/lib/globalnetwork.dart new file mode 100644 index 0000000000000000000000000000000000000000..b2e731207dfa40fce69fb8130cd8cfd8ed9ac4f6 --- /dev/null +++ b/lib/globalnetwork.dart @@ -0,0 +1,40 @@ +import 'package:dio/dio.dart'; +import 'package:mockito/mockito.dart'; + +class MockHttpClient extends Mock implements Dio {} + +var dio; + +getDioInstance(String env) { + dio = env == 'build' ? Dio() : MockHttpClient(); +} + +mockLokasiDependencies() { + when(dio.get( + any, + )).thenAnswer((_) async { + final expected = Future<Response<List<Map<String, dynamic>>>>.value( + Response<List<Map<String, dynamic>>>(statusCode: 200, data: [ + { + "id": 1, + "name": "Soppeng", + "latitude": 100039203300.0, + "longitude": 100000000000.0, + "alamat": "Jalan Margonda Raya", + "no_telp": "081111111111", + "image": "test.jpg" + } + ])); + return expected; + }); +} + +mockFasilitasDependencies(Map<String, dynamic> mockFasilitas) { + when(dio.get( + any, + )).thenAnswer((_) async { + final expected = Future<Response<Map<String, dynamic>>>.value( + Response<Map<String, dynamic>>(statusCode: 200, data: mockFasilitas)); + return expected; + }); +} diff --git a/lib/main.dart b/lib/main.dart index aaab915666b9af6288858f0d23c2cfa1106286f8..f6d755441d0695331112d6686d35908d3615aa5c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:ppl_disabilitas/app.dart'; import 'flavor/flavor.dart'; +import 'globalnetwork.dart'; -void main() { +Future main() async { + await DotEnv().load('.env'); + getDioInstance('build'); + dio.options.receiveTimeout = 15000; ApiFlavor.flavor = BuildFlavor.production.toString(); runApp(BisaGo()); -} \ No newline at end of file +} diff --git a/lib/model/komentar.dart b/lib/model/komentar.dart index 7c37c099eead509b5db45fb96c56c4f0aee6a568..d9069765ad2604a6978534dba00f77ff7c18738c 100644 --- a/lib/model/komentar.dart +++ b/lib/model/komentar.dart @@ -1,4 +1,5 @@ import 'package:json_annotation/json_annotation.dart'; +//import 'package:ppl_disabilitas/config/custom_serializer.dart'; part 'komentar.g.dart'; @@ -10,13 +11,21 @@ class KomentarList { @JsonSerializable() class KomentarModel { - final String nama_orang; - final int suka; - final int tidak_suka; - final String foto; + final int id; + final String nama_lokasi; + final String deskripsi; + final String creator; + final DateTime date_time; + final int like; + final int dislike; + final int rating; + final List<String> tag; + final String image; + final bool is_verified; KomentarModel( - {this.nama_orang, this.suka, this.tidak_suka, this.foto}); + {this.id, this.nama_lokasi, this.deskripsi, this.creator, this.date_time, + this.like, this.dislike, this.rating, this.tag, this.image, this.is_verified}); factory KomentarModel.fromJson(Map<String, dynamic> json) => _$KomentarModelFromJson(json); diff --git a/lib/model/komentar.g.dart b/lib/model/komentar.g.dart index 14d38aac572c9f1c5ab7fa8d26ae282e37fa59f2..0554c631ecf45172f8c4e1bb39a15c7bb65946ec 100644 --- a/lib/model/komentar.g.dart +++ b/lib/model/komentar.g.dart @@ -23,17 +23,31 @@ Map<String, dynamic> _$KomentarListToJson(KomentarList instance) => KomentarModel _$KomentarModelFromJson(Map<String, dynamic> json) { return KomentarModel( - nama_orang: json['nama_orang'] as String, - suka: json['suka'] as int, - tidak_suka: json['tidak_suka'] as int, - foto: json['foto'] as String, + nama_lokasi: json['nama_lokasi'] as String, + deskripsi: json['deskripsi'] as String, + creator: json['creator'] as String, + date_time: json['date_time'] == null + ? null + : DateTime.parse(json['date_time'] as String), + like: json['like'] as int, + dislike: json['dislike'] as int, + rating: json['rating'] as int, + tag: (json['tag'] as List)?.map((e) => e as String)?.toList(), + image: json['image'] as String, + is_verified: json['is_verified'] as bool, ); } Map<String, dynamic> _$KomentarModelToJson(KomentarModel instance) => <String, dynamic>{ - 'nama_orang': instance.nama_orang, - 'suka': instance.suka, - 'tidak_suka': instance.tidak_suka, - 'foto': instance.foto, + 'nama_lokasi': instance.nama_lokasi, + 'deskripsi': instance.deskripsi, + 'creator': instance.creator, + 'date_time': instance.date_time?.toIso8601String(), + 'like': instance.like, + 'dislike': instance.dislike, + 'rating': instance.rating, + 'tag': instance.tag, + 'image': instance.image, + 'is_verified': instance.is_verified, }; diff --git a/lib/model/lokasi.dart b/lib/model/lokasi.dart index 90aea3a69a0c3f7d4358f670cee510ebf8803697..020fe369a004f00903d228bff13b8a0bce7560f0 100644 --- a/lib/model/lokasi.dart +++ b/lib/model/lokasi.dart @@ -9,12 +9,13 @@ class LokasiListResponse { @JsonSerializable(nullable: true) class Lokasi { - String nama; + int id; + String name; double latitude; double longitude; String alamat; - String foto; - String telepon; + String image; + String no_telp; Lokasi(); diff --git a/lib/model/lokasi.g.dart b/lib/model/lokasi.g.dart index f1909a9f4abf0925d5b814d4bc6292899aff3c4a..68a5ac9d568bec015b93239456f17ef90b8e9700 100644 --- a/lib/model/lokasi.g.dart +++ b/lib/model/lokasi.g.dart @@ -22,19 +22,21 @@ Map<String, dynamic> _$LokasiListResponseToJson(LokasiListResponse instance) => Lokasi _$LokasiFromJson(Map<String, dynamic> json) { return Lokasi() - ..nama = json['name'] as String + ..id = json['id'] as int + ..name = json['name'] as String ..latitude = (json['latitude'] as num)?.toDouble() ..longitude = (json['longitude'] as num)?.toDouble() ..alamat = json['alamat'] as String - ..foto = json['image'] as String - ..telepon = json['no_telp'] as String; + ..image = json['image'] as String + ..no_telp = json['no_telp'] as String; } Map<String, dynamic> _$LokasiToJson(Lokasi instance) => <String, dynamic>{ - 'nama': instance.nama, + 'id': instance.id, + 'name': instance.name, 'latitude': instance.latitude, 'longitude': instance.longitude, 'alamat': instance.alamat, - 'foto': instance.foto, - 'telepon': instance.telepon, + 'image': instance.image, + 'no_telp': instance.no_telp, }; diff --git a/lib/model/sekolah.dart b/lib/model/sekolah.dart new file mode 100644 index 0000000000000000000000000000000000000000..f5aa5f8d6140b210600ad356f11cdef08be2d812 --- /dev/null +++ b/lib/model/sekolah.dart @@ -0,0 +1,26 @@ +import 'package:json_annotation/json_annotation.dart'; +part 'sekolah.g.dart'; +@JsonSerializable() +class SekolahList { + List<SekolahModel> allSekolah; + + SekolahList(this.allSekolah); +} + +@JsonSerializable() +class SekolahModel { + int id; + String name; + String alamat; + String no_telp; + String website; + int jumlah_siswa; + String status; + String jenis_sekolah; + String akreditasi; + + SekolahModel(); + + factory SekolahModel.fromJson(Map<String, dynamic> json) => _$SekolahModelFromJson(json); + Map<String, dynamic> toJson() => _$SekolahModelToJson(this); +} \ No newline at end of file diff --git a/lib/model/sekolah.g.dart b/lib/model/sekolah.g.dart new file mode 100644 index 0000000000000000000000000000000000000000..2baf76f8ac40b4b2e6c47b9ef0e8f02ba8b83f30 --- /dev/null +++ b/lib/model/sekolah.g.dart @@ -0,0 +1,47 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sekolah.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SekolahList _$SekolahListFromJson(Map<String, dynamic> json) { + return SekolahList( + (json['allSekolah'] as List) + ?.map((e) => + e == null ? null : SekolahModel.fromJson(e as Map<String, dynamic>)) + ?.toList(), + ); +} + +Map<String, dynamic> _$SekolahListToJson(SekolahList instance) => + <String, dynamic>{ + 'allSekolah': instance.allSekolah, + }; + +SekolahModel _$SekolahModelFromJson(Map<String, dynamic> json) { + return SekolahModel() + ..id = json['id'] as int + ..name = json['name'] as String + ..alamat = json['alamat'] as String + ..no_telp = json['no_telp'] as String + ..website = json['website'] as String + ..jumlah_siswa = json['jumlah_siswa'] as int + ..status = json['status'] as String + ..jenis_sekolah = json['jenis_sekolah'] as String + ..akreditasi = json['akreditasi'] as String; +} + +Map<String, dynamic> _$SekolahModelToJson(SekolahModel instance) => + <String, dynamic>{ + 'id': instance.id, + 'name': instance.name, + 'alamat': instance.alamat, + 'no_telp': instance.no_telp, + 'website': instance.website, + 'jumlah_siswa': instance.jumlah_siswa, + 'status': instance.status, + 'jenis_sekolah': instance.jenis_sekolah, + 'akreditasi': instance.akreditasi, + }; diff --git a/lib/model/user.dart b/lib/model/user.dart new file mode 100644 index 0000000000000000000000000000000000000000..0fabc0d866e1753f03375e384925329dbbc6e5d9 --- /dev/null +++ b/lib/model/user.dart @@ -0,0 +1,40 @@ +import 'dart:convert'; + +class User { + bool is_login; + String username; + String name; + String email; + String phone_number; + String token; + + User({this.is_login, this.username, this.name, this.email, this.phone_number, this.token}); + + factory User.fromJson(Map<String, dynamic> map) { + return User( + username: map["username"], + name: map["name"], + email: map["email"], + phone_number: map["phone_number"],); + } + + Map<String, dynamic> toJson() { + return {"username": username, "name": name, "email": email, "phone_number": phone_number}; + } + + @override + String toString() { + return 'User{"username": $username, "name": $name, "email": $email, "phone_number": $phone_number}'; + } + +} + +List<User> userFromJson(String jsonData) { + final data = json.decode(jsonData); + return List<User>.from(data.map((item) => User.fromJson(item))); +} + +String userToJson(User data) { + final jsonData = data.toJson(); + return json.encode(jsonData); +} \ No newline at end of file diff --git a/lib/network/cookies_interface.dart b/lib/network/cookies_interface.dart index 52ac47bcd60e780aba333c2d13cc6326ff4572cf..4bb6c1f6d030cf38bdee87ab503ed021f7ba747c 100644 --- a/lib/network/cookies_interface.dart +++ b/lib/network/cookies_interface.dart @@ -10,14 +10,14 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File cookieFile = File("${dir.path}/$fileName.json"); - bool cookiesExist = cookieFile.existsSync(); + final cookieFile = File("${dir.path}/$fileName.json"); + final cookiesExist = cookieFile.existsSync(); return cookiesExist; } - Future<File> createSignInCookie({ - Map<String, dynamic> responseHeaders}) async { + Future<File> createSignInCookie( + {Map<String, dynamic> responseHeaders}) async { try { String setCookie; String csrfToken; @@ -29,7 +29,7 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File cookieFile = File("${dir.path}/usercookies.json"); + final cookieFile = File("${dir.path}/usercookies.json"); cookieFile.createSync(); setCookie = responseHeaders["set-cookie"]; @@ -51,8 +51,8 @@ class CookiesInterface { } } - Future<File> createSearchHistoryCookie({ - Map<String, dynamic> recentSearch}) async { + Future<File> createSearchHistoryCookie( + {Map<String, dynamic> recentSearch}) async { print("recent searrch $recentSearch"); Directory dir; List currentSearchHistory; @@ -60,9 +60,10 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File cookieFile = File('${dir.path}/searchhistory.json'); + final cookieFile = File('${dir.path}/searchhistory.json'); cookieFile.createSync(); - await checkCookieFileAvailability(fileName: "searchhistory").then((available) async { + await checkCookieFileAvailability(fileName: "searchhistory") + .then((available) async { if (available) { await getCookieFile(fileName: "searchhistory").then((cookie) { if (cookie == null) { @@ -70,7 +71,9 @@ class CookiesInterface { } else { currentSearchHistory = cookie == "" ? [] : json.decode(cookie); } - currentSearchHistory.insert(0, recentSearch); + if (!currentSearchHistory.contains(recentSearch)) { + currentSearchHistory.insert(0, recentSearch); + } }); } else { currentSearchHistory = []; @@ -89,7 +92,7 @@ class CookiesInterface { await getApplicationDocumentsDirectory().then((Directory directory) { dir = directory; }); - File file = File("${dir.path}/$fileName.json"); + final file = File("${dir.path}/$fileName.json"); dynamic res; try { res = file.readAsStringSync(); diff --git a/lib/network/network_interface.dart b/lib/network/network_interface.dart index a451cf3934eafb869984372427c71a5aad9b6e95..76f97f6db05ae53204dbd9880b6b8535caaca029 100644 --- a/lib/network/network_interface.dart +++ b/lib/network/network_interface.dart @@ -1,29 +1,36 @@ import 'dart:convert'; +import 'package:dio/dio.dart'; +import 'package:ppl_disabilitas/globalnetwork.dart'; import 'package:ppl_disabilitas/network/CustomException.dart'; -import 'package:http/http.dart' as http; import 'dart:io'; -class NetworkInterface { - //String key = KEY; +import 'package:shared_preferences/shared_preferences.dart'; - // POST request +class NetworkInterface { Future<dynamic> post({ - String url, //url nya apa - dynamic bodyParams, //data apa yang mau dikasih - bool isLogin, //dia login apa ngga + String url, + Map<String, dynamic> bodyParams, + bool isLogin, + bool formData = true, }) async { var responseJson; - Map<String, String> headersJson = - await _buildRequestHeader(isLogin); //butuh header apa ngga try { - final response = await http.post( + SharedPreferences sharedPreferences = + await SharedPreferences.getInstance(); + print('Token ${sharedPreferences.getString('token')}'); + dio.options.headers['Authorization'] = + 'Token ${sharedPreferences.getString('token')}'; + dio.options.headers['content-type'] = 'application/json'; + + final response = await dio.post( "$url", - body: json.encode(bodyParams), - headers: headersJson, + data: formData ? FormData.fromMap(bodyParams) : json.encode(bodyParams), ); responseJson = _response(response); } on SocketException { throw FetchDataException("No Internet Connection"); + } catch (e) { + print(e.toString()); } return responseJson; } @@ -34,57 +41,55 @@ class NetworkInterface { bool isLogin, }) async { var responseJson; - Map<String, dynamic> headersJson = await _buildRequestHeader(isLogin); try { - final response = await http.get( + final response = await dio.get( "$url", - headers: headersJson, ); responseJson = _response(response); } on SocketException { throw FetchDataException("No Internet Connection"); + } catch (e) { + print(e.toString()); } return responseJson; } - // buildRequestHeader: untuk nentuin pake header apa aja berdasarkan login apa ngga - Future<Map<String, dynamic>> _buildRequestHeader(bool isLogin) async { - Map<String, String> headers = Map<String, String>(); - headers.putIfAbsent("Content-Type", () => "application/json"); - //if (isLogin) { - //List<dynamic> cookieFile = await CookiesInterface().getCookieFile( - // fileName: - // "userCookies"); //ngambil data dari yg udh disimpen di cookie - //print("cookieFile list --> ${cookieFile.toString()}"); - //print("check key here >>> $key"); - //setKey(cookieFile[2]); - //key = cookieFile[2]; - //headers.putIfAbsent( - // "Authorization", - // () => - // 'Token $key'); //ini kalau authorization nya ngga ada baru taro token nya - //headers.putIfAbsent("X-CSRFToken", () => cookieFile[0]); //csrf token - //headers.putIfAbsent( - // "Cookie", - // () => - // "csrftoken=${cookieFile[0]};sessionid=${cookieFile[1]}"); //cookie file - //print("headers --> ${headers}"); - //} - return headers; + Future<dynamic> put({String url}) async { + var responseJson; + try { + SharedPreferences sharedPreferences = + await SharedPreferences.getInstance(); + dio.options.headers['Authorization'] = + 'Token ${sharedPreferences.getString('token')}'; + print(dio.options.headers); + final response = await dio.put( + url, + ); + responseJson = response.data; + } on SocketException { + throw FetchDataException("No Internet Connection"); + } on DioError catch (e){ + if (e.response.statusCode == 406) { + return e.response.data; + } + } + return responseJson; } - dynamic _response(http.Response response) { + dynamic _response(Response response) { switch (response.statusCode) { case 200: - var responseJson = json.decode(response.body.toString()); - return responseJson; + return response.data; + case 201: + return response.data; case 400: - throw BadRequestException(response.body.toString()); + throw BadRequestException(response.data.toString()); case 401: case 403: - throw UnauthorisedException(response.body.toString()); - case 500: + throw UnauthorisedException(response.data.toString()); + case 406: + return response.data; default: throw FetchDataException( diff --git a/lib/page/addInformasi/addInfromasi.dart b/lib/page/addInformasi/addInfromasi.dart new file mode 100644 index 0000000000000000000000000000000000000000..ceabf6adef42d42e45471a4f1a4d1481b35b7068 --- /dev/null +++ b/lib/page/addInformasi/addInfromasi.dart @@ -0,0 +1,306 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:http/http.dart' as http; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/utils/customDeskripsiField.dart'; +import 'package:ppl_disabilitas/utils/customButton.dart'; +import 'package:ppl_disabilitas/utils/validator.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:smooth_star_rating/smooth_star_rating.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + + +class AddInformasi extends StatefulWidget{ + final String nama; + AddInformasiState createState() => AddInformasiState(); + + AddInformasi({this.nama}); +} + +class AddInformasiState extends State<AddInformasi> { + File _image; + TextEditingController deskripsiController = TextEditingController(); + var rating = 0.0; + var tag = ''; + final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); + Map<String, bool> fasilitas = { + 'Kursi Roda': false, + 'Lift Disabilitas': false, + 'Toilet Disabilitas': false, + 'Masjid/Mushola': false, + 'Guiding Block': false, + 'Bidang Miring': false, + 'Teman Disabilitas': false, + 'Juru Bahasa Isyarat': false, + 'Tongkat Disabilitas Netra':false, + 'Kursi Umum Disabilitas': false, + 'Tempat Parkir Disabilitas': false, + 'Running Text': false, + 'Tempat Parkir Biasa' : false, + }; + + Map<String, String> tags = { + 'Kursi Roda': 'KD', + 'Lift Disabilitas': 'LF', + 'Toilet Disabilitas': 'TD', + 'Masjid/Mushola': 'MM', + 'Guiding Block': 'GB', + 'Bidang Miring': 'BM', + 'Teman Disabilitas': 'CP', + 'Juru Bahasa Isyarat': 'JI', + 'Tongkat Disabilitas Netra':'TN', + 'Kursi Umum Disabilitas': 'KD', + 'Tempat Parkir Disabilitas': 'PK', + 'Running Text': 'RT', + 'Tempat Parkir Biasa' : 'TB', + }; + + Future _getImage() async { + var image = await ImagePicker.pickImage(source: ImageSource.gallery); + + setState(() { + _image = image; + print('_image : $_image'); + }); + } + Future _clearImage() async { + + setState(() { + _image = null; + print('_image : $_image'); + }); + } + + Future _clearCheckBox() async{ + fasilitas.forEach((k, v) { + var key = k; + fasilitas[key]=false; + }); + } + + + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Tambah Informasi'), + + centerTitle: true, + backgroundColor: Color(0xff3A903A), + ), + body: SingleChildScrollView( + child: Form( + key: _formKey, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + SizedBox(height: 20), + Text("Foto Fasilitas",style: TextStyle(fontSize: 18),textAlign: TextAlign.left,), + GridView.count( + key: Key('Input Gambar'), + shrinkWrap: true, + primary: false, + padding: const EdgeInsets.all(10), + crossAxisSpacing: 10, + crossAxisCount: 2, + children: <Widget>[ + GestureDetector( + onTap: _getImage, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 2.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20.0), + topRight: Radius.circular(20.0), + bottomLeft: Radius.circular(20.0), + bottomRight: Radius.circular(20.0), + ), + color: Colors.black12, + ), + child: _image == null ? Icon(FontAwesomeIcons.plus) : Image.file(_image), + ), + ) + ], + ), + CustomDeskripsiField( + title: 'Informasi Fasilitas', + key: Key('Text Field Informasi'), + onSaved: (input) { + }, + validator: FieldValidator.validateInfo, + controller: deskripsiController, + ), + SizedBox(height: 20), + Text("Tag Pencarian",style: TextStyle(fontSize: 18),textAlign: TextAlign.left,), + ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + key: Key('Checkbox Fasilitas'), + children: fasilitas.keys.map((String key) { + return CheckboxListTile( + title: Text(key), + value: fasilitas[key], + onChanged: (bool value) { + setState(() { + fasilitas[key] = value; + }); + }, + ); + }).toList(), + ), + SizedBox(height: 20), + Container( + alignment: Alignment.center, + key: Key('Star Rating'), + child: SmoothStarRating( + allowHalfRating: false, + onRatingChanged: (v) { + rating = v; + setState(() {}); + }, + starCount: 5, + rating: rating, + size: 40.0, + filledIconData: Icons.star, + halfFilledIconData: Icons.star_half, + color: Colors.green, + borderColor: Colors.green, + spacing:0.0, + ), + ), + Container( + margin: EdgeInsets.fromLTRB(0, 30, 0, 10), + alignment: Alignment.center, + child: Row( + children: <Widget>[ + Expanded( + child: ButtonTheme( + key: Key("Batal Button"), + minWidth: double.infinity, + height: 40, + child: RaisedButton( + padding: EdgeInsets.symmetric(vertical: 15), + highlightElevation: 0.0, + splashColor: Color(0xff3A903A), + highlightColor: Color(0xff3A903A), + elevation: 0.0, + color: Colors.white70, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + side: BorderSide(color: Color(0xff3A903A)) + ), + + child: Text( + 'Batal', + style: TextStyle(fontSize: 20, color: Colors.black, fontWeight: FontWeight.bold), + ), + onPressed: (){ + _resetInput(); + } + + ), + + ), + ), + + SizedBox(width: 5,), + Expanded( + child : ButtonTheme( + key: Key("Simpan Button"), + minWidth: double.infinity, + height: 40, + child: submitButton( + 'Simpan', Color(0xff3A903A), Colors.white, + Color(0xff3A903A), Colors.white, _validateInformationInput), + ), + + ), + + ], + ), + ), + + ], + ), + ), + + ) + + ) + + + ); + + } + + addInfo(String tag, String deskripsi, String rating) async { + for(MapEntry<String, bool> me in fasilitas.entries) { + if(me.value == true) tag = tag + tags[me.key] + ' '; + } + Map data = { + 'tag': tag, + 'deskripsi': deskripsi, + 'rating' : rating, + }; + + SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); + String namaTempat = widget.nama; + var response = await http.post( + 'http://poipole-staging.herokuapp.com/informasi-fasilitas/lokasi/add-fasilitas/$namaTempat/', + headers: {"Authorization" : "token " + sharedPreferences.getString("token")}, + body: data); + Map<String, dynamic> test = jsonDecode(response.body); + String testing = test['response']; +// var response = await http.get('http://poipole-staging.herokuapp.com/informasi-fasilitas/lokasi/list-fasilitas/$namaTempat/'); + if (response.statusCode == 201) { + print(response.body); + inputData(context); + } + else { + print(sharedPreferences.getString("token")); + print(namaTempat); + print(response.statusCode); + print(data); + print(testing); + inputData(context); + } + } + + void inputData(BuildContext context){ + var alertDialog = AlertDialog( + title: Text('Tambah Informasi berhasil'), + content: Icon(FontAwesomeIcons.checkCircle), + ); + showDialog( + context: context, + builder: (BuildContext context){ + return alertDialog; + } + ); + } + + void _validateInformationInput() async { + final FormState form = _formKey.currentState; + if(_formKey.currentState.validate()) { + form.save(); + int ratingInt = rating.toInt(); + await addInfo(tag, deskripsiController.text.toString(), ratingInt.toString()); + } + } + + void _resetInput() async{ + deskripsiController.clear(); + rating = 0.0; + await _clearImage(); + await _clearCheckBox(); + + + } + + + +} \ No newline at end of file diff --git a/lib/page/addLokasi/addLokasi.dart b/lib/page/addLokasi/addLokasi.dart new file mode 100644 index 0000000000000000000000000000000000000000..93f545d5aa901294e44aeb1b37902ea3d837a746 --- /dev/null +++ b/lib/page/addLokasi/addLokasi.dart @@ -0,0 +1,395 @@ +import 'dart:io'; + +import 'package:dio/dio.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:flutter_google_places/flutter_google_places.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:google_maps_webservice/places.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:ppl_disabilitas/component/bisago_appbar.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/network/network_interface.dart'; + +class AddLokasi extends StatefulWidget { + @override + _AddLokasiState createState() => _AddLokasiState(); +} + +class _AddLokasiState extends State<AddLokasi> { + Map<String, dynamic> data = { + 'name': '', + 'altitude': 0, + 'longitude': 0, + 'alamat': '', + 'no_telp': '', + }; + File _image; + GoogleMapController mapController; + LatLng currentLatLng; + Set<Marker> _markers = {}; + + TextEditingController namaLokasitController = TextEditingController(); + TextEditingController alamatController = TextEditingController(); + TextEditingController phoneNumbController = TextEditingController(); + TextEditingController latitudeController = TextEditingController(); + TextEditingController langitudeController = TextEditingController(); + Future<File> _getImage() async { + File image = await ImagePicker.pickImage(source: ImageSource.gallery); + return image; + } + + @override + void initState() { + super.initState(); + getInitalUserLocation(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: BisaGoAppBar( + title: 'Tambah Lokasi', + ), + body: Stack( + children: <Widget>[ + checkAvailabilityofUserLocation(), + InkWell( + onTap: () async { + resetData(); + Prediction locationPrediction = await PlacesAutocomplete.show( + context: context, + apiKey: DotEnv().env['API_KEY'], + mode: Mode.overlay); + if (locationPrediction != null) { + List<Placemark> placemark = await Geolocator() + .placemarkFromAddress(locationPrediction.description); + double latitude = placemark[0].position.latitude; + double longitude = placemark[0].position.longitude; + LatLng position = LatLng(latitude, longitude); + setState(() { + data['altitude'] = latitude; + data['longitude'] = longitude; + alamatController.text = locationPrediction.description; + namaLokasitController.text = placemark[0].name; + _markers.add(Marker( + markerId: MarkerId('Selected Location'), + position: position)); + }); + await mapController.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition(target: position, zoom: 15), + ), + ); + await Future.delayed(Duration(seconds: 1)); + await showModalBottomSheet( + context: context, + builder: (context) => addLokasiModal(), + backgroundColor: Colors.transparent, + isScrollControlled: true); + } + }, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: regularBorderRadius, + boxShadow: regularShadow), + padding: EdgeInsets.all(doubleSpace), + margin: EdgeInsets.only( + top: doubleSpace, left: doubleSpace, right: doubleSpace), + child: Text( + 'Cari lokasi yang anda inginkan', + style: TextStyle(color: Colors.grey), + ), + ), + ) + ], + ), + ); + } + + void onCreated(GoogleMapController controller) { + setState(() { + mapController = controller; + }); + } + + void _onCameraMove(CameraPosition position) { + setState(() { + currentLatLng = position.target; + }); + } + + void inputData(BuildContext context) { + var alertDialog = AlertDialog( + backgroundColor: greenPrimary, + title: Text( + 'Tambah lokasi berhasil', + style: TextStyle( + color: Colors.white, + fontFamily: 'Muli', + fontWeight: FontWeight.w600, + ), + ), + content: Icon(FontAwesomeIcons.checkCircle), + ); + showDialog( + context: context, + builder: (BuildContext context) { + return alertDialog; + }); + } + + void inputDataFail(BuildContext context) { + var alertDialog = AlertDialog( + backgroundColor: redPrimary, + title: Text( + 'Tambah lokasi tidak berhasil, coba lagi', + style: TextStyle( + color: Colors.white, + fontFamily: 'Muli', + fontWeight: FontWeight.w600, + ), + ), + content: Icon(Icons.close), + ); + showDialog( + context: context, + builder: (BuildContext context) { + return alertDialog; + }); + } + + void getInitalUserLocation() async { + Position position = await Geolocator() + .getCurrentPosition(desiredAccuracy: LocationAccuracy.high); + + setState(() { + currentLatLng = LatLng(position.latitude, position.longitude); + _markers.add(Marker(markerId: MarkerId('Current Location'))); + }); + } + + checkAvailabilityofUserLocation() { + if (currentLatLng == null) { + return Container( + child: Center( + child: CircularProgressIndicator(), + ), + ); + } else { + return GoogleMap( + mapType: MapType.normal, + initialCameraPosition: CameraPosition(target: currentLatLng, zoom: 15), + onMapCreated: onCreated, + myLocationEnabled: true, + compassEnabled: true, + markers: _markers, + onCameraMove: _onCameraMove, + ); + } + } + + Widget addLokasiModal() { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setStateModal) { + return Container( + height: MediaQuery.of(context).size.height / 2, + padding: EdgeInsets.all(regularSpace), + decoration: BoxDecoration( + boxShadow: regularShadow, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10)), + color: Colors.white, + ), + child: Column( + children: <Widget>[ + Container( + decoration: BoxDecoration( + color: Colors.grey[100], borderRadius: regularBorderRadius), + padding: EdgeInsets.all(smallSpace), + child: TextField( + decoration: InputDecoration( + border: InputBorder.none, + focusColor: grayPrimary, + hintText: 'Nama Lokasi'), + controller: namaLokasitController, + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w800), + ), + ), + Container( + decoration: BoxDecoration( + color: Colors.grey[100], borderRadius: regularBorderRadius), + padding: EdgeInsets.all(2), + margin: EdgeInsets.only(top: regularSpace), + child: TextField( + decoration: InputDecoration( + contentPadding: EdgeInsets.all(0), + border: InputBorder.none, + focusColor: grayPrimary, + hintText: 'Alamat Lokasi'), + controller: alamatController, + style: TextStyle(fontSize: 15), + ), + ), + Container( + decoration: BoxDecoration( + color: Colors.grey[100], borderRadius: regularBorderRadius), + padding: EdgeInsets.all(smallSpace), + margin: EdgeInsets.only(top: regularSpace), + child: TextField( + decoration: InputDecoration( + border: InputBorder.none, + focusColor: grayPrimary, + prefixIcon: Icon(Icons.phone), + hintText: 'Telepon Lokasi'), + controller: phoneNumbController, + keyboardType: TextInputType.phone, + style: TextStyle(fontSize: 15), + ), + ), + Expanded( + flex: 4, + child: _image == null + ? InkWell( + onTap: () async { + var imageSelected = await _getImage(); + print(imageSelected); + setStateModal(() { + _image = imageSelected; + }); + setState(() { + _image = imageSelected; + }); + }, + child: Container( + margin: + EdgeInsets.symmetric(vertical: regularSpace), + decoration: + BoxDecoration(color: Colors.grey[100]), + child: Center(child: Text('Put Image'))), + ) + : Container( + width: double.infinity, + margin: EdgeInsets.symmetric(vertical: regularSpace), + decoration: BoxDecoration(color: Colors.grey[100]), + child: Center( + child: Stack( + children: <Widget>[ + FittedBox( + fit: BoxFit.contain, + child: Image.file(_image), + ), + InkWell( + onTap: () { + setStateModal(() { + _image = null; + }); + setState(() { + _image = null; + }); + }, + child: Icon( + Icons.close, + color: Colors.white, + ), + ) + ], + ), + ), + )), + Expanded( + child: FlatButton( + color: greenPrimary, + onPressed: () { + addLocationToApi(); + }, + child: Text( + 'Daftarkan Lokasi', + style: TextStyle(color: Colors.white), + ), + ), + ) + ], + ), + ); + }, + ); + } + + void resetData() { + _image = null; + data['altitude'] = 0; + data['longitude'] = 0; + alamatController.text = ''; + namaLokasitController.text = ''; + _markers.removeWhere( + (marker) => marker.markerId == MarkerId('Selected Location')); + } + + Future<void> addLocationToApi() async { + data['name'] = namaLokasitController.text; + data['alamat'] = alamatController.text; + data['no_telp'] = phoneNumbController.text; + String fileName = _image.path.split('/').last; + data['image'] = await MultipartFile.fromFile( + _image.path, + filename: fileName, + ); + print('data $data'); + final post = await NetworkInterface().post( + url: + 'https://poipole-staging.herokuapp.com/informasi-fasilitas/lokasi/add/', + formData: true, + bodyParams: data, + ); + } +} + +class FieldValidator { + static String validateNamaLokasi(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } + + static String validateAlamat(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } + + static String validatePhoneNumb(String value) { + //String pattern = r'(^(?:[+0]9)?[0-9]{11,12}$)'; + //RegExp regExp = RegExp(pattern); + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } + + static String validateLatitude(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } + + static String validateLangitude(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } +} diff --git a/lib/page/dashboard/dashboard.dart b/lib/page/dashboard/dashboard.dart index a8c24ec04d86ccf7a26ad49651e23816c808e6e3..01d9c29604901af18a2b5346576220d734a68645 100644 --- a/lib/page/dashboard/dashboard.dart +++ b/lib/page/dashboard/dashboard.dart @@ -1,10 +1,12 @@ import 'dart:async'; -import 'package:location/location.dart'; + import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:location/location.dart'; import 'package:ppl_disabilitas/component/bisago_appbar.dart'; import 'package:ppl_disabilitas/component/bisago_drawer.dart'; import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/page/informasi/layananDisabilitas.dart'; import 'package:ppl_disabilitas/page/pencarian/pencarian.dart'; class Dashboard extends StatefulWidget { @@ -13,8 +15,8 @@ class Dashboard extends StatefulWidget { class DashboardState extends State<Dashboard> { final Completer<GoogleMapController> _controller = Completer(); - final double cameraZoom = 16; - final LatLng defaultLocation = LatLng(-6.1753924, 106.8249641); + final double cameraZoom = 40; + final LatLng defaultLocation = const LatLng(-6.1753924, 106.8249641); final String currentLocationIconAsset = "assets/icon/current_loc.png"; Location location; Set<Marker> _markers = Set<Marker>(); @@ -25,7 +27,7 @@ class DashboardState extends State<Dashboard> { Marker contohMarker = Marker( markerId: MarkerId("contoh1"), position: LatLng(-6.365474, 106.828157), - infoWindow: InfoWindow(title: "Fasilkom"), + infoWindow: const InfoWindow(title: "Fasilkom"), icon: BitmapDescriptor.defaultMarkerWithHue( BitmapDescriptor.hueViolet, ), @@ -45,7 +47,7 @@ class DashboardState extends State<Dashboard> { _markers.add(contohMarker); } - void enableLocationService() async { + enableLocationService() async { await location.changeSettings(accuracy: LocationAccuracy.HIGH); _serviceEnabled = await location.serviceEnabled(); if (!_serviceEnabled) { @@ -63,23 +65,28 @@ class DashboardState extends State<Dashboard> { } } - void _navigateToPencarianPage(BuildContext context) { + void _navigateToPencarianPage(BuildContext context) { final route = MaterialPageRoute(builder: (_) => Pencarian()); Navigator.of(context).push(route); } + void _navigateToInformasiLayananDisabilitasPage(BuildContext context) { + final route = MaterialPageRoute(builder: (_) => LayananDisabilitas()); + Navigator.of(context).push(route); + } + static const textFieldKey = Key('Text Field Mau Kemana'); @override Widget build(BuildContext context) { return Scaffold( drawer: BisaGoDrawer(), - body: Stack(key: Key("Stack"),children: <Widget>[ + body: Stack(key: const Key("Stack"), children: <Widget>[ _buildGoogleMap(context), InkWell( - key: Key("Navigate to Pencarian"), + key: const Key("Navigate to Pencarian"), onTap: () => _navigateToPencarianPage(context), child: Container( - key: Key("Container Text Field"), + key: const Key("Container Text Field"), margin: EdgeInsets.only( left: doubleSpace, right: doubleSpace, top: doubleSpace), decoration: BoxDecoration( @@ -88,7 +95,7 @@ class DashboardState extends State<Dashboard> { boxShadow: regularShadow), child: TextFormField( enabled: false, - key: Key("Text Field Mau Kemana"), + key: const Key("Text Field Mau Kemana"), decoration: InputDecoration( prefixIcon: Icon( Icons.search, @@ -104,7 +111,7 @@ class DashboardState extends State<Dashboard> { fontFamily: 'Muli', fontWeight: FontWeight.w700), suffixIcon: IconButton( - key: Key("IconButton Text Field"), + key: const Key("IconButton Text Field"), icon: Icon( Icons.mic, color: greenPrimary, @@ -116,10 +123,20 @@ class DashboardState extends State<Dashboard> { ), ), ]), + floatingActionButton: FloatingActionButton.extended( + key: const Key("FloatingActionButton"), + onPressed: () { + _navigateToInformasiLayananDisabilitasPage(context); + }, + label: Text('Informasi Layanan Disabilitas'), + icon: Icon(Icons.search), + backgroundColor: greenPrimary, + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, appBar: PreferredSize( - preferredSize: Size.fromHeight(55), + preferredSize: const Size.fromHeight(55), child: BisaGoAppBar(), - key: Key("Scaffold Text Field"), + key: const Key("Scaffold Text Field"), ), ); } @@ -136,11 +153,11 @@ class DashboardState extends State<Dashboard> { ); } return Container( - key: Key("Container GoogleMap"), + key: const Key("Container GoogleMap"), height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, child: GoogleMap( - key: Key("Google Map"), + key: const Key("Google Map"), markers: _markers, mapType: MapType.normal, initialCameraPosition: initialCameraPosition, @@ -151,12 +168,12 @@ class DashboardState extends State<Dashboard> { ); } - void setSourceAndDestinationIcons() async { + setSourceAndDestinationIcons() async { currentLocationIcon = await BitmapDescriptor.fromAssetImage( ImageConfiguration(devicePixelRatio: 5), currentLocationIconAsset); } - void updatePinOnMap() async { + updatePinOnMap() async { CameraPosition cPosition = CameraPosition( zoom: cameraZoom, target: LatLng(currentLocation.latitude, currentLocation.longitude), @@ -174,7 +191,7 @@ class DashboardState extends State<Dashboard> { }); } - void setInitialLocation() async { + setInitialLocation() async { currentLocation = await location.getLocation(); } } diff --git a/lib/page/filter_fasilitas/fasilitas.dart b/lib/page/filter_fasilitas/fasilitas.dart index bcbdd8fcc575fd983905e7eb0eb7445c1363b9d8..13a5503725f5dff79b7509e9585eb6bf6f2b59d0 100644 --- a/lib/page/filter_fasilitas/fasilitas.dart +++ b/lib/page/filter_fasilitas/fasilitas.dart @@ -5,34 +5,53 @@ import 'package:ppl_disabilitas/component/bisago_appbar.dart'; import 'package:ppl_disabilitas/component/bisago_drawer.dart'; import 'package:ppl_disabilitas/config/styles.dart'; import 'package:ppl_disabilitas/network/data/network_model.dart'; +import 'package:ppl_disabilitas/page/addInformasi/addInfromasi.dart'; import 'package:ppl_disabilitas/page/filter_fasilitas/komentar.dart'; +import 'package:ppl_disabilitas/model/komentar.dart'; +import 'package:ppl_disabilitas/page/login/login.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + class Fasilitas extends StatefulWidget { final String nama; final String alamat; final String url; final String telpon; - Fasilitas({this.nama, this.alamat, this.url, this.telpon}); + final int id; + Fasilitas({this.nama, this.alamat, this.url, this.telpon, this.id}); @override _FasilitasState createState() => _FasilitasState(); } class _FasilitasState extends State<Fasilitas> { - var kursiRodaVal = false; - var liftVal = false; - var toiletDisabilitasVal = false; - var tempatIbadahVal = false; - var bidangMiringVal = false; - var parkirUmumVal = false; - var parkirDisabilitasVal = false; - var komentarTerbaru = false; - var komentarRatingTertinggi = false; - var komentarTerpopuler = false; + var kursiRodaVal = true; + var liftVal = true; + var toiletDisabilitasVal = true; + var tempatIbadahVal = true; + var bidangMiringVal = true; + var parkirUmumVal = true; + var parkirDisabilitasVal = true; + var guidingBlockVal = true; + var temanDisabilitasVal = true; + var juruIsyaratVal = true; + var tongkatVal = true; + var kursiDisabilitasVal = true; + var runningTextVal = true; + var sortKomentar = -1; var showUrutan = true; - final KomentarBloc _bloc = KomentarBloc(); + var komentarStream; + List<KomentarModel> allKomentarFromApi; + KomentarBloc _bloc; + + @override + void initState() { + allKomentarFromApi = []; + _bloc = KomentarBloc(widget.nama); + super.initState(); + } + @override Widget build(BuildContext context) { - print('widget.telpon ${widget.url}'); return Scaffold( backgroundColor: Colors.white, drawer: BisaGoDrawer(), @@ -63,6 +82,7 @@ class _FasilitasState extends State<Fasilitas> { children: <Widget>[ Icon(Icons.place, color: Colors.black, size: 20), Flexible( + key: Key('Alamat'), child: Text( widget.alamat, softWrap: true, @@ -87,7 +107,7 @@ class _FasilitasState extends State<Fasilitas> { ), Flexible( child: Text( - '08724981274', + widget.telpon, softWrap: true, textAlign: TextAlign.left, style: TextStyle( @@ -117,7 +137,7 @@ class _FasilitasState extends State<Fasilitas> { side: BorderSide(color: Colors.transparent)), splashColor: Colors.lightGreen, onPressed: () { - /*...*/ + checkLoginStatus(); }, child: Text( "Tambah Informasi", @@ -173,7 +193,6 @@ class _FasilitasState extends State<Fasilitas> { ], ), ), - // TODO change with komentar stream StreamBuilder( stream: _bloc.komentarListStream, builder: (context, snapshot) { @@ -183,29 +202,18 @@ class _FasilitasState extends State<Fasilitas> { return Center( child: CircularProgressIndicator( valueColor: - AlwaysStoppedAnimation<Color>(greenPrimary), + AlwaysStoppedAnimation<Color>(greenPrimary), ), ); break; case Status.COMPLETED: - final komentar = snapshot.data.data; - return ListView.builder( - shrinkWrap: true, - itemCount: komentar.allKomentar.length, - itemBuilder: (BuildContext context, int index) { - return Komentar( - dislike: - komentar.allKomentar[index].tidak_suka, - komentar: 'Lorem ipsum', - like: komentar.allKomentar[index].suka, - tags: ['#toiletdisabilitas', '#kursiroda'], - urlImage: [ - komentar.allKomentar[index].foto - ], - user: - komentar.allKomentar[index].nama_orang, - ); - }); + allKomentarFromApi = snapshot.data.data.allKomentar; + return Column( + children: allKomentarFromApi + .map<Widget>((k) => Komentar( + komentar: k, + )) + .toList()); break; case Status.ERROR: return Center( @@ -221,534 +229,745 @@ class _FasilitasState extends State<Fasilitas> { ), ]), ), - appBar: PreferredSize( - preferredSize: Size.fromHeight(55), - child: BisaGoAppBar(), + appBar: BisaGoAppBar( key: Key('Scaffold Text Field'), ), ); } - + InsideFilter() { return StatefulBuilder( - builder: (context, setStateModal) => Container( + builder: (BuildContext context, StateSetter setStateModal) => Container( height: MediaQuery.of(context).size.height / 2, decoration: BoxDecoration( boxShadow: regularShadow, - borderRadius: BorderRadius.all( - Radius.circular(10) // <--- border radius here - ), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10), topRight: Radius.circular(10)), color: Colors.white, ), - child: Container( - child: Column( - children: <Widget>[ - Container( - padding: EdgeInsets.all(regularBiggerSpace), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: <Widget>[ - Row( - children: <Widget>[ - Icon(Icons.filter_list), - Container( - margin: EdgeInsets.only(left: regularSpace), - child: Text( - 'Filter Pencarian', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.w800, - fontSize: 20.0), - ), - ), - ], - ), - Row( - children: <Widget>[ - Text( - 'BATAL', + child: Column( + children: <Widget>[ + Container( + padding: EdgeInsets.all(regularBiggerSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + Row( + children: <Widget>[ + Icon(Icons.filter_list), + Container( + margin: EdgeInsets.only(left: regularSpace), + child: Text( + 'Filter Pencarian', style: TextStyle( color: Colors.black, fontWeight: FontWeight.w800, - fontSize: 17), + fontSize: 20.0), ), - ], + ), + ], + ), + InkWell( + onTap: () => Navigator.pop(context), + child: Text( + 'BATAL', + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w800, + fontSize: 17), ), - ], - ), - ), - Container( - decoration: BoxDecoration( - border: Border( - top: BorderSide(color: greenPrimary, width: 1.5))), + ), + ], ), - Expanded( - child: Container( - child: Row( - children: <Widget>[ - Expanded( - flex: 1, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - ), - child: ListView( - children: <Widget>[ - InkWell( - child: Container( - decoration: BoxDecoration( - color: greenPale, - ), - padding: EdgeInsets.only( - left: regularSpace, - right: regularSpace, - top: doubleSpace, - bottom: doubleSpace), - child: Text( - 'Urutan', - style: TextStyle( - fontSize: 18, - color: Colors.white, - fontFamily: 'Muli', - ), - ), - ), - splashColor: Colors.green[400], - highlightColor: Colors.green[400], - onTap: () => setStateModal(() { - print('no'); - showUrutan = true; - })), - Container( + ), + Container( + decoration: BoxDecoration( + border: + Border(top: BorderSide(color: greenPrimary, width: 1.5))), + ), + Expanded( + child: Row( + children: <Widget>[ + Expanded( + flex: 1, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + ), + child: ListView( + children: <Widget>[ + InkWell( + + key: Key('Urutan'), + child: Container( decoration: BoxDecoration( - border: Border( - top: BorderSide( - color: greenPrimary, width: 1.5), - )), - ), - InkWell( - child: Container( - decoration: BoxDecoration( - color: greenPale, - ), - padding: EdgeInsets.only( - left: regularSpace, - right: regularSpace, - top: doubleSpace, - bottom: doubleSpace), - child: Text( - 'Jenis Fasilitas', - style: TextStyle( - fontSize: 18, - color: Colors.white, - fontFamily: 'Muli', - ), - ), + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Urutan', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', ), - splashColor: Colors.green[400], - highlightColor: Colors.green[400], - onTap: () => setStateModal(() { - print("yes"); - showUrutan = false; - })), - Container( + ), + ), + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + showUrutan = true; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: greenPrimary, width: 1.5), + )), + ), + InkWell( + key: Key('Jenis Fasilitas'), + child: Container( decoration: BoxDecoration( - border: Border( - top: BorderSide( - color: greenPrimary, width: 1.5))), + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Jenis Fasilitas', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', + ), + ), ), - ], + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + showUrutan = false; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: greenPrimary, width: 1.5))), ), + ], + ), + ), + ), + Expanded( + flex: 3, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border( + left: BorderSide(color: greenPrimary, width: 1.5), ), ), - Expanded( - flex: 3, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - border: Border( - left: BorderSide(color: greenPrimary, width: 1.5), - ), - ), - child: Stack( - children: <Widget>[ - Opacity( - opacity: showUrutan ? 0 : 1, - child: ListView( + child: Stack( + children: <Widget>[ + Opacity( + opacity: showUrutan ? 1 : 0, + child: ListView( + children: <Widget>[ + Row( + key: Key('Komentar Terbaru'), + crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: komentarTerbaru, - onChanged: (bool value) { - setStateModal(() { - komentarTerbaru = value; - }); - }, - ), - ), - Text( - "Komentar Terbaru", - style: TextStyle( - color: Colors.black, - fontSize: 18), - ), - ], + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Radio( + value: 0, + groupValue: sortKomentar, + activeColor: greenPale, + onChanged: (sort) { + _bloc.sortKomentarList( + sort, allKomentarFromApi); + + setStateModal(() { + sortKomentar = sort; + }); + }, + ), ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: komentarTerpopuler, - onChanged: (bool value) { - setStateModal(() { - komentarTerpopuler = value; - }); - }, - ), - ), - Text( - "Komentar Terpopuler", - style: TextStyle( - color: Colors.black, - fontSize: 18), - ), - ], + Text( + "Komentar Terbaru", + style: TextStyle( + color: Colors.black, fontSize: 18), ), - Container( - child: Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: - greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: komentarTerpopuler, - onChanged: (bool value) { - setStateModal(() { - komentarTerpopuler = value; - }); - }, - ), - ), - Flexible( - child: Text( - "Komentar dengan Rating Tertinggi", - style: TextStyle( - color: Colors.black, - fontSize: 18), - ), - ), - ], + ], + ), + Row( + key: Key('Komentar Terpopuler'), + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Radio( + value: 1, + groupValue: sortKomentar, + activeColor: greenPale, + onChanged: (sort) { + _bloc.sortKomentarList( + sort, allKomentarFromApi); + + setStateModal(() { + sortKomentar = sort; + }); + }, ), ), + Text( + "Komentar Terpopuler", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), ], ), - ), - Opacity( - opacity: showUrutan ? 1 : 0, - child: ListView( - children: <Widget>[ - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: kursiRodaVal, - onChanged: (bool value) { - setStateModal(() { - kursiRodaVal = value; - }); - }, - ), + Container( + key: Key('Komentar dengan Rating Tertinggi'), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Kursi roda", + child: Radio( + value: 2, + groupValue: sortKomentar, + activeColor: greenPale, + onChanged: (sort) { + _bloc.sortKomentarList( + sort, allKomentarFromApi); + + setStateModal(() { + sortKomentar = sort; + }); + }, + ), + ), + Flexible( + child: Text( + "Komentar dengan Rating Tertinggi", style: TextStyle( color: Colors.black, fontSize: 18), ), - ], - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: liftVal, - onChanged: (bool value) { - setStateModal(() { - liftVal = value; - }); - }, - ), + ), + ], + ), + ), + ], + ), + ), + IgnorePointer( + ignoring: showUrutan, + child: Opacity( + opacity: showUrutan ? 0 : 1, + child: ListView( + children: <Widget>[ + Row( + key: Key('Kursi Roda'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Lift", - style: TextStyle( - color: Colors.black, - fontSize: 18), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: kursiRodaVal, + onChanged: (bool value) { + _bloc.filterKomentarList('KR', + value, allKomentarFromApi); + setStateModal(() { + kursiRodaVal = value; + }); + }, ), - ], - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: toiletDisabilitasVal, - onChanged: (bool value) { - setStateModal(() { - toiletDisabilitasVal = value; - }); - }, - ), + ), + Text( + "Kursi Roda", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Lift'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Toilet Disabilitas", - style: TextStyle( - color: Colors.black, - fontSize: 18), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: liftVal, + onChanged: (bool value) { + _bloc.filterKomentarList('LF', + value, allKomentarFromApi); + setStateModal(() { + liftVal = value; + }); + }, ), - ], - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: tempatIbadahVal, - onChanged: (bool value) { - setStateModal(() { - tempatIbadahVal = value; - }); - }, - ), + ), + Text( + "Lift", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Toilet Disabilitas'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Tempat Ibadah", - style: TextStyle( - color: Colors.black, - fontSize: 18), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: toiletDisabilitasVal, + onChanged: (bool value) { + _bloc.filterKomentarList('TD', + value, allKomentarFromApi); + setStateModal(() { + toiletDisabilitasVal = value; + }); + }, ), - ], - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: bidangMiringVal, - onChanged: (bool value) { - setStateModal(() { - bidangMiringVal = value; - }); - }, - ), + ), + Text( + "Toilet Disabilitas", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Tempat Ibadah'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Bidang Miring (Ramp)", - style: TextStyle( - color: Colors.black, - fontSize: 18), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: tempatIbadahVal, + onChanged: (bool value) { + _bloc.filterKomentarList('MM', + value, allKomentarFromApi); + setStateModal(() { + tempatIbadahVal = value; + }); + }, ), - ], - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: parkirUmumVal, - onChanged: (bool value) { - setStateModal(() { - parkirUmumVal = value; - }); - }, - ), + ), + Text( + "Tempat Ibadah", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Guiding Block'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Parkir Umum", - style: TextStyle( - color: Colors.black, - fontSize: 18), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: guidingBlockVal, + onChanged: (bool value) { + _bloc.filterKomentarList('GB', + value, allKomentarFromApi); + setStateModal(() { + guidingBlockVal = value; + }); + }, ), - ], - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.center, - children: <Widget>[ - Theme( - data: Theme.of(context).copyWith( - unselectedWidgetColor: greenPrimary, - ), - child: Checkbox( - checkColor: Colors.red, - activeColor: Colors.amberAccent, - value: parkirDisabilitasVal, - onChanged: (bool value) { - setStateModal(() { - parkirDisabilitasVal = value; - }); - }, - ), + ), + Text( + "Guiding Block", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Bidang Miring (Ramp)'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, ), - Text( - "Parkir Disabilitas", - style: TextStyle( - color: Colors.black, - fontSize: 18), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: bidangMiringVal, + onChanged: (bool value) { + _bloc.filterKomentarList('BM', + value, allKomentarFromApi); + setStateModal(() { + bidangMiringVal = value; + }); + }, ), - //Container(height: 1.0,), - ], - ), - ], - ), + ), + Text( + "Bidang Miring (Ramp)", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Teman Disabilitas'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: temanDisabilitasVal, + onChanged: (bool value) { + _bloc.filterKomentarList('CP', + value, allKomentarFromApi); + setStateModal(() { + temanDisabilitasVal = value; + }); + }, + ), + ), + Text( + "Teman Disabilitas", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Juru Bahasa Isyarat'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: juruIsyaratVal, + onChanged: (bool value) { + _bloc.filterKomentarList('JI', + value, allKomentarFromApi); + setStateModal(() { + juruIsyaratVal = value; + }); + }, + ), + ), + Text( + "Juru Bahasa Isyarat", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ),Row( + key: Key("Tongkat Disabilitas Netra"), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: tongkatVal, + onChanged: (bool value) { + _bloc.filterKomentarList('TN', + value, allKomentarFromApi); + setStateModal(() { + tongkatVal = value; + }); + }, + ), + ), + Text( + "Tongkat Disabilitas Netra", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key("Kursi Umum Disabilitas"), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: kursiDisabilitasVal, + onChanged: (bool value) { + _bloc.filterKomentarList('KD', + value, allKomentarFromApi); + setStateModal(() { + kursiDisabilitasVal = value; + }); + }, + ), + ), + Text( + "Kursi Umum Disabilitas", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key("Parkir Umum"), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: parkirUmumVal, + onChanged: (bool value) { + _bloc.filterKomentarList('TB', + value, allKomentarFromApi); + setStateModal(() { + parkirUmumVal = value; + }); + }, + ), + ), + Text( + "Parkir Umum", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Running Text'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: runningTextVal, + onChanged: (bool value) { + _bloc.filterKomentarList('RT', + value, allKomentarFromApi); + setStateModal(() { + runningTextVal = value; + }); + }, + ), + ), + Text( + "Running Text", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + ], + ), + Row( + key: Key('Parkir Disabilitas'), + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: parkirDisabilitasVal, + onChanged: (bool value) { + _bloc.filterKomentarList('PK', + value, allKomentarFromApi); + setStateModal(() { + parkirDisabilitasVal = value; + }); + }, + ), + ), + Text( + "Parkir Disabilitas", + style: TextStyle( + color: Colors.black, fontSize: 18), + ), + //Container(height: 1.0,), + ], + ), + ], ), - ], + ), ), - ), + ], ), - ], + ), ), - ), + ], ), - Column( - children: <Widget>[ - Container( - decoration: BoxDecoration( - border: Border( - top: BorderSide(color: greenPrimary, width: 1.5), - )), - ), - Container( - margin: - EdgeInsets.only(left: doubleSpace, right: doubleSpace), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: <Widget>[ - Container( - margin: EdgeInsets.only( - top: regularSpace, bottom: regularSpace), - decoration: BoxDecoration(boxShadow: regularShadow), - child: SizedBox( - child: FlatButton( - color: redPrimary, - textColor: Colors.white, - padding: EdgeInsets.only( - top: regularBiggerSpace, - bottom: regularBiggerSpace, - left: doubleSpace, - right: doubleSpace), - shape: RoundedRectangleBorder( - borderRadius: regularBorderRadius, - side: BorderSide(color: Colors.transparent)), - splashColor: greenPrimary, - onPressed: () { - /*...*/ - }, - child: Text( - "Hapus Semua", - style: TextStyle( - fontSize: 20, fontWeight: FontWeight.w400), - ), - ), - ), - ), - Container( - margin: EdgeInsets.only( - top: regularSpace, bottom: regularSpace), - decoration: BoxDecoration(boxShadow: regularShadow), - child: SizedBox( - child: FlatButton( - color: greenPrimary, - textColor: Colors.white, - padding: EdgeInsets.only( - top: regularBiggerSpace, - bottom: regularBiggerSpace, - left: spaceFourty, - right: spaceFourty), - shape: RoundedRectangleBorder( - borderRadius: regularBorderRadius, - side: BorderSide(color: Colors.transparent)), - splashColor: greenPrimary, - onPressed: () { - /*...*/ - }, - child: Text( - "Terapkan", - style: TextStyle( - fontSize: 20, fontWeight: FontWeight.w400), - ), - ), + ), + Column( + children: <Widget>[ + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: greenPrimary, width: 1.5), + )), + ), + Container( + margin: + EdgeInsets.only(left: doubleSpace, right: doubleSpace), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + Container( + margin: EdgeInsets.only( + top: regularSpace, bottom: regularSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: FlatButton( + color: redPrimary, + textColor: Colors.white, + padding: EdgeInsets.only( + top: regularBiggerSpace, + bottom: regularBiggerSpace, + left: doubleSpace, + right: doubleSpace), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide(color: Colors.transparent)), + splashColor: greenPrimary, + onPressed: () { + setStateModal(() { + kursiRodaVal = true; + liftVal = true; + toiletDisabilitasVal = true; + tempatIbadahVal = true; + bidangMiringVal = true; + parkirUmumVal = true; + parkirDisabilitasVal = true; + guidingBlockVal = true; + temanDisabilitasVal = true; + juruIsyaratVal = true; + tongkatVal = true; + kursiDisabilitasVal = true; + runningTextVal = true; + sortKomentar = -1; + }); + _bloc.resetKomentarList(); + }, + child: Text( + "Hapus Semua", + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w400), ), ), - ], - ), + ), + + ], ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), ); } + + @override + void dispose() { + kursiRodaVal = true; + liftVal = true; + toiletDisabilitasVal = true; + tempatIbadahVal = true; + bidangMiringVal = true; + parkirUmumVal = true; + parkirDisabilitasVal = true; + guidingBlockVal = true; + temanDisabilitasVal = true; + juruIsyaratVal = true; + tongkatVal = true; + kursiDisabilitasVal = true; + runningTextVal = true; + sortKomentar = -1; + super.dispose(); + } + + checkLoginStatus() async { + SharedPreferences sharedPreferences = await SharedPreferences.getInstance(); + if(sharedPreferences.getString("token") == null) { + await Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => Login()), (Route<dynamic> route) => false); + } + else { + await Navigator.of(context).push(MaterialPageRoute( + builder: (BuildContext context) => AddInformasi( + nama: widget.nama, + ))).then((value) => _bloc.fetchKomentarList(widget.nama)); + } + } + + } diff --git a/lib/page/filter_fasilitas/komentar.dart b/lib/page/filter_fasilitas/komentar.dart index 4dbad48cffaec09ee0911901196625ea41d80588..0675851636086d6f32b880d1bb210c61d5eefddc 100644 --- a/lib/page/filter_fasilitas/komentar.dart +++ b/lib/page/filter_fasilitas/komentar.dart @@ -1,21 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/component/ImageHolder.dart'; +import 'package:ppl_disabilitas/config/strings.dart'; import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/model/komentar.dart'; +import 'package:ppl_disabilitas/page/filter_fasilitas/postingan/detailpost.dart'; class Komentar extends StatefulWidget { - final String user; - final int like; - final int dislike; - final List<String> urlImage; - final String komentar; - final List<String> tags; + final KomentarModel komentar; - Komentar( - {@required this.user, - @required this.like, - @required this.dislike, - @required this.urlImage, - @required this.komentar, - @required this.tags}); + Komentar({@required this.komentar}); @override _KomentarState createState() => _KomentarState(); } @@ -23,97 +16,103 @@ class Komentar extends StatefulWidget { class _KomentarState extends State<Komentar> { @override Widget build(BuildContext context) { - return Container( - margin: EdgeInsets.only(bottom: regularSpace), - padding: EdgeInsets.all(doubleSpace), - decoration: BoxDecoration( - boxShadow: regularShadow, - border: Border.all(width: 2, color: greenPrimary.withOpacity(0.4)), - borderRadius: BorderRadius.all( - Radius.circular(10) // <--- border radius here - ), - color: Colors.white, - ), - child: Column( - children: <Widget>[ - Container( - margin: EdgeInsets.only(bottom: regularSpace), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: <Widget>[ - Text( - widget.user, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w800, - color: Colors.black, - fontFamily: 'Muli', + return InkWell( + onTap: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (BuildContext context) => DetailPostPage( + komentar: widget.komentar, + ))); + }, + child: Container( + margin: EdgeInsets.only(bottom: regularSpace), + padding: EdgeInsets.all(doubleSpace), + decoration: BoxDecoration( + boxShadow: regularShadow, + border: Border.all(width: 2, color: greenPrimary.withOpacity(0.4)), + borderRadius: BorderRadius.all( + Radius.circular(10) // <--- border radius here + ), + color: Colors.white, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Container( + margin: EdgeInsets.only(bottom: regularSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + Text( + widget.komentar.creator, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + ), ), - ), - Row( - children: <Widget>[ - Container( - margin: EdgeInsets.only(right: regularSpace), - child: Row( - children: <Widget>[ - Icon(Icons.thumb_up, - color: Colors.green[800], size: 20), - Text( - '${widget.like} suka', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Colors.green[800], + Row( + children: <Widget>[ + Container( + margin: EdgeInsets.only(right: regularSpace), + child: Row( + children: <Widget>[ + Icon(Icons.thumb_up, + color: Colors.green[800], size: 20), + Text( + '${widget.komentar.like} suka', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: Colors.green[800], + ), ), - ), - ], - )), - Icon(Icons.thumb_down, color: redPrimary, size: 20), - Text( - '${widget.dislike} tidak suka', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: redPrimary, + ], + )), + Icon(Icons.thumb_down, color: redPrimary, size: 20), + Text( + '${widget.komentar.dislike} tidak suka', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: redPrimary, + ), ), - ), - ], - ) - ], + ], + ) + ], + ), ), - ), - Container( - margin: EdgeInsets.only(bottom: regularSpace), - child: ClipRRect( - borderRadius: BorderRadius.circular(5), - child: Image.asset('assets/images/disabletoilet.jpg'), - )), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: <Widget>[ - Flexible( - child: Text( - widget.komentar, - softWrap: true, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', + Container( + margin: EdgeInsets.only(bottom: regularSpace), + child: ImageHolder(url: widget.komentar.image)), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Flexible( + child: Text( + widget.komentar.deskripsi, + softWrap: true, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 15, + color: Colors.black, + fontFamily: 'Muli', + ), ), ), - ), - ], - ), - Row( - children: <Widget>[ - ...widget.tags.map<Widget>((tag) { - return _tag(tag); - }).toList() - ], - ), - ], - )); + ], + ), + Wrap( + children: <Widget>[ + ...widget.komentar.tag.map<Widget>((tag) { + return _tag(tag); + }).toList() + ], + ), + ], + )), + ); } Widget _tag(String tag) { @@ -129,7 +128,7 @@ class _KomentarState extends State<Komentar> { color: Colors.white, ), child: Text( - tag, + '#${getTag(tag)}', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w800, diff --git a/lib/page/filter_fasilitas/postingan/detailpost.dart b/lib/page/filter_fasilitas/postingan/detailpost.dart new file mode 100644 index 0000000000000000000000000000000000000000..f6b0e4bde031e1dbb126a90edba44e9b95ae9009 --- /dev/null +++ b/lib/page/filter_fasilitas/postingan/detailpost.dart @@ -0,0 +1,240 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:ppl_disabilitas/component/ImageHolder.dart'; +import 'package:ppl_disabilitas/component/bisago_appbar.dart'; +import 'package:ppl_disabilitas/config/strings.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/model/komentar.dart'; + +class DetailPostPage extends StatefulWidget { + final KomentarModel komentar; + DetailPostPage({@required this.komentar}); + @override + _DetailPostPageState createState() => _DetailPostPageState(); +} + +class _DetailPostPageState extends State<DetailPostPage> { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: BisaGoAppBar( + title: widget.komentar.nama_lokasi, + key: Key('appbar-text-${widget.komentar.nama_lokasi}'), + ), + body: Container( + margin: EdgeInsets.all(doubleSpace), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + ImageHolder(url: widget.komentar.image), + Wrap( + alignment: WrapAlignment.start, + direction: Axis.horizontal, + crossAxisAlignment: WrapCrossAlignment.start, + children: widget.komentar.tag + .map<Widget>((tag) => _createTagContainer(getTag(tag))) + .toList(), + ), + Container( + key: Key('desc'), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: regularShadow, + border: Border.all(color: greenPale), + borderRadius: regularBorderRadius), + padding: EdgeInsets.all(doubleSpace), + margin: EdgeInsets.symmetric(vertical: regularSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + 'Informasi', + style: + TextStyle(fontSize: 20, fontWeight: FontWeight.w800), + ), + Container( + margin: EdgeInsets.symmetric(vertical: regularSpace), + child: Text( + widget.komentar.deskripsi, + style: TextStyle(fontSize: 18), + ), + ), + Container( + margin: EdgeInsets.symmetric(vertical: regularSpace), + child: Text( + 'Diposting oleh', + style: TextStyle(fontSize: 18), + ), + ), + Text( + '${widget.komentar.creator}', style: TextStyle(fontSize: 18), + key: Key('creator-${widget.komentar.creator}'), + ), + Text( + '${DateFormat('dd MMMM yyy hh:mm').format(widget.komentar.date_time)}', + style: TextStyle(color: grayPrimary, fontSize: 16), + key: Key('timestamp'), + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + Expanded( + child: Container( + key: Key('like'), + decoration: BoxDecoration( + color: greenPrimary, + borderRadius: regularBorderRadius, + boxShadow: regularShadow), + padding: EdgeInsets.all(smallSpace), + margin: + EdgeInsets.symmetric(horizontal: smallSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + Icon( + Icons.thumb_up, + color: Colors.white, + ), + Text( + '${widget.komentar.like} Suka', + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.white, + fontSize: 16), + ), + ], + ), + ), + ), + Expanded( + child: Container( + key: Key('dislike'), + decoration: BoxDecoration( + color: redPrimary, + borderRadius: regularBorderRadius, + boxShadow: regularShadow), + padding: EdgeInsets.all(smallSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + Icon( + Icons.thumb_down, + color: Colors.white, + ), + Text( + '${widget.komentar.dislike} Tidak Suka', + style: TextStyle( + fontWeight: FontWeight.w700, + color: Colors.white, + fontSize: 16), + ), + ], + ), + ), + ) + ], + ) + ], + ), + ), + Container( + key: Key('rating'), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: regularShadow, + border: Border.all(color: greenPale), + borderRadius: regularBorderRadius), + padding: EdgeInsets.all(doubleSpace), + child: Column( + children: <Widget>[ + Text( + 'Rating', + style: TextStyle( + fontWeight: FontWeight.w800, + ), + ), + Row( + children: <Widget>[ + Text('${widget.komentar.rating}/5'), + ...List<Widget>.generate( + widget.komentar.rating, + (number) => Icon( + Icons.star, + color: Colors.yellow, + )) + ], + ) + ], + ), + ), + Container( + key: Key('Komentar'), + padding: EdgeInsets.symmetric(vertical: regularSpace), + child: Text( + 'Komentar', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.w800), + )), + komentarPlaceHolder( + 'test', widget.komentar.date_time, 'hard coded komentar') + ], + ), + ), + ), + ); + } + + _createTagContainer(String tag) { + return Container( + key: Key('tag-$tag'), + padding: EdgeInsets.all(smallSpace), + margin: EdgeInsets.all(smallSpace), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: regularBorderRadius, + border: Border.all(color: greenPale), + boxShadow: regularShadow), + child: Text( + '#$tag', + style: TextStyle( + fontWeight: FontWeight.w800, fontSize: 16, color: greenPrimary), + ), + ); + } + + komentarPlaceHolder(String nama, DateTime date, String description) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: <Widget>[ + CircleAvatar( + backgroundColor: greenPrimary, + child: Text('Test'), + ), + Padding( + padding: const EdgeInsets.all(regularSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + nama, + style: TextStyle(fontSize: 18), + ), + Text('${DateFormat('dd MMMM yyy hh:mm').format(date)}', + style: TextStyle(color: grayPrimary, fontSize: 16)) + ], + ), + ) + ], + ), + Container( + margin: EdgeInsets.only(bottom: regularSpace), + child: Text(description)), + Divider(color: grayPrimary,) + ], + ); + } +} diff --git a/lib/page/informasi/detailSekolah.dart b/lib/page/informasi/detailSekolah.dart new file mode 100644 index 0000000000000000000000000000000000000000..492a3ae0bf3c2176eaa030767ad0adeea9c38d28 --- /dev/null +++ b/lib/page/informasi/detailSekolah.dart @@ -0,0 +1,267 @@ +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/component/bisago_drawer.dart'; +import 'package:ppl_disabilitas/component/informasi_sekolah_appbar.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:share/share.dart'; + +class DetailSekolah extends StatefulWidget { + final String namaSekolah; + final String alamat; + final String nomerTelpon; + final String website; + final String jumlahSiswa; + final String status; + final String jenisSekolah; + final String akreditasi; + + DetailSekolah(this.namaSekolah, this.alamat, this.nomerTelpon, this.website, + this.jumlahSiswa, this.status, this.jenisSekolah, this.akreditasi); + + @override + DetailSekolahState createState() => DetailSekolahState(); +} + +class DetailSekolahState extends State<DetailSekolah> { + @override + Widget build(BuildContext context) { + return Scaffold( + drawer: BisaGoDrawer(), + appBar: PreferredSize( + preferredSize: Size.fromHeight(55), + child: InformasiSekolahAppBar(), + ), + body: ListView( + children: <Widget>[ + Container( + padding: EdgeInsets.only( + top: tripleSpace, + bottom: tripleSpace, + right: doubleSpace, + left: doubleSpace), + child: Text(widget.namaSekolah, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + )), + ), + Container( + padding: EdgeInsets.all(doubleSpace), + margin: EdgeInsets.only( + bottom: doubleSpace, left: doubleSpace, right: doubleSpace), + decoration: BoxDecoration( + border: + Border.all(width: 2, color: greenPrimary.withOpacity(0.4)), + borderRadius: regularBorderRadius, + color: Colors.white, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Container( + margin: EdgeInsets.only(bottom: regularSpace), + child: Text( + "Alamat", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + child: Text( + widget.alamat, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + Divider( + color: greenPrimary.withOpacity(0.4), + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + bottom: regularSpace, top: regularSpace), + child: Text( + "Nomor Telepon", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + child: Text( + widget.nomerTelpon, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + Divider( + color: greenPrimary.withOpacity(0.4), + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + bottom: regularSpace, top: regularSpace), + child: Text( + "Website", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + child: Text( + widget.website, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + Divider( + color: greenPrimary.withOpacity(0.4), + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + bottom: regularSpace, top: regularSpace), + child: Text( + "Jumlah Siswa", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + child: Text( + widget.jumlahSiswa, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + Divider( + color: greenPrimary.withOpacity(0.4), + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + bottom: regularSpace, top: regularSpace), + child: Text( + "Status", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + child: Text( + widget.status, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + Divider( + color: greenPrimary.withOpacity(0.4), + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + bottom: regularSpace, top: regularSpace), + child: Text( + "Jenis Sekolah", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + child: Text( + widget.jenisSekolah, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + Divider( + color: greenPrimary.withOpacity(0.4), + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + bottom: regularSpace, top: regularSpace), + child: Text( + "Akreditasi", + style: TextStyle( + fontSize: 22, + color: greenPrimary, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + Container( + margin: EdgeInsets.only(bottom: smallSpace), + child: Text( + widget.akreditasi, + style: TextStyle( + fontSize: 18, + color: Colors.black, + fontFamily: 'Muli'), + ), + ), + ], + ), + ), + InkWell( + onTap: () { + Share.share( + '${widget.namaSekolah} \n\n${widget.alamat} \n${widget.nomerTelpon} \n${widget.website} \nDibagikan dari bisaGo'); + }, + child: Container( + margin: EdgeInsets.all(regularSpace), + padding: EdgeInsets.symmetric(vertical: doubleSpace), + decoration: BoxDecoration( + boxShadow: regularShadow, + borderRadius: regularBorderRadius, + color: greenPrimary), + child: Center( + child: Text( + 'Bagikan', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w800, + fontSize: 18), + )), + ), + ) + ], + )); + } +} diff --git a/lib/page/informasi/layananDisabilitas.dart b/lib/page/informasi/layananDisabilitas.dart new file mode 100644 index 0000000000000000000000000000000000000000..b50f3d4f1430b0c4e474f2e689eb8a7fceae5a55 --- /dev/null +++ b/lib/page/informasi/layananDisabilitas.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/component/bisago_appbar.dart'; +import 'package:ppl_disabilitas/component/bisago_drawer.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/page/informasi/list_sekolah.dart'; +import 'package:ppl_disabilitas/page/registrasi_penyandang_disabilitas/registrasiInformasiLayananDisabilitas.dart'; + +class LayananDisabilitas extends StatefulWidget { + @override + _LayananDisabilitasState createState() => _LayananDisabilitasState(); +} + +class _LayananDisabilitasState extends State<LayananDisabilitas> { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + preferredSize: Size.fromHeight(55), + child: BisaGoAppBar(), + key: Key("Scaffold Text Field"), + ), + drawer: BisaGoDrawer(), + body: Container( + padding: EdgeInsets.only(top: tripleSpace, right: doubleSpace, left: doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Container( + child: Flexible( + child: Text( + 'Informasi Layanan Disabilitas', + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + ), + ), + ), + ), + Container( + margin: EdgeInsets.only(top: tripleSpace, bottom: doubleSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: SizedBox( + width: double.infinity, + child: FlatButton( + color: Colors.white, + textColor: Colors.black, + disabledColor: Colors.grey, + disabledTextColor: Colors.black, + padding: EdgeInsets.all(regularBiggerSpace), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide( + width: 2, color: greenPrimary.withOpacity(0.4))), + //splashColor: Colors.lightGreen, + onPressed: () { + _navigateToRegistrasiDisabilitasPage(context); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: <Widget>[ + Container( + padding: EdgeInsets.only(right: regularSpace), + child: Icon(Icons.add_box, color: greenPrimary, size: 30)), + Flexible( + child: Text( + "Registrasi Penyandang Disabilitas", + style: TextStyle(fontSize: 20), + ), + ), + Icon(Icons.chevron_right, color: greenPrimary, size: 30), + ], + ), + ), + ), + ), + Container( + margin: EdgeInsets.only(bottom: doubleSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: SizedBox( + width: double.infinity, + child: FlatButton( + color: Colors.white, + textColor: Colors.black, + disabledColor: Colors.grey, + disabledTextColor: Colors.black, + padding: EdgeInsets.all(regularBiggerSpace), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide( + width: 2, color: greenPrimary.withOpacity(0.4))), + //splashColor: Colors.lightGreen, + onPressed: () { + _navigateToListSekolahPage(context); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: <Widget>[ + Container( + padding: EdgeInsets.only(right: regularSpace), + child: Icon(Icons.info, color: greenPrimary, size: 30)), + Flexible( + child: Text( + "Informasi Sekolah dengan Dukungan Disabilitas", + style: TextStyle(fontSize: 20), + ), + ), + Icon(Icons.chevron_right, color: greenPrimary, size: 30), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } + + void _navigateToListSekolahPage(BuildContext context) { + final route = MaterialPageRoute(builder: (_) => ListSekolah()); + Navigator.of(context).push(route); + } + + void _navigateToRegistrasiDisabilitasPage(BuildContext context) { + final route = MaterialPageRoute(builder: (_) => RegistrasiInformasiLayananDisabilitas()); + Navigator.of(context).push(route); + } +} diff --git a/lib/page/informasi/list_sekolah.dart b/lib/page/informasi/list_sekolah.dart new file mode 100644 index 0000000000000000000000000000000000000000..c97453b820c04e74f08b9fdd2c15573efd784afd --- /dev/null +++ b/lib/page/informasi/list_sekolah.dart @@ -0,0 +1,876 @@ +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/bloc/SekolahBloc.dart'; +import 'package:ppl_disabilitas/component/bisago_drawer.dart'; +import 'package:flutter/widgets.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +//import 'package:ppl_disabilitas/model/lokasi.dart'; +import 'package:ppl_disabilitas/model/sekolah.dart'; +import 'package:ppl_disabilitas/network/data/network_model.dart'; +import 'package:ppl_disabilitas/page/informasi/detailSekolah.dart'; + +class ListSekolah extends StatefulWidget { + @override + _ListSekolahState createState() => _ListSekolahState(); +} + +class _ListSekolahState extends State<ListSekolah> { + var jawaTengah = false; + var inklusi = false; + var luarBiasa = false; + var showProvinsi = true; + var showKota = false; + var showKecamatan = false; + var showKategoriSekolah = false; + var showTingkatSekolah = false; + + List<SekolahModel> sekolah = []; + + /// BLoC for sekolah + SekolahBloc _bloc = SekolahBloc(); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + drawer: BisaGoDrawer(), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Container( + child: Padding( + padding: EdgeInsets.only(top: tripleSpace, left: doubleSpace, right: doubleSpace), + child: Text( + "Sekolah dengan Dukungan Disabilitas", + style: TextStyle( + fontSize: 25, + fontFamily: 'Muli', + fontWeight: FontWeight.w800), + ), + ), + ), + Container( + padding: EdgeInsets.only(bottom: smallSpace), + margin: EdgeInsets.only(left: doubleSpace, right: doubleSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: FlatButton( + key: Key('FilterButton'), + color: Colors.green[700], + textColor: Colors.white, + disabledColor: Colors.grey, + disabledTextColor: Colors.black, + padding: EdgeInsets.all(8), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide(color: Colors.transparent)), + splashColor: Colors.lightGreen, + onPressed: () => {showModalBottomSheet( + context: context, + builder: (context) => InsideFilter(), + backgroundColor: Colors.transparent, + isScrollControlled: true), + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Icon(Icons.filter_list, color: Colors.white, size: 20), + Text( + "Filter Pencarian", + style: TextStyle(fontSize: 13), + ), + ], + ), + ), + ), + StreamBuilder<NetworkModel<SekolahList>>( + stream: _bloc.sekolahListStream, + builder: (context, snapshot) { + if (snapshot.hasData) { + switch (snapshot.data.status) { + case Status.LOADING: + return Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation<Color>(greenPrimary), + ), + ); + break; + case Status.COMPLETED: + sekolah = snapshot.data.data.allSekolah; + return makeLokasiWidget("api", sekolah); + break; + case Status.ERROR: + return Center( + child: Text(snapshot.data.data.toString()), + ); + break; + } + } + return Container(); + }, + ), + ], + ), + ), + appBar: AppBar( + elevation: 15, + key: Key("appbar-text-informasi-sekolah"), + backgroundColor: greenPrimary, + leading: IconButton( + icon: Icon(Icons.arrow_back_ios, size: 20), + key: Key('Back Icon Key'), + onPressed: () => Navigator.pop(context, 'Take me back')), + centerTitle: true, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Padding( + padding: EdgeInsets.all(doubleSpace), + child: Text( + "Informasi Sekolah", + style: TextStyle( + fontSize: 25, + fontFamily: 'Comfortaa', + fontWeight: FontWeight.w800), + ), + ) + ], + ), + ), + ); + } + + Widget makeLokasiWidget( + String key, List<SekolahModel> sekolah) { + return ListView.builder( + shrinkWrap: true, + itemCount: sekolah.length, + itemBuilder: (context, index) { + return InkWell( + key: Key("$key-${sekolah[index].name}"), + onTap: () {_navigateToDetailSekolahPage(context, sekolah[index]);}, + child: Container( + decoration: BoxDecoration( + color: Colors.transparent, + border: Border(bottom: BorderSide(color: Colors.grey[400]))), + margin: EdgeInsets.only(left: doubleSpace, right: doubleSpace), + height: 90, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + + CircleAvatar( + backgroundColor: greenPrimary, + child: Text('Test'), + ), + Expanded( + child: Container( + padding: EdgeInsets.all(doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + Text( + sekolah[index].name, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + ), + ), + Text( + sekolah[index].alamat, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 15, + color: Colors.black, + fontFamily: 'Muli', + ), + ), + + ], + ), + ), + ), + Icon( + Icons.arrow_forward_ios, + color: Colors.grey[400], + size: 20, + ) + ], + ), + ), + ); + }); + + } + + InsideFilter() { + return StatefulBuilder( + builder: (context, setStateModal) => Container( + height: MediaQuery.of(context).size.height / 2, + decoration: BoxDecoration( + boxShadow: regularShadow, + borderRadius: BorderRadius.all( + Radius.circular(10) // <--- border radius here + ), + color: Colors.white, + ), + child: Container( + child: Column( + children: <Widget>[ + Container( + padding: EdgeInsets.all(regularBiggerSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + Row( + children: <Widget>[ + Icon(Icons.filter_list), + Container( + margin: EdgeInsets.only(left: regularSpace), + child: Text( + 'Filter Pencarian', + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w800, + fontSize: 20.0), + ), + ), + ], + ), + Row( + children: <Widget>[ + Text( + 'BATAL', + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w800, + fontSize: 17), + ), + ], + ), + ], + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: greenPrimary, width: 1.5))), + ), + Expanded( + child: Container( + child: Row( + children: <Widget>[ + Expanded( + flex: 1, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + ), + child: ListView( + children: <Widget>[ + InkWell( + child: Container( + decoration: BoxDecoration( + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Provinsi', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', + ), + ), + ), + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + print('no'); + showProvinsi = true; + showKota = false; + showKecamatan = false; + showKategoriSekolah = false; + showTingkatSekolah = false; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: greenPrimary, width: 1.5), + )), + ), + InkWell( + child: Container( + decoration: BoxDecoration( + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Kota', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', + ), + ), + ), + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + print("yes"); + showProvinsi = false; + showKota = true; + showKecamatan = false; + showKategoriSekolah = false; + showTingkatSekolah = false; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: greenPrimary, width: 1.5))), + ), + InkWell( + child: Container( + decoration: BoxDecoration( + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Kecamatan', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', + ), + ), + ), + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + print("yes"); + showProvinsi = false; + showKota = false; + showKecamatan = true; + showKategoriSekolah = false; + showTingkatSekolah = false; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: greenPrimary, width: 1.5))), + ), + InkWell( + child: Container( + decoration: BoxDecoration( + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Kategori Sekolah', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', + ), + ), + ), + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + print("yes"); + showProvinsi = false; + showKota = false; + showKecamatan = false; + showKategoriSekolah = true; + showTingkatSekolah = false; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: greenPrimary, width: 1.5))), + ), + InkWell( + child: Container( + decoration: BoxDecoration( + color: greenPale, + ), + padding: EdgeInsets.only( + left: regularSpace, + right: regularSpace, + top: doubleSpace, + bottom: doubleSpace), + child: Text( + 'Tingkat Sekolah', + style: TextStyle( + fontSize: 18, + color: Colors.white, + fontFamily: 'Muli', + ), + ), + ), + splashColor: Colors.green[400], + highlightColor: Colors.green[400], + onTap: () => setStateModal(() { + print("yes"); + showProvinsi = false; + showKota = false; + showKecamatan = false; + showKategoriSekolah = false; + showTingkatSekolah = true; + })), + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: greenPrimary, width: 1.5))), + ), + ], + ), + ), + ), + Expanded( + flex: 3, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border( + left: BorderSide(color: greenPrimary, width: 1.5), + ), + ), + child: Stack( + children: <Widget>[ + Opacity( + opacity: showProvinsi ? 1 : 0, + child: ListView( + children: <Widget>[ + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "Jawa Tengah", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "Jawa Tengah", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + ], + ), + ), + Opacity( + opacity: showKota ? 1 : 0, + child: ListView( + children: <Widget>[ + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "Bandung", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "Sukabumi", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + ], + ), + ), + Opacity( + opacity: showKecamatan ? 1 : 0, + child: ListView( + children: <Widget>[ + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "Beji", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "Bojongsari", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + ], + ), + ), + Opacity( + opacity: showKategoriSekolah ? 1 : 0, + child: ListView( + children: <Widget>[ + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: inklusi, + onChanged: (bool value) { + setStateModal(() { + inklusi = value; + }); + }, + ), + ), + Text( + "Inklusi", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: luarBiasa, + onChanged: (bool value) { + setStateModal(() { + luarBiasa = value; + }); + }, + ), + ), + Text( + "Luar Biasa", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + ], + ), + ), + Opacity( + opacity: showTingkatSekolah ? 1 : 0, + child: ListView( + children: <Widget>[ + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "SD", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + Row( + crossAxisAlignment: + CrossAxisAlignment.center, + children: <Widget>[ + Theme( + data: Theme.of(context).copyWith( + unselectedWidgetColor: greenPrimary, + ), + child: Checkbox( + checkColor: greenPrimary, + activeColor: greenPale, + value: jawaTengah, + onChanged: (bool value) { + setStateModal(() { + jawaTengah = value; + }); + }, + ), + ), + Text( + "SMP", + style: TextStyle( + color: Colors.black, + fontSize: 18), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + Column( + children: <Widget>[ + Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: greenPrimary, width: 1.5), + )), + ), + Container( + margin: + EdgeInsets.only(left: doubleSpace, right: doubleSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + Container( + margin: EdgeInsets.only( + top: regularSpace, bottom: regularSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: SizedBox( + child: FlatButton( + color: redPrimary, + textColor: Colors.white, + padding: EdgeInsets.only( + top: regularBiggerSpace, + bottom: regularBiggerSpace, + left: doubleSpace, + right: doubleSpace), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide(color: Colors.transparent)), + splashColor: greenPrimary, + onPressed: () { + /*...*/ + }, + child: Text( + "Hapus Semua", + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w400), + ), + ), + ), + ), + Container( + margin: EdgeInsets.only( + top: regularSpace, bottom: regularSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: SizedBox( + child: FlatButton( + color: greenPrimary, + textColor: Colors.white, + padding: EdgeInsets.only( + top: regularBiggerSpace, + bottom: regularBiggerSpace, + left: spaceFourty, + right: spaceFourty), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide(color: Colors.transparent)), + splashColor: greenPrimary, + onPressed: () { + /*...*/ + }, + child: Text( + "Terapkan", + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w400), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ); + } + + void _navigateToDetailSekolahPage(BuildContext context, SekolahModel sekolah) { + final route = MaterialPageRoute(builder: (_) => DetailSekolah( + sekolah.name, + sekolah.alamat, + sekolah.no_telp, + sekolah.website, + (sekolah.jumlah_siswa).toString(), + sekolah.status , + sekolah.jenis_sekolah, + sekolah.akreditasi)); + Navigator.of(context).push(route); + } +} diff --git a/lib/page/login/login.dart b/lib/page/login/login.dart new file mode 100644 index 0000000000000000000000000000000000000000..7524a7acb926385884a2a2e80af73b17bb9037e8 --- /dev/null +++ b/lib/page/login/login.dart @@ -0,0 +1,158 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/page/registrasi/registrasi.dart'; +import 'package:ppl_disabilitas/utils/customButton.dart'; +import 'package:ppl_disabilitas/utils/customTextField.dart'; +import 'package:ppl_disabilitas/utils/validator.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; + +class Login extends StatefulWidget { + LoginState createState() => LoginState(); +} + +class LoginState extends State<Login> { + final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); + + SharedPreferences sharedPreferences; + + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 15, + centerTitle: true, + backgroundColor: greenPrimary, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Padding( + padding: EdgeInsets.all(doubleSpace), + child: Text( + "bisaGo", + style: TextStyle( + fontSize: 25, + fontFamily: 'Comfortaa', + fontWeight: FontWeight.w800), + ), + ) + ], + ), + actions: <Widget>[ + Padding( + padding: EdgeInsets.all(doubleSpace), + child: InkWell( + child: Text( + 'Daftar', + style: TextStyle(fontSize: 15), + ), + onTap: () { + _navigateToRegistrasiPage(context); + }, + ), + ) + ], + ), + body: SingleChildScrollView( + child: Form( + key: _formKey, + child: Center( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + SizedBox(height: 25), + Text( + 'Masuk ke Akun', + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), + ), + SizedBox(height: 20), + CustomTextField( + title: 'Nomor Telepon atau Email', + key: Key('Text Field Akun'), + validator: FieldValidator.validateEmail, + controller: emailController, + ), + CustomTextField( + title: 'Password', + key: Key('Text Field Password'), + obsecure: true, + validator: FieldValidator.validatePassword, + controller: passwordController, + ), + Container( + margin: EdgeInsets.fromLTRB(0, 30, 0, 10), + alignment: Alignment.center, + child: ButtonTheme( + minWidth: double.infinity, + height: 40, + child: submitButton( + 'Masuk', + Color(0xff3A903A), + Colors.white, + Color(0xff3A903A), + Colors.white, + _validateLoginInput), + )), + Container( + child: separator('Atau masuk dengan', 12, 0xff000000, + 1, 0xff000000), + ), + Container( + margin: EdgeInsets.fromLTRB(0, 10, 0, 30), + alignment: Alignment.center, + child: googleButton(), + ), + ], + ), + ), + )))); + } + + void _validateLoginInput() async { + final FormState form = _formKey.currentState; + if (_formKey.currentState.validate()) { + form.save(); + login(emailController.text, passwordController.text); + } + } + + TextEditingController emailController = TextEditingController(); + TextEditingController passwordController = TextEditingController(); + + login(String email, String password) async { + Map data = {'username': email, 'password': password}; + + sharedPreferences = await SharedPreferences.getInstance(); + var response = await http.post( + 'http://poipole-staging.herokuapp.com/api-token-auth/', + body: data); + if (response.statusCode == 200) { + print('ok'); + Map<String, dynamic> tokenMap = jsonDecode(response.body); + setState(() { + sharedPreferences.setString("token", tokenMap['token']); + + sharedPreferences.setString("email", email); + + Navigator.pushNamed(context, '/'); + }); + } else { + print(response.body); + } + } + + void _navigateToRegistrasiPage(BuildContext context) { + final route = MaterialPageRoute(builder: (_) => Registrasi()); + Navigator.of(context).push(route); + } +} diff --git a/lib/page/pencarian/pencarian.dart b/lib/page/pencarian/pencarian.dart index 59e1d2dcbf72b4b9a00bcca5ea01fe07c001c4e9..0bed8188a0e51dc0196303286683d2bc70a1699f 100644 --- a/lib/page/pencarian/pencarian.dart +++ b/lib/page/pencarian/pencarian.dart @@ -1,9 +1,11 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:ppl_disabilitas/bloc/LokasiResponseBloc.dart'; +import 'package:ppl_disabilitas/component/ImageHolder.dart'; import 'package:ppl_disabilitas/config/styles.dart'; import 'package:ppl_disabilitas/model/lokasi.dart'; import 'package:ppl_disabilitas/network/data/network_model.dart'; +import 'package:ppl_disabilitas/page/addLokasi/addLokasi.dart'; import 'package:ppl_disabilitas/page/filter_fasilitas/fasilitas.dart'; /// Create Pencarian page widget with a state @@ -47,7 +49,7 @@ class PencarianState extends State<Pencarian> { for (int i = 0; i < places.length; i++) { if (myController.text.isNotEmpty) { if (places[i] - .nama + .name .toLowerCase() .contains(myController.text.toLowerCase())) { tempList.add(places[i]); @@ -55,6 +57,8 @@ class PencarianState extends State<Pencarian> { } } setState(() { + // print(places); + // print(places[0].nama); currentSearch = tempList; }); }); @@ -178,7 +182,21 @@ class PencarianState extends State<Pencarian> { return Expanded( flex: 2, child: currentSearch.isEmpty - ? Center(child: Text('Cari lokasi')) + ? Center( + child: Column( + children: <Widget>[ + Text('Cari lokasi'), + RaisedButton( + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => + AddLokasi())); + }, + child: Text('Tambah Lokasi'), + ) + ], + )) : makeLokasiWidget("api", currentSearch)); break; case Status.ERROR: @@ -202,16 +220,19 @@ class PencarianState extends State<Pencarian> { itemCount: places.length, itemBuilder: (context, index) { return InkWell( - key: Key("$key-${places[index].nama}"), + key: Key("$key-${places[index].name}"), onTap: () { _bloc.saveRecentSearch(places[index]); - Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => Fasilitas( - alamat: places[index].alamat, - nama: places[index].nama, - telpon: places[index].telepon, - url: 'http://dummyimage.com/128x141.png/ff4444/ffffff', - ))); + Navigator.of(context) + .push(MaterialPageRoute( + builder: (BuildContext context) => Fasilitas( + alamat: places[index].alamat, + nama: places[index].name, + telpon: places[index].no_telp, + url: places[index].image, + id: places[index].id, + ))) + .then((value) => _bloc.fetchRecentSearch()); }, child: Container( decoration: BoxDecoration( @@ -223,39 +244,47 @@ class PencarianState extends State<Pencarian> { mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ - Row( - children: <Widget>[ - CircleAvatar( - backgroundColor: greenPrimary, - child: Text('Test'), - ), - Container( - padding: EdgeInsets.all(doubleSpace), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: <Widget>[ - Text( - places[index].nama, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w800, - color: Colors.black, - fontFamily: 'Muli', - ), - ), - Text( - places[index].alamat, - style: TextStyle( - fontSize: 15, - color: Colors.black, - fontFamily: 'Muli', - ), + Expanded( + child: Row( + children: <Widget>[ + CircleAvatar( + backgroundColor: greenPrimary, + child: ImageHolder( + url: places[index].image, + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.all(doubleSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + Text( + places[index].name, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w800, + color: Colors.black, + fontFamily: 'Muli', + ), + overflow: TextOverflow.ellipsis, + ), + Text( + places[index].alamat, + style: TextStyle( + fontSize: 15, + color: Colors.black, + fontFamily: 'Muli', + ), + overflow: TextOverflow.ellipsis, + ), + ], ), - ], + ), ), - ), - ], + ], + ), ), Icon( Icons.arrow_forward_ios, diff --git a/lib/page/registrasi/registrasi.dart b/lib/page/registrasi/registrasi.dart new file mode 100644 index 0000000000000000000000000000000000000000..fc2306be97a75f08f32a07b8ac85ccbdfd845394 --- /dev/null +++ b/lib/page/registrasi/registrasi.dart @@ -0,0 +1,191 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/page/dashboard/dashboard.dart'; +import 'package:ppl_disabilitas/utils/customButton.dart'; +import 'package:ppl_disabilitas/utils/customTextField.dart'; +import 'package:ppl_disabilitas/utils/validator.dart'; +import 'package:http/http.dart' as http; + +class Registrasi extends StatefulWidget { + RegistrasiState createState() => RegistrasiState(); +} + +class RegistrasiState extends State<Registrasi> { + final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); + + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + elevation: 15, + centerTitle: true, + backgroundColor: greenPrimary, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Padding(padding: EdgeInsets.all(doubleSpace), + child: Text( + "bisaGo", + style: TextStyle( + fontSize: 25, + fontFamily: 'Comfortaa', + fontWeight: FontWeight.w800), + ), + ) + ], + ), + actions: <Widget>[ + Padding( + padding: EdgeInsets.all(doubleSpace), + child: InkWell( + child: Text( + 'Login', + style: TextStyle(fontSize: 15), + ), + onTap: () { + Navigator.pop(context); + }, + ), + ) + ], + ), + body: SingleChildScrollView( + child: Form( + key: _formKey, + child: Center( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + SizedBox(height: 25), + Text('Daftar Akun Baru', + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), + ), + SizedBox(height: 20), + CustomTextField( + title: 'Nama Lengkap', + key: Key('Text Field Nama'), + validator: FieldValidator.validateName, + controller: nameController, + ), + CustomTextField( + title: 'Nomor Telepon', + key: Key('Text Field Nomor Telepon'), + validator: FieldValidator.validatePhoneNumber, + controller: phoneController, + ), + CustomTextField( + title: 'Email', + key: Key('Text Field Email'), + controller: emailController, + validator: FieldValidator.validateEmail, + ), + CustomTextField( + title: 'Password', + key: Key('Text Field Password'), + obsecure: true, + validator: FieldValidator.validatePassword, + controller: passwordController, + ), + CustomTextField( + title: 'Konfirmasi Password', + key: Key('Text Field Konfirmasi Password'), + obsecure: true, + validator: (input) { + if (input != passwordController.text) { + return '*Password tidak sesuai. Coba lagi'; + } + return null; + }, + ), + Container( + margin: EdgeInsets.fromLTRB(0, 30, 0, 10), + alignment: Alignment.center, + child: ButtonTheme( + minWidth: double.infinity, + height: 40, + child: submitButton('Daftar', Color(0xff3A903A), Colors.white, + Color(0xff3A903A), Colors.white, _validateLoginInput), + ) + ), + Container( + child: separator('Atau daftar dengan', 12, 0xff000000, 1, 0xff000000), + ), + Container( + margin: EdgeInsets.fromLTRB(0, 10, 0, 30), + alignment: Alignment.center, + child: googleButton(), + ), + ], + ), + ), + ), + ), + ), + ); + } + + void _validateLoginInput() async { + final FormState form = _formKey.currentState; + if (_formKey.currentState.validate()) { + form.save(); + await createUser(nameController.text.toString(), phoneController.text.toString(), + emailController.text.toString(), passwordController.text.toString()); + _showDialog(); + } + } + + TextEditingController nameController = TextEditingController(); + TextEditingController phoneController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + TextEditingController passwordController = TextEditingController(); + + createUser(String name, String phone_number, String email, String password) async { + Map data = { + 'name' : name, + 'phone_number' : phone_number, + 'email' : email, + 'password' : password, + }; + final response = await http.post( + "http://poipole-staging.herokuapp.com/api/register/", +// headers: {"Content-Type": "application/json"}, + body: data, + ); + if (response.statusCode == 200) { + } else { + return false; + } + } + + void _showDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text("Pendaftaran Berhasil"), + content: Text("Silahkan kembali ke halaman utama untuk login"), + actions: <Widget>[ + FlatButton(onPressed: () { + _navigateToDashboard(context); + }, + child: Text("Dashboard")) + ], + ); + } + ); + } + + void _navigateToDashboard(BuildContext context) { + final route = MaterialPageRoute(builder: (_) => Dashboard()); + Navigator.of(context).push(route); + } +} + diff --git a/lib/page/registrasi_penyandang_disabilitas/registrasiInformasiLayananDisabilitas.dart b/lib/page/registrasi_penyandang_disabilitas/registrasiInformasiLayananDisabilitas.dart new file mode 100644 index 0000000000000000000000000000000000000000..8eeed7ff20aa5a516d712a27e049ad67332f2416 --- /dev/null +++ b/lib/page/registrasi_penyandang_disabilitas/registrasiInformasiLayananDisabilitas.dart @@ -0,0 +1,571 @@ + +import 'dart:io'; + +import 'package:flutter/cupertino.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:ppl_disabilitas/config/styles.dart'; +import 'package:ppl_disabilitas/utils/customTextField.dart'; +import 'package:ppl_disabilitas/utils/validator.dart'; +import 'package:ppl_disabilitas/network/network_interface.dart'; + + +class RegistrasiInformasiLayananDisabilitas extends StatefulWidget { + @override + _RegistrasiInformasiLayananDisabilitasState createState() => + _RegistrasiInformasiLayananDisabilitasState(); +} + +class _RegistrasiInformasiLayananDisabilitasState + extends State<RegistrasiInformasiLayananDisabilitas> { + _RegistrasiInformasiLayananDisabilitasState(); + Map<String, dynamic> data = { + 'name':'', + 'alamat':'', + 'tempat_lahir': '', + 'jenis_kelamin': '', + 'pendidikan':'', + 'pekerjaan':'', + 'kategori': '', + 'no_telp': '', + 'email': '', + 'nama_wali': '', + 'alamat_wali': '', + 'telp_wali': '' + }; + //get isSelected => null; + final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); + final List<String> _dropdownValues = [ + "Laki - Laki", + "Perempuan" + ]; + final sexInitial = [ + "LAKI-LAKI", + 'PEREMPUAN' + ]; + String showSex = 'Pilih salah satu'; + String showPendidikan = 'Pilih salah satu'; + String showPekerjaan = 'Pilih salah satu'; + String showKategori = 'Pilih salah satu'; + final List<String> _dropdownValues2 = [ + "SD", + "SMP/SLTP", + "SMA/SLTA", + "D1", + "D2", + "D3", + "S1", + "S2", + "S3", + "Non Formal", + "Tidak Sekolah" + ]; + final List<String> pendidikanInitial = [ + "SD", + "MP", + "MA", + "D1", + "D2", + "D3", + "S1", + "S2", + "S3", + "NF", + "NA" + ]; + final List<String> _dropdownValues3 = [ + "Fisik", + "Intelektual", + "Mental", + "Sensorik" + ]; + final List<String> kategoriInitial = [ + 'FS', + 'IN', + 'MN', + 'SN' + ]; + final pekerjaanList = [ + 'Petani', + 'Buruh', + 'Pedagang/Wiraswasta', + 'Jasa', + 'PNS/TNI/POLRI', + 'Pensiunan', + 'Ibu Rumah Tangga', + 'Pelajar', + 'Lainnya', + 'Tidak Bekerja' + ]; + final List<String> pekerjaanInitial = [ + 'PT', + 'BR', + 'WS', + 'JS', + 'PN', + 'SN', + 'IR', + 'PL', + 'LA', + 'NA' + ]; + String tanggalLahir = 'Pilih tanggal lahir'; + + @override + Widget build(BuildContext context) { + //final List<bool> isSelected; + + return Scaffold( + appBar: AppBar( + elevation: 15, + backgroundColor: greenPrimary, + leading: IconButton( + icon: Icon(Icons.arrow_back_ios, size: 20), + key: Key('Back Icon Key'), + onPressed: () => Navigator.pop(context, 'Take me back')), + centerTitle: true, + key: _formKey, + title: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + Padding( + padding: EdgeInsets.only( + top: regularBiggerSpace, + bottom: regularBiggerSpace, + left: spaceFourty, + right: spaceFourty), + child: Text( + "bisaGo", + style: TextStyle( + fontSize: 25, + fontFamily: 'Comfortaa', + fontWeight: FontWeight.w800), + ), + ) + ], + ), + ), + body: SingleChildScrollView( + child: Form( + child: Center( + child: Container( + margin: EdgeInsets.symmetric(horizontal: 20.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + SizedBox(height: 25), + Text( + 'Registrasi Penyandang Disabilitas', + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), + ), + SizedBox(height: 20), + CustomTextField( + title: 'Nama Lengkap Penyandang', +// key: Key('Text Field Nomor Telepon'), + controller: namaPenyandangController, + ), + CustomTextField( + title: 'Alamat penyandang', +// key: Key('Text Field Nomor Telepon'), + controller: alamatController, + ), + CustomTextField( + title: 'Tempat Lahir', + //key: Key('Text Field Email'), + controller: ttlController, + validator: FieldValidator.validateTtl, + ), + InkWell( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text('Tanggal Lahir'), + FlatButton( + onPressed: () { + DatePicker.showDatePicker(context, + showTitleActions: true, + maxTime: DateTime.now(), + onChanged: (date) { + setState(() { + tanggalLahir = '${DateFormat('yyyy-MM-dd').format(date)}'; + }); + + }); + }, + child: Text( + tanggalLahir, + style: TextStyle(color: Colors.white), + ), + color: greenPrimary, + ) + ], + )), + Container(height: 5), + Text( + "Jenis Kelamin", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18, + ), + ), + FormField( + builder: (FormFieldState<String> state) { + return InputDecorator( + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + top: smallSpace, + bottom: smallSpace, + left: smallSpace, + right: smallSpace), + hintText: "pilih salah satu", + //errorStyle: TextStyle(color: Colors.redAccent, fontSize: 16.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5.0), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + items: _dropdownValues + .map((value) => DropdownMenuItem( + child: Text(value), + value: value, + )) + .toList(), + onChanged: (String value) { + setState(() { + showSex = value; + data['jenis_kelamin'] = sexInitial[_dropdownValues.indexOf(value)]; + print(data); + }); + }, + isExpanded: false, + hint: Text(showSex), + ), + ), + ); + }, + ), + Text( + "Pendidikan Terakhir", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18, + ), + ), + FormField( + builder: (FormFieldState<String> state) { + return InputDecorator( + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + top: smallSpace, + bottom: smallSpace, + left: smallSpace, + right: smallSpace), + hintText: "pilih salah satu", + //errorStyle: TextStyle(color: Colors.redAccent, fontSize: 16.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5.0), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + items: _dropdownValues2 + .map((value) => DropdownMenuItem( + child: Text(value), + value: value, + )) + .toList(), + onChanged: (String value) { + setState(() { + showPendidikan = value; + data['pendidikan'] = pendidikanInitial[_dropdownValues2.indexOf(value)]; + print(data); + }); + }, + isExpanded: false, + hint: Text(showPendidikan), + ), + ), + ); + }, + ), + Text( + "Pekerjaan", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18, + ), + ), + FormField( + builder: (FormFieldState<String> state) { + return InputDecorator( + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + top: smallSpace, + bottom: smallSpace, + left: smallSpace, + right: smallSpace), + hintText: "pilih salah satu", + //errorStyle: TextStyle(color: Colors.redAccent, fontSize: 16.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5.0), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + items: pekerjaanList + .map((value) => DropdownMenuItem( + child: Text(value), + value: value, + )) + .toList(), + onChanged: (String value) { + setState(() { + showPekerjaan = value; + data['pekerjaan'] = pekerjaanInitial[pekerjaanList.indexOf(value)]; + print(data); + }); + }, + isExpanded: false, + hint: Text(showPekerjaan), + ), + ), + ); + }, + ), + Container(height: 10), + Text( + "Kategori Disabilitas", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.normal, + fontSize: 18, + ), + ), + FormField( + builder: (FormFieldState<String> state) { + return InputDecorator( + decoration: InputDecoration( + contentPadding: EdgeInsets.only( + top: smallSpace, + bottom: smallSpace, + left: smallSpace, + right: smallSpace), + hintText: "pilih salah satu", + //errorStyle: TextStyle(color: Colors.redAccent, fontSize: 16.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(5.0), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + items: _dropdownValues3 + .map((value) => DropdownMenuItem( + child: Text(value), + value: value, + )) + .toList(), + onChanged: (String value) { + setState(() { + showKategori = value; + data['kategori'] = kategoriInitial[_dropdownValues3.indexOf(value)]; + print(data); + }); + }, + isExpanded: false, + hint: Text(showKategori), + ), + ), + ); + }, + ), + CustomTextField( + title: 'Nomor Telepon', + controller: phoneController, + ),CustomTextField( + title: 'Email', + controller: emailController, + ), + CustomTextField( + title: 'Nama lengkap orang tua/wali', +// key: Key('Text Field Nama'), + validator: FieldValidator.validateNamaPengisiData, + controller: namaWaliController, + ), + CustomTextField( + title: 'Alamat lengkap orang tua/wali', +// key: Key('Text Field Nama'), +// validator: FieldValidator.validateName, + controller: alamatWaliController, + ), + CustomTextField( + title: 'No. hp orang tua/wali', +// key: Key('Text Field Nama'), + validator: FieldValidator.validateAlamat, + controller: phoneNumbOrtuController, + ), + Container(height: 10), + Container( + margin: + EdgeInsets.only(left: doubleSpace, right: doubleSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: <Widget>[ + Container( + margin: EdgeInsets.only( + top: regularSpace, bottom: regularSpace), + decoration: BoxDecoration(), + child: SizedBox( + child: FlatButton( + color: Colors.transparent, + textColor: Colors.black, + padding: EdgeInsets.only( + top: regularBiggerSpace, + bottom: regularBiggerSpace, + left: doubleSpace, + right: doubleSpace), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide(color: Colors.grey)), + splashColor: white, + onPressed: () { + /*...*/ + }, + child: Text( + "Batal", + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w400), + ), + ), + ), + ), + Container( + margin: EdgeInsets.only( + top: regularSpace, bottom: regularSpace), + decoration: BoxDecoration(boxShadow: regularShadow), + child: SizedBox( + child: FlatButton( + color: greenPrimary, + textColor: Colors.white, + padding: EdgeInsets.only( + top: regularBiggerSpace, + bottom: regularBiggerSpace, + left: spaceFourty, + right: spaceFourty), + shape: RoundedRectangleBorder( + borderRadius: regularBorderRadius, + side: BorderSide(color: Colors.transparent)), + splashColor: greenPrimary, + onPressed: () { + _validateRegisInput(); + }, + child: Text( + "Simpan", + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.w400), + ), + ), + ), + ), + ], + ), + ), + ], + ), + )), + ), + ), + ); + } + + void _validateRegisInput() async { + + await createPenyandang(); + //_showDialog(); + + } + + TextEditingController alamatController = TextEditingController(); + TextEditingController namaPenyandangController = TextEditingController(); + TextEditingController phoneNumbOrtuController = TextEditingController(); + TextEditingController ttlController = TextEditingController(); + TextEditingController phoneController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + TextEditingController namaWaliController = TextEditingController(); + TextEditingController alamatWaliController = TextEditingController(); + + createPenyandang() async { + data['name'] = namaPenyandangController.text; + data['alamat'] = alamatController.text; + data['tempat_lahir'] = ttlController.text; + data['tanggal_lahir'] = tanggalLahir; + data['no_telp'] = phoneController.text; + data['email'] = emailController.text; + data['nama_wali'] = namaWaliController.text; + data['alamat_wali'] = alamatWaliController.text; + data['telp_wali'] = phoneNumbOrtuController.text; + print('data $data'); + final response = await NetworkInterface().post( + url: "https://poipole-staging.herokuapp.com/layanan-khusus/penyandang/register/", + bodyParams: data, + ); + if (response != null) { + inputData(context); + } else { + inputDataFail(context); + } + } + void inputData(BuildContext context) { + var alertDialog = AlertDialog( + backgroundColor: greenPrimary, + title: Text( + 'Registrasi penyandang disabilitas berhasil', + style: TextStyle( + color: Colors.white, + fontFamily: 'Muli', + fontWeight: FontWeight.w600, + ), + ), + content: Icon(FontAwesomeIcons.checkCircle), + ); + showDialog( + context: context, + builder: (BuildContext context) { + return alertDialog; + }); + } + + void inputDataFail(BuildContext context) { + var alertDialog = AlertDialog( + backgroundColor: redPrimary, + title: Text( + 'Registrasi tidak berhasil, coba lagi', + style: TextStyle( + color: Colors.white, + fontFamily: 'Muli', + fontWeight: FontWeight.w600, + ), + ), + content: Icon(Icons.close), + ); + showDialog( + context: context, + builder: (BuildContext context) { + return alertDialog; + }); + } + +} diff --git a/lib/repository/KomentarRepository.dart b/lib/repository/KomentarRepository.dart index a1bd088128787159dfdcb0527d45acf163a14de5..7b84603dee4ca4cce0b70477e6228472d8652b01 100644 --- a/lib/repository/KomentarRepository.dart +++ b/lib/repository/KomentarRepository.dart @@ -1,15 +1,16 @@ import 'package:ppl_disabilitas/model/komentar.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; - class KomentarRepository { NetworkInterface _network = NetworkInterface(); - Future<KomentarList> fetchKomentar() async { + Future<KomentarList> fetchKomentar(String namaLokasi) async { + String nama = namaLokasi.replaceAll(" ", "%20"); + String url = "https://poipole-staging.herokuapp.com/informasi-fasilitas/lokasi/list-fasilitas/" + nama; final response = await _network.get( - url: 'https://my.api.mockaroo.com/postingan.json?key=dbcde960', + url: url, isLogin: false); - print(response); + final data = response.values.toList().reversed.toList(); return KomentarList( - response.map<KomentarModel>((komentar) => KomentarModel.fromJson(komentar)).toList()); + data.map<KomentarModel>((komentar) => KomentarModel.fromJson(komentar)).toList()); } } diff --git a/lib/repository/LokasiRepository.dart b/lib/repository/LokasiRepository.dart index 7c44aefe12ed01b6fc83a7e3fe6d6ef1b5c0cf86..9b488571f418f63e24be22b3f7eaf4e4b3bdbb8f 100644 --- a/lib/repository/LokasiRepository.dart +++ b/lib/repository/LokasiRepository.dart @@ -5,12 +5,14 @@ import 'package:ppl_disabilitas/network/cookies_interface.dart'; import 'package:ppl_disabilitas/network/network_interface.dart'; class LokasiRepository { - NetworkInterface _network = NetworkInterface(); - CookiesInterface _cookie = CookiesInterface(); + final _network = NetworkInterface(); + final _cookie = CookiesInterface(); Future<LokasiListResponse> fetchLokasi() async { final response = await _network.get( - url: 'http://poipole-staging.herokuapp.com/informasi-fasilitas/lokasi/list/', + url: + 'https://poipole-staging.herokuapp.com/informasi-fasilitas/lokasi/list/', isLogin: false); + return LokasiListResponse( response.map<Lokasi>((lokasi) => Lokasi.fromJson(lokasi)).toList()); } @@ -27,7 +29,7 @@ class LokasiRepository { await _cookie.getCookieFile(fileName: "searchhistory").then((cookie) { response = json.decode(cookie); }); - } on Exception{ + } on Exception { response = []; } } @@ -37,7 +39,7 @@ class LokasiRepository { } Future<void> saveRecentSearch(Lokasi recentSearch) async { - Map<String, dynamic> searchToMap = recentSearch.toJson(); + final searchToMap = recentSearch.toJson(); await _cookie.createSearchHistoryCookie(recentSearch: searchToMap); } } diff --git a/lib/repository/SekolahRepository.dart b/lib/repository/SekolahRepository.dart new file mode 100644 index 0000000000000000000000000000000000000000..ffec6a30b7c84c8b1003dc570eb68aa4e2d9c5d9 --- /dev/null +++ b/lib/repository/SekolahRepository.dart @@ -0,0 +1,14 @@ +import 'package:ppl_disabilitas/model/sekolah.dart'; +import 'package:ppl_disabilitas/network/network_interface.dart'; + +class SekolahRepository { + NetworkInterface _network = NetworkInterface(); + + Future<SekolahList> fetchSekolah() async { + final response = await _network.get( + url: 'https://poipole-staging.herokuapp.com/layanan-khusus/sekolah/list/', + isLogin: false); + return SekolahList( + response.map<SekolahModel>((sekolah) => SekolahModel.fromJson(sekolah)).toList()); + } +} \ No newline at end of file diff --git a/lib/utils/customButton.dart b/lib/utils/customButton.dart new file mode 100644 index 0000000000000000000000000000000000000000..cdab226fa51da5285c4086510454f0a642dd31c8 --- /dev/null +++ b/lib/utils/customButton.dart @@ -0,0 +1,104 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +Widget submitButton(String text, Color splashColor, Color highlightColor, +Color fillColor, Color textColor, void function()) { + return RaisedButton( + padding: EdgeInsets.symmetric(vertical: 15), + highlightElevation: 0.0, + splashColor: splashColor, + highlightColor: highlightColor, + elevation: 0.0, + color: fillColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: Text( + text, + style: TextStyle(fontSize: 20, color: textColor, fontWeight: FontWeight.bold), + ), + onPressed: () => function(), + ); +} + +Widget separator(String text, double textSize, int textColor, double thickness, int color) { + return Row( + children: <Widget>[ + SizedBox( + width: 20, + ), + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Divider( + thickness: thickness, + color: Color(color), + ), + ), + ), + Text(text, + style: TextStyle(fontSize: textSize, color: Color(textColor))), + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Divider( + thickness: thickness, + color: Color(color), + ), + ), + ), + SizedBox( + width: 20, + ), + ], + ); +} + +Widget googleButton() { + return InkWell( + onTap: () { + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + border: Border.all(), + boxShadow: <BoxShadow>[ + BoxShadow( + color: Colors.grey.shade200, + offset: Offset(2, 4), + blurRadius: 5, + spreadRadius: 2) + ], + color: Colors.white, + ), + child: Stack( + children: <Widget>[ + Container( + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(10), + topLeft: Radius.circular(10)), + ), + child: Image( + image: AssetImage('assets/logo/google.png'), + width: 20.0, + ), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 15), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(10), + topRight: Radius.circular(10)), + ), + alignment: Alignment.center, + child: Text('Akun Google', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold) + ), + ), + ], + ), + ), + ); +} \ No newline at end of file diff --git a/lib/utils/customDeskripsiField.dart b/lib/utils/customDeskripsiField.dart new file mode 100644 index 0000000000000000000000000000000000000000..9976c23ece6ea36ab7ada86046e660b90f246eb4 --- /dev/null +++ b/lib/utils/customDeskripsiField.dart @@ -0,0 +1,71 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class CustomDeskripsiField extends StatelessWidget { + CustomDeskripsiField( + { this.title, + this.hint, + this.obsecure = false, + this.key, + this.validator, + this.controller, + this.onSaved}); + final String title; + final Key key; + final FormFieldSetter<String> onSaved; + final String hint; + final bool obsecure; + final FormFieldValidator<String> validator; + final TextEditingController controller; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + title, + style: TextStyle(fontSize: 18), + ), + SizedBox( + height: 10, + ), + TextFormField( + keyboardType: TextInputType.multiline, + maxLines: null, + onSaved: onSaved, + validator: validator, + controller: controller, + autofocus: true, + obscureText: obsecure, + style: TextStyle( + fontSize: 15, + ), + decoration: InputDecoration( + hintStyle: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + hintText: hint, + contentPadding: EdgeInsets.all(8.0), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Theme.of(context).primaryColor, + width: 1, + ), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Theme.of(context).primaryColor, + width: 1, + ), + ), + ), + ), + + ], + ), + ); + } +} diff --git a/lib/utils/customTextField.dart b/lib/utils/customTextField.dart new file mode 100644 index 0000000000000000000000000000000000000000..2f127b616832ee3b3cc20fc8088ff4948e35543e --- /dev/null +++ b/lib/utils/customTextField.dart @@ -0,0 +1,70 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class CustomTextField extends StatelessWidget { + CustomTextField( + {this.title, + this.hint, + this.obsecure = false, + this.key, + this.validator, + this.controller, + this.onSaved, + this.onTap}); + final String title; + final Key key; + final FormFieldSetter<String> onSaved; + final String hint; + final bool obsecure; + final FormFieldValidator<String> validator; + final TextEditingController controller; + final Function onTap; + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + Text( + title, + style: TextStyle(fontSize: 18), + ), + SizedBox( + height: 10, + ), + TextFormField( + onSaved: onSaved, + validator: validator, + controller: controller, + autofocus: true, + obscureText: obsecure, + onTap: onTap, + style: TextStyle( + fontSize: 15, + ), + decoration: InputDecoration( + hintStyle: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + hintText: hint, + contentPadding: EdgeInsets.all(8.0), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Theme.of(context).primaryColor, + width: 1, + ), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Theme.of(context).primaryColor, + width: 1, + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/utils/validator.dart b/lib/utils/validator.dart new file mode 100644 index 0000000000000000000000000000000000000000..23f98eab00f82e8395e271b0629774f29c750883 --- /dev/null +++ b/lib/utils/validator.dart @@ -0,0 +1,86 @@ +class FieldValidator { + static String validatePengisiData(String value){ + if (value.isEmpty) { + return '*Wajib diisi'; + } + else { + return null; + } + } + static String validateNamaPengisiData(String value){ + if (value.isEmpty) { + return '*Wajib diisi'; + } + else { + return null; + } + } + static String validateTtl(String value){ + if (value.isEmpty) { + return '*Wajib diisi'; + } + else { + return null; + } + } + static String validateAlamat(String value){ + if (value.isEmpty) { + return '*Wajib diisi'; + } + else { + return null; + } + } + + static String validateEmail(String value) { + Pattern 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,}))$'; + RegExp regex = RegExp(pattern); + if (value.isEmpty) return '*Wajib diisi'; + if (!regex.hasMatch(value)) { + return '*Masukkan email yang valid'; + } else { + return null; + } + } + + static String validatePassword(String value) { + if (value.isEmpty) return '*Wajib diisi'; + + if (value.length < 7) { + return '*Password harus lebih dari 6 karakter'; + } else { + return null; + } + } + + + static String validatePhoneNumber(String value) { + String pattern = r'(^(?:[+0]9)?[0-9]{11,12}$)'; + RegExp regExp = RegExp(pattern); + if (value.isEmpty) { + return '*Wajib diisi'; + } + else if (!regExp.hasMatch(value)) { + return '*Masukkan nomor telepon yang valid'; + } + return null; + } + + static String validateName(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } + else { + return null; + } + } + + static String validateInfo(String value) { + if (value.isEmpty) { + return '*Wajib diisi'; + } else { + return null; + } + } +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index b30c8feeb134c875596efc5042f7789e3088ff16..d475bf894b02bb5fff6b7e5277c7766c50a59611 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,16 @@ dependencies: flutter_dotenv: ^2.1.0 json_serializable: ^3.2.5 cached_network_image: ^2.0.0 + shared_preferences: 0.5.6+3 + smooth_star_rating: ^1.0.4+2 + image_picker: ^0.6.5 + font_awesome_flutter: ^8.8.1 + dio: ^3.0.9 + share: ^0.6.4 + flutter_datetime_picker: ^1.3.8 + flutter_google_places: ^0.2.4 + google_maps_webservice: ^0.0.16 + geolocator: ^5.3.1 dev_dependencies: flutter_test: @@ -39,6 +49,7 @@ dev_dependencies: # Linter dependency pedantic: ^1.8.0 # The default Linter package used in Google build_runner: ^1.8.0 + rxdart: ^0.23.1 flutter_icons: android: "launcher_icon" @@ -58,12 +69,15 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: + # - assets/logo/google.png assets: - assets/icon/loc.png - assets/icon/current_loc.png - assets/icon/icon_launcher.png + - assets/logo/google.png - assets/images/margocity.jpg - assets/images/disabletoilet.jpg + - .env # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware. @@ -125,6 +139,5 @@ flutter: weight: 700 - asset: assets/fonts/Comfortaa-Bold.ttf weight: 800 - # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/addInformasi_test.dart b/test/addInformasi_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..041b14b3e846f750d162a1cbb8d9359e124cee86 --- /dev/null +++ b/test/addInformasi_test.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/utils/validator.dart'; +import 'package:ppl_disabilitas/page/addInformasi/addInfromasi.dart'; + +void main(){ + testWidgets('Test Input Gambar', (WidgetTester tester) async { + final testInputImage = Key("Input Gambar"); + await tester.pumpWidget(MaterialApp(home: AddInformasi())); + expect(find.byKey(testInputImage), findsOneWidget); + }); + + testWidgets('Info Text Field Test', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Informasi"); + await tester.pumpWidget(MaterialApp(home: AddInformasi())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + + testWidgets('Checkbox Fasilitas Test', (WidgetTester tester) async { + final checkBoxKey = Key("Checkbox Fasilitas"); + await tester.pumpWidget(MaterialApp(home: AddInformasi())); + expect(find.byKey(checkBoxKey), findsOneWidget); + }); + + testWidgets('Star Rating Exist Test', (WidgetTester tester) async { + final starKey = Key("Star Rating"); + await tester.pumpWidget(MaterialApp(home: AddInformasi())); + expect(find.byKey(starKey), findsOneWidget); + }); + + testWidgets('Simpan Button Test', (WidgetTester tester) async { + final simpanKey = Key("Simpan Button"); + await tester.pumpWidget(MaterialApp(home: AddInformasi())); + expect(find.byKey(simpanKey), findsOneWidget); + }); + + testWidgets('Batal Button Test', (WidgetTester tester) async { + final batalKey = Key("Batal Button"); + await tester.pumpWidget(MaterialApp(home: AddInformasi())); + expect(find.byKey(batalKey), findsOneWidget); + }); + + test('Empty Info Test', () { + var result = FieldValidator.validateInfo(''); + expect(result, '*Wajib diisi'); + }); + + test('Valid Info Test', () { + var result = FieldValidator.validateInfo('Margo city punya kursi roda'); + expect(result, null); + }); + + test('Star rating start from zero', (){ + var info = AddInformasiState(); + expect(info.rating, 0.0); + }); + +} \ No newline at end of file diff --git a/test/addLokasi_test.dart b/test/addLokasi_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..167deae3f1ddc7d853b7432136a1d1d8e82454d7 --- /dev/null +++ b/test/addLokasi_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/page/registrasi_penyandang_disabilitas/registrasiInformasiLayananDisabilitas.dart'; + +void main() { + Widget buildTestableWidget(Widget widget) { + // https://docs.flutter.io/flutter/widgets/MediaQuery-class.html + return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); + } + + testWidgets('find add lokasi page', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(RegistrasiInformasiLayananDisabilitas())); + final scaffoldTextFieldKey = Key("Scaffold Text Field"); + + //positive test + expect(find.byType(Container), findsNWidgets(53)); + expect(find.byType(Column), findsNWidgets(10)); + expect(find.byType(Text), findsNWidgets(53)); + expect(find.byType(Icon), findsNWidgets(5)); + expect(find.byType(Row), findsNWidgets(6)); + expect(find.byType(Scaffold), findsOneWidget); + expect(find.byType(SizedBox), findsNWidgets(61)); + expect(find.byType(FlatButton), findsNWidgets(3)); + + + //negative test + expect(find.byType(FormField), findsNothing); + expect(find.byType(BoxDecoration), findsNothing); + expect(find.byType(Flex), findsNothing); + expect(find.byKey(scaffoldTextFieldKey), findsNothing); + expect(find.text('tambh lokasi'), findsNothing); + expect(find.text('almt'), findsNothing); + expect(find.text('nm lkssss'), findsNothing); + expect(find.text('latitde'), findsNothing); + + }); + + + + +} diff --git a/test/bisago_drawer_test.dart b/test/bisago_drawer_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..27f3483dcfd71480826336a902ab3c8853e44fdd --- /dev/null +++ b/test/bisago_drawer_test.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/component/bisago_drawer.dart'; + + +void main() { + + group('drawer tests', () { + testWidgets('my drawer test', (WidgetTester tester) async { + final berandaText = "Beranda"; + await tester.pumpWidget(MaterialApp( + home: Scaffold( + drawer: BisaGoDrawer(), + ))); + + await tester.dragFrom(tester.getTopLeft(find.byType(MaterialApp)), Offset(300, 0)); + await tester.pumpAndSettle(); + +// await tester.tap(find.text(loginText)); +// await tester.pumpAndSettle(); +// +// final textFieldLogin = 'Masuk ke Akun'; + + expect(find.text(berandaText), findsOneWidget); + }); + }); +} \ No newline at end of file diff --git a/test/detailSekolah_test.dart b/test/detailSekolah_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..e3216fb6b7ea8958d837fce7a111086471054c64 --- /dev/null +++ b/test/detailSekolah_test.dart @@ -0,0 +1,39 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/page/informasi/detailSekolah.dart'; + + +void main() { + Widget buildTestableWidget(Widget widget) { + // https://docs.flutter.io/flutter/widgets/MediaQuery-class.html + return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); + } + + testWidgets('find fasilitas page', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(DetailSekolah( + "Sekolah Pilar Indonesia", + "Jl. Paso No.84, Jagakarsa, Kec. Jagakarsa, Kota Jakarta Selatan, Daerah Khusus Ibukota Jakarta 12620", + "02149305494", + "www.pilarindonesia.com", + "1000", + "Swasta", + "Inklusi", + "A"))); + // Search for the childWidget in the tree and verify it exists. + expect(find.byType(Scaffold), findsOneWidget); + expect(find.byType(ListView), findsOneWidget); + expect(find.byType(Container), findsNWidgets(23)); + expect(find.byType(Column), findsNWidgets(1)); + expect(find.byType(Text), findsNWidgets(16)); + }); + +} diff --git a/test/detail_post_test.dart b/test/detail_post_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..c66ec4b20270c09df78a25aa0f4bed26db2225c0 --- /dev/null +++ b/test/detail_post_test.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/config/strings.dart'; +import 'package:ppl_disabilitas/model/komentar.dart'; +import 'package:ppl_disabilitas/page/filter_fasilitas/postingan/detailpost.dart'; + +void main() { + Widget buildTestableWidget(Widget widget) { + return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); + } + final detailPostData = { + "nama_lokasi": "Margo City", + "deskripsi": "Ada toilet khusus disabilitas terletak di lantai 2 dekat kintan, kondisinya bagus dan bersih layak pakai.\r\n\r\nAda kursi roda juga di customer service lantai dasar, saya tidak ingat jumlahnya ada berapa, tapi ada lumayan banyak.", + "creator": "", + "date_time": "2020-04-12T14:33:54.442Z", + "like": 20, + "dislike": 1, + "rating": 3, + "tag": [ + "KR", + "TD" + ], + "image": "static/img/2669211407.jpg", + "is_verified": false + }; + final detailPostPage = DetailPostPage( + komentar: KomentarModel.fromJson(detailPostData) + ); + testWidgets('Detail post positive test', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(detailPostPage)); + expect(find.byKey(Key('appbar-text-${detailPostData['nama_lokasi']}')), findsOneWidget); + expect(find.byKey(Key('desc')), findsOneWidget); + expect(find.byKey(Key('creator-${detailPostData['creator']}')), findsOneWidget); + expect(find.byKey(Key('timestamp')), findsOneWidget); + expect(find.byKey(Key('like')), findsOneWidget); + expect(find.byKey(Key('dislike')), findsOneWidget); + expect(find.byKey(Key('rating')), findsOneWidget); + expect(find.byKey(Key('Komentar')), findsOneWidget); + }); + + testWidgets('Detail post negative test', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(detailPostPage)); + expect(find.byKey(Key('appbar-text')), findsNothing); + expect(find.byKey(Key('creator')), findsNothing); + expect(find.byKey(Key('komentar')), findsNothing); + }); + + test('Should decrypt tag code', () { + expect(getTag('KR'), tags['KR']); + }); +} \ No newline at end of file diff --git a/test/fasilitas_test.dart b/test/fasilitas_test.dart index a689a5493cb526ff2debbbc214c8919ca799391c..d6cb77514f3a80c0223ff385db2fdc3b3f6ecfa2 100644 --- a/test/fasilitas_test.dart +++ b/test/fasilitas_test.dart @@ -5,18 +5,39 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. - import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/globalnetwork.dart'; import 'package:ppl_disabilitas/page/filter_fasilitas/fasilitas.dart'; void main() { + final mockFasilitas = { + "2": { + "id": 2, + "nama_lokasi": "Margo City", + "deskripsi": + "Ada toilet khusus disabilitas terletak di lantai 2 dekat kintan, kondisinya bagus dan bersih layak pakai.\r\n\r\nAda kursi roda juga di customer service lantai dasar, saya tidak ingat jumlahnya ada berapa, tapi ada lumayan banyak.", + "creator": "", + "date_time": "2020-04-12T14:33:54.442Z", + "like": 20, + "dislike": 1, + "rating": 3, + "tag": ["KR", "TD"], + "image": "static/img/2669211407.jpg", + "is_verified": false + } + }; Widget buildTestableWidget(Widget widget) { // https://docs.flutter.io/flutter/widgets/MediaQuery-class.html return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); } + setUp(() { + getDioInstance('test'); + mockFasilitasDependencies(mockFasilitas); + }); + testWidgets('find inside filter page', (WidgetTester tester) async { // Provide the childWidget to the Container. await tester.pumpWidget(buildTestableWidget(Fasilitas( @@ -28,18 +49,27 @@ void main() { await tester.tap(find.byKey(Key('FilterButton'))); await tester.pump(Duration(seconds: 1)); // inside filter - expect(find.byType(Container), findsNWidgets(28)); - expect(find.byType(Row), findsNWidgets(17)); - expect(find.byType(Column), findsNWidgets(4)); - expect(find.byType(Text), findsNWidgets(21)); - expect(find.byType(Flex), findsNothing); - expect(find.text('jns fasilitas'), findsNothing); - expect(find.text('urutn'), findsNothing); - expect(find.text('hps smw'), findsNothing); + expect(find.byKey(Key('Urutan')), findsOneWidget); + expect(find.byKey(Key('Jenis Fasilitas')), findsOneWidget); + expect(find.byKey(Key('Komentar Terbaru')), findsOneWidget); + expect(find.byKey(Key('Komentar Terpopuler')), findsOneWidget); + expect(find.byKey(Key('Komentar dengan Rating Tertinggi')), findsOneWidget); + expect(find.byKey(Key('Kursi Roda')), findsOneWidget); + expect(find.byKey(Key('Lift')), findsOneWidget); + expect(find.byKey(Key('Toilet Disabilitas')), findsOneWidget); + expect(find.byKey(Key('Tempat Ibadah')), findsOneWidget); + await tester.drag(find.byKey(Key('Tempat Ibadah')), Offset(0,-200)); + await tester.pump(); + // expect(find.byKey(Key('Guiding Block')), findsOneWidget); + //expect(find.byKey(Key('Bidang Miring (Ramp)')), findsOneWidget); + //expect(find.byKey(Key('Juru Bahasa Isyarat')), findsOneWidget); + //expect(find.byKey(Key('Tongkat Disabilitas Netra')), findsOneWidget); + //expect(find.byKey(Key('Kursi Umum Disabilitas')), findsOneWidget); + //expect(find.byKey(Key('Parkir Umum')), findsOneWidget); + //expect(find.byKey(Key('Runing Text')), findsOneWidget); + //expect(find.byKey(Key('Parkir Disabilitas')), findsOneWidget); // filter - expect(find.byType(Scaffold), findsOneWidget); - expect(find.byType(Icon), findsNWidgets(5)); - await tester.tap(find.byKey(Key('Tambah Informasi'))); + await tester.tap(find.byKey(Key('Alamat'))); await tester.pump(); }); @@ -51,15 +81,14 @@ void main() { telpon: '9217424', url: 'afalklksafn', ))); - // Search for the childWidget in the tree and verify it exists. - expect(find.byType(Scaffold), findsOneWidget); - expect(find.byType(Container), findsNWidgets(10)); - expect(find.byType(Icon), findsNWidgets(4)); - expect(find.byType(Column), findsNWidgets(2)); - expect(find.byType(Row), findsNWidgets(5)); - expect(find.byType(Text), findsNWidgets(7)); - expect(find.byType(Flexible), findsNWidgets(2)); - expect(find.byType(FlatButton), findsNWidgets(2)); + expect(find.text('9217424'), findsOneWidget); + expect(find.text('Ya'), findsOneWidget); + expect(find.text('Itu'), findsOneWidget); + await tester.pump(); + expect(find.text(mockFasilitas['2']['deskripsi']), findsOneWidget); + await tester.tap(find.byKey(Key('Alamat'))); + await tester.pump(); + await tester.pump(); + await tester.pump(); }); - } diff --git a/test/layananDisabilitas_test.dart b/test/layananDisabilitas_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..fcad741486a6395985a732744de48ae43202752a --- /dev/null +++ b/test/layananDisabilitas_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/page/informasi/layananDisabilitas.dart'; + +void main() { + Widget buildTestableWidget(Widget widget) { + // https://docs.flutter.io/flutter/widgets/MediaQuery-class.html + return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); + } + + testWidgets('find informasi layanan disabilitas page', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(LayananDisabilitas())); + final scaffoldTextFieldKey = Key("Scaffold Text Field"); + + //positive test + //expect(find.byType(Container), findsNWidgets(4)); + expect(find.byType(Column), findsOneWidget); + expect(find.byType(Text), findsNWidgets(4)); + expect(find.byType(Icon), findsNWidgets(5)); + expect(find.byType(Row), findsNWidgets(3)); + expect(find.byType(Scaffold), findsOneWidget); + expect(find.byType(SizedBox), findsNWidgets(8)); + expect(find.byType(FlatButton), findsNWidgets(2)); + expect(find.byKey(scaffoldTextFieldKey), findsOneWidget); + + + //negative test + expect(find.byType(Flex), findsNothing); + expect(find.byType(BoxDecoration), findsNothing); + expect(find.byType(BorderSide), findsNothing); + expect(find.byType(TextStyle), findsNothing); + expect(find.text('regtrs pnydng disabilts'), findsNothing); + expect(find.text('informs pyndg disable'), findsNothing); + expect(find.text('informasshi sklh dngn dkgn disable'), findsNothing); + + }); + + + + +} diff --git a/test/list_sekolah_test.dart b/test/list_sekolah_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..7617d60a3db017e69621618f9a04596e395d6192 --- /dev/null +++ b/test/list_sekolah_test.dart @@ -0,0 +1,44 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/page/informasi/list_sekolah.dart'; + +void main() { + Widget buildTestableWidget(Widget widget) { + // https://docs.flutter.io/flutter/widgets/MediaQuery-class.html + return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); + } + + testWidgets("find a title app bar", (WidgetTester tester) async { + final textAppBar = Key("appbar-text-informasi-sekolah"); + await tester.pumpWidget(MaterialApp(home: ListSekolah())); + + expect(find.byKey(textAppBar), findsOneWidget); + expect(find.text("Sekolah dengan Dukungan Disabilitas"), findsOneWidget); + }); + + testWidgets('find inside filter page', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(ListSekolah())); + await tester.tap(find.byKey(Key('FilterButton'))); + await tester.pump(Duration(seconds: 1)); + expect(find.byType(Container), findsNWidgets(25)); + expect(find.byType(Row), findsNWidgets(17)); + expect(find.byType(Column), findsNWidgets(3)); + expect(find.byType(Text), findsNWidgets(22)); + expect(find.byType(Flex), findsNothing); + expect(find.text('jns fasilitas'), findsNothing); + expect(find.text('urutn'), findsNothing); + expect(find.text('hps smw'), findsNothing); + expect(find.byType(Scaffold), findsOneWidget); + expect(find.byType(Icon), findsNWidgets(3)); + await tester.tap(find.byKey(Key('FilterButton'))); + await tester.pump(); + }); +} diff --git a/test/login_test.dart b/test/login_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..6c3923c6325b25abef1a469dbec3a891a6b448e0 --- /dev/null +++ b/test/login_test.dart @@ -0,0 +1,42 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:ppl_disabilitas/network/network_interface.dart'; +import 'package:ppl_disabilitas/page/login/login.dart'; +//import 'package:http/http.dart' as http; + +class MockNetwork extends Mock implements NetworkInterface {} + +void main() { + MockNetwork mockNetwork; + setUp(() { + mockNetwork = MockNetwork(); + when(mockNetwork.get(isLogin: false, url: anyNamed('url'))) + .thenAnswer((_) async { + await Future.delayed(Duration(milliseconds: 50)); + return Future<dynamic>.value([ + { + "username": "dummy@mail.com", + "name": "Dummy", + "email": "dummy@mail.com", + "phone_number": "085222333444", + } + ]); + }); + }); + + testWidgets('Find Username Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Akun"); + await tester.pumpWidget(MaterialApp(home: Login())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + + testWidgets('Find Password Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Password"); + await tester.pumpWidget(MaterialApp(home: Login())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + +} \ No newline at end of file diff --git a/test/pencarian_test.dart b/test/pencarian_test.dart index db66d48281936f9d23071a6a5fd3ca0838684ae5..fe290abdff0e818537f832042ed535bc2150ce73 100644 --- a/test/pencarian_test.dart +++ b/test/pencarian_test.dart @@ -5,7 +5,6 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. - import 'dart:io'; import 'package:flutter/material.dart'; @@ -20,19 +19,18 @@ void main() { MockNetwork mockNetwork; setUp(() { mockNetwork = MockNetwork(); - when(mockNetwork.get(isLogin: false, url: anyNamed('url'))).thenAnswer((_) async { + when(mockNetwork.get(isLogin: false, url: anyNamed('url'))) + .thenAnswer((_) async { await Future.delayed(Duration(milliseconds: 50)); - return Future<dynamic>.value( - [ - { - "nama": "Coolidge", - "latitude": -23.7169139, - "longitude": -46.8498038, - "alamat": "74809 Hooker Drive", - "telepon": "+55 956 836 5799" - } - ] - ); + return Future<dynamic>.value([ + { + "nama": "Coolidge", + "latitude": -23.7169139, + "longitude": -46.8498038, + "alamat": "74809 Hooker Drive", + "telepon": "+55 956 836 5799" + } + ]); }); }); testWidgets('display list view in pencarian', (WidgetTester tester) async { @@ -40,7 +38,8 @@ void main() { expect(find.byKey(const Key("Text Field Mau Kemana")), findsOneWidget); //var textField = find.byKey(const Key("Text Field Mau Kemana")); //await tester.tap(textField); - await tester.enterText(find.byKey(const Key("Text Field Mau Kemana")), "Coolidge"); + await tester.enterText( + find.byKey(const Key("Text Field Mau Kemana")), "Coolidge"); await tester.pump(); expect(find.text("Hasil Pencarian"), findsOneWidget); @@ -60,13 +59,11 @@ void main() { expect(find.byKey(textFieldKey), findsOneWidget); }); - testWidgets('test textfield result', (WidgetTester tester) async { final textFieldKey = Key("Text Field Mau Kemana"); await tester.pumpWidget(MaterialApp(home: Pencarian())); await tester.enterText(find.byKey(textFieldKey), 'Mallory'); await tester.pump(); expect(find.text('Mallory'), findsOneWidget); -}); - + }); } diff --git a/test/registrasiInformasiLayananDisabilitas_test.dart b/test/registrasiInformasiLayananDisabilitas_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..285b6f7a9ecee751a70f297e338efee02f902fc2 --- /dev/null +++ b/test/registrasiInformasiLayananDisabilitas_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/page/registrasi_penyandang_disabilitas/registrasiInformasiLayananDisabilitas.dart'; + +void main() { + Widget buildTestableWidget(Widget widget) { + // https://docs.flutter.io/flutter/widgets/MediaQuery-class.html + return MediaQuery(data: MediaQueryData(), child: MaterialApp(home: widget)); + } + + testWidgets('find registrasi page', (WidgetTester tester) async { + // Provide the childWidget to the Container. + await tester.pumpWidget(buildTestableWidget(RegistrasiInformasiLayananDisabilitas())); + final scaffoldTextFieldKey = Key("Scaffold Text Field"); + + //positive test + expect(find.byType(Container), findsNWidgets(53)); + expect(find.byType(Column), findsNWidgets(10)); + expect(find.byType(Text), findsNWidgets(53)); + expect(find.byType(Icon), findsNWidgets(5)); + expect(find.byType(Row), findsNWidgets(6)); + expect(find.byType(Scaffold), findsOneWidget); + expect(find.byType(SizedBox), findsNWidgets(61)); + expect(find.byType(FlatButton), findsNWidgets(3)); + + + //negative test + expect(find.byType(FormField), findsNothing); + expect(find.byType(BoxDecoration), findsNothing); + expect(find.byType(Flex), findsNothing); + expect(find.byKey(scaffoldTextFieldKey), findsNothing); + expect(find.text('regtrs pnydng disabilts'), findsNothing); + expect(find.text('pengisi dt'), findsNothing); + expect(find.text('nm lngkp pnyndng'), findsNothing); + expect(find.text('jenis kelaMINNNN'), findsNothing); + + }); + + + + +} diff --git a/test/registrasi_test.dart b/test/registrasi_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..cfc2e29150660e95affaf7335b5b12c7e8789c46 --- /dev/null +++ b/test/registrasi_test.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/page/registrasi/registrasi.dart'; +//import 'package:ppl_disabilitas/model/user.dart'; +//import 'package:http/http.dart' as http; + +void main() { + testWidgets('Find Name Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Nama"); + await tester.pumpWidget(MaterialApp(home: Registrasi())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + + testWidgets('Find Phone Number Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Nomor Telepon"); + await tester.pumpWidget(MaterialApp(home: Registrasi())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + + testWidgets('Find Email Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Email"); + await tester.pumpWidget(MaterialApp(home: Registrasi())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + + testWidgets('Find Password Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Password"); + await tester.pumpWidget(MaterialApp(home: Registrasi())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + + testWidgets('Find Password Confirmation Text Field', (WidgetTester tester) async { + final textFieldKey = Key("Text Field Konfirmasi Password"); + await tester.pumpWidget(MaterialApp(home: Registrasi())); + expect(find.byKey(textFieldKey), findsOneWidget); + }); + +// test('Valid API end point for registering user', () async { +// User user = User( +// username: 'Dummy user', +// phonenumber: '081100000000', +// email: 'dummy@dummy.com', +// password: 'dummypassword' +// ); +// final result = await http.post( +// "https://my.api.mockaroo.com/register.json?key=095ee610&__method=POST", +// headers: {"content-type": "application/json"}, +// body: userToJson(user), +// ); +// expect(result.statusCode, 200); +// }); +} \ No newline at end of file diff --git a/test/validator_test.dart b/test/validator_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..4fcd0e0c5d510c2ee15f214026fae01f4e5787bb --- /dev/null +++ b/test/validator_test.dart @@ -0,0 +1,60 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:ppl_disabilitas/utils/validator.dart'; + +void main() { + test('Empty Name Test', () { + var result = FieldValidator.validateName(''); + expect(result, '*Wajib diisi'); + }); + + test('Valid Name Test', () { + var result = FieldValidator.validateName('Dummy User'); + expect(result, null); + }); + + test('Empty Phone Number Test', () { + var result = FieldValidator.validatePhoneNumber(''); + expect(result, '*Wajib diisi'); + }); + + test('Invalid Phone Number Test', () { + var result = FieldValidator.validatePhoneNumber('abcd1234'); + expect(result, '*Masukkan nomor telepon yang valid'); + }); + + test('Valid Phone Number Test', () { + var result = FieldValidator.validatePhoneNumber('081000000000'); + expect(result, null); + }); + + test('Empty Email Test', () { + var result = FieldValidator.validateEmail(''); + expect(result, '*Wajib diisi'); + }); + + test('Invalid Email Test', () { + var result = FieldValidator.validateEmail('dummy'); + expect(result, '*Masukkan email yang valid'); + }); + + test('Valid Email Test', () { + var result = FieldValidator.validateEmail('dummy@test.com'); + expect(result, null); + }); + + test('Empty Password Test', () { + var result = FieldValidator.validatePassword(''); + expect(result, '*Wajib diisi'); + }); + + test('Invalid Password Test', () { + var result = FieldValidator.validatePassword('ab456'); + expect(result, '*Password harus lebih dari 6 karakter'); + }); + + test('Valid Password Test', () { + var result = FieldValidator.validatePassword('abcd1234'); + expect(result, null); + }); + +} diff --git a/test/widget_test.dart b/test/widget_test.dart index 0a223972d3cab637dbed4c8c3d3ed006175fa98c..3859e88c0d7cd59deb7968c98120a43fa4d01b52 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -16,7 +16,7 @@ void main() { expect(find.byType(Scaffold), findsOneWidget); expect(find.byKey(Key("Stack")), findsOneWidget); expect(find.byType(TextFormField), findsOneWidget); - expect(find.byType(Icon), findsNWidgets(3)); + expect(find.byType(Icon), findsNWidgets(4)); expect(find.text('Kamu mau kemana?'), findsOneWidget); expect(find.text('Kamu mau kmn?'), findsNothing); expect(find.byKey(containerTextField), findsOneWidget); @@ -30,11 +30,17 @@ void main() { final googleMapKey = Key("Google Map"); await tester.pumpWidget(MaterialApp(home: Dashboard())); expect(find.byType(GoogleMap), findsOneWidget); - expect(find.byType(Container), findsNWidgets(3)); + expect(find.byType(Container), findsNWidgets(4)); expect(find.byKey(googleMapKey), findsOneWidget); expect(find.byKey(containerGoogleMap), findsOneWidget); }); + testWidgets('finds a floating in dashboard', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: Dashboard())); + expect(find.byKey(Key("FloatingActionButton")), findsOneWidget); + expect(find.byKey(Key("FloatingActionButtonnnn")), findsNothing); + }); + // testWidgets('finds a marker in google map', (WidgetTester tester) async { // await tester.pumpWidget(MaterialApp(home: Dashboard())); // expect(find.byType(Marker), findsOneWidget);