├── ios ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── .gitignore └── Podfile ├── fonts ├── trado.ttf └── tradbdo.ttf ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ └── Icon-512.png ├── manifest.json └── index.html ├── image ├── segitiga.png ├── lingkaran.png ├── masjid.svg ├── quran.svg ├── doa.svg └── praying.svg ├── android ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── values │ │ │ │ │ └── styles.xml │ │ │ │ └── values-night │ │ │ │ │ └── styles.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── my_alquran │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── lib ├── utils │ ├── alice_service.dart │ ├── http_overrides.dart │ ├── extensions.dart │ ├── indonesia_locale.dart │ ├── logging_interceptor.dart │ └── notification_handler.dart ├── ui │ ├── pages │ │ ├── surah │ │ │ ├── surah_arguments.dart │ │ │ ├── surah_pages.dart │ │ │ ├── surah_bottom_sheet_view.dart │ │ │ └── surah_detail_view.dart │ │ ├── hadits │ │ │ ├── hadits_people │ │ │ │ ├── hadits_people_arguments.dart │ │ │ │ └── hadits_people_page.dart │ │ │ ├── hadits_pages.dart │ │ │ └── hadits_view.dart │ │ ├── shalat │ │ │ ├── shalat_arguments.dart │ │ │ └── shalat_pages.dart │ │ ├── alquran │ │ │ ├── alquran_pages.dart │ │ │ └── alquran_view.dart │ │ ├── home │ │ │ ├── home_kajian.dart │ │ │ ├── home_menu.dart │ │ │ └── home_ngaji.dart │ │ └── custome_tab_bar.dart │ └── widget │ │ ├── loading_progress.dart │ │ └── custome_page.dart ├── config │ ├── route_name.dart │ ├── route_config.dart │ └── app_config.dart ├── bloc │ ├── b_shalat │ │ ├── shalat_event.dart │ │ ├── shalat_state.dart │ │ └── shalat_bloc.dart │ ├── b_alquran │ │ ├── alquran_event.dart │ │ ├── alquran_state.dart │ │ └── alquran_bloc.dart │ └── b_hadits │ │ ├── hadits_event.dart │ │ ├── hadits_state.dart │ │ └── hadits_bloc.dart ├── main_prod.dart ├── main_stag.dart ├── theme │ ├── theme_text.dart │ └── theme_color.dart ├── main_dev.dart ├── network │ ├── dio_client.dart │ ├── api_repository.dart │ └── api_service.dart ├── cubit │ └── c_hadits │ │ ├── hadits_state.dart │ │ └── hadits_cubit.dart ├── repositories │ └── hadits_repository │ │ └── list_hadits_repository.dart ├── main.dart ├── model │ ├── hadits │ │ ├── m_list_hadits.dart │ │ ├── m_list_hadits_people.dart │ │ └── m_list_hadits_range.dart │ ├── al-quran │ │ ├── m_list_alquran.dart │ │ └── m_detail_surah.dart │ └── m_list_shalat.dart └── global_bloc_observer.dart ├── .metadata ├── .gitignore ├── README.md ├── test └── widget_test.dart ├── pubspec.yaml └── pubspec.lock /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /fonts/trado.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/fonts/trado.ttf -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/web/favicon.png -------------------------------------------------------------------------------- /fonts/tradbdo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/fonts/tradbdo.ttf -------------------------------------------------------------------------------- /image/segitiga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/image/segitiga.png -------------------------------------------------------------------------------- /image/lingkaran.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/image/lingkaran.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/web/icons/Icon-512.png -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/utils/alice_service.dart: -------------------------------------------------------------------------------- 1 | // import 'package:alice/alice.dart'; 2 | // 3 | // Alice alice = Alice( 4 | // showNotification: true, 5 | // darkTheme: true, 6 | // ); 7 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rakafajars/my_alquran/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/my_alquran/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.my_alquran 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/ui/pages/surah/surah_arguments.dart: -------------------------------------------------------------------------------- 1 | class SurahArguments { 2 | final String idSurah; 3 | final String nameSurah; 4 | 5 | SurahArguments({ 6 | this.idSurah, 7 | this.nameSurah, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /lib/ui/widget/loading_progress.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class LoadingProgress extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | return Center( 7 | child: CircularProgressIndicator(), 8 | ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /lib/ui/pages/hadits/hadits_people/hadits_people_arguments.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class HaditsPeopleArguments { 4 | final String idPeople; 5 | final String namePeople; 6 | 7 | HaditsPeopleArguments({ 8 | @required this.idPeople, 9 | @required this.namePeople, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 4d7946a68d26794349189cf21b3f68cc6fe61dcb 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /lib/config/route_name.dart: -------------------------------------------------------------------------------- 1 | class RouteName { 2 | static final String home = '/home'; 3 | static final String listAlQuran = '/listAlQuran'; 4 | static final String detailSurah = '/detailSurah'; 5 | static final String listHadits = '/listHadits'; 6 | static final String listShalat = '/listShalat'; 7 | static final String ListHaditsPeople = '/listHaditsPeople'; 8 | } 9 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /lib/utils/http_overrides.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | // untuk handle SSL Handshake 4 | class MyHttpOverrides extends HttpOverrides { 5 | @override 6 | HttpClient createHttpClient(SecurityContext securityContext) { 7 | return super.createHttpClient(securityContext) 8 | ..badCertificateCallback = 9 | (X509Certificate cert, String host, int port) => true; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/ui/pages/shalat/shalat_arguments.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class ShalatArguments { 4 | final String nameCity; 5 | final String dateTime; 6 | final String time; 7 | final String dateTimeHijri; 8 | 9 | ShalatArguments({ 10 | @required this.nameCity, 11 | @required this.dateTime, 12 | @required this.time, 13 | @required this.dateTimeHijri, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/bloc/b_shalat/shalat_event.dart: -------------------------------------------------------------------------------- 1 | part of 'shalat_bloc.dart'; 2 | 3 | abstract class ShalatEvent extends Equatable { 4 | const ShalatEvent(); 5 | } 6 | 7 | class GetListShalatFromApi extends ShalatEvent { 8 | final String nameCity; 9 | final String dateTime; 10 | 11 | GetListShalatFromApi({ 12 | @required this.nameCity, 13 | @required this.dateTime, 14 | }); 15 | 16 | @override 17 | List get props => [nameCity, dateTime]; 18 | } 19 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/bloc/b_alquran/alquran_event.dart: -------------------------------------------------------------------------------- 1 | part of 'alquran_bloc.dart'; 2 | 3 | abstract class AlQuranEvent extends Equatable { 4 | const AlQuranEvent(); 5 | } 6 | 7 | class GetListAlQuranFromApi extends AlQuranEvent { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class GetDetailSurahFromApi extends AlQuranEvent { 13 | final String idSurah; 14 | 15 | GetDetailSurahFromApi({ 16 | @required this.idSurah, 17 | }); 18 | 19 | @override 20 | List get props => [idSurah]; 21 | } 22 | -------------------------------------------------------------------------------- /lib/main_prod.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/config/app_config.dart'; 4 | import 'package:my_alquran/global_bloc_observer.dart'; 5 | import 'package:my_alquran/main.dart'; 6 | import 'package:my_alquran/utils/notification_handler.dart'; 7 | 8 | void main() { 9 | Constants.setEnvironment(Environment.PROD); 10 | Bloc.observer = GlobalBlocObserver(); 11 | 12 | // initialNotification(); 13 | runApp(MyApp()); 14 | } 15 | -------------------------------------------------------------------------------- /lib/main_stag.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/config/app_config.dart'; 4 | import 'package:my_alquran/global_bloc_observer.dart'; 5 | import 'package:my_alquran/main.dart'; 6 | import 'package:my_alquran/utils/notification_handler.dart'; 7 | 8 | void main() { 9 | Constants.setEnvironment(Environment.STAG); 10 | Bloc.observer = GlobalBlocObserver(); 11 | 12 | // initialNotification(); 13 | runApp(MyApp()); 14 | } 15 | -------------------------------------------------------------------------------- /lib/theme/theme_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:google_fonts/google_fonts.dart'; 3 | 4 | TextStyle textFontWeight00 = GoogleFonts.poppins( 5 | fontWeight: FontWeight.w700, 6 | ); 7 | 8 | TextStyle googlePoppinsMedium = GoogleFonts.poppins( 9 | fontWeight: FontWeight.w500, 10 | ); 11 | 12 | TextStyle googlePoppinsRegular = GoogleFonts.poppins( 13 | fontWeight: FontWeight.w400, 14 | ); 15 | 16 | TextStyle arabicFont = TextStyle( 17 | fontFamily: 'Traditional Arabic', 18 | ); -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /lib/main_dev.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:my_alquran/config/app_config.dart'; 4 | import 'package:my_alquran/global_bloc_observer.dart'; 5 | import 'package:my_alquran/main.dart'; 6 | 7 | import 'utils/notification_handler.dart'; 8 | 9 | void main() { 10 | WidgetsFlutterBinding.ensureInitialized(); 11 | Bloc.observer = GlobalBlocObserver(); 12 | 13 | // initialNotification(); 14 | Constants.setEnvironment(Environment.DEV); 15 | runApp(MyApp()); 16 | } 17 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/ui/pages/alquran/alquran_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/bloc/b_alquran/alquran_bloc.dart'; 4 | import 'alquran_view.dart'; 5 | 6 | class InitialAlQuranPages extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return BlocProvider( 10 | create: (context) => AlQuranBloc() 11 | ..add( 12 | GetListAlQuranFromApi(), 13 | ), 14 | child: AlQuranView(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/network/dio_client.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:my_alquran/utils/alice_service.dart'; 3 | import 'package:my_alquran/utils/logging_interceptor.dart'; 4 | 5 | Dio dioClient() { 6 | final options = BaseOptions( 7 | // baseUrl: 'https://api.quran.sutanlab.id/', 8 | connectTimeout: 120000, 9 | receiveTimeout: 120000, 10 | contentType: 'application/json', 11 | ); 12 | 13 | var dio = Dio(options); 14 | dio.interceptors.add(LogginInterceptors()); 15 | // dio.interceptors.add(alice.getDioInterceptor()); 16 | 17 | return dio; 18 | } 19 | -------------------------------------------------------------------------------- /lib/theme/theme_color.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const Color primaryColor = Color(0xFFE21683); 4 | const Color whiteColor = Colors.white; 5 | const Color blackColor = Color(0xFF000000); 6 | const Color blackColor1 = Color(0xFF121212); 7 | const Color blackColor2 = Color(0xFF2B3247); 8 | const Color blueColor = Color(0xFF4E7D96); 9 | const Color blueColor1 = Color(0xFFCEECFD); 10 | const Color blueColor2 = Color(0xFF1778B0); 11 | const Color greyColor = Color(0xFFECECEC); 12 | const Color greyColor1 = Color(0xFFEDF3F7); 13 | const Color orangeColor = Color(0xFFFAC915); 14 | const Color orangeColor1 = Color(0xFFFAC915); -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my_alquran", 3 | "short_name": "my_alquran", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /lib/ui/pages/hadits/hadits_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/cubit/c_hadits/hadits_cubit.dart'; 4 | import 'file:///E:/Project/Project%20Baru/my_alquran/lib/repositories/hadits_repository/list_hadits_repository.dart'; 5 | import 'package:my_alquran/ui/pages/hadits/hadits_view.dart'; 6 | 7 | class InitialHaditsPages extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return BlocProvider( 11 | create:(context)=> HaditsCubit( 12 | repositry: ListHaditsRepositry(), 13 | ) , 14 | child: HaditsViewPage(), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /lib/bloc/b_shalat/shalat_state.dart: -------------------------------------------------------------------------------- 1 | part of 'shalat_bloc.dart'; 2 | 3 | abstract class ShalatState extends Equatable { 4 | const ShalatState(); 5 | } 6 | 7 | class ShalatInitial extends ShalatState { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class ShalatLoadedSuccess extends ShalatState { 13 | final ModelListShalat modelListShalat; 14 | 15 | ShalatLoadedSuccess({this.modelListShalat}); 16 | 17 | @override 18 | List get props => [modelListShalat]; 19 | } 20 | 21 | class ShalatLoadedError extends ShalatState { 22 | final String message; 23 | 24 | ShalatLoadedError({ 25 | @required this.message, 26 | }); 27 | 28 | @override 29 | List get props => [message]; 30 | } 31 | -------------------------------------------------------------------------------- /lib/cubit/c_hadits/hadits_state.dart: -------------------------------------------------------------------------------- 1 | part of 'hadits_cubit.dart'; 2 | 3 | abstract class HaditsState extends Equatable { 4 | const HaditsState(); 5 | } 6 | 7 | class ListHaditsLoadInProgress extends HaditsState { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class ListHaditsLoadedSuccess extends HaditsState { 13 | final ModeListHadits modeListHadits; 14 | 15 | ListHaditsLoadedSuccess({ 16 | @required this.modeListHadits, 17 | }); 18 | 19 | @override 20 | List get props => [modeListHadits]; 21 | } 22 | 23 | class ListHaditsLoadedError extends HaditsState { 24 | final String message; 25 | 26 | ListHaditsLoadedError({ 27 | @required this.message, 28 | }); 29 | @override 30 | List get props => [message]; 31 | } 32 | -------------------------------------------------------------------------------- /lib/repositories/hadits_repository/list_hadits_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:my_alquran/model/hadits/m_list_hadits.dart'; 3 | import 'package:my_alquran/network/dio_client.dart'; 4 | import 'package:my_alquran/utils/extensions.dart'; 5 | 6 | 7 | class ListHaditsRepositry { 8 | Dio get dio => dioClient(); 9 | 10 | Future getListHadits() async { 11 | String urlListHadits = 'https://api-hadits.azharimm.tk/books'; 12 | 13 | try { 14 | Response response = await dio.get( 15 | urlListHadits, 16 | ); 17 | return ModeListHadits.fromJson(response.data); 18 | } on DioError catch (e) { 19 | throw e.getErrorMessage(); 20 | } catch (error, stacktrace) { 21 | throw showException(error, stacktrace); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:my_alquran/config/route_config.dart'; 3 | import 'package:my_alquran/config/route_name.dart'; 4 | import 'package:my_alquran/ui/pages/home/home.dart'; 5 | import 'package:my_alquran/utils/alice_service.dart'; 6 | 7 | class MyApp extends StatelessWidget { 8 | // This widget is the root of your application. 9 | @override 10 | Widget build(BuildContext context) { 11 | return MaterialApp( 12 | // navigatorKey: alice.getNavigatorKey(), 13 | debugShowCheckedModeBanner: false, 14 | initialRoute: RouteName.home, 15 | routes: RouteConfig.routes, 16 | title: 'Flutter Starter Pack', 17 | theme: ThemeData( 18 | primarySwatch: Colors.blue, 19 | ), 20 | home: HomePages(), 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/ui/pages/shalat/shalat_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/bloc/b_shalat/shalat_bloc.dart'; 4 | import 'package:my_alquran/ui/pages/shalat/shalat_arguments.dart'; 5 | import 'package:my_alquran/ui/pages/shalat/shalat_view.dart'; 6 | 7 | class InitialShalatPages extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | final ShalatArguments arg = ModalRoute.of(context).settings.arguments; 11 | 12 | return BlocProvider( 13 | create: (context) => ShalatBloc() 14 | ..add( 15 | GetListShalatFromApi( 16 | nameCity: arg.nameCity, 17 | dateTime: arg.dateTime, 18 | ), 19 | ), 20 | child: ShalatView(), 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/ui/pages/surah/surah_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/bloc/b_alquran/alquran_bloc.dart'; 4 | import 'package:my_alquran/ui/pages/surah/surah_arguments.dart'; 5 | import 'package:my_alquran/ui/pages/surah/surah_detail_view.dart'; 6 | 7 | class InitialSurahPages extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | final SurahArguments arg = ModalRoute.of(context).settings.arguments; 11 | 12 | return BlocProvider( 13 | create: (context) => AlQuranBloc() 14 | ..add( 15 | GetDetailSurahFromApi( 16 | idSurah: arg.idSurah, 17 | ), 18 | ), 19 | child: SurahDetailView( 20 | nameSurah: arg.nameSurah, 21 | idSurah: arg.idSurah, 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/bloc/b_hadits/hadits_event.dart: -------------------------------------------------------------------------------- 1 | part of 'hadits_bloc.dart'; 2 | 3 | abstract class HaditsEvent extends Equatable { 4 | const HaditsEvent(); 5 | } 6 | 7 | class GetListHaditsPeople extends HaditsEvent { 8 | final String idPeople; 9 | 10 | GetListHaditsPeople({ 11 | this.idPeople, 12 | }); 13 | 14 | @override 15 | List get props => [idPeople]; 16 | } 17 | 18 | class GetPaginationListHaditsPeople extends HaditsEvent { 19 | final String idPeople; 20 | 21 | GetPaginationListHaditsPeople({ 22 | this.idPeople, 23 | }); 24 | 25 | @override 26 | List get props => [idPeople]; 27 | } 28 | 29 | class GetListHaditsPeopleRange extends HaditsEvent { 30 | final String idPeople; 31 | final String range; 32 | 33 | GetListHaditsPeopleRange({ 34 | @required this.idPeople, 35 | @required this.range, 36 | }); 37 | @override 38 | List get props => []; 39 | } 40 | -------------------------------------------------------------------------------- /lib/ui/pages/hadits/hadits_people/hadits_people_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:my_alquran/bloc/b_hadits/hadits_bloc.dart'; 4 | import 'package:my_alquran/ui/pages/hadits/hadits_people/hadits_people_arguments.dart'; 5 | import 'package:my_alquran/ui/pages/hadits/hadits_people/hadits_people_view.dart'; 6 | 7 | class InitialHaditsPeoplePages extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | final HaditsPeopleArguments arg = ModalRoute.of(context).settings.arguments; 11 | 12 | return BlocProvider( 13 | create: (context) => HaditsBloc() 14 | ..add( 15 | GetListHaditsPeople( 16 | idPeople: arg.idPeople, 17 | ), 18 | ), 19 | child: HaditsPeopleView( 20 | idPeople: arg.idPeople, 21 | ), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/ui/widget/custome_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:my_alquran/theme/theme_color.dart'; 4 | 5 | class CustomePage extends StatelessWidget { 6 | final Scaffold scaffold; 7 | final Color statusBarColor; 8 | final Brightness statusBarIconBrightness; 9 | final double Function(double) sy; 10 | 11 | const CustomePage({ 12 | Key key, 13 | this.scaffold, 14 | this.statusBarColor = primaryColor, 15 | this.statusBarIconBrightness = Brightness.light, 16 | this.sy, 17 | }) : super(key: key); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return AnnotatedRegion( 22 | value: SystemUiOverlayStyle( 23 | statusBarColor: statusBarColor, 24 | statusBarIconBrightness: statusBarIconBrightness, 25 | ), 26 | child: scaffold, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /lib/network/api_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'file:///E:/Project/Project%20Baru/my_alquran/lib/model/al-quran/m_detail_surah.dart'; 3 | import 'package:my_alquran/model/al-quran//m_list_alquran.dart'; 4 | import 'package:my_alquran/model/hadits/m_list_hadits_people.dart'; 5 | import 'package:my_alquran/model/hadits/m_list_hadits_range.dart'; 6 | import 'package:my_alquran/model/m_list_shalat.dart'; 7 | 8 | abstract class Repository { 9 | Future getListAlQuran(); 10 | 11 | Future getDetailSurah({ 12 | @required String idSurah, 13 | }); 14 | 15 | Future getListShalat({ 16 | @required String nameCity, 17 | @required String dateTime, 18 | }); 19 | 20 | Future getListHaditsPeople({ 21 | @required String idPeople, 22 | @required String page, 23 | }); 24 | 25 | Future getListHaditsRange({ 26 | @required String idPeople, 27 | @required String range, 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /lib/config/route_config.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:my_alquran/config/route_name.dart'; 3 | import 'package:my_alquran/ui/pages/custome_tab_bar.dart'; 4 | import 'package:my_alquran/ui/pages/hadits/hadits_pages.dart'; 5 | import 'package:my_alquran/ui/pages/hadits/hadits_people/hadits_people_page.dart'; 6 | import 'package:my_alquran/ui/pages/home/home.dart'; 7 | import 'package:my_alquran/ui/pages/shalat/shalat_pages.dart'; 8 | import 'package:my_alquran/ui/pages/surah/surah_pages.dart'; 9 | 10 | // Route Config disimpen di MaterialApp 11 | class RouteConfig { 12 | static final Map routes = { 13 | RouteName.home: (context) => HomePages(), 14 | RouteName.listAlQuran: (context) => CustomeTabBarAlQuran(), 15 | RouteName.detailSurah: (context) => InitialSurahPages(), 16 | RouteName.listHadits: (context) => InitialHaditsPages(), 17 | RouteName.listShalat: (context) => InitialShalatPages(), 18 | RouteName.ListHaditsPeople: (context) => InitialHaditsPeoplePages(), 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /lib/cubit/c_hadits/hadits_cubit.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:equatable/equatable.dart'; 3 | import 'package:meta/meta.dart'; 4 | import 'package:my_alquran/model/hadits/m_list_hadits.dart'; 5 | import 'file:///E:/Project/Project%20Baru/my_alquran/lib/repositories/hadits_repository/list_hadits_repository.dart'; 6 | 7 | part 'hadits_state.dart'; 8 | 9 | class HaditsCubit extends Cubit { 10 | final ListHaditsRepositry repositry; 11 | ModeListHadits modeListHadits; 12 | 13 | HaditsCubit({ 14 | @required this.repositry, 15 | }) : super(ListHaditsLoadInProgress()); 16 | 17 | Future getListHadits() async { 18 | try { 19 | emit( 20 | ListHaditsLoadInProgress(), 21 | ); 22 | 23 | modeListHadits = await repositry.getListHadits(); 24 | 25 | emit( 26 | ListHaditsLoadedSuccess(modeListHadits: modeListHadits), 27 | ); 28 | } catch (e) { 29 | emit( 30 | ListHaditsLoadedError( 31 | message: "$e", 32 | ), 33 | ); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/utils/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | 4 | extension DioErrorX on DioError { 5 | String getErrorMessage() { 6 | String _message = 'Server Error'; 7 | 8 | if (this.type == DioErrorType.RESPONSE) { 9 | if (this.response.statusCode == 401) { 10 | _message = 'Anda Belum Login'; 11 | } else if (this.response.statusCode == 500) { 12 | _message = 'Silahkan coba lagi'; 13 | } else { 14 | if (kReleaseMode) { 15 | _message = 'Error Koneksi'; 16 | } else { 17 | // Response langsung dari API 18 | _message = this.response.data["message"]; 19 | } 20 | } 21 | } else if (this.type == DioErrorType.CONNECT_TIMEOUT) 22 | _message = "Connection timeout"; 23 | else if (this.type == DioErrorType.DEFAULT) 24 | _message = "Kesalahan tdak terhubung"; 25 | 26 | return _message; 27 | } 28 | } 29 | 30 | String showException(final error, final stacktrace) { 31 | print("Exception occurred: $error stackTrace: $stacktrace"); 32 | return "Failed Get Data"; 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design 2 | https://dribbble.com/shots/15375120-Al-Hijrah-App 3 | 4 | # my_alquran 5 | 6 | ![Screenshot 2021-04-04 201536](https://user-images.githubusercontent.com/73903697/113510282-59380f80-9584-11eb-8c94-c77a113c2119.png) 7 | ![Screenshot 2021-04-04 201559](https://user-images.githubusercontent.com/73903697/113510285-5a693c80-9584-11eb-8c34-136e8ca6d145.png) 8 | ![Screenshot 2021-04-04 201613](https://user-images.githubusercontent.com/73903697/113510288-5b01d300-9584-11eb-8b75-2bee64370062.png) 9 | ![Screenshot 2021-04-04 201633](https://user-images.githubusercontent.com/73903697/113510289-5b9a6980-9584-11eb-9b75-4c5a343abc12.png) 10 | ![Screenshot 2021-04-04 201647](https://user-images.githubusercontent.com/73903697/113510292-5b9a6980-9584-11eb-95dd-78e85096dd2d.png) 11 | ![Screenshot 2021-04-04 201657](https://user-images.githubusercontent.com/73903697/113510294-5c330000-9584-11eb-8581-5811ade42282.png) 12 | 13 | 14 | ## API : 15 | al-quran : https://github.com/sutanlab/quran-api 16 | 17 | jadwal Shalat : https://waktusholat.org/api/docs/day 18 | 19 | hadits : https://github.com/azharimm/hadits-api (Azhari Muhammad M) 20 | -------------------------------------------------------------------------------- /lib/utils/indonesia_locale.dart: -------------------------------------------------------------------------------- 1 | import 'package:date_format/date_format.dart'; 2 | 3 | class IndonesiaLocale implements DateLocale { 4 | const IndonesiaLocale(); 5 | 6 | final List monthsShort = const [ 7 | 'Jan', 8 | 'Feb', 9 | 'Mar', 10 | 'Apr', 11 | 'Mei', 12 | 'Jun', 13 | 'Jul', 14 | 'Agu', 15 | 'Sep', 16 | 'Okt', 17 | 'Nov', 18 | 'Des' 19 | ]; 20 | 21 | final List monthsLong = const [ 22 | 'Januari', 23 | 'Februari', 24 | 'Maret', 25 | 'April', 26 | 'Mei', 27 | 'Juni', 28 | 'Juli', 29 | 'Agustus', 30 | 'September', 31 | 'Oktober', 32 | 'November', 33 | 'Desember' 34 | ]; 35 | 36 | final List daysShort = const [ 37 | 'Sen', 38 | 'Sel', 39 | 'Rab', 40 | 'Kam', 41 | 'Jum', 42 | 'Sab', 43 | 'Min' 44 | ]; 45 | 46 | final List daysLong = const [ 47 | 'Senin', 48 | 'Selasa', 49 | 'Rabu', 50 | 'Kamis', 51 | 'Jumat', 52 | 'Sabtu', 53 | 'Minggu' 54 | ]; 55 | 56 | @override 57 | String get am => "AM"; 58 | 59 | @override 60 | String get pm => "PM"; 61 | } -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:my_alquran/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/bloc/b_shalat/shalat_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:equatable/equatable.dart'; 5 | import 'package:meta/meta.dart'; 6 | import 'package:my_alquran/model/m_list_shalat.dart'; 7 | import 'package:my_alquran/network/api_repository.dart'; 8 | import 'package:my_alquran/network/api_service.dart'; 9 | 10 | part 'shalat_event.dart'; 11 | part 'shalat_state.dart'; 12 | 13 | class ShalatBloc extends Bloc { 14 | ShalatBloc() : super(ShalatInitial()); 15 | Repository _repository = ApiService(); 16 | ModelListShalat modelListShalat; 17 | 18 | @override 19 | Stream mapEventToState( 20 | ShalatEvent event, 21 | ) async* { 22 | if (event is GetListShalatFromApi) { 23 | yield ShalatInitial(); 24 | try { 25 | modelListShalat = await _repository.getListShalat( 26 | nameCity: event.nameCity, 27 | dateTime: event.dateTime, 28 | ); 29 | 30 | yield ShalatLoadedSuccess( 31 | modelListShalat: modelListShalat, 32 | ); 33 | } catch (e) { 34 | yield ShalatLoadedError( 35 | message: "$e", 36 | ); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/bloc/b_alquran/alquran_state.dart: -------------------------------------------------------------------------------- 1 | part of 'alquran_bloc.dart'; 2 | 3 | abstract class AlQuranState extends Equatable { 4 | const AlQuranState(); 5 | } 6 | 7 | class AlQuranLoadInProgress extends AlQuranState { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class AlQuranLoadedSuccess extends AlQuranState { 13 | final ModelListAlQuran modelListAlQuran; 14 | 15 | AlQuranLoadedSuccess({ 16 | @required this.modelListAlQuran, 17 | }); 18 | 19 | @override 20 | List get props => [modelListAlQuran]; 21 | } 22 | 23 | class AlQuranLoadedError extends AlQuranState { 24 | final String message; 25 | 26 | AlQuranLoadedError({ 27 | @required this.message, 28 | }); 29 | 30 | @override 31 | List get props => [message]; 32 | } 33 | 34 | class DetailSurahLoadInProgress extends AlQuranState { 35 | @override 36 | List get props => []; 37 | } 38 | 39 | class DetailSurahLoadedSuccess extends AlQuranState { 40 | final ModelDetailSurah modelDetailSurah; 41 | 42 | DetailSurahLoadedSuccess({ 43 | @required this.modelDetailSurah, 44 | }); 45 | @override 46 | List get props => [modelDetailSurah]; 47 | } 48 | 49 | class DetailSurahLoadedError extends AlQuranState { 50 | final String message; 51 | 52 | DetailSurahLoadedError({ 53 | @required this.message, 54 | }); 55 | 56 | @override 57 | List get props => [message]; 58 | } 59 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/config/app_config.dart: -------------------------------------------------------------------------------- 1 | enum Environment { 2 | DEV, 3 | STAG, 4 | PROD, 5 | } 6 | 7 | enum UserRole { 8 | GUEST, 9 | MEMBER, 10 | CHEMIST, 11 | DOCTOR, 12 | } 13 | 14 | class ConfigUrl { 15 | static const String baseUrl = "baseUrl"; 16 | 17 | static Map debugConstants = { 18 | baseUrl: "https://api-football.azharimm.tk/", 19 | }; 20 | static Map stagConstants = { 21 | baseUrl: "", 22 | }; 23 | static Map prodConstants = { 24 | baseUrl: "", 25 | }; 26 | } 27 | 28 | class Constants { 29 | static Map config; 30 | static UserRole _userRole; 31 | 32 | static void setEnvironment(Environment env) { 33 | switch (env) { 34 | case Environment.DEV: 35 | config = ConfigUrl.debugConstants; 36 | break; 37 | case Environment.STAG: 38 | config = ConfigUrl.stagConstants; 39 | break; 40 | case Environment.PROD: 41 | config = ConfigUrl.prodConstants; 42 | break; 43 | } 44 | } 45 | 46 | static String get baseUrl => config[ConfigUrl.baseUrl]; 47 | 48 | static void setUserRole(UserRole role) => _userRole = role; 49 | 50 | static UserRole get userRole => _userRole; 51 | } 52 | 53 | class ConstantUserRole { 54 | static const String KEY_USER_ROLE = "user-role"; 55 | 56 | static const String MEMBER = "member"; 57 | static const String GUEST = "guest"; 58 | static const String CHEMIST = "chemist"; 59 | static const String DOCTOR = "doctor"; 60 | } 61 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | my_alquran 30 | 31 | 32 | 33 | 36 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | my_alquran 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /lib/model/hadits/m_list_hadits.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | ModeListHadits modeListHaditsFromJson(String str) => ModeListHadits.fromJson(json.decode(str)); 4 | 5 | String modeListHaditsToJson(ModeListHadits data) => json.encode(data.toJson()); 6 | 7 | class ModeListHadits { 8 | ModeListHadits({ 9 | this.status, 10 | this.data, 11 | }); 12 | 13 | bool status; 14 | List data; 15 | 16 | ModeListHadits copyWith({ 17 | bool status, 18 | List data, 19 | }) => 20 | ModeListHadits( 21 | status: status ?? this.status, 22 | data: data ?? this.data, 23 | ); 24 | 25 | factory ModeListHadits.fromJson(Map json) => ModeListHadits( 26 | status: json["status"], 27 | data: List.from(json["data"].map((x) => Datum.fromJson(x))), 28 | ); 29 | 30 | Map toJson() => { 31 | "status": status, 32 | "data": List.from(data.map((x) => x.toJson())), 33 | }; 34 | } 35 | 36 | class Datum { 37 | Datum({ 38 | this.id, 39 | this.available, 40 | this.name, 41 | }); 42 | 43 | String id; 44 | int available; 45 | String name; 46 | 47 | Datum copyWith({ 48 | String id, 49 | int available, 50 | String name, 51 | }) => 52 | Datum( 53 | id: id ?? this.id, 54 | available: available ?? this.available, 55 | name: name ?? this.name, 56 | ); 57 | 58 | factory Datum.fromJson(Map json) => Datum( 59 | id: json["id"], 60 | available: json["available"], 61 | name: json["name"], 62 | ); 63 | 64 | Map toJson() => { 65 | "id": id, 66 | "available": available, 67 | "name": name, 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /lib/utils/logging_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:dio/dio.dart'; 4 | 5 | class LogginInterceptors extends Interceptor { 6 | @override 7 | Future onRequest(RequestOptions options) async { 8 | print( 9 | "--> ${options.method != null ? options.method.toUpperCase() : 'METHOD'} ${"" + (options.baseUrl ?? "") + (options.path ?? "")}", 10 | ); 11 | print("Headers: "); 12 | 13 | options.headers.forEach((key, value) => print('$key : $value')); 14 | if (options.queryParameters != null) { 15 | print("queryParameters:"); 16 | options.queryParameters.forEach((key, value) => print("$key : $value")); 17 | } 18 | if (options.data != null) { 19 | print("Body : ${options.data}"); 20 | } 21 | print( 22 | "--> END ${options.method != null ? options.method.toUpperCase() : 'METHOD'}", 23 | ); 24 | return options; 25 | } 26 | 27 | @override 28 | Future onError(DioError dioError) async { 29 | print( 30 | "<-- ${dioError.message} ${(dioError.response?.request != null ? (dioError.response.request.baseUrl + dioError.response.request.path) : 'URL')}"); 31 | print( 32 | "${dioError.response != null ? dioError.response.data : 'Unknown Error'}"); 33 | print("<-- End error"); 34 | } 35 | 36 | @override 37 | Future onResponse(Response response) async { 38 | print( 39 | "<-- ${response.statusCode} ${(response.request != null ? (response.request.baseUrl + response.request.path) : 'URL')}"); 40 | print("Headers:"); 41 | response.headers?.forEach((k, v) => print('$k: $v')); 42 | print("Response: ${response.data}"); 43 | print("<-- END HTTP"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/bloc/b_alquran/alquran_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:equatable/equatable.dart'; 5 | import 'package:meta/meta.dart'; 6 | import 'file:///E:/Project/Project%20Baru/my_alquran/lib/model/al-quran/m_detail_surah.dart'; 7 | import 'package:my_alquran/model/al-quran//m_list_alquran.dart'; 8 | import 'package:my_alquran/network/api_repository.dart'; 9 | import 'package:my_alquran/network/api_service.dart'; 10 | 11 | part 'alquran_event.dart'; 12 | part 'alquran_state.dart'; 13 | 14 | class AlQuranBloc extends Bloc { 15 | AlQuranBloc() : super(AlQuranLoadInProgress()); 16 | 17 | Repository _repository = ApiService(); 18 | ModelListAlQuran modelListAlQuran; 19 | ModelDetailSurah modelDetailSurah; 20 | 21 | @override 22 | Stream mapEventToState( 23 | AlQuranEvent event, 24 | ) async* { 25 | if (event is GetListAlQuranFromApi) { 26 | yield AlQuranLoadInProgress(); 27 | try { 28 | modelListAlQuran = await _repository.getListAlQuran(); 29 | 30 | yield AlQuranLoadedSuccess( 31 | modelListAlQuran: modelListAlQuran, 32 | ); 33 | } catch (e) { 34 | yield AlQuranLoadedError( 35 | message: "$e", 36 | ); 37 | } 38 | } else if (event is GetDetailSurahFromApi) { 39 | yield DetailSurahLoadInProgress(); 40 | try { 41 | modelDetailSurah = 42 | await _repository.getDetailSurah(idSurah: event.idSurah); 43 | 44 | yield DetailSurahLoadedSuccess( 45 | modelDetailSurah: modelDetailSurah, 46 | ); 47 | 48 | } catch (e) { 49 | yield DetailSurahLoadedError( 50 | message: "$e", 51 | ); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/model/hadits/m_list_hadits_people.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | ModelListHaditsPeople modelListHaditsPeopleFromJson(String str) => ModelListHaditsPeople.fromJson(json.decode(str)); 4 | 5 | String modelListHaditsPeopleToJson(ModelListHaditsPeople data) => json.encode(data.toJson()); 6 | 7 | class ModelListHaditsPeople { 8 | ModelListHaditsPeople({ 9 | this.status, 10 | this.data, 11 | }); 12 | 13 | bool status; 14 | Data data; 15 | 16 | factory ModelListHaditsPeople.fromJson(Map json) => ModelListHaditsPeople( 17 | status: json["status"], 18 | data: Data.fromJson(json["data"]), 19 | ); 20 | 21 | Map toJson() => { 22 | "status": status, 23 | "data": data.toJson(), 24 | }; 25 | } 26 | 27 | class Data { 28 | Data({ 29 | this.page, 30 | this.limit, 31 | this.lastPage, 32 | this.hadits, 33 | }); 34 | 35 | int page; 36 | int limit; 37 | int lastPage; 38 | List hadits; 39 | 40 | factory Data.fromJson(Map json) => Data( 41 | page: json["page"], 42 | limit: json["limit"], 43 | lastPage: json["last_page"], 44 | hadits: List.from(json["hadits"].map((x) => Hadit.fromJson(x))), 45 | ); 46 | 47 | Map toJson() => { 48 | "page": page, 49 | "limit": limit, 50 | "last_page": lastPage, 51 | "hadits": List.from(hadits.map((x) => x.toJson())), 52 | }; 53 | } 54 | 55 | class Hadit { 56 | Hadit({ 57 | this.number, 58 | this.arab, 59 | this.id, 60 | }); 61 | 62 | int number; 63 | String arab; 64 | String id; 65 | 66 | factory Hadit.fromJson(Map json) => Hadit( 67 | number: json["number"], 68 | arab: json["arab"], 69 | id: json["id"], 70 | ); 71 | 72 | Map toJson() => { 73 | "number": number, 74 | "arab": arab, 75 | "id": id, 76 | }; 77 | } 78 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 30 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.example.my_alquran" 38 | minSdkVersion 23 39 | targetSdkVersion 30 40 | versionCode flutterVersionCode.toInteger() 41 | versionName flutterVersionName 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 59 | } 60 | -------------------------------------------------------------------------------- /lib/global_bloc_observer.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | 3 | class GlobalBlocObserver extends BlocObserver { 4 | // Pada method onEvent di muculkan ketika ada aksi event ke salah satu Bloc, 5 | // jadi untuk semua event di semua state management Bloc akan bisa dilihat disini. 6 | @override 7 | void onEvent(Bloc bloc, Object event) { 8 | print('onEvent $event'); 9 | super.onEvent(bloc, event); 10 | } 11 | 12 | //Pada method onTransition dipanggil ketika ada perubahan state dari 13 | // Bloc lewat event trigger .add() dan di handle di mapEventToState pada Bloc. 14 | @override 15 | void onTransition(Bloc bloc, Transition transition) { 16 | print('onTransition $transition'); 17 | super.onTransition(bloc, transition); 18 | } 19 | 20 | // Pada method onChange ketika ada perubahan state pada StateManagement Cubit. 21 | @override 22 | void onChange(Cubit cubit, Change change) { 23 | print('onChange ${cubit.runtimeType}' 24 | 'From: ${change?.currentState}' 25 | 'To: ${change.nextState}'); 26 | super.onChange(cubit, change); 27 | } 28 | // Method ini dipanggil ketika Cubit telah di close 29 | // atau dispose oleh sistem atau juga user. Misal jika user 30 | // pindah halaman dengan replace halaman sebelumnya dengan Provider 31 | // pada halaman yang di replace, maka method onClose ini dijalankan. 32 | @override 33 | void onClose(Cubit cubit) { 34 | print('Close ${cubit.runtimeType}'); 35 | super.onClose(cubit); 36 | } 37 | 38 | // Pada method onCreate ini, dimana State Management Bloc ataupun Cubit di 39 | // Flutter dibuat/di inisialisasikan saat pertama kalinya. 40 | @override 41 | void onCreate(Cubit cubit) { 42 | print('Create ${cubit.runtimeType}'); 43 | super.onCreate(cubit); 44 | } 45 | 46 | // Method ini dipanggil ketika terjadi error pada salah satu state management di Bloc 47 | @override 48 | void onError(Cubit cubit, Object error, StackTrace stackTrace) { 49 | print('Error in : ${cubit.runtimeType}' 50 | 'Error: $error' 51 | 'StackTrace: $stackTrace'); 52 | super.onError(cubit, error, stackTrace); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/model/hadits/m_list_hadits_range.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | ModelListHaditsRange modelListHaditsRangeFromJson(String str) => 4 | ModelListHaditsRange.fromJson(json.decode(str)); 5 | 6 | String modelListHaditsRangeToJson(ModelListHaditsRange data) => 7 | json.encode(data.toJson()); 8 | 9 | class ModelListHaditsRange { 10 | ModelListHaditsRange({ 11 | this.status, 12 | this.data, 13 | }); 14 | 15 | bool status; 16 | Data data; 17 | 18 | factory ModelListHaditsRange.fromJson(Map json) => 19 | ModelListHaditsRange( 20 | status: json["status"], 21 | data: Data.fromJson(json["data"]), 22 | ); 23 | 24 | Map toJson() => { 25 | "status": status, 26 | "data": data.toJson(), 27 | }; 28 | } 29 | 30 | class Data { 31 | Data({ 32 | this.start, 33 | this.end, 34 | this.total, 35 | this.book, 36 | this.hadits, 37 | }); 38 | 39 | int start; 40 | int end; 41 | int total; 42 | String book; 43 | List hadits; 44 | 45 | factory Data.fromJson(Map json) => Data( 46 | start: json["start"], 47 | end: json["end"], 48 | total: json["total"], 49 | book: json["book"], 50 | hadits: List.from( 51 | json["hadits"].map((x) => HaditsRange.fromJson(x))), 52 | ); 53 | 54 | Map toJson() => { 55 | "start": start, 56 | "end": end, 57 | "total": total, 58 | "book": book, 59 | "hadits": List.from(hadits.map((x) => x.toJson())), 60 | }; 61 | } 62 | 63 | class HaditsRange { 64 | HaditsRange({ 65 | this.number, 66 | this.arab, 67 | this.id, 68 | }); 69 | 70 | int number; 71 | String arab; 72 | String id; 73 | 74 | factory HaditsRange.fromJson(Map json) => HaditsRange( 75 | number: json["number"], 76 | arab: json["arab"], 77 | id: json["id"], 78 | ); 79 | 80 | Map toJson() => { 81 | "number": number, 82 | "arab": arab, 83 | "id": id, 84 | }; 85 | } 86 | -------------------------------------------------------------------------------- /lib/bloc/b_hadits/hadits_state.dart: -------------------------------------------------------------------------------- 1 | part of 'hadits_bloc.dart'; 2 | 3 | abstract class HaditsState extends Equatable { 4 | const HaditsState(); 5 | } 6 | 7 | class HaditsInitial extends HaditsState { 8 | @override 9 | List get props => []; 10 | } 11 | 12 | class ListHaditsPeopleLoadInProgress extends HaditsState { 13 | @override 14 | List get props => []; 15 | } 16 | 17 | class ListHaditsPeopleLoadedSuccess extends HaditsState { 18 | final ModelListHaditsPeople modelListHaditsPeople; 19 | final List hadits; 20 | final String page; 21 | final bool hasReachedMax; 22 | 23 | ListHaditsPeopleLoadedSuccess({ 24 | @required this.modelListHaditsPeople, 25 | @required this.hadits, 26 | @required this.page, 27 | @required this.hasReachedMax, 28 | }); 29 | 30 | ListHaditsPeopleLoadedSuccess copyWith({ 31 | final ModelListHaditsPeople modelListHaditsPeople, 32 | final List hadits, 33 | final String page, 34 | final bool hasReachedMax, 35 | }) { 36 | return ListHaditsPeopleLoadedSuccess( 37 | modelListHaditsPeople: modelListHaditsPeople, 38 | hadits: hadits, 39 | page: page, 40 | hasReachedMax: hasReachedMax ?? this.hasReachedMax, 41 | ); 42 | } 43 | 44 | @override 45 | List get props => [ 46 | modelListHaditsPeople, 47 | hadits, 48 | page, 49 | hasReachedMax, 50 | ]; 51 | } 52 | 53 | class ListHaditsPeopleLoadedEmpty extends HaditsState { 54 | @override 55 | List get props => []; 56 | } 57 | 58 | class ListHaditsPeopleLoadedError extends HaditsState { 59 | final String message; 60 | 61 | ListHaditsPeopleLoadedError({ 62 | @required this.message, 63 | }); 64 | @override 65 | List get props => [message]; 66 | } 67 | 68 | class ListHaditsRangeLoadInProgress extends HaditsState { 69 | @override 70 | List get props => []; 71 | } 72 | 73 | class ListHaditsRangeLoadedSuccess extends HaditsState { 74 | final ModelListHaditsRange modelListHaditsRange; 75 | 76 | ListHaditsRangeLoadedSuccess({ 77 | @required this.modelListHaditsRange, 78 | }); 79 | 80 | @override 81 | List get props => [modelListHaditsRange]; 82 | } 83 | 84 | class ListHaditsRangeLoadedError extends HaditsState { 85 | final String message; 86 | 87 | ListHaditsRangeLoadedError({ 88 | @required this.message, 89 | }); 90 | @override 91 | List get props => [message]; 92 | } 93 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: my_alquran 2 | description: A new Flutter application. 3 | 4 | publish_to: 'none' 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.7.0 <3.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | 16 | # The following adds the Cupertino Icons font to your application. 17 | # Use with the CupertinoIcons class for iOS style icons. 18 | cupertino_icons: ^1.0.2 19 | # alice: ^0.1.12 20 | bloc: ^6.1.3 21 | dio: ^3.0.10 22 | equatable: ^2.0.0 23 | flutter_bloc: ^6.1.3 24 | # flutter_local_notifications: ^4.0.1+2 25 | google_fonts: 1.1.2 26 | relative_scale: ^2.0.0 27 | audioplayers: ^0.18.1 28 | modal_bottom_sheet: ^2.0.0 29 | share: ^2.0.1 30 | flutter_svg: ^0.19.3 31 | intl: ^0.17.0 32 | geolocator: ^7.0.1 33 | geocoding: ^2.0.0 34 | date_format: ^2.0.2 35 | hijri: ^2.0.3 36 | rxdart: ^0.26.0 37 | numberpicker: ^2.0.1 38 | 39 | 40 | dev_dependencies: 41 | flutter_test: 42 | sdk: flutter 43 | 44 | # For information on the generic Dart part of this file, see the 45 | # following page: https://dart.dev/tools/pub/pubspec 46 | 47 | # The following section is specific to Flutter. 48 | flutter: 49 | 50 | 51 | uses-material-design: true 52 | 53 | assets: 54 | - image/ 55 | 56 | # An image asset can refer to one or more resolution-specific "variants", see 57 | # https://flutter.dev/assets-and-images/#resolution-aware. 58 | 59 | # For details regarding adding assets from package dependencies, see 60 | # https://flutter.dev/assets-and-images/#from-packages 61 | 62 | # To add custom fonts to your application, add a fonts section here, 63 | # in this "flutter" section. Each entry in this list should have a 64 | # "family" key with the font family name, and a "fonts" key with a 65 | # list giving the asset and other descriptors for the font. For 66 | # example: 67 | # fonts: 68 | # - family: Traditional Arabic 69 | # fonts: 70 | # - asset: fonts/tradbdo.ttf 71 | # - asset: fonts/trado.ttf 72 | 73 | fonts: 74 | - family: Traditional Arabic 75 | fonts: 76 | - asset: fonts/tradbdo.ttf 77 | - asset: fonts/trado.ttf 78 | 79 | # - family: Trajan Pro 80 | # fonts: 81 | # - asset: fonts/TrajanPro.ttf 82 | # - asset: fonts/TrajanPro_Bold.ttf 83 | # weight: 700 84 | # 85 | # For details regarding fonts from package dependencies, 86 | # see https://flutter.dev/custom-fonts/#from-packages 87 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 10 | 17 | 21 | 25 | 30 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /lib/utils/notification_handler.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter_local_notifications/flutter_local_notifications.dart'; 2 | // 3 | // initialNotification() async { 4 | // FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = 5 | // FlutterLocalNotificationsPlugin(); 6 | // 7 | // const AndroidInitializationSettings initializationSettingsAndroid = 8 | // AndroidInitializationSettings('@mipmap/ic_launcher'); 9 | // final IOSInitializationSettings initializationSettingsIOS = 10 | // IOSInitializationSettings(); 11 | // 12 | // final InitializationSettings initializationSettings = InitializationSettings( 13 | // android: initializationSettingsAndroid, 14 | // iOS: initializationSettingsIOS, 15 | // ); 16 | // 17 | // flutterLocalNotificationsPlugin.initialize(initializationSettings); 18 | // } 19 | // 20 | // Future myBackgroundMessageHandler(Map message) async { 21 | // print('onBackgroundMessage: $message'); 22 | // 23 | // if (message.containsKey('notification')) { 24 | // // Handle notification message 25 | // final dynamic notification = message['notification']; 26 | // print('raka notif $notification'); 27 | // showNotification( 28 | // notificationsPlugin: FlutterLocalNotificationsPlugin(), 29 | // title: notification['title'] ?? message['data']['title'], 30 | // body: notification['body'] ?? message['data']['body'], 31 | // ); 32 | // } else { 33 | // // Handle data message 34 | // final dynamic data = message['data']; 35 | // print('raka $data'); 36 | // showNotification( 37 | // notificationsPlugin: FlutterLocalNotificationsPlugin(), 38 | // title: data['title'], 39 | // body: data['body'], 40 | // ); 41 | // } 42 | // 43 | // // Or do other work. 44 | // } 45 | // 46 | // showNotification({ 47 | // FlutterLocalNotificationsPlugin notificationsPlugin, 48 | // String title, 49 | // String body, 50 | // }) async { 51 | // var android = AndroidNotificationDetails( 52 | // 'id', 53 | // 'channel ', 54 | // 'description', 55 | // priority: Priority.high, 56 | // importance: Importance.max, 57 | // sound: RawResourceAndroidNotificationSound('shopee_sound'), 58 | // ); 59 | // var iOS = IOSNotificationDetails(); 60 | // 61 | // var platform = new NotificationDetails( 62 | // android: android, 63 | // iOS: iOS, 64 | // ); 65 | // 66 | // var id = DateTime.now().millisecond; 67 | // 68 | // await notificationsPlugin.show( 69 | // id, 70 | // title, 71 | // body, 72 | // platform, 73 | // ); 74 | // } 75 | -------------------------------------------------------------------------------- /lib/ui/pages/home/home_kajian.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:my_alquran/theme/theme_color.dart'; 3 | import 'package:my_alquran/theme/theme_text.dart'; 4 | import 'package:relative_scale/relative_scale.dart'; 5 | 6 | class HomeKajian extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return RelativeBuilder(builder: (context, height, width, sy, sx) { 10 | return Padding( 11 | padding: EdgeInsets.only( 12 | right: 16, 13 | ), 14 | child: Container( 15 | height: sy(100), 16 | width: sy(185), 17 | padding: EdgeInsets.only( 18 | left: 16, 19 | ), 20 | decoration: BoxDecoration( 21 | color: whiteColor, 22 | borderRadius: BorderRadius.all( 23 | Radius.circular( 24 | 8.0, 25 | ), 26 | ), 27 | ), 28 | child: Column( 29 | crossAxisAlignment: CrossAxisAlignment.start, 30 | mainAxisAlignment: MainAxisAlignment.center, 31 | children: [ 32 | Container( 33 | height: sy(20), 34 | width: sy(80), 35 | decoration: BoxDecoration( 36 | color: Color(0xFFDEEAF0), 37 | borderRadius: BorderRadius.all( 38 | Radius.circular( 39 | 8.0, 40 | ), 41 | ), 42 | ), 43 | alignment: Alignment.center, 44 | child: Text( 45 | 'Kajian Fiqih', 46 | style: googlePoppinsMedium.copyWith( 47 | fontSize: 8, 48 | color: Color(0xFF87A9BB), 49 | ), 50 | ), 51 | ), 52 | SizedBox( 53 | height: 8, 54 | ), 55 | Text( 56 | 'Persiapan Bulan\nRamadhan', 57 | style: googlePoppinsMedium.copyWith( 58 | fontSize: 14, 59 | color: Color(0xFF2B3247), 60 | ), 61 | ), 62 | SizedBox( 63 | height: 8, 64 | ), 65 | Text( 66 | '12 April 2021', 67 | style: googlePoppinsRegular.copyWith( 68 | fontSize: 10, 69 | color: Color(0xFF2B3247), 70 | ), 71 | ), 72 | ], 73 | ), 74 | ), 75 | ); 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/network/api_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:dio/dio.dart'; 4 | import 'file:///E:/Project/Project%20Baru/my_alquran/lib/model/al-quran/m_detail_surah.dart'; 5 | import 'package:my_alquran/model/al-quran//m_list_alquran.dart'; 6 | import 'package:my_alquran/model/hadits/m_list_hadits_people.dart'; 7 | import 'package:my_alquran/model/hadits/m_list_hadits_range.dart'; 8 | import 'package:my_alquran/model/m_list_shalat.dart'; 9 | import 'package:my_alquran/network/api_repository.dart'; 10 | import 'package:my_alquran/network/dio_client.dart'; 11 | import 'package:my_alquran/utils/extensions.dart'; 12 | 13 | class ApiService implements Repository { 14 | Response response; 15 | String baseUrlAlQuran = 'https://api.quran.sutanlab.id'; 16 | String baseUrlShalat = 'https://api.pray.zone/v2/times'; 17 | String urlListHaditsPeople = 'https://api-hadits.azharimm.tk/books'; 18 | 19 | Dio get dio => dioClient(); 20 | 21 | @override 22 | Future getListAlQuran() async { 23 | try { 24 | response = await dio.get( 25 | '$baseUrlAlQuran/surah', 26 | ); 27 | return ModelListAlQuran.fromJson( 28 | json.decode( 29 | response.data, 30 | ), 31 | ); 32 | } on DioError catch (e) { 33 | throw e.getErrorMessage(); 34 | } catch (error, stacktrace) { 35 | throw showException(error, stacktrace); 36 | } 37 | } 38 | 39 | @override 40 | Future getDetailSurah({ 41 | idSurah, 42 | }) async { 43 | try { 44 | response = await dio.get( 45 | '$baseUrlAlQuran/surah/$idSurah', 46 | ); 47 | 48 | return ModelDetailSurah.fromJson( 49 | json.decode( 50 | response.data, 51 | ), 52 | ); 53 | } on DioError catch (e) { 54 | throw e.getErrorMessage(); 55 | } catch (error, stacktrace) { 56 | throw showException(error, stacktrace); 57 | } 58 | } 59 | 60 | @override 61 | Future getListShalat({ 62 | nameCity, 63 | dateTime, 64 | }) async { 65 | try { 66 | response = await dio.get( 67 | '$baseUrlShalat/today.json?city=$nameCity&dat=$dateTime', 68 | ); 69 | 70 | return ModelListShalat.fromJson(response.data); 71 | } on DioError catch (e) { 72 | throw e.getErrorMessage(); 73 | } catch (error, stacktrace) { 74 | throw showException(error, stacktrace); 75 | } 76 | } 77 | 78 | @override 79 | Future getListHaditsPeople( 80 | {String idPeople, String page}) async { 81 | try { 82 | Response response = await dio.get( 83 | '$urlListHaditsPeople/$idPeople?page=$page', 84 | ); 85 | 86 | return ModelListHaditsPeople.fromJson( 87 | response.data, 88 | ); 89 | } on DioError catch (e) { 90 | throw e.getErrorMessage(); 91 | } catch (error, stacktrace) { 92 | throw showException(error, stacktrace); 93 | } 94 | } 95 | 96 | @override 97 | Future getListHaditsRange({ 98 | String range, 99 | String idPeople, 100 | }) async { 101 | try { 102 | Response response = await dio.get( 103 | '$urlListHaditsPeople/range/$idPeople?range=$range', 104 | ); 105 | 106 | return ModelListHaditsRange.fromJson( 107 | response.data, 108 | ); 109 | } on DioError catch (e) { 110 | throw e.response.data["error"]; 111 | } catch (error, stacktrace) { 112 | throw showException(error, stacktrace); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /image/masjid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /image/quran.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/bloc/b_hadits/hadits_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:equatable/equatable.dart'; 5 | import 'package:meta/meta.dart'; 6 | import 'package:my_alquran/model/hadits/m_list_hadits_people.dart'; 7 | import 'package:my_alquran/model/hadits/m_list_hadits_range.dart'; 8 | import 'package:my_alquran/network/api_repository.dart'; 9 | import 'package:my_alquran/network/api_service.dart'; 10 | import 'package:rxdart/rxdart.dart'; 11 | 12 | part 'hadits_event.dart'; 13 | part 'hadits_state.dart'; 14 | 15 | class HaditsBloc extends Bloc { 16 | Repository _repository = ApiService(); 17 | ModelListHaditsPeople modelListHaditsPeople; 18 | ModelListHaditsRange modelListHaditsRange; 19 | 20 | HaditsBloc() : super(HaditsInitial()); 21 | 22 | @override 23 | Stream> transformEvents( 24 | Stream events, 25 | TransitionFunction transitionFn, 26 | ) { 27 | return super.transformEvents( 28 | events.debounceTime(const Duration(milliseconds: 500)), 29 | transitionFn, 30 | ); 31 | } 32 | 33 | @override 34 | Stream mapEventToState( 35 | HaditsEvent event, 36 | ) async* { 37 | HaditsState currentState = state; 38 | if (event is GetListHaditsPeople) { 39 | yield ListHaditsPeopleLoadInProgress(); 40 | try { 41 | modelListHaditsPeople = await _repository.getListHaditsPeople( 42 | page: '1', 43 | idPeople: event.idPeople, 44 | ); 45 | 46 | if (modelListHaditsPeople.data.hadits.length == 0) { 47 | yield ListHaditsPeopleLoadedEmpty(); 48 | } else { 49 | yield ListHaditsPeopleLoadedSuccess( 50 | modelListHaditsPeople: modelListHaditsPeople, 51 | hadits: modelListHaditsPeople.data.hadits, 52 | page: modelListHaditsPeople.data.page.toString(), 53 | hasReachedMax: modelListHaditsPeople.data.limit > 6 ? false : true, 54 | ); 55 | } 56 | } catch (e) { 57 | yield ListHaditsPeopleLoadedError( 58 | message: "$e", 59 | ); 60 | } 61 | } 62 | if (event is GetPaginationListHaditsPeople) { 63 | print('Masuk ga'); 64 | 65 | if (currentState is ListHaditsPeopleLoadedSuccess && 66 | !currentState.hasReachedMax) { 67 | print('Masuk Sini'); 68 | try { 69 | int currentPage = int.parse(currentState.page); 70 | 71 | modelListHaditsPeople = await _repository.getListHaditsPeople( 72 | page: "${currentPage + 1}", 73 | idPeople: event.idPeople, 74 | ); 75 | print(currentPage); 76 | 77 | yield modelListHaditsPeople.data.hadits.isEmpty 78 | ? currentState.copyWith( 79 | hadits: currentState.hadits, 80 | modelListHaditsPeople: currentState.modelListHaditsPeople, 81 | hasReachedMax: true, 82 | page: modelListHaditsPeople.data.page.toString(), 83 | ) 84 | : ListHaditsPeopleLoadedSuccess( 85 | modelListHaditsPeople: currentState.modelListHaditsPeople, 86 | hadits: 87 | currentState.hadits + modelListHaditsPeople.data.hadits, 88 | page: modelListHaditsPeople.data.page.toString(), 89 | hasReachedMax: false, 90 | ); 91 | } catch (e) { 92 | yield ListHaditsPeopleLoadedError( 93 | message: "$e", 94 | ); 95 | } 96 | } 97 | } 98 | if (event is GetListHaditsPeopleRange) { 99 | yield ListHaditsRangeLoadInProgress(); 100 | try { 101 | modelListHaditsRange = await _repository.getListHaditsRange( 102 | idPeople: event.idPeople, 103 | range: event.range, 104 | ); 105 | 106 | yield ListHaditsRangeLoadedSuccess( 107 | modelListHaditsRange: modelListHaditsRange, 108 | ); 109 | } catch (e) { 110 | yield ListHaditsRangeLoadedError( 111 | message: "$e", 112 | ); 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /image/doa.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib/ui/pages/home/home_menu.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:my_alquran/config/route_name.dart'; 4 | import 'package:my_alquran/theme/theme_color.dart'; 5 | import 'package:my_alquran/theme/theme_text.dart'; 6 | import 'package:my_alquran/ui/pages/shalat/shalat_arguments.dart'; 7 | import 'package:relative_scale/relative_scale.dart'; 8 | 9 | class HomeMenu extends StatelessWidget { 10 | final String nameCity; 11 | final String dateTime; 12 | final String time; 13 | final String dateTimeHijri; 14 | 15 | const HomeMenu({ 16 | Key key, 17 | @required this.nameCity, 18 | @required this.dateTime, 19 | @required this.time, 20 | @required this.dateTimeHijri, 21 | }) : super(key: key); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return RelativeBuilder( 26 | builder: (context, height, width, sy, sx) { 27 | return Container( 28 | height: sy(116), 29 | margin: EdgeInsets.only( 30 | top: 24, 31 | ), 32 | width: double.infinity, 33 | child: ListView( 34 | padding: EdgeInsets.only( 35 | left: 20, 36 | ), 37 | shrinkWrap: true, 38 | scrollDirection: Axis.horizontal, 39 | children: [ 40 | menuButton( 41 | image: 'image/quran.svg', 42 | titleName: "Al-Qur'an &\nHadits", 43 | onTap: () { 44 | Navigator.pushNamed( 45 | context, 46 | RouteName.listAlQuran, 47 | ); 48 | }, 49 | ), 50 | menuButton( 51 | image: 'image/praying.svg', 52 | titleName: "Jadwal\nSholat", 53 | onTap: () { 54 | Navigator.pushNamed( 55 | context, 56 | RouteName.listShalat, 57 | arguments: ShalatArguments( 58 | nameCity: nameCity, 59 | dateTime: dateTime, 60 | dateTimeHijri: dateTimeHijri, 61 | time: time 62 | ), 63 | ); 64 | }, 65 | ), 66 | menuButton( 67 | image: 'image/doa.svg', 68 | titleName: "Doa-Doa", 69 | ), 70 | menuButton( 71 | image: 'image/masjid.svg', 72 | titleName: "Masjid\nTerdekat", 73 | ), 74 | ], 75 | ), 76 | ); 77 | }, 78 | ); 79 | } 80 | 81 | Widget menuButton({ 82 | String image, 83 | String titleName, 84 | VoidCallback onTap, 85 | }) { 86 | return RelativeBuilder( 87 | builder: (context, height, width, sy, sx) { 88 | return Padding( 89 | padding: EdgeInsets.only( 90 | right: 16, 91 | ), 92 | child: Column( 93 | mainAxisAlignment: MainAxisAlignment.center, 94 | children: [ 95 | GestureDetector( 96 | onTap: onTap, 97 | child: Stack( 98 | alignment: Alignment.center, 99 | children: [ 100 | Container( 101 | decoration: BoxDecoration( 102 | color: whiteColor, 103 | borderRadius: BorderRadius.all( 104 | Radius.circular( 105 | 8.0, 106 | ), 107 | ), 108 | ), 109 | width: sy(72), 110 | height: sy(72), 111 | ), 112 | SvgPicture.asset( 113 | image, 114 | width: sy(42), 115 | height: sy(42), 116 | ), 117 | ], 118 | ), 119 | ), 120 | // ), 121 | Container( 122 | padding: EdgeInsets.only( 123 | top: 4, 124 | ), 125 | height: sy(32), 126 | child: Text( 127 | titleName, 128 | style: googlePoppinsRegular.copyWith( 129 | fontSize: 10, 130 | color: blackColor2, 131 | letterSpacing: 0.3, 132 | ), 133 | textAlign: TextAlign.center, 134 | ), 135 | ), 136 | ], 137 | ), 138 | ); 139 | }, 140 | ); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /lib/model/al-quran/m_list_alquran.dart: -------------------------------------------------------------------------------- 1 | class ModelListAlQuran { 2 | int code; 3 | String status; 4 | String message; 5 | List data; 6 | 7 | ModelListAlQuran({this.code, this.status, this.message, this.data}); 8 | 9 | ModelListAlQuran.fromJson(Map json) { 10 | code = json['code']; 11 | status = json['status']; 12 | message = json['message']; 13 | if (json['data'] != null) { 14 | // ignore: deprecated_member_use 15 | data = new List(); 16 | json['data'].forEach((v) { 17 | data.add(new Data.fromJson(v)); 18 | }); 19 | } 20 | } 21 | 22 | Map toJson() { 23 | final Map data = new Map(); 24 | data['code'] = this.code; 25 | data['status'] = this.status; 26 | data['message'] = this.message; 27 | if (this.data != null) { 28 | data['data'] = this.data.map((v) => v.toJson()).toList(); 29 | } 30 | return data; 31 | } 32 | } 33 | 34 | class Data { 35 | int number; 36 | int sequence; 37 | int numberOfVerses; 38 | Name name; 39 | Revelation revelation; 40 | Tafsir tafsir; 41 | 42 | Data( 43 | {this.number, 44 | this.sequence, 45 | this.numberOfVerses, 46 | this.name, 47 | this.revelation, 48 | this.tafsir}); 49 | 50 | Data.fromJson(Map json) { 51 | number = json['number']; 52 | sequence = json['sequence']; 53 | numberOfVerses = json['numberOfVerses']; 54 | name = json['name'] != null ? new Name.fromJson(json['name']) : null; 55 | revelation = json['revelation'] != null 56 | ? new Revelation.fromJson(json['revelation']) 57 | : null; 58 | tafsir = 59 | json['tafsir'] != null ? new Tafsir.fromJson(json['tafsir']) : null; 60 | } 61 | 62 | Map toJson() { 63 | final Map data = new Map(); 64 | data['number'] = this.number; 65 | data['sequence'] = this.sequence; 66 | data['numberOfVerses'] = this.numberOfVerses; 67 | if (this.name != null) { 68 | data['name'] = this.name.toJson(); 69 | } 70 | if (this.revelation != null) { 71 | data['revelation'] = this.revelation.toJson(); 72 | } 73 | if (this.tafsir != null) { 74 | data['tafsir'] = this.tafsir.toJson(); 75 | } 76 | return data; 77 | } 78 | } 79 | 80 | class Name { 81 | String short; 82 | String long; 83 | TransliterationAlQuran transliteration; 84 | TransliterationAlQuran translation; 85 | 86 | Name({this.short, this.long, this.transliteration, this.translation}); 87 | 88 | Name.fromJson(Map json) { 89 | short = json['short']; 90 | long = json['long']; 91 | transliteration = json['transliteration'] != null 92 | ? new TransliterationAlQuran.fromJson(json['transliteration']) 93 | : null; 94 | translation = json['translation'] != null 95 | ? new TransliterationAlQuran.fromJson(json['translation']) 96 | : null; 97 | } 98 | 99 | Map toJson() { 100 | final Map data = new Map(); 101 | data['short'] = this.short; 102 | data['long'] = this.long; 103 | if (this.transliteration != null) { 104 | data['transliteration'] = this.transliteration.toJson(); 105 | } 106 | if (this.translation != null) { 107 | data['translation'] = this.translation.toJson(); 108 | } 109 | return data; 110 | } 111 | } 112 | 113 | class TransliterationAlQuran { 114 | String en; 115 | String id; 116 | 117 | TransliterationAlQuran({this.en, this.id}); 118 | 119 | TransliterationAlQuran.fromJson(Map json) { 120 | en = json['en']; 121 | id = json['id']; 122 | } 123 | 124 | Map toJson() { 125 | final Map data = new Map(); 126 | data['en'] = this.en; 127 | data['id'] = this.id; 128 | return data; 129 | } 130 | } 131 | 132 | class Revelation { 133 | String arab; 134 | String en; 135 | String id; 136 | 137 | Revelation({this.arab, this.en, this.id}); 138 | 139 | Revelation.fromJson(Map json) { 140 | arab = json['arab']; 141 | en = json['en']; 142 | id = json['id']; 143 | } 144 | 145 | Map toJson() { 146 | final Map data = new Map(); 147 | data['arab'] = this.arab; 148 | data['en'] = this.en; 149 | data['id'] = this.id; 150 | return data; 151 | } 152 | } 153 | 154 | class Tafsir { 155 | String id; 156 | 157 | Tafsir({this.id}); 158 | 159 | Tafsir.fromJson(Map json) { 160 | id = json['id']; 161 | } 162 | 163 | Map toJson() { 164 | final Map data = new Map(); 165 | data['id'] = this.id; 166 | return data; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /lib/ui/pages/home/home_ngaji.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:my_alquran/theme/theme_color.dart'; 3 | import 'package:my_alquran/theme/theme_text.dart'; 4 | import 'package:relative_scale/relative_scale.dart'; 5 | 6 | class HomeNgaji extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return RelativeBuilder( 10 | builder: (context, height, width, sy, sx) { 11 | return Padding( 12 | padding: EdgeInsets.only( 13 | right: 16, 14 | ), 15 | child: Container( 16 | height: sy(100), 17 | width: sy(225), 18 | decoration: BoxDecoration( 19 | color: whiteColor, 20 | borderRadius: BorderRadius.all( 21 | Radius.circular( 22 | 8.0, 23 | ), 24 | ), 25 | ), 26 | child: Column( 27 | crossAxisAlignment: CrossAxisAlignment.start, 28 | mainAxisAlignment: MainAxisAlignment.center, 29 | children: [ 30 | ListTile( 31 | leading: Icon( 32 | Icons.image, 33 | size: sy(35), 34 | ), 35 | minLeadingWidth: sy(2), 36 | title: Text( 37 | 'Belajar Tajwid Bacth 1', 38 | style: googlePoppinsMedium.copyWith( 39 | fontSize: 14, 40 | color: blackColor2, 41 | letterSpacing: 0.3, 42 | ), 43 | ), 44 | subtitle: Text( 45 | '11 - 20 Desember 2021', 46 | style: googlePoppinsRegular.copyWith( 47 | fontSize: 10, 48 | letterSpacing: 0.3, 49 | color: blackColor2, 50 | ), 51 | ), 52 | ), 53 | Padding( 54 | padding: const EdgeInsets.only( 55 | left: 20, 56 | right: 24, 57 | ), 58 | child: Row( 59 | crossAxisAlignment: CrossAxisAlignment.center, 60 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 61 | children: [ 62 | Row( 63 | children: [ 64 | Container( 65 | width: sy(65), 66 | child: Stack( 67 | children: [ 68 | Container( 69 | height: sy(24), 70 | width: sy(24), 71 | decoration: BoxDecoration( 72 | shape: BoxShape.circle, 73 | color: Colors.red), 74 | ), 75 | Positioned( 76 | left: sy(20), 77 | child: Container( 78 | height: sy(24), 79 | width: sy(24), 80 | decoration: BoxDecoration( 81 | shape: BoxShape.circle, 82 | color: Colors.orange, 83 | ), 84 | ), 85 | ), 86 | Positioned( 87 | left: sy(40), 88 | child: Container( 89 | height: sy(24), 90 | width: sy(24), 91 | decoration: BoxDecoration( 92 | shape: BoxShape.circle, 93 | color: Colors.blue, 94 | ), 95 | ), 96 | ), 97 | ], 98 | ), 99 | ), 100 | SizedBox( 101 | width: 8, 102 | ), 103 | Text( 104 | '+ 20 Anggota', 105 | style: googlePoppinsRegular.copyWith( 106 | fontSize: 10, 107 | letterSpacing: 0.3, 108 | color: blackColor2, 109 | ), 110 | ), 111 | ], 112 | ), 113 | Icon( 114 | Icons.add_circle_outline, 115 | size: sy(16), 116 | color: greyColor, 117 | ), 118 | ], 119 | ), 120 | ), 121 | SizedBox( 122 | height: 8, 123 | ), 124 | ], 125 | ), 126 | ), 127 | ); 128 | }, 129 | ); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /lib/model/m_list_shalat.dart: -------------------------------------------------------------------------------- 1 | // To parse this JSON data, do 2 | // 3 | // final modelListShalat = modelListShalatFromJson(jsonString); 4 | 5 | import 'dart:convert'; 6 | 7 | ModelListShalat modelListShalatFromJson(String str) => ModelListShalat.fromJson(json.decode(str)); 8 | 9 | String modelListShalatToJson(ModelListShalat data) => json.encode(data.toJson()); 10 | 11 | class ModelListShalat { 12 | ModelListShalat({ 13 | this.code, 14 | this.status, 15 | this.results, 16 | }); 17 | 18 | int code; 19 | String status; 20 | Results results; 21 | 22 | factory ModelListShalat.fromJson(Map json) => ModelListShalat( 23 | code: json["code"], 24 | status: json["status"], 25 | results: Results.fromJson(json["results"]), 26 | ); 27 | 28 | Map toJson() => { 29 | "code": code, 30 | "status": status, 31 | "results": results.toJson(), 32 | }; 33 | } 34 | 35 | class Results { 36 | Results({ 37 | this.datetime, 38 | this.location, 39 | this.settings, 40 | }); 41 | 42 | List datetime; 43 | Location location; 44 | Settings settings; 45 | 46 | factory Results.fromJson(Map json) => Results( 47 | datetime: List.from(json["datetime"].map((x) => Datetime.fromJson(x))), 48 | location: Location.fromJson(json["location"]), 49 | settings: Settings.fromJson(json["settings"]), 50 | ); 51 | 52 | Map toJson() => { 53 | "datetime": List.from(datetime.map((x) => x.toJson())), 54 | "location": location.toJson(), 55 | "settings": settings.toJson(), 56 | }; 57 | } 58 | 59 | class Datetime { 60 | Datetime({ 61 | this.times, 62 | this.date, 63 | }); 64 | 65 | Times times; 66 | Date date; 67 | 68 | factory Datetime.fromJson(Map json) => Datetime( 69 | times: Times.fromJson(json["times"]), 70 | date: Date.fromJson(json["date"]), 71 | ); 72 | 73 | Map toJson() => { 74 | "times": times.toJson(), 75 | "date": date.toJson(), 76 | }; 77 | } 78 | 79 | class Date { 80 | Date({ 81 | this.timestamp, 82 | this.gregorian, 83 | this.hijri, 84 | }); 85 | 86 | int timestamp; 87 | DateTime gregorian; 88 | DateTime hijri; 89 | 90 | factory Date.fromJson(Map json) => Date( 91 | timestamp: json["timestamp"], 92 | gregorian: DateTime.parse(json["gregorian"]), 93 | hijri: DateTime.parse(json["hijri"]), 94 | ); 95 | 96 | Map toJson() => { 97 | "timestamp": timestamp, 98 | "gregorian": "${gregorian.year.toString().padLeft(4, '0')}-${gregorian.month.toString().padLeft(2, '0')}-${gregorian.day.toString().padLeft(2, '0')}", 99 | "hijri": "${hijri.year.toString().padLeft(4, '0')}-${hijri.month.toString().padLeft(2, '0')}-${hijri.day.toString().padLeft(2, '0')}", 100 | }; 101 | } 102 | 103 | class Times { 104 | Times({ 105 | this.imsak, 106 | this.sunrise, 107 | this.fajr, 108 | this.dhuhr, 109 | this.asr, 110 | this.sunset, 111 | this.maghrib, 112 | this.isha, 113 | this.midnight, 114 | }); 115 | 116 | String imsak; 117 | String sunrise; 118 | String fajr; 119 | String dhuhr; 120 | String asr; 121 | String sunset; 122 | String maghrib; 123 | String isha; 124 | String midnight; 125 | 126 | factory Times.fromJson(Map json) => Times( 127 | imsak: json["Imsak"], 128 | sunrise: json["Sunrise"], 129 | fajr: json["Fajr"], 130 | dhuhr: json["Dhuhr"], 131 | asr: json["Asr"], 132 | sunset: json["Sunset"], 133 | maghrib: json["Maghrib"], 134 | isha: json["Isha"], 135 | midnight: json["Midnight"], 136 | ); 137 | 138 | Map toJson() => { 139 | "Imsak": imsak, 140 | "Sunrise": sunrise, 141 | "Fajr": fajr, 142 | "Dhuhr": dhuhr, 143 | "Asr": asr, 144 | "Sunset": sunset, 145 | "Maghrib": maghrib, 146 | "Isha": isha, 147 | "Midnight": midnight, 148 | }; 149 | } 150 | 151 | class Location { 152 | Location({ 153 | this.latitude, 154 | this.longitude, 155 | this.elevation, 156 | this.city, 157 | this.country, 158 | this.countryCode, 159 | this.timezone, 160 | this.localOffset, 161 | }); 162 | 163 | double latitude; 164 | double longitude; 165 | double elevation; 166 | String city; 167 | String country; 168 | String countryCode; 169 | String timezone; 170 | double localOffset; 171 | 172 | factory Location.fromJson(Map json) => Location( 173 | latitude: json["latitude"].toDouble(), 174 | longitude: json["longitude"].toDouble(), 175 | elevation: json["elevation"], 176 | city: json["city"], 177 | country: json["country"], 178 | countryCode: json["country_code"], 179 | timezone: json["timezone"], 180 | localOffset: json["local_offset"], 181 | ); 182 | 183 | Map toJson() => { 184 | "latitude": latitude, 185 | "longitude": longitude, 186 | "elevation": elevation, 187 | "city": city, 188 | "country": country, 189 | "country_code": countryCode, 190 | "timezone": timezone, 191 | "local_offset": localOffset, 192 | }; 193 | } 194 | 195 | class Settings { 196 | Settings({ 197 | this.timeformat, 198 | this.school, 199 | this.juristic, 200 | this.highlat, 201 | this.fajrAngle, 202 | this.ishaAngle, 203 | }); 204 | 205 | String timeformat; 206 | String school; 207 | String juristic; 208 | String highlat; 209 | double fajrAngle; 210 | double ishaAngle; 211 | 212 | factory Settings.fromJson(Map json) => Settings( 213 | timeformat: json["timeformat"], 214 | school: json["school"], 215 | juristic: json["juristic"], 216 | highlat: json["highlat"], 217 | fajrAngle: json["fajr_angle"], 218 | ishaAngle: json["isha_angle"], 219 | ); 220 | 221 | Map toJson() => { 222 | "timeformat": timeformat, 223 | "school": school, 224 | "juristic": juristic, 225 | "highlat": highlat, 226 | "fajr_angle": fajrAngle, 227 | "isha_angle": ishaAngle, 228 | }; 229 | } 230 | -------------------------------------------------------------------------------- /lib/ui/pages/hadits/hadits_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:google_fonts/google_fonts.dart'; 4 | import 'package:my_alquran/config/route_name.dart'; 5 | import 'package:my_alquran/cubit/c_hadits/hadits_cubit.dart'; 6 | import 'package:my_alquran/theme/theme_color.dart'; 7 | import 'package:my_alquran/theme/theme_text.dart'; 8 | import 'package:my_alquran/ui/pages/hadits/hadits_people/hadits_people_arguments.dart'; 9 | import 'package:my_alquran/ui/widget/custome_page.dart'; 10 | import 'package:relative_scale/relative_scale.dart'; 11 | 12 | class HaditsViewPage extends StatefulWidget { 13 | @override 14 | _HaditsViewPageState createState() => _HaditsViewPageState(); 15 | } 16 | 17 | class _HaditsViewPageState extends State { 18 | @override 19 | void initState() { 20 | super.initState(); 21 | context.read().getListHadits(); 22 | } 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return RelativeBuilder( 27 | builder: (context, height, width, sy, sx) { 28 | return CustomePage( 29 | scaffold: Scaffold( 30 | backgroundColor: whiteColor, 31 | body: BlocConsumer( 32 | listener: (context, state) {}, 33 | builder: (context, state) { 34 | if (state is ListHaditsLoadInProgress) { 35 | return Center( 36 | child: CircularProgressIndicator(), 37 | ); 38 | } 39 | if (state is ListHaditsLoadedSuccess) { 40 | return ListView.builder( 41 | shrinkWrap: true, 42 | itemCount: state.modeListHadits.data.length, 43 | itemBuilder: (context, int index) { 44 | return GestureDetector( 45 | onTap: () { 46 | Navigator.pushNamed( 47 | context, 48 | RouteName.ListHaditsPeople, 49 | arguments: HaditsPeopleArguments( 50 | idPeople: state.modeListHadits.data[index].id, 51 | namePeople: state.modeListHadits.data[index].name, 52 | ), 53 | ); 54 | }, 55 | child: Column( 56 | children: [ 57 | Container( 58 | height: sy(32), 59 | width: double.infinity, 60 | child: ListTile( 61 | dense: true, 62 | minLeadingWidth: sy(5), 63 | leading: Container( 64 | alignment: Alignment.center, 65 | width: sy(36), 66 | height: sy(36), 67 | decoration: BoxDecoration( 68 | shape: BoxShape.circle, 69 | color: greyColor1, 70 | ), 71 | child: Text( 72 | '${index + 1}', 73 | style: googlePoppinsMedium.copyWith( 74 | fontSize: 20, 75 | color: blueColor, 76 | ), 77 | ), 78 | ), 79 | title: Text( 80 | state.modeListHadits.data[index].name, 81 | style: googlePoppinsMedium.copyWith( 82 | fontSize: 16, 83 | color: blackColor1, 84 | letterSpacing: 0.3, 85 | ), 86 | ), 87 | trailing: Text( 88 | state.modeListHadits.data[index].available 89 | .toString(), 90 | style: googlePoppinsRegular.copyWith( 91 | letterSpacing: 0.3, 92 | color: Colors.grey, 93 | fontSize: 12, 94 | ), 95 | ), 96 | ), 97 | ), 98 | Padding( 99 | padding: EdgeInsets.only( 100 | right: 20, 101 | left: 76, 102 | ), 103 | child: Divider( 104 | thickness: 1, 105 | color: greyColor, 106 | ), 107 | ), 108 | ], 109 | ), 110 | ); 111 | }, 112 | ); 113 | } 114 | if (state is ListHaditsLoadedError) { 115 | return Center( 116 | child: Column( 117 | mainAxisAlignment: MainAxisAlignment.center, 118 | children: [ 119 | Text( 120 | state.message, 121 | ), 122 | ElevatedButton( 123 | onPressed: () {}, 124 | child: Text( 125 | 'Refresh', 126 | ), 127 | ), 128 | ], 129 | ), 130 | ); 131 | } 132 | return Container(); 133 | }, 134 | ), 135 | ), 136 | ); 137 | }, 138 | ); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /image/praying.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib/ui/pages/surah/surah_bottom_sheet_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:my_alquran/theme/theme_color.dart'; 5 | import 'package:my_alquran/theme/theme_text.dart'; 6 | import 'package:relative_scale/relative_scale.dart'; 7 | import 'package:share/share.dart'; 8 | 9 | class SurahBottomSheetView extends StatefulWidget { 10 | final String nameSurah; 11 | final String ayatSurah; 12 | final int indexAudio; 13 | final String urlAudio; 14 | final String textarab; 15 | 16 | const SurahBottomSheetView({ 17 | Key key, 18 | this.nameSurah, 19 | this.ayatSurah, 20 | this.indexAudio, 21 | this.urlAudio, 22 | this.textarab, 23 | }) : super(key: key); 24 | 25 | @override 26 | _SurahBottomSheetViewState createState() => _SurahBottomSheetViewState(); 27 | } 28 | 29 | class _SurahBottomSheetViewState extends State { 30 | AudioPlayer audioPlayer = 31 | AudioPlayer(); //VARIABLE YANG AKAN MENG-HANDLE AUDIO 32 | 33 | // bool 34 | int _currentSelectedAyat = -1; 35 | 36 | @override 37 | void initState() { 38 | ayatEnd(); 39 | super.initState(); 40 | } 41 | 42 | void ayatEnd() { 43 | audioPlayer.onPlayerCompletion.listen((event) { 44 | setState(() { 45 | _currentSelectedAyat = -1; 46 | }); 47 | }); 48 | } 49 | 50 | @override 51 | void dispose() { 52 | audioPlayer.dispose(); 53 | super.dispose(); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return RelativeBuilder( 59 | builder: (context, height, width, sy, sx) { 60 | return Container( 61 | height: sy(314), 62 | width: double.infinity, 63 | child: ListView( 64 | children: [ 65 | Padding( 66 | padding: EdgeInsets.only( 67 | left: 20, 68 | bottom: 24, 69 | ), 70 | child: Text( 71 | '${widget.nameSurah} : ${widget.ayatSurah}', 72 | style: googlePoppinsMedium.copyWith( 73 | fontSize: 20, 74 | color: blackColor1, 75 | letterSpacing: 0.3, 76 | ), 77 | ), 78 | ), 79 | Column( 80 | children: [ 81 | buttonFunctionSurah( 82 | icon: Icon( 83 | _currentSelectedAyat != widget.indexAudio 84 | ? Icons.play_arrow_outlined 85 | : Icons.pause_outlined, 86 | size: sy(24), 87 | ), 88 | nameFunction: 'Putar Murotal', 89 | onTap: () async { 90 | if (_currentSelectedAyat == widget.indexAudio) { 91 | _currentSelectedAyat = -1; 92 | 93 | if (_currentSelectedAyat == -1) { 94 | await audioPlayer.pause(); 95 | } 96 | } else { 97 | _currentSelectedAyat = widget.indexAudio; 98 | // ketika _currentSelectedAyat sama dengan index 99 | // Maka Ayat akan di jalankan 100 | if (_currentSelectedAyat == widget.indexAudio) { 101 | await audioPlayer.play(widget.urlAudio); 102 | } 103 | } 104 | setState(() {}); 105 | }, 106 | ), 107 | buttonFunctionSurah( 108 | icon: Icon( 109 | Icons.share_outlined, 110 | size: sy(24), 111 | color: Color(0xFF595959), 112 | ), 113 | nameFunction: 'Bagikan Ayat', 114 | onTap: () async { 115 | Share.share( 116 | widget.textarab, 117 | subject: '${widget.nameSurah} : ${widget.ayatSurah}', 118 | ); 119 | }, 120 | ), 121 | buttonFunctionSurah( 122 | icon: Icon( 123 | Icons.copy_outlined, 124 | size: sy(24), 125 | color: Color(0xFF595959), 126 | ), 127 | nameFunction: 'Salin Ayat', 128 | onTap: () { 129 | Navigator.pop(context); 130 | Clipboard.setData( 131 | ClipboardData( 132 | text: widget.textarab, 133 | ), 134 | ); 135 | 136 | final snackBar = SnackBar( 137 | content: Text( 138 | 'Ayat berhasil disalin', 139 | style: googlePoppinsMedium.copyWith( 140 | fontSize: 12, 141 | color: Colors.white, 142 | letterSpacing: 0.3, 143 | ), 144 | ), 145 | ); 146 | 147 | ScaffoldMessenger.of(context).showSnackBar(snackBar); 148 | }, 149 | ), 150 | buttonFunctionSurah( 151 | icon: Icon( 152 | Icons.favorite_border_outlined, 153 | size: sy(24), 154 | color: Color(0xFF595959), 155 | ), 156 | nameFunction: 'Tambahkan ke bookmark', 157 | onTap: () {}, 158 | ), 159 | buttonFunctionSurah( 160 | icon: Icon( 161 | Icons.bookmark_border, 162 | size: sy(24), 163 | color: Color(0xFF595959), 164 | ), 165 | nameFunction: 'Tandai terakhir dibaca', 166 | onTap: () {}, 167 | ), 168 | ], 169 | ), 170 | ], 171 | ), 172 | ); 173 | }, 174 | ); 175 | } 176 | 177 | Widget buttonFunctionSurah({ 178 | String nameFunction, 179 | Icon icon, 180 | VoidCallback onTap, 181 | }) { 182 | return Container( 183 | padding: EdgeInsets.only( 184 | left: 16, 185 | bottom: 16, 186 | ), 187 | width: double.infinity, 188 | child: Row( 189 | mainAxisAlignment: MainAxisAlignment.start, 190 | children: [ 191 | GestureDetector( 192 | onTap: onTap, 193 | child: icon, 194 | ), 195 | SizedBox( 196 | width: 24, 197 | ), 198 | Text( 199 | nameFunction, 200 | style: googlePoppinsRegular.copyWith( 201 | fontSize: 16, 202 | color: blackColor1, 203 | letterSpacing: 0.3, 204 | ), 205 | ), 206 | ], 207 | ), 208 | ); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /lib/model/al-quran/m_detail_surah.dart: -------------------------------------------------------------------------------- 1 | // To parse this JSON data, do 2 | // 3 | // final modelDetailSurah = modelDetailSurahFromJson(jsonString); 4 | 5 | import 'dart:convert'; 6 | 7 | ModelDetailSurah modelDetailSurahFromJson(String str) => ModelDetailSurah.fromJson(json.decode(str)); 8 | 9 | String modelDetailSurahToJson(ModelDetailSurah data) => json.encode(data.toJson()); 10 | 11 | class ModelDetailSurah { 12 | ModelDetailSurah({ 13 | this.code, 14 | this.status, 15 | this.message, 16 | this.data, 17 | }); 18 | 19 | int code; 20 | String status; 21 | String message; 22 | Data data; 23 | 24 | factory ModelDetailSurah.fromJson(Map json) => ModelDetailSurah( 25 | code: json["code"], 26 | status: json["status"], 27 | message: json["message"], 28 | data: Data.fromJson(json["data"]), 29 | ); 30 | 31 | Map toJson() => { 32 | "code": code, 33 | "status": status, 34 | "message": message, 35 | "data": data.toJson(), 36 | }; 37 | } 38 | 39 | class Data { 40 | Data({ 41 | this.number, 42 | this.sequence, 43 | this.numberOfVerses, 44 | this.name, 45 | this.revelation, 46 | this.tafsir, 47 | this.preBismillah, 48 | this.verses, 49 | }); 50 | 51 | int number; 52 | int sequence; 53 | int numberOfVerses; 54 | Name name; 55 | Revelation revelation; 56 | DataTafsir tafsir; 57 | dynamic preBismillah; 58 | List verses; 59 | 60 | factory Data.fromJson(Map json) => Data( 61 | number: json["number"], 62 | sequence: json["sequence"], 63 | numberOfVerses: json["numberOfVerses"], 64 | name: Name.fromJson(json["name"]), 65 | revelation: Revelation.fromJson(json["revelation"]), 66 | tafsir: DataTafsir.fromJson(json["tafsir"]), 67 | preBismillah: json["preBismillah"], 68 | verses: List.from(json["verses"].map((x) => Verse.fromJson(x))), 69 | ); 70 | 71 | Map toJson() => { 72 | "number": number, 73 | "sequence": sequence, 74 | "numberOfVerses": numberOfVerses, 75 | "name": name.toJson(), 76 | "revelation": revelation.toJson(), 77 | "tafsir": tafsir.toJson(), 78 | "preBismillah": preBismillah, 79 | "verses": List.from(verses.map((x) => x.toJson())), 80 | }; 81 | } 82 | 83 | class Name { 84 | Name({ 85 | this.short, 86 | this.long, 87 | this.transliteration, 88 | this.translation, 89 | }); 90 | 91 | String short; 92 | String long; 93 | Translation transliteration; 94 | Translation translation; 95 | 96 | factory Name.fromJson(Map json) => Name( 97 | short: json["short"], 98 | long: json["long"], 99 | transliteration: Translation.fromJson(json["transliteration"]), 100 | translation: Translation.fromJson(json["translation"]), 101 | ); 102 | 103 | Map toJson() => { 104 | "short": short, 105 | "long": long, 106 | "transliteration": transliteration.toJson(), 107 | "translation": translation.toJson(), 108 | }; 109 | } 110 | 111 | class Translation { 112 | Translation({ 113 | this.en, 114 | this.id, 115 | }); 116 | 117 | String en; 118 | String id; 119 | 120 | factory Translation.fromJson(Map json) => Translation( 121 | en: json["en"], 122 | id: json["id"], 123 | ); 124 | 125 | Map toJson() => { 126 | "en": en, 127 | "id": id, 128 | }; 129 | } 130 | 131 | class Revelation { 132 | Revelation({ 133 | this.arab, 134 | this.en, 135 | this.id, 136 | }); 137 | 138 | String arab; 139 | String en; 140 | String id; 141 | 142 | factory Revelation.fromJson(Map json) => Revelation( 143 | arab: json["arab"], 144 | en: json["en"], 145 | id: json["id"], 146 | ); 147 | 148 | Map toJson() => { 149 | "arab": arab, 150 | "en": en, 151 | "id": id, 152 | }; 153 | } 154 | 155 | class DataTafsir { 156 | DataTafsir({ 157 | this.id, 158 | }); 159 | 160 | String id; 161 | 162 | factory DataTafsir.fromJson(Map json) => DataTafsir( 163 | id: json["id"], 164 | ); 165 | 166 | Map toJson() => { 167 | "id": id, 168 | }; 169 | } 170 | 171 | class Verse { 172 | Verse({ 173 | this.number, 174 | this.meta, 175 | this.text, 176 | this.translation, 177 | this.audio, 178 | this.tafsir, 179 | }); 180 | 181 | Number number; 182 | Meta meta; 183 | TextQuran text; 184 | Translation translation; 185 | Audio audio; 186 | VerseTafsir tafsir; 187 | 188 | factory Verse.fromJson(Map json) => Verse( 189 | number: Number.fromJson(json["number"]), 190 | meta: Meta.fromJson(json["meta"]), 191 | text: TextQuran.fromJson(json["text"]), 192 | translation: Translation.fromJson(json["translation"]), 193 | audio: Audio.fromJson(json["audio"]), 194 | tafsir: VerseTafsir.fromJson(json["tafsir"]), 195 | ); 196 | 197 | Map toJson() => { 198 | "number": number.toJson(), 199 | "meta": meta.toJson(), 200 | "text": text.toJson(), 201 | "translation": translation.toJson(), 202 | "audio": audio.toJson(), 203 | "tafsir": tafsir.toJson(), 204 | }; 205 | } 206 | 207 | class Audio { 208 | Audio({ 209 | this.primary, 210 | this.secondary, 211 | }); 212 | 213 | String primary; 214 | List secondary; 215 | 216 | factory Audio.fromJson(Map json) => Audio( 217 | primary: json["primary"], 218 | secondary: List.from(json["secondary"].map((x) => x)), 219 | ); 220 | 221 | Map toJson() => { 222 | "primary": primary, 223 | "secondary": List.from(secondary.map((x) => x)), 224 | }; 225 | } 226 | 227 | class Meta { 228 | Meta({ 229 | this.juz, 230 | this.page, 231 | this.manzil, 232 | this.ruku, 233 | this.hizbQuarter, 234 | this.sajda, 235 | }); 236 | 237 | int juz; 238 | int page; 239 | int manzil; 240 | int ruku; 241 | int hizbQuarter; 242 | Sajda sajda; 243 | 244 | factory Meta.fromJson(Map json) => Meta( 245 | juz: json["juz"], 246 | page: json["page"], 247 | manzil: json["manzil"], 248 | ruku: json["ruku"], 249 | hizbQuarter: json["hizbQuarter"], 250 | sajda: Sajda.fromJson(json["sajda"]), 251 | ); 252 | 253 | Map toJson() => { 254 | "juz": juz, 255 | "page": page, 256 | "manzil": manzil, 257 | "ruku": ruku, 258 | "hizbQuarter": hizbQuarter, 259 | "sajda": sajda.toJson(), 260 | }; 261 | } 262 | 263 | class Sajda { 264 | Sajda({ 265 | this.recommended, 266 | this.obligatory, 267 | }); 268 | 269 | bool recommended; 270 | bool obligatory; 271 | 272 | factory Sajda.fromJson(Map json) => Sajda( 273 | recommended: json["recommended"], 274 | obligatory: json["obligatory"], 275 | ); 276 | 277 | Map toJson() => { 278 | "recommended": recommended, 279 | "obligatory": obligatory, 280 | }; 281 | } 282 | 283 | class Number { 284 | Number({ 285 | this.inQuran, 286 | this.inSurah, 287 | }); 288 | 289 | int inQuran; 290 | int inSurah; 291 | 292 | factory Number.fromJson(Map json) => Number( 293 | inQuran: json["inQuran"], 294 | inSurah: json["inSurah"], 295 | ); 296 | 297 | Map toJson() => { 298 | "inQuran": inQuran, 299 | "inSurah": inSurah, 300 | }; 301 | } 302 | 303 | class VerseTafsir { 304 | VerseTafsir({ 305 | this.id, 306 | }); 307 | 308 | Id id; 309 | 310 | factory VerseTafsir.fromJson(Map json) => VerseTafsir( 311 | id: Id.fromJson(json["id"]), 312 | ); 313 | 314 | Map toJson() => { 315 | "id": id.toJson(), 316 | }; 317 | } 318 | 319 | class Id { 320 | Id({ 321 | this.short, 322 | this.long, 323 | }); 324 | 325 | String short; 326 | String long; 327 | 328 | factory Id.fromJson(Map json) => Id( 329 | short: json["short"], 330 | long: json["long"], 331 | ); 332 | 333 | Map toJson() => { 334 | "short": short, 335 | "long": long, 336 | }; 337 | } 338 | 339 | class TextQuran { 340 | TextQuran({ 341 | this.arab, 342 | this.transliteration, 343 | }); 344 | 345 | String arab; 346 | Transliteration transliteration; 347 | 348 | factory TextQuran.fromJson(Map json) => TextQuran( 349 | arab: json["arab"], 350 | transliteration: Transliteration.fromJson(json["transliteration"]), 351 | ); 352 | 353 | Map toJson() => { 354 | "arab": arab, 355 | "transliteration": transliteration.toJson(), 356 | }; 357 | } 358 | 359 | class Transliteration { 360 | Transliteration({ 361 | this.en, 362 | }); 363 | 364 | String en; 365 | 366 | factory Transliteration.fromJson(Map json) => Transliteration( 367 | en: json["en"], 368 | ); 369 | 370 | Map toJson() => { 371 | "en": en, 372 | }; 373 | } 374 | -------------------------------------------------------------------------------- /lib/ui/pages/custome_tab_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:my_alquran/theme/theme_color.dart'; 3 | import 'package:my_alquran/theme/theme_text.dart'; 4 | import 'package:my_alquran/ui/pages/alquran/alquran_pages.dart'; 5 | import 'package:my_alquran/ui/pages/hadits/hadits_pages.dart'; 6 | import 'package:my_alquran/ui/widget/custome_page.dart'; 7 | import 'package:relative_scale/relative_scale.dart'; 8 | 9 | class CustomeTabBarAlQuran extends StatefulWidget { 10 | @override 11 | _CustomeTabBarAlQuranState createState() => _CustomeTabBarAlQuranState(); 12 | } 13 | 14 | class _CustomeTabBarAlQuranState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return RelativeBuilder( 18 | builder: (context, height, width, sy, sx) { 19 | return DefaultTabController( 20 | length: 3, 21 | child: CustomePage( 22 | scaffold: Scaffold( 23 | backgroundColor: whiteColor, 24 | appBar: PreferredSize( 25 | preferredSize: Size.fromHeight( 26 | sy(175), 27 | ), 28 | child: Column( 29 | crossAxisAlignment: CrossAxisAlignment.start, 30 | children: [ 31 | AppBar( 32 | backgroundColor: whiteColor, 33 | elevation: 0.0, 34 | iconTheme: IconThemeData( 35 | color: blackColor, 36 | size: 24, 37 | ), 38 | actions: [ 39 | IconButton( 40 | icon: Icon( 41 | Icons.more_vert, 42 | color: blackColor1, 43 | size: 24, 44 | ), 45 | onPressed: () {}, 46 | ) 47 | ], 48 | ), 49 | Padding( 50 | padding: EdgeInsets.only( 51 | left: 21, 52 | right: 19, 53 | ), 54 | child: Row( 55 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 56 | crossAxisAlignment: CrossAxisAlignment.center, 57 | children: [ 58 | Text( 59 | 'Bacaan Pilihan', 60 | style: googlePoppinsMedium.copyWith( 61 | fontSize: 18, 62 | ), 63 | ), 64 | Text( 65 | 'Lihat Semua', 66 | style: googlePoppinsMedium.copyWith( 67 | fontSize: 10, 68 | color: blueColor2, 69 | ), 70 | ), 71 | ], 72 | ), 73 | ), 74 | SizedBox( 75 | height: 16, 76 | ), 77 | SizedBox( 78 | height: sy(45), 79 | width: double.infinity, 80 | child: ListView.builder( 81 | padding: EdgeInsets.only( 82 | left: 21, 83 | ), 84 | itemCount: listModelBacaanPilihan.length, 85 | shrinkWrap: true, 86 | scrollDirection: Axis.horizontal, 87 | itemBuilder: (context, int index) { 88 | return Padding( 89 | padding: EdgeInsets.only( 90 | right: 24, 91 | ), 92 | child: Stack( 93 | children: [ 94 | Container( 95 | alignment: Alignment.center, 96 | height: sy(65), 97 | width: sy(142), 98 | decoration: BoxDecoration( 99 | color: blueColor, 100 | borderRadius: BorderRadius.circular( 101 | sy(16), 102 | ), 103 | ), 104 | child: Text( 105 | listModelBacaanPilihan[index].nameBacaan, 106 | style: googlePoppinsMedium.copyWith( 107 | fontSize: 14, 108 | color: whiteColor, 109 | ), 110 | ), 111 | ), 112 | Positioned( 113 | bottom: sy(15), 114 | left: sy(-20), 115 | child: Container( 116 | height: sy(53), 117 | width: sy(53), 118 | child: Image.asset( 119 | 'image/segitiga.png', 120 | color: whiteColor, 121 | ), 122 | ), 123 | ), 124 | Positioned( 125 | bottom: sy(10), 126 | right: sy(-20), 127 | child: Container( 128 | height: sy(86), 129 | width: sy(86), 130 | decoration: BoxDecoration( 131 | shape: BoxShape.circle, 132 | color: Colors.grey.withOpacity(.1), 133 | ), 134 | ), 135 | ), 136 | Positioned( 137 | top: sy(10), 138 | right: sy(-20), 139 | child: Container( 140 | height: sy(86), 141 | width: sy(86), 142 | decoration: BoxDecoration( 143 | shape: BoxShape.circle, 144 | color: Colors.grey.withOpacity(.1), 145 | ), 146 | ), 147 | ), 148 | ], 149 | ), 150 | ); 151 | }, 152 | ), 153 | ), 154 | 155 | // TabBar 156 | Column( 157 | children: [ 158 | TabBar( 159 | labelStyle: googlePoppinsRegular.copyWith( 160 | fontSize: 16, 161 | letterSpacing: 0.3, 162 | color: blackColor1, 163 | ), 164 | labelColor: blackColor1, 165 | unselectedLabelColor: blackColor1.withOpacity(0.5), 166 | unselectedLabelStyle: googlePoppinsRegular.copyWith( 167 | fontSize: 16, 168 | letterSpacing: 0.3, 169 | color: blackColor1, 170 | ), 171 | indicatorSize: TabBarIndicatorSize.label, 172 | // isScrollable: true, 173 | indicatorWeight: 2.0, 174 | indicatorColor: blackColor1, 175 | tabs: [ 176 | Tab( 177 | text: 'Surat', 178 | ), 179 | Tab( 180 | text: 'Hadits', 181 | ), 182 | Tab( 183 | text: 'Bookmark', 184 | ), 185 | ], 186 | ), 187 | Container( 188 | margin: EdgeInsets.only( 189 | left: 20, 190 | right: 20, 191 | ), 192 | decoration: BoxDecoration( 193 | border: Border( 194 | bottom: BorderSide( 195 | color: greyColor, 196 | width: 1, 197 | ), 198 | ), 199 | ), 200 | ), 201 | ], 202 | ) 203 | ], 204 | ), 205 | ), 206 | body: TabBarView( 207 | children: [ 208 | InitialAlQuranPages(), 209 | InitialHaditsPages(), 210 | Container(), 211 | ], 212 | ), 213 | ), 214 | ), 215 | ); 216 | }, 217 | ); 218 | } 219 | } 220 | 221 | class ModelBacaanPilihan { 222 | final int id; 223 | final String nameBacaan; 224 | 225 | ModelBacaanPilihan({ 226 | this.id, 227 | this.nameBacaan, 228 | }); 229 | } 230 | 231 | List listModelBacaanPilihan = [ 232 | ModelBacaanPilihan( 233 | id: 1, 234 | nameBacaan: "Kumpulan Do'a", 235 | ), 236 | ModelBacaanPilihan( 237 | id: 2, 238 | nameBacaan: "Ayat Pilihan", 239 | ), 240 | ModelBacaanPilihan( 241 | id: 3, 242 | nameBacaan: "Juz Amma", 243 | ), 244 | ModelBacaanPilihan( 245 | id: 4, 246 | nameBacaan: "Kumpulan Hadits", 247 | ), 248 | ]; 249 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.5.0" 11 | audioplayers: 12 | dependency: "direct main" 13 | description: 14 | name: audioplayers 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "0.18.1" 18 | bloc: 19 | dependency: "direct main" 20 | description: 21 | name: bloc 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "6.1.3" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.1.0" 32 | characters: 33 | dependency: transitive 34 | description: 35 | name: characters 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.2.0" 46 | clock: 47 | dependency: transitive 48 | description: 49 | name: clock 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.1.0" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.15.0" 60 | convert: 61 | dependency: transitive 62 | description: 63 | name: convert 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.1.1" 67 | crypto: 68 | dependency: transitive 69 | description: 70 | name: crypto 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "3.0.0" 74 | cupertino_icons: 75 | dependency: "direct main" 76 | description: 77 | name: cupertino_icons 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "1.0.2" 81 | date_format: 82 | dependency: "direct main" 83 | description: 84 | name: date_format 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "2.0.2" 88 | dio: 89 | dependency: "direct main" 90 | description: 91 | name: dio 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "3.0.10" 95 | equatable: 96 | dependency: "direct main" 97 | description: 98 | name: equatable 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "2.0.0" 102 | fake_async: 103 | dependency: transitive 104 | description: 105 | name: fake_async 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "1.2.0" 109 | ffi: 110 | dependency: transitive 111 | description: 112 | name: ffi 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "1.0.0" 116 | file: 117 | dependency: transitive 118 | description: 119 | name: file 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "6.1.0" 123 | flutter: 124 | dependency: "direct main" 125 | description: flutter 126 | source: sdk 127 | version: "0.0.0" 128 | flutter_bloc: 129 | dependency: "direct main" 130 | description: 131 | name: flutter_bloc 132 | url: "https://pub.dartlang.org" 133 | source: hosted 134 | version: "6.1.3" 135 | flutter_svg: 136 | dependency: "direct main" 137 | description: 138 | name: flutter_svg 139 | url: "https://pub.dartlang.org" 140 | source: hosted 141 | version: "0.19.3" 142 | flutter_test: 143 | dependency: "direct dev" 144 | description: flutter 145 | source: sdk 146 | version: "0.0.0" 147 | flutter_web_plugins: 148 | dependency: transitive 149 | description: flutter 150 | source: sdk 151 | version: "0.0.0" 152 | geocoding: 153 | dependency: "direct main" 154 | description: 155 | name: geocoding 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "2.0.0" 159 | geocoding_platform_interface: 160 | dependency: transitive 161 | description: 162 | name: geocoding_platform_interface 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "2.0.0" 166 | geolocator: 167 | dependency: "direct main" 168 | description: 169 | name: geolocator 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "7.0.1" 173 | geolocator_platform_interface: 174 | dependency: transitive 175 | description: 176 | name: geolocator_platform_interface 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "2.0.0" 180 | geolocator_web: 181 | dependency: transitive 182 | description: 183 | name: geolocator_web 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "2.0.3" 187 | google_fonts: 188 | dependency: "direct main" 189 | description: 190 | name: google_fonts 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.1.2" 194 | hijri: 195 | dependency: "direct main" 196 | description: 197 | name: hijri 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "2.0.3" 201 | http: 202 | dependency: transitive 203 | description: 204 | name: http 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "0.12.2" 208 | http_parser: 209 | dependency: transitive 210 | description: 211 | name: http_parser 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "3.1.4" 215 | intl: 216 | dependency: "direct main" 217 | description: 218 | name: intl 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "0.17.0" 222 | js: 223 | dependency: transitive 224 | description: 225 | name: js 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "0.6.3" 229 | matcher: 230 | dependency: transitive 231 | description: 232 | name: matcher 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "0.12.10" 236 | meta: 237 | dependency: transitive 238 | description: 239 | name: meta 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "1.3.0" 243 | mime: 244 | dependency: transitive 245 | description: 246 | name: mime 247 | url: "https://pub.dartlang.org" 248 | source: hosted 249 | version: "1.0.0" 250 | modal_bottom_sheet: 251 | dependency: "direct main" 252 | description: 253 | name: modal_bottom_sheet 254 | url: "https://pub.dartlang.org" 255 | source: hosted 256 | version: "2.0.0" 257 | nested: 258 | dependency: transitive 259 | description: 260 | name: nested 261 | url: "https://pub.dartlang.org" 262 | source: hosted 263 | version: "1.0.0" 264 | numberpicker: 265 | dependency: "direct main" 266 | description: 267 | name: numberpicker 268 | url: "https://pub.dartlang.org" 269 | source: hosted 270 | version: "2.0.1" 271 | path: 272 | dependency: transitive 273 | description: 274 | name: path 275 | url: "https://pub.dartlang.org" 276 | source: hosted 277 | version: "1.8.0" 278 | path_drawing: 279 | dependency: transitive 280 | description: 281 | name: path_drawing 282 | url: "https://pub.dartlang.org" 283 | source: hosted 284 | version: "0.4.1+1" 285 | path_parsing: 286 | dependency: transitive 287 | description: 288 | name: path_parsing 289 | url: "https://pub.dartlang.org" 290 | source: hosted 291 | version: "0.1.4" 292 | path_provider: 293 | dependency: transitive 294 | description: 295 | name: path_provider 296 | url: "https://pub.dartlang.org" 297 | source: hosted 298 | version: "2.0.1" 299 | path_provider_linux: 300 | dependency: transitive 301 | description: 302 | name: path_provider_linux 303 | url: "https://pub.dartlang.org" 304 | source: hosted 305 | version: "2.0.0" 306 | path_provider_macos: 307 | dependency: transitive 308 | description: 309 | name: path_provider_macos 310 | url: "https://pub.dartlang.org" 311 | source: hosted 312 | version: "2.0.0" 313 | path_provider_platform_interface: 314 | dependency: transitive 315 | description: 316 | name: path_provider_platform_interface 317 | url: "https://pub.dartlang.org" 318 | source: hosted 319 | version: "2.0.0" 320 | path_provider_windows: 321 | dependency: transitive 322 | description: 323 | name: path_provider_windows 324 | url: "https://pub.dartlang.org" 325 | source: hosted 326 | version: "2.0.0" 327 | pedantic: 328 | dependency: transitive 329 | description: 330 | name: pedantic 331 | url: "https://pub.dartlang.org" 332 | source: hosted 333 | version: "1.11.0" 334 | petitparser: 335 | dependency: transitive 336 | description: 337 | name: petitparser 338 | url: "https://pub.dartlang.org" 339 | source: hosted 340 | version: "3.1.0" 341 | platform: 342 | dependency: transitive 343 | description: 344 | name: platform 345 | url: "https://pub.dartlang.org" 346 | source: hosted 347 | version: "3.0.0" 348 | plugin_platform_interface: 349 | dependency: transitive 350 | description: 351 | name: plugin_platform_interface 352 | url: "https://pub.dartlang.org" 353 | source: hosted 354 | version: "2.0.0" 355 | process: 356 | dependency: transitive 357 | description: 358 | name: process 359 | url: "https://pub.dartlang.org" 360 | source: hosted 361 | version: "4.2.0" 362 | provider: 363 | dependency: transitive 364 | description: 365 | name: provider 366 | url: "https://pub.dartlang.org" 367 | source: hosted 368 | version: "4.3.3" 369 | relative_scale: 370 | dependency: "direct main" 371 | description: 372 | name: relative_scale 373 | url: "https://pub.dartlang.org" 374 | source: hosted 375 | version: "2.0.0" 376 | rxdart: 377 | dependency: "direct main" 378 | description: 379 | name: rxdart 380 | url: "https://pub.dartlang.org" 381 | source: hosted 382 | version: "0.26.0" 383 | share: 384 | dependency: "direct main" 385 | description: 386 | name: share 387 | url: "https://pub.dartlang.org" 388 | source: hosted 389 | version: "2.0.1" 390 | sky_engine: 391 | dependency: transitive 392 | description: flutter 393 | source: sdk 394 | version: "0.0.99" 395 | source_span: 396 | dependency: transitive 397 | description: 398 | name: source_span 399 | url: "https://pub.dartlang.org" 400 | source: hosted 401 | version: "1.8.0" 402 | stack_trace: 403 | dependency: transitive 404 | description: 405 | name: stack_trace 406 | url: "https://pub.dartlang.org" 407 | source: hosted 408 | version: "1.10.0" 409 | stream_channel: 410 | dependency: transitive 411 | description: 412 | name: stream_channel 413 | url: "https://pub.dartlang.org" 414 | source: hosted 415 | version: "2.1.0" 416 | string_scanner: 417 | dependency: transitive 418 | description: 419 | name: string_scanner 420 | url: "https://pub.dartlang.org" 421 | source: hosted 422 | version: "1.1.0" 423 | term_glyph: 424 | dependency: transitive 425 | description: 426 | name: term_glyph 427 | url: "https://pub.dartlang.org" 428 | source: hosted 429 | version: "1.2.0" 430 | test_api: 431 | dependency: transitive 432 | description: 433 | name: test_api 434 | url: "https://pub.dartlang.org" 435 | source: hosted 436 | version: "0.2.19" 437 | typed_data: 438 | dependency: transitive 439 | description: 440 | name: typed_data 441 | url: "https://pub.dartlang.org" 442 | source: hosted 443 | version: "1.3.0" 444 | uuid: 445 | dependency: transitive 446 | description: 447 | name: uuid 448 | url: "https://pub.dartlang.org" 449 | source: hosted 450 | version: "3.0.2" 451 | vector_math: 452 | dependency: transitive 453 | description: 454 | name: vector_math 455 | url: "https://pub.dartlang.org" 456 | source: hosted 457 | version: "2.1.0" 458 | win32: 459 | dependency: transitive 460 | description: 461 | name: win32 462 | url: "https://pub.dartlang.org" 463 | source: hosted 464 | version: "2.0.4" 465 | xdg_directories: 466 | dependency: transitive 467 | description: 468 | name: xdg_directories 469 | url: "https://pub.dartlang.org" 470 | source: hosted 471 | version: "0.2.0" 472 | xml: 473 | dependency: transitive 474 | description: 475 | name: xml 476 | url: "https://pub.dartlang.org" 477 | source: hosted 478 | version: "4.5.1" 479 | sdks: 480 | dart: ">=2.12.0 <3.0.0" 481 | flutter: ">=1.24.0-10.1.pre" 482 | -------------------------------------------------------------------------------- /lib/ui/pages/alquran/alquran_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:my_alquran/bloc/b_alquran/alquran_bloc.dart'; 6 | import 'package:my_alquran/config/route_name.dart'; 7 | import 'package:my_alquran/theme/theme_color.dart'; 8 | import 'package:my_alquran/theme/theme_text.dart'; 9 | import 'package:my_alquran/ui/pages/surah/surah_arguments.dart'; 10 | import 'package:my_alquran/ui/widget/custome_page.dart'; 11 | import 'package:relative_scale/relative_scale.dart'; 12 | 13 | class AlQuranView extends StatefulWidget { 14 | @override 15 | _AlQuranViewState createState() => _AlQuranViewState(); 16 | } 17 | 18 | class _AlQuranViewState extends State { 19 | // Refresh 20 | Completer _refreshCompleter; 21 | 22 | // Bloc 23 | AlQuranBloc _alQuranBloc; 24 | 25 | @override 26 | void initState() { 27 | _alQuranBloc = BlocProvider.of(context); 28 | _refreshCompleter = Completer(); 29 | super.initState(); 30 | } 31 | 32 | @override 33 | void dispose() { 34 | _alQuranBloc.close(); 35 | super.dispose(); 36 | } 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return RelativeBuilder( 41 | builder: (context, height, width, sy, sx) { 42 | return CustomePage( 43 | scaffold: Scaffold( 44 | backgroundColor: whiteColor, 45 | body: BlocListener( 46 | listener: (context, state) { 47 | if (state is AlQuranLoadInProgress) { 48 | _refreshCompleter?.complete(); 49 | _refreshCompleter = Completer(); 50 | } 51 | }, 52 | child: BlocBuilder( 53 | cubit: _alQuranBloc, 54 | builder: (context, state) { 55 | if (state is AlQuranLoadInProgress) { 56 | return Center( 57 | child: CircularProgressIndicator(), 58 | ); 59 | } 60 | if (state is AlQuranLoadedSuccess) { 61 | return RefreshIndicator( 62 | onRefresh: () { 63 | _alQuranBloc 64 | ..add( 65 | GetListAlQuranFromApi(), 66 | ); 67 | return _refreshCompleter.future; 68 | }, 69 | child: Stack( 70 | alignment: Alignment.bottomCenter, 71 | children: [ 72 | ListView.builder( 73 | shrinkWrap: true, 74 | padding: EdgeInsets.only( 75 | bottom: sy(90), 76 | ), 77 | itemCount: state.modelListAlQuran.data.length, 78 | itemBuilder: (context, int index) { 79 | return GestureDetector( 80 | onTap: () { 81 | Navigator.pushNamed( 82 | context, 83 | RouteName.detailSurah, 84 | arguments: SurahArguments( 85 | idSurah: state 86 | .modelListAlQuran.data[index].number 87 | .toString(), 88 | nameSurah: state.modelListAlQuran 89 | .data[index].name.transliteration.id, 90 | ), 91 | ); 92 | }, 93 | child: Column( 94 | children: [ 95 | Container( 96 | height: sy(52), 97 | width: double.infinity, 98 | child: ListTile( 99 | dense: true, 100 | minLeadingWidth: sy(5), 101 | leading: Container( 102 | alignment: Alignment.center, 103 | width: sy(36), 104 | height: sy(36), 105 | decoration: BoxDecoration( 106 | shape: BoxShape.circle, 107 | color: greyColor1, 108 | ), 109 | child: Text( 110 | state.modelListAlQuran.data[index] 111 | .number 112 | .toString(), 113 | style: googlePoppinsMedium.copyWith( 114 | fontSize: 20, 115 | color: blueColor, 116 | ), 117 | ), 118 | ), 119 | title: Text( 120 | state.modelListAlQuran.data[index] 121 | .name.transliteration.id, 122 | style: googlePoppinsMedium.copyWith( 123 | fontSize: 16, 124 | color: blackColor1, 125 | letterSpacing: 0.3, 126 | ), 127 | ), 128 | subtitle: Text( 129 | '${state.modelListAlQuran.data[index].name.translation.id} | ${state.modelListAlQuran.data[index].numberOfVerses} Ayat', 130 | style: googlePoppinsRegular.copyWith( 131 | letterSpacing: 0.3, 132 | color: Colors.grey, 133 | fontSize: 12, 134 | ), 135 | ), 136 | trailing: Padding( 137 | padding: const EdgeInsets.only( 138 | right: 24, 139 | ), 140 | child: Text( 141 | state.modelListAlQuran.data[index] 142 | .name.short, 143 | style: arabicFont.copyWith( 144 | fontSize: 30, 145 | ), 146 | textAlign: TextAlign.right, 147 | ), 148 | ), 149 | ), 150 | ), 151 | Padding( 152 | padding: EdgeInsets.only( 153 | right: 20, 154 | left: 76, 155 | ), 156 | child: Divider( 157 | thickness: 1, 158 | color: greyColor, 159 | ), 160 | ), 161 | ], 162 | ), 163 | ); 164 | }, 165 | ), 166 | Container( 167 | height: sy(84), 168 | width: double.infinity, 169 | padding: EdgeInsets.only( 170 | left: 20, 171 | right: 20, 172 | ), 173 | decoration: BoxDecoration( 174 | color: Colors.white, 175 | boxShadow: [ 176 | BoxShadow( 177 | color: Colors.grey.withOpacity(0.5), 178 | spreadRadius: 1, 179 | blurRadius: 3, 180 | offset: Offset( 181 | 0, 182 | 3, 183 | ), // changes position of shadow 184 | ), 185 | ], 186 | ), 187 | alignment: Alignment.centerLeft, 188 | child: Row( 189 | crossAxisAlignment: CrossAxisAlignment.center, 190 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 191 | children: [ 192 | Expanded( 193 | flex: 1, 194 | child: Row( 195 | crossAxisAlignment: 196 | CrossAxisAlignment.center, 197 | children: [ 198 | Icon( 199 | Icons.bookmark, 200 | size: sy(24), 201 | color: orangeColor, 202 | ), 203 | SizedBox( 204 | width: sy(8), 205 | ), 206 | Column( 207 | crossAxisAlignment: 208 | CrossAxisAlignment.start, 209 | mainAxisAlignment: 210 | MainAxisAlignment.center, 211 | children: [ 212 | Text( 213 | 'Terakhir dibaca', 214 | style: 215 | googlePoppinsRegular.copyWith( 216 | fontSize: 10, 217 | letterSpacing: 0.3, 218 | color: blackColor1, 219 | ), 220 | ), 221 | Text( 222 | 'Al-Qamar Ayat 28', 223 | style: googlePoppinsMedium.copyWith( 224 | fontSize: 14, 225 | letterSpacing: 0.3, 226 | color: blackColor1, 227 | ), 228 | ), 229 | ], 230 | ), 231 | ], 232 | ), 233 | ), 234 | ElevatedButton( 235 | style: ElevatedButton.styleFrom( 236 | 237 | primary: blueColor, 238 | textStyle: googlePoppinsMedium.copyWith( 239 | color: whiteColor, 240 | letterSpacing: 0.3, 241 | fontSize: 14, 242 | ), 243 | shape: RoundedRectangleBorder( 244 | borderRadius: new BorderRadius.circular( 245 | 8.0, 246 | ), 247 | ), 248 | ), 249 | onPressed: () {}, 250 | child: Text( 251 | 'Lanjut Baca', 252 | ), 253 | ), 254 | ], 255 | ), 256 | ), 257 | ], 258 | ), 259 | ); 260 | } 261 | if (state is AlQuranLoadedError) { 262 | return Center( 263 | child: Column( 264 | mainAxisAlignment: MainAxisAlignment.center, 265 | children: [ 266 | Text( 267 | state.message, 268 | ), 269 | ElevatedButton( 270 | onPressed: () { 271 | _alQuranBloc 272 | ..add( 273 | GetListAlQuranFromApi(), 274 | ); 275 | }, 276 | child: Text( 277 | 'Refresh', 278 | ), 279 | ), 280 | ], 281 | ), 282 | ); 283 | } 284 | return Container(); 285 | }, 286 | ), 287 | ), 288 | ), 289 | ); 290 | }, 291 | ); 292 | } 293 | } 294 | 295 | class ModelBacaanPilihan { 296 | final int id; 297 | final String nameBacaan; 298 | 299 | ModelBacaanPilihan({ 300 | this.id, 301 | this.nameBacaan, 302 | }); 303 | } 304 | 305 | List listModelBacaanPilihan = [ 306 | ModelBacaanPilihan( 307 | id: 1, 308 | nameBacaan: "Kumpulan Do'a", 309 | ), 310 | ModelBacaanPilihan( 311 | id: 2, 312 | nameBacaan: "Ayat Pilihan", 313 | ), 314 | ModelBacaanPilihan( 315 | id: 3, 316 | nameBacaan: "Juz Amma", 317 | ), 318 | ModelBacaanPilihan( 319 | id: 4, 320 | nameBacaan: "Kumpulan Hadits", 321 | ), 322 | ]; 323 | -------------------------------------------------------------------------------- /lib/ui/pages/surah/surah_detail_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:google_fonts/google_fonts.dart'; 6 | import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; 7 | import 'package:my_alquran/bloc/b_alquran/alquran_bloc.dart'; 8 | import 'package:my_alquran/theme/theme_color.dart'; 9 | import 'package:my_alquran/theme/theme_text.dart'; 10 | import 'package:my_alquran/ui/pages/surah/surah_bottom_sheet_view.dart'; 11 | import 'package:my_alquran/ui/widget/custome_page.dart'; 12 | import 'package:relative_scale/relative_scale.dart'; 13 | 14 | class SurahDetailView extends StatefulWidget { 15 | final String nameSurah; 16 | final String idSurah; 17 | 18 | const SurahDetailView({ 19 | Key key, 20 | @required this.nameSurah, 21 | @required this.idSurah, 22 | }) : super(key: key); 23 | @override 24 | _SurahDetailViewState createState() => _SurahDetailViewState(); 25 | } 26 | 27 | class _SurahDetailViewState extends State { 28 | // Refresh 29 | Completer _refreshCompleter; 30 | 31 | // Bloc 32 | AlQuranBloc _alQuranBloc; 33 | 34 | @override 35 | void initState() { 36 | _alQuranBloc = BlocProvider.of(context); 37 | _refreshCompleter = Completer(); 38 | super.initState(); 39 | } 40 | 41 | @override 42 | void dispose() { 43 | _alQuranBloc.close(); 44 | super.dispose(); 45 | } 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | return RelativeBuilder( 50 | builder: (context, height, width, sy, sx) { 51 | return CustomePage( 52 | statusBarColor: Colors.transparent, 53 | statusBarIconBrightness: Brightness.dark, 54 | scaffold: Scaffold( 55 | backgroundColor: Colors.white, 56 | appBar: AppBar( 57 | backgroundColor: whiteColor, 58 | elevation: 0.0, 59 | title: Text( 60 | "Al-Quran", 61 | style: googlePoppinsMedium.copyWith( 62 | fontSize: 20, 63 | color: blackColor1, 64 | letterSpacing: 0.3, 65 | ), 66 | ), 67 | iconTheme: IconThemeData( 68 | color: blackColor, 69 | size: 24, 70 | ), 71 | actions: [ 72 | IconButton( 73 | icon: Icon( 74 | Icons.search, 75 | color: blackColor1, 76 | size: 24, 77 | ), 78 | onPressed: () {}, 79 | ), 80 | IconButton( 81 | icon: Icon( 82 | Icons.more_vert, 83 | color: blackColor1, 84 | size: 24, 85 | ), 86 | onPressed: () {}, 87 | ), 88 | ], 89 | ), 90 | body: BlocListener( 91 | listener: (context, state) { 92 | if (state is DetailSurahLoadInProgress) { 93 | _refreshCompleter?.complete(); 94 | _refreshCompleter = Completer(); 95 | } 96 | }, 97 | child: BlocBuilder( 98 | cubit: _alQuranBloc, 99 | builder: (context, state) { 100 | if (state is DetailSurahLoadInProgress) { 101 | return Column( 102 | children: [ 103 | Container( 104 | height: sy(32), 105 | padding: EdgeInsets.only( 106 | left: 20, 107 | right: 18, 108 | ), 109 | width: double.infinity, 110 | color: blueColor, 111 | ), 112 | Expanded( 113 | child: Center( 114 | child: CircularProgressIndicator(), 115 | ), 116 | ), 117 | ], 118 | ); 119 | } 120 | if (state is DetailSurahLoadedSuccess) { 121 | var juz = state.modelDetailSurah.data.verses.first; 122 | return RefreshIndicator( 123 | onRefresh: () { 124 | _alQuranBloc 125 | ..add( 126 | GetDetailSurahFromApi( 127 | idSurah: widget.idSurah, 128 | ), 129 | ); 130 | return _refreshCompleter.future; 131 | }, 132 | child: Column( 133 | children: [ 134 | Container( 135 | height: sy(32), 136 | padding: EdgeInsets.only( 137 | left: 20, 138 | right: 18, 139 | ), 140 | width: double.infinity, 141 | color: blueColor, 142 | child: Row( 143 | crossAxisAlignment: CrossAxisAlignment.center, 144 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 145 | children: [ 146 | Text( 147 | '${state.modelDetailSurah.data.number}. ${state.modelDetailSurah.data.name.transliteration.id}', 148 | style: googlePoppinsMedium.copyWith( 149 | fontSize: 16, 150 | letterSpacing: 0.3, 151 | color: whiteColor, 152 | ), 153 | ), 154 | Text( 155 | 'Juz ${juz.meta.juz}', 156 | style: googlePoppinsMedium.copyWith( 157 | fontSize: 16, 158 | letterSpacing: 0.3, 159 | color: whiteColor, 160 | ), 161 | ), 162 | ], 163 | ), 164 | ), 165 | Expanded( 166 | child: Container( 167 | child: ListView( 168 | children: [ 169 | state.modelDetailSurah.data.number == 1 170 | ? Container() 171 | : Container( 172 | color: Colors.transparent, 173 | alignment: Alignment.center, 174 | height: sy(54), 175 | width: double.infinity, 176 | child: Text( 177 | 'بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيم', 178 | style: arabicFont.copyWith( 179 | fontSize: 30, 180 | ), 181 | textAlign: TextAlign.center, 182 | ), 183 | ), 184 | ListView.builder( 185 | physics: NeverScrollableScrollPhysics(), 186 | shrinkWrap: true, 187 | itemCount: state 188 | .modelDetailSurah.data.verses.length, 189 | itemBuilder: (context, int index) { 190 | return GestureDetector( 191 | onTap: () => 192 | showMaterialModalBottomSheet( 193 | context: context, 194 | expand: false, 195 | elevation: 0.0, 196 | shape: RoundedRectangleBorder( 197 | borderRadius: BorderRadius.only( 198 | topLeft: Radius.circular(30.0), 199 | topRight: Radius.circular(30.0), 200 | ), 201 | ), 202 | backgroundColor: Colors.white, 203 | builder: (context) => 204 | SurahBottomSheetView( 205 | nameSurah: widget.nameSurah, 206 | ayatSurah: state 207 | .modelDetailSurah 208 | .data 209 | .verses[index] 210 | .number 211 | .inSurah 212 | .toString(), 213 | indexAudio: index, 214 | urlAudio: state 215 | .modelDetailSurah 216 | .data 217 | .verses[index] 218 | .audio 219 | .primary, 220 | textarab: state.modelDetailSurah 221 | .data.verses[index].text.arab, 222 | ), 223 | ), 224 | child: Container( 225 | padding: EdgeInsets.only( 226 | top: 12, 227 | left: 20, 228 | right: 20, 229 | bottom: 16, 230 | ), 231 | color: index % 2 == 0 232 | ? Color(0xFFF0F5FC) 233 | : Colors.white, 234 | child: Column( 235 | crossAxisAlignment: 236 | CrossAxisAlignment.start, 237 | children: [ 238 | Row( 239 | crossAxisAlignment: 240 | CrossAxisAlignment.start, 241 | children: [ 242 | Expanded( 243 | flex: 1, 244 | child: Text( 245 | '${state.modelDetailSurah.data.verses[index].number.inSurah.toString()}.', 246 | style: GoogleFonts 247 | .robotoMono( 248 | fontSize: sy(12), 249 | fontWeight: 250 | FontWeight.w400, 251 | ), 252 | ), 253 | ), 254 | Expanded( 255 | flex: 7, 256 | child: Text( 257 | state 258 | .modelDetailSurah 259 | .data 260 | .verses[index] 261 | .text 262 | .arab, 263 | style: 264 | arabicFont.copyWith( 265 | fontSize: 30, 266 | ), 267 | textAlign: 268 | TextAlign.right, 269 | ), 270 | ), 271 | ], 272 | ), 273 | Text( 274 | state 275 | .modelDetailSurah 276 | .data 277 | .verses[index] 278 | .translation 279 | .id, 280 | style: googlePoppinsRegular 281 | .copyWith( 282 | letterSpacing: 0.3, 283 | color: Colors.grey, 284 | fontSize: 12, 285 | ), 286 | textAlign: TextAlign.justify, 287 | ), 288 | ], 289 | ), 290 | ), 291 | ); 292 | }, 293 | ), 294 | ], 295 | ), 296 | ), 297 | ), 298 | ], 299 | ), 300 | ); 301 | } 302 | if (state is DetailSurahLoadedError) { 303 | return Center( 304 | child: Column( 305 | mainAxisAlignment: MainAxisAlignment.center, 306 | children: [ 307 | Text( 308 | state.message, 309 | ), 310 | ElevatedButton( 311 | onPressed: () { 312 | _alQuranBloc 313 | ..add( 314 | GetDetailSurahFromApi( 315 | idSurah: widget.idSurah), 316 | ); 317 | }, 318 | child: Text( 319 | 'Refresh', 320 | ), 321 | ), 322 | ], 323 | ), 324 | ); 325 | } 326 | return Container(); 327 | }, 328 | ), 329 | ), 330 | ), 331 | ); 332 | }, 333 | ); 334 | } 335 | } 336 | --------------------------------------------------------------------------------