├── ios ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── 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 ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── project.pbxproj ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── RunnerTests │ └── RunnerTests.swift └── .gitignore ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png ├── manifest.json └── index.html ├── 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 │ │ │ │ │ └── azhar │ │ │ │ │ └── absensi │ │ │ │ │ └── absensi_flutter │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── google-services.json │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── build.gradle └── settings.gradle ├── assets └── images │ ├── ic_absen.png │ ├── ic_leave.png │ └── ic_history.png ├── lib ├── utils │ └── facedetection │ │ ├── google_ml_kit.dart │ │ └── vision.dart ├── main.dart └── page │ ├── main_page.dart │ ├── history │ └── history_page.dart │ ├── absen │ ├── camera_page.dart │ └── absen_page.dart │ └── leave │ └── leave_page.dart ├── pubspec.yaml ├── .gitignore ├── test └── widget_test.dart ├── .metadata ├── analysis_options.yaml ├── README.md └── pubspec.lock /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/web/favicon.png -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/web/icons/Icon-512.png -------------------------------------------------------------------------------- /assets/images/ic_absen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/assets/images/ic_absen.png -------------------------------------------------------------------------------- /assets/images/ic_leave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/assets/images/ic_leave.png -------------------------------------------------------------------------------- /assets/images/ic_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/assets/images/ic_history.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/utils/facedetection/google_ml_kit.dart: -------------------------------------------------------------------------------- 1 | import 'vision.dart'; 2 | 3 | class GoogleMlKit { 4 | GoogleMlKit._(); 5 | 6 | static final Vision vision = Vision.instance; 7 | } 8 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/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/AzharRivaldi/absensi-face-detection-flutter/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/azhar/absensi/absensi_flutter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.azhar.absensi.absensi_flutter 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lib/utils/facedetection/vision.dart: -------------------------------------------------------------------------------- 1 | import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart'; 2 | 3 | class Vision { 4 | Vision._(); 5 | 6 | static final Vision instance = Vision._(); 7 | 8 | FaceDetector faceDetector([FaceDetectorOptions? options]) { 9 | return FaceDetector(options: options ?? FaceDetectorOptions()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "", 4 | "project_id": "", 5 | "storage_bucket": "" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "", 11 | "android_client_info": { 12 | "package_name": "com.azhar.absensi.absensi_flutter" 13 | } 14 | }, 15 | "oauth_client": [], 16 | "api_key": [ 17 | { 18 | "current_key": "" 19 | } 20 | ], 21 | "services": { 22 | "appinvite_service": { 23 | "other_platform_oauth_client": [] 24 | } 25 | } 26 | } 27 | ], 28 | "configuration_version": "1" 29 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: absensi_flutter 2 | description: "A new Flutter project." 3 | publish_to: 'none' 4 | version: 1.0.0+1 5 | 6 | environment: 7 | sdk: '>=3.2.4 <4.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | cupertino_icons: ^1.0.2 13 | dotted_border: ^2.1.0 14 | camera: ^0.10.5+9 15 | geolocator: ^11.0.0 16 | geocoding: ^2.1.1 17 | intl: ^0.19.0 18 | lottie: ^3.0.0 19 | google_mlkit_face_detection: ^0.5.0 20 | cloud_firestore: ^4.15.5 21 | firebase_core: ^2.25.4 22 | 23 | dev_dependencies: 24 | flutter_test: 25 | sdk: flutter 26 | flutter_lints: ^2.0.0 27 | 28 | flutter: 29 | uses-material-design: true 30 | assets: 31 | - assets/images/ 32 | - assets/raw/ -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.9.0' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath "com.google.gms:google-services:4.4.1" 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 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 | tasks.register("clean", Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | -------------------------------------------------------------------------------- /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 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false 21 | } 22 | } 23 | 24 | plugins { 25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 26 | id "com.android.application" version "7.3.0" apply false 27 | } 28 | 29 | include ":app" 30 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "absensi_flutter", 3 | "short_name": "absensi_flutter", 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 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 in the flutter_test package. 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:absensi_flutter/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(const 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/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:firebase_core/firebase_core.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'page/main_page.dart'; 4 | 5 | Future main() async { 6 | WidgetsFlutterBinding.ensureInitialized(); 7 | await Firebase.initializeApp( 8 | options: const FirebaseOptions( 9 | 10 | //ddta lihat di file google-services.json 11 | apiKey: 'AIzaSyCHiTpCHmKCLB1Z2a_xp4LKQctjsdeT', //current_key 12 | appId: '1:279022690649:android:19d829aab9c503436ea', //mobilesdk_app_id 13 | messagingSenderId: '279022690', //project_number 14 | projectId: 'absensi'), //project_id 15 | ); 16 | runApp(const MyApp()); 17 | } 18 | 19 | class MyApp extends StatelessWidget { 20 | const MyApp({Key? key}) : super(key: key); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return MaterialApp( 25 | debugShowCheckedModeBanner: false, 26 | theme: ThemeData( 27 | cardTheme: const CardTheme(surfaceTintColor: Colors.white), 28 | dialogTheme: const DialogTheme(surfaceTintColor: Colors.white, backgroundColor: Colors.white), 29 | colorScheme: ColorScheme.fromSeed(seedColor: Colors.pinkAccent), 30 | useMaterial3: true, 31 | ), 32 | home: const MainPage(), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.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: "ef1af02aead6fe2414f3aafa5a61087b610e1332" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 17 | base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 18 | - platform: android 19 | create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 20 | base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 21 | - platform: ios 22 | create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 23 | base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 24 | - platform: web 25 | create_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 26 | base_revision: ef1af02aead6fe2414f3aafa5a61087b610e1332 27 | 28 | # User provided section 29 | 30 | # List of Local paths (relative to this file) that should be 31 | # ignored by the migrate tool. 32 | # 33 | # Files that are not part of the templates will be ignored by default. 34 | unmanaged_files: 35 | - 'lib/main.dart' 36 | - 'ios/Runner.xcodeproj/project.pbxproj' 37 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Tutorial Membuat Aplikasi Absensi dengan Face Detection Flutter 2 | 3 | # Tutorial Build with Android Studio 4 | https://youtu.be/ur7pOxQRMPw 5 | 6 | # Tutorial Build with Step by Step 7 | https://rivaldi48.blogspot.com/2024/06/tutorial-membuat-aplikasi-absensi-dengan-face-detection-flutter.html 8 | 9 | 10 | 11 | ****If you use the Source Code, please make sure to credit and backlink to [Azhar Rivaldi](https://rivaldi48.blogspot.com/)*** 12 | 13 | ## 👇 Click For Support Me : 14 | 15 | 16 | 17 | ## 📄 License 18 | 19 | ``` 20 | Copyright (C) Azhar Rivaldi 21 | 22 | Licensed under the Apache License, Version 2.0 (the "License"); 23 | you may not use this file except in compliance with the License. 24 | You may obtain a copy of the License at 25 | 26 | http://www.apache.org/licenses/LICENSE-2.0 27 | 28 | Unless required by applicable law or agreed to in writing, software 29 | distributed under the License is distributed on an "AS IS" BASIS, 30 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 31 | See the License for the specific language governing permissions and 32 | limitations under the License. 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | id "com.google.gms.google-services" 6 | } 7 | 8 | def localProperties = new Properties() 9 | def localPropertiesFile = rootProject.file('local.properties') 10 | if (localPropertiesFile.exists()) { 11 | localPropertiesFile.withReader('UTF-8') { reader -> 12 | localProperties.load(reader) 13 | } 14 | } 15 | 16 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 17 | if (flutterVersionCode == null) { 18 | flutterVersionCode = '1' 19 | } 20 | 21 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 22 | if (flutterVersionName == null) { 23 | flutterVersionName = '1.0' 24 | } 25 | 26 | android { 27 | namespace "com.azhar.absensi.absensi_flutter" 28 | compileSdkVersion 34 29 | ndkVersion flutter.ndkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | applicationId "com.azhar.absensi.absensi_flutter" 46 | minSdkVersion 24 47 | targetSdkVersion 34 48 | versionCode flutterVersionCode.toInteger() 49 | versionName flutterVersionName 50 | multiDexEnabled = true 51 | } 52 | 53 | buildTypes { 54 | release { 55 | signingConfig signingConfigs.debug 56 | } 57 | } 58 | } 59 | 60 | flutter { 61 | source '../..' 62 | } 63 | 64 | dependencies { 65 | implementation(platform("com.google.firebase:firebase-bom:32.7.2")) //tambahkan ini 66 | } 67 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Absensi Flutter 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | absensi_flutter 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | absensi_flutter 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 20 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /lib/page/main_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:absensi_flutter/page/absen/absen_page.dart'; 2 | import 'package:absensi_flutter/page/history/history_page.dart'; 3 | import 'package:absensi_flutter/page/leave/leave_page.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | 7 | class MainPage extends StatelessWidget { 8 | const MainPage({super.key}); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return PopScope( 13 | canPop: false, 14 | onPopInvoked: (bool didPop) { 15 | if (didPop) { 16 | return; 17 | } 18 | _onWillPop(context); 19 | }, 20 | child: Scaffold( 21 | backgroundColor: Colors.white, 22 | body: SafeArea( 23 | child: Center( 24 | child: Column( 25 | mainAxisAlignment: MainAxisAlignment.center, 26 | children: [ 27 | Container( 28 | margin: const EdgeInsets.all(10), 29 | child: Expanded( 30 | child: InkWell( 31 | highlightColor: Colors.transparent, 32 | splashColor: Colors.transparent, 33 | onTap: () { 34 | Navigator.push(context, MaterialPageRoute(builder: (context) => const AbsenPage())); 35 | }, 36 | child: const Column( 37 | children: [ 38 | Image( 39 | image: AssetImage('assets/images/ic_absen.png'), 40 | height: 100, 41 | width: 100, 42 | ), 43 | SizedBox(height: 10), 44 | Text( 45 | "Absen Kehadiran", 46 | style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), 47 | ), 48 | ], 49 | ), 50 | ), 51 | ), 52 | ), 53 | const SizedBox(height: 40), 54 | Container( 55 | margin: const EdgeInsets.all(10), 56 | child: Expanded( 57 | child: InkWell( 58 | highlightColor: Colors.transparent, 59 | splashColor: Colors.transparent, 60 | onTap: () { 61 | Navigator.push(context, MaterialPageRoute(builder: (context) => const LeavePage())); 62 | }, 63 | child: const Column( 64 | children: [ 65 | Image( 66 | image: AssetImage('assets/images/ic_leave.png'), 67 | height: 100, 68 | width: 100, 69 | ), 70 | SizedBox(height: 10), 71 | Text( 72 | "Cuti / Izin", 73 | style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), 74 | ), 75 | ], 76 | ), 77 | ), 78 | ), 79 | ), 80 | const SizedBox(height: 40), 81 | Container( 82 | margin: const EdgeInsets.all(10), 83 | child: Expanded( 84 | child: InkWell( 85 | highlightColor: Colors.transparent, 86 | splashColor: Colors.transparent, 87 | onTap: () { 88 | Navigator.push(context, MaterialPageRoute(builder: (context) => const HistoryPage())); 89 | }, 90 | child: const Column( 91 | children: [ 92 | Image( 93 | image: AssetImage('assets/images/ic_history.png'), 94 | height: 100, 95 | width: 100, 96 | ), 97 | SizedBox(height: 10), 98 | Text( 99 | "Riwayat Absensi", 100 | style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), 101 | ), 102 | ], 103 | ), 104 | ), 105 | ), 106 | ), 107 | ], 108 | ), 109 | ), 110 | ), 111 | ), 112 | ); 113 | } 114 | 115 | Future _onWillPop(BuildContext context) async { 116 | return (await showDialog( 117 | barrierDismissible: false, 118 | context: context, 119 | builder: (context) => 120 | AlertDialog( 121 | title: const Text("INFO", 122 | style: TextStyle( 123 | color: Colors.black, 124 | fontSize: 20, 125 | fontWeight: FontWeight.bold), 126 | ), 127 | content: const Text("Apa Anda ingin keluar dari aplikasi?", 128 | style: TextStyle(color: Colors.black, fontSize: 16)), 129 | actions: [ 130 | TextButton( 131 | onPressed: () => Navigator.of(context).pop(false), 132 | child: const Text("Batal", 133 | style: TextStyle( 134 | color: Colors.black, 135 | fontSize: 14)), 136 | ), 137 | TextButton( 138 | onPressed: () => SystemNavigator.pop(), 139 | child: const Text("Ya", 140 | style: TextStyle( 141 | color: Colors.pinkAccent, 142 | fontSize: 14)), 143 | ), 144 | ], 145 | ), 146 | )) ?? false; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/page/history/history_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:cloud_firestore/cloud_firestore.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | class HistoryPage extends StatefulWidget { 7 | const HistoryPage({super.key}); 8 | 9 | @override 10 | State createState() => _HistoryPageState(); 11 | } 12 | 13 | class _HistoryPageState extends State { 14 | final CollectionReference dataCollection = FirebaseFirestore.instance.collection('absensi'); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return Scaffold( 19 | backgroundColor: Colors.white, 20 | appBar: AppBar( 21 | elevation: 0, 22 | backgroundColor: Colors.pinkAccent, 23 | leading: IconButton( 24 | icon: const Icon(Icons.arrow_back_ios, color: Colors.white), 25 | onPressed: () => Navigator.of(context).pop(), 26 | ), 27 | title: const Text( 28 | "Riwayat Absensi", 29 | style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white), 30 | ), 31 | ), 32 | body: FutureBuilder( 33 | future: dataCollection.get(), 34 | builder: (context, snapshot) { 35 | if (snapshot.hasData) { 36 | var data = snapshot.data!.docs; 37 | return data.isNotEmpty ? ListView.builder( 38 | itemCount: data.length, 39 | itemBuilder: (context, index) { 40 | return GestureDetector( 41 | onTap: () { 42 | AlertDialog dialogHapus = AlertDialog( 43 | title: const Text("Hapus Data", style: TextStyle(fontSize: 18, color: Colors.black)), 44 | content: const SizedBox( 45 | height: 20, 46 | child: Column( 47 | children: [ 48 | Text("Yakin ingin menghapus data ini?", style: 49 | TextStyle(fontSize: 14, color: Colors.black)) 50 | ], 51 | ), 52 | ), 53 | actions: [ 54 | TextButton( 55 | onPressed: () { 56 | setState(() { 57 | dataCollection.doc(data[index].id).delete(); 58 | Navigator.pop(context); 59 | }); 60 | }, 61 | child: const Text("Ya", 62 | style: TextStyle(fontSize: 14, color: Colors.pinkAccent), 63 | ), 64 | ), 65 | TextButton( 66 | child: const Text("Tidak", 67 | style: TextStyle(fontSize: 14, color: Colors.black)), 68 | onPressed: () { 69 | Navigator.pop(context); 70 | }, 71 | ), 72 | ], 73 | ); 74 | showDialog( 75 | context: context, 76 | builder: (context) => dialogHapus); 77 | }, 78 | child: Card( 79 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), 80 | elevation: 5, 81 | margin: const EdgeInsets.all(10), 82 | color: Colors.white, 83 | child: Padding( 84 | padding: const EdgeInsets.all(8), 85 | child: Row( 86 | children: [ 87 | Container( 88 | height: 50, 89 | width: 50, 90 | decoration: BoxDecoration( 91 | color: Colors.primaries[Random().nextInt(Colors.primaries.length)], 92 | borderRadius: const BorderRadius.all(Radius.circular(50)) 93 | ), 94 | child: Center( 95 | child: Text(data[index]['nama'][0].toUpperCase(), style: const TextStyle( 96 | color: Colors.white, 97 | fontSize: 14), 98 | ) 99 | ), 100 | ), 101 | const SizedBox( 102 | width: 10, 103 | ), 104 | Flexible( 105 | child: Column( 106 | crossAxisAlignment: CrossAxisAlignment.start, 107 | mainAxisAlignment: MainAxisAlignment.center, 108 | children: [ 109 | Row( 110 | children: [ 111 | const Expanded( 112 | flex: 4, 113 | child: Text("Nama", style: TextStyle( 114 | color: Colors.black, 115 | fontSize: 14), 116 | ), 117 | ), 118 | const Expanded( 119 | flex: 1, 120 | child: Text(" : ", style: TextStyle( 121 | color: Colors.black, 122 | fontSize: 14), 123 | ), 124 | ), 125 | Expanded( 126 | flex: 8, 127 | child: Text(data[index]['nama'], 128 | style: const TextStyle( 129 | color: Colors.black, 130 | fontSize: 14), 131 | ), 132 | ), 133 | ], 134 | ), 135 | Row( 136 | children: [ 137 | const Expanded( 138 | flex: 4, 139 | child: Text("Alamat", style: TextStyle( 140 | color: Colors.black, 141 | fontSize: 14), 142 | ), 143 | ), 144 | const Expanded( 145 | flex: 1, 146 | child: Text(" : ", style: TextStyle( 147 | color: Colors.black, 148 | fontSize: 14), 149 | ), 150 | ), 151 | Expanded( 152 | flex: 8, 153 | child: Text(data[index]['alamat'], 154 | style: const TextStyle( 155 | color: Colors.black, 156 | fontSize: 14), 157 | ), 158 | ), 159 | ], 160 | ), 161 | Row( 162 | children: [ 163 | const Expanded( 164 | flex: 4, 165 | child: Text("Keterangan", style: TextStyle( 166 | color: Colors.black, 167 | fontSize: 14), 168 | ), 169 | ), 170 | const Expanded( 171 | flex: 1, 172 | child: Text(" : ", style: TextStyle( 173 | color: Colors.black, 174 | fontSize: 14), 175 | ), 176 | ), 177 | Expanded( 178 | flex: 8, 179 | child: Text(data[index]['keterangan'], 180 | style: const TextStyle( 181 | color: Colors.black, 182 | fontSize: 14), 183 | ), 184 | ), 185 | ], 186 | ), 187 | Row( 188 | children: [ 189 | const Expanded( 190 | flex: 4, 191 | child: Text("Waktu Absen", style: TextStyle( 192 | color: Colors.black, 193 | fontSize: 14), 194 | ), 195 | ), 196 | const Expanded( 197 | flex: 1, 198 | child: Text(" : ", style: TextStyle( 199 | color: Colors.black, 200 | fontSize: 14), 201 | ), 202 | ), 203 | Expanded( 204 | flex: 8, 205 | child: Text(data[index]['datetime'], 206 | style: const TextStyle( 207 | color: Colors.black, 208 | fontSize: 14), 209 | ), 210 | ), 211 | ], 212 | ), 213 | ], 214 | ), 215 | ) 216 | ], 217 | ), 218 | ), 219 | ), 220 | ); 221 | }) : const Center( child: Text("Ups, tidak ada data!", 222 | style: TextStyle(fontSize: 20))); 223 | } else { 224 | return const Center(child: CircularProgressIndicator( 225 | valueColor: AlwaysStoppedAnimation(Colors.pinkAccent), 226 | )); 227 | } 228 | }, 229 | ), 230 | ); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /lib/page/absen/camera_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:absensi_flutter/page/absen/absen_page.dart'; 4 | import 'package:absensi_flutter/utils/facedetection/google_ml_kit.dart'; 5 | import 'package:camera/camera.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:geolocator/geolocator.dart'; 8 | import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart'; 9 | import 'package:lottie/lottie.dart'; 10 | 11 | class CameraAbsenPage extends StatefulWidget { 12 | const CameraAbsenPage({super.key}); 13 | 14 | @override 15 | State createState() => _State(); 16 | } 17 | 18 | class _State extends State with TickerProviderStateMixin { 19 | 20 | //set face detection 21 | FaceDetector faceDetector = GoogleMlKit.vision.faceDetector(FaceDetectorOptions( 22 | enableContours: true, 23 | enableClassification: true, 24 | enableTracking: true, 25 | enableLandmarks: true 26 | )); 27 | 28 | List? cameras; 29 | CameraController? controller; 30 | XFile? image; 31 | bool isBusy = false; 32 | 33 | @override 34 | void initState() { 35 | loadCamera(); 36 | super.initState(); 37 | } 38 | 39 | //set open front camera device 40 | //if 1 front, if 0 rear 41 | loadCamera() async { 42 | cameras = await availableCameras(); 43 | if (cameras != null) { 44 | controller = CameraController(cameras![1], ResolutionPreset.max); 45 | controller!.initialize().then((_) { 46 | if (!mounted) { 47 | return; 48 | } 49 | setState(() {}); 50 | }); 51 | } else { 52 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 53 | content: Row( 54 | children: [ 55 | Icon( 56 | Icons.camera_enhance_outlined, 57 | color: Colors.white, 58 | ), 59 | SizedBox(width: 10), 60 | Text("Ups, kamera tidak ditemukan!", style: TextStyle(color: Colors.white)) 61 | ], 62 | ), 63 | backgroundColor: Colors.redAccent, 64 | shape: StadiumBorder(), 65 | behavior: SnackBarBehavior.floating, 66 | )); 67 | } 68 | } 69 | 70 | @override 71 | Widget build(BuildContext context) { 72 | Size size = MediaQuery.of(context).size; 73 | 74 | //set loading 75 | showLoaderDialog(BuildContext context) { 76 | AlertDialog alert = AlertDialog( 77 | content: Row( 78 | children: [ 79 | const CircularProgressIndicator(valueColor: 80 | AlwaysStoppedAnimation(Colors.pinkAccent)), 81 | Container( 82 | margin: const EdgeInsets.only(left: 20), 83 | child: const Text("Sedang memeriksa data...") 84 | ), 85 | ], 86 | ), 87 | ); 88 | showDialog( 89 | barrierDismissible: false, 90 | context: context, 91 | builder: (BuildContext context) { 92 | return alert; 93 | }, 94 | ); 95 | } 96 | 97 | return Scaffold( 98 | appBar: AppBar( 99 | elevation: 0, 100 | backgroundColor: Colors.pinkAccent, 101 | leading: IconButton( 102 | icon: const Icon(Icons.arrow_back_ios, color: Colors.white), 103 | onPressed: () => Navigator.of(context).pop(), 104 | ), 105 | title: const Text( 106 | "Foto Selfie", 107 | style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white), 108 | ), 109 | ), 110 | body: Stack( 111 | children: [ 112 | SizedBox( 113 | height: size.height, 114 | width: size.width, 115 | child: controller == null 116 | ? const Center(child: Text("Ups, kamera bermasalah!", 117 | style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold))) 118 | : !controller!.value.isInitialized 119 | ? const Center(child: CircularProgressIndicator()) 120 | : CameraPreview(controller!) 121 | ), 122 | Padding( 123 | padding: const EdgeInsets.only(top: 40), 124 | child: Lottie.asset( 125 | "assets/raw/face_id_ring.json", 126 | fit: BoxFit.cover, 127 | ), 128 | ), 129 | Align( 130 | alignment: Alignment.bottomCenter, 131 | child: Container( 132 | width: size.width, 133 | height: 200, 134 | padding: const EdgeInsets.symmetric(horizontal: 30), 135 | decoration: const BoxDecoration( 136 | color: Colors.white, 137 | borderRadius: BorderRadius.only( 138 | topLeft: Radius.circular(28), 139 | topRight: Radius.circular(28), 140 | ), 141 | ), 142 | child: Column( 143 | children: [ 144 | const SizedBox( 145 | height: 20, 146 | ), 147 | const Text( 148 | "Pastikan Anda berada di tempat terang, agar wajah terlihat jelas.", 149 | style: TextStyle(fontSize: 16, color: Colors.black), 150 | ), 151 | Padding( 152 | padding: const EdgeInsets.only(top: 40), 153 | child: ClipOval( 154 | child: Material( 155 | color: Colors.pinkAccent, // Button color 156 | child: InkWell( 157 | splashColor: Colors.pink, // Splash color 158 | onTap: () async { 159 | final hasPermission = await handleLocationPermission(); 160 | try { 161 | if (controller != null) { 162 | if (controller!.value.isInitialized) { 163 | controller!.setFlashMode(FlashMode.off); 164 | image = await controller!.takePicture(); 165 | setState(() { 166 | if (hasPermission) { 167 | showLoaderDialog(context); 168 | final inputImage = InputImage.fromFilePath(image!.path); 169 | Platform.isAndroid ? processImage(inputImage) : Navigator.push(context, 170 | MaterialPageRoute(builder: (context) => AbsenPage(image: image))); 171 | } 172 | else { 173 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 174 | content: Row( 175 | children: [ 176 | Icon( 177 | Icons.location_on_outlined, 178 | color: Colors.white, 179 | ), 180 | SizedBox(width: 10), 181 | Text("Nyalakan perizinan lokasi terlebih dahulu!", 182 | style: TextStyle(color: Colors.white), 183 | ) 184 | ], 185 | ), 186 | backgroundColor: Colors.redAccent, 187 | shape: StadiumBorder(), 188 | behavior: SnackBarBehavior.floating, 189 | )); 190 | } 191 | }); 192 | } 193 | } 194 | } catch (e) { 195 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 196 | content: Row( 197 | children: [ 198 | const Icon( 199 | Icons.error_outline, 200 | color: Colors.white, 201 | ), 202 | const SizedBox(width: 10), 203 | Text("Ups, $e", 204 | style: const TextStyle(color: Colors.white), 205 | ) 206 | ], 207 | ), 208 | backgroundColor: Colors.redAccent, 209 | shape: const StadiumBorder(), 210 | behavior: SnackBarBehavior.floating, 211 | )); 212 | } 213 | }, 214 | child: const SizedBox( 215 | width: 56, 216 | height: 56, 217 | child: Icon( 218 | Icons.camera_enhance_outlined, 219 | color: Colors.white, 220 | ), 221 | ), 222 | ), 223 | ), 224 | ), 225 | ), 226 | ], 227 | ), 228 | ), 229 | ), 230 | ], 231 | ), 232 | ); 233 | } 234 | 235 | //permission location 236 | Future handleLocationPermission() async { 237 | bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); 238 | if (!serviceEnabled) { 239 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 240 | content: Row( 241 | children: [ 242 | Icon( 243 | Icons.location_off, 244 | color: Colors.white, 245 | ), 246 | SizedBox(width: 10), 247 | Text("Location services are disabled. Please enable the services.", 248 | style: TextStyle(color: Colors.white), 249 | ) 250 | ], 251 | ), 252 | backgroundColor: Colors.redAccent, 253 | shape: StadiumBorder(), 254 | behavior: SnackBarBehavior.floating, 255 | )); 256 | return false; 257 | } 258 | 259 | LocationPermission permission = await Geolocator.checkPermission(); 260 | if (permission == LocationPermission.denied) { 261 | permission = await Geolocator.requestPermission(); 262 | if (permission == LocationPermission.denied) { 263 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 264 | content: Row( 265 | children: [ 266 | Icon( 267 | Icons.location_off, 268 | color: Colors.white, 269 | ), 270 | SizedBox(width: 10), 271 | Text("Location permission denied.", 272 | style: TextStyle(color: Colors.white), 273 | ) 274 | ], 275 | ), 276 | backgroundColor: Colors.redAccent, 277 | shape: StadiumBorder(), 278 | behavior: SnackBarBehavior.floating, 279 | )); 280 | return false; 281 | } 282 | } 283 | 284 | if (permission == LocationPermission.deniedForever) { 285 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 286 | content: Row( 287 | children: [ 288 | Icon( 289 | Icons.location_off, 290 | color: Colors.white, 291 | ), 292 | SizedBox(width: 10), 293 | Text("Location permission denied forever, we cannot access.", 294 | style: TextStyle(color: Colors.white), 295 | ) 296 | ], 297 | ), 298 | backgroundColor: Colors.redAccent, 299 | shape: StadiumBorder(), 300 | behavior: SnackBarBehavior.floating, 301 | )); 302 | return false; 303 | } 304 | return true; 305 | } 306 | 307 | //face detection 308 | Future processImage(InputImage inputImage) async { 309 | if (isBusy) return; 310 | isBusy = true; 311 | final faces = await faceDetector.processImage(inputImage); 312 | isBusy = false; 313 | 314 | if (mounted) { 315 | setState(() { 316 | Navigator.of(context).pop(true); 317 | if (faces.length > 0) { 318 | Navigator.pushReplacement(context, 319 | MaterialPageRoute(builder: (context) => AbsenPage(image: image))); 320 | } else { 321 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 322 | content: Row( 323 | children: [ 324 | Icon( 325 | Icons.face_retouching_natural_outlined, 326 | color: Colors.white, 327 | ), 328 | SizedBox(width: 10), 329 | Expanded( 330 | child: Text( 331 | "Ups, pastikan wajah Anda terlihat jelas dengan cahaya yang cukup!", 332 | style: TextStyle(color: Colors.white), 333 | ), 334 | ) 335 | ], 336 | ), 337 | backgroundColor: Colors.redAccent, 338 | shape: StadiumBorder(), 339 | behavior: SnackBarBehavior.floating, 340 | )); 341 | } 342 | }); 343 | } 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _flutterfire_internals: 5 | dependency: transitive 6 | description: 7 | name: _flutterfire_internals 8 | sha256: "737321f9be522620ed3794937298fb0027a48a402624fa2500f7532f94aea810" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "1.3.22" 12 | archive: 13 | dependency: transitive 14 | description: 15 | name: archive 16 | sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "3.4.10" 20 | async: 21 | dependency: transitive 22 | description: 23 | name: async 24 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.11.0" 28 | boolean_selector: 29 | dependency: transitive 30 | description: 31 | name: boolean_selector 32 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.1.1" 36 | camera: 37 | dependency: "direct main" 38 | description: 39 | name: camera 40 | sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "0.10.5+9" 44 | camera_android: 45 | dependency: transitive 46 | description: 47 | name: camera_android 48 | sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "0.10.8+16" 52 | camera_avfoundation: 53 | dependency: transitive 54 | description: 55 | name: camera_avfoundation 56 | sha256: "7d0763dfcbf060f56aa254a68c103210280bee9e97bbe4fdef23e257a4f70ab9" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "0.9.14" 60 | camera_platform_interface: 61 | dependency: transitive 62 | description: 63 | name: camera_platform_interface 64 | sha256: fceb2c36038b6392317b1d5790c6ba9e6ca9f1da3031181b8bea03882bf9387a 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "2.7.3" 68 | camera_web: 69 | dependency: transitive 70 | description: 71 | name: camera_web 72 | sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "0.3.2+4" 76 | characters: 77 | dependency: transitive 78 | description: 79 | name: characters 80 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.3.0" 84 | clock: 85 | dependency: transitive 86 | description: 87 | name: clock 88 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "1.1.1" 92 | cloud_firestore: 93 | dependency: "direct main" 94 | description: 95 | name: cloud_firestore 96 | sha256: e51b896f23f96c541c29171ccfbe771696cc280767d1412df1237db4effea285 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "4.15.5" 100 | cloud_firestore_platform_interface: 101 | dependency: transitive 102 | description: 103 | name: cloud_firestore_platform_interface 104 | sha256: "8c5834277519f7e68d4bdf5ae04046ede3cb98ce7e3cfced3153fb83a16d2508" 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "6.1.6" 108 | cloud_firestore_web: 109 | dependency: transitive 110 | description: 111 | name: cloud_firestore_web 112 | sha256: "4f5d9164cf9873d05573eddeec62210be0efa5e4cb047ea81253b6da25ebd9dc" 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "3.10.5" 116 | collection: 117 | dependency: transitive 118 | description: 119 | name: collection 120 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 121 | url: "https://pub.dev" 122 | source: hosted 123 | version: "1.18.0" 124 | convert: 125 | dependency: transitive 126 | description: 127 | name: convert 128 | sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" 129 | url: "https://pub.dev" 130 | source: hosted 131 | version: "3.1.1" 132 | cross_file: 133 | dependency: transitive 134 | description: 135 | name: cross_file 136 | sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e 137 | url: "https://pub.dev" 138 | source: hosted 139 | version: "0.3.3+8" 140 | crypto: 141 | dependency: transitive 142 | description: 143 | name: crypto 144 | sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab 145 | url: "https://pub.dev" 146 | source: hosted 147 | version: "3.0.3" 148 | cupertino_icons: 149 | dependency: "direct main" 150 | description: 151 | name: cupertino_icons 152 | sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d 153 | url: "https://pub.dev" 154 | source: hosted 155 | version: "1.0.6" 156 | dotted_border: 157 | dependency: "direct main" 158 | description: 159 | name: dotted_border 160 | sha256: "108837e11848ca776c53b30bc870086f84b62ed6e01c503ed976e8f8c7df9c04" 161 | url: "https://pub.dev" 162 | source: hosted 163 | version: "2.1.0" 164 | fake_async: 165 | dependency: transitive 166 | description: 167 | name: fake_async 168 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 169 | url: "https://pub.dev" 170 | source: hosted 171 | version: "1.3.1" 172 | firebase_core: 173 | dependency: "direct main" 174 | description: 175 | name: firebase_core 176 | sha256: "7e049e32a9d347616edb39542cf92cd53fdb4a99fb6af0a0bff327c14cd76445" 177 | url: "https://pub.dev" 178 | source: hosted 179 | version: "2.25.4" 180 | firebase_core_platform_interface: 181 | dependency: transitive 182 | description: 183 | name: firebase_core_platform_interface 184 | sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63 185 | url: "https://pub.dev" 186 | source: hosted 187 | version: "5.0.0" 188 | firebase_core_web: 189 | dependency: transitive 190 | description: 191 | name: firebase_core_web 192 | sha256: "57e61d6010e253b36d38191cefd6199d7849152cdcd234b61ca290cdb278a0ba" 193 | url: "https://pub.dev" 194 | source: hosted 195 | version: "2.11.4" 196 | fixnum: 197 | dependency: transitive 198 | description: 199 | name: fixnum 200 | sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" 201 | url: "https://pub.dev" 202 | source: hosted 203 | version: "1.1.0" 204 | flutter: 205 | dependency: "direct main" 206 | description: flutter 207 | source: sdk 208 | version: "0.0.0" 209 | flutter_lints: 210 | dependency: "direct dev" 211 | description: 212 | name: flutter_lints 213 | sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 214 | url: "https://pub.dev" 215 | source: hosted 216 | version: "2.0.3" 217 | flutter_plugin_android_lifecycle: 218 | dependency: transitive 219 | description: 220 | name: flutter_plugin_android_lifecycle 221 | sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da 222 | url: "https://pub.dev" 223 | source: hosted 224 | version: "2.0.17" 225 | flutter_test: 226 | dependency: "direct dev" 227 | description: flutter 228 | source: sdk 229 | version: "0.0.0" 230 | flutter_web_plugins: 231 | dependency: transitive 232 | description: flutter 233 | source: sdk 234 | version: "0.0.0" 235 | geocoding: 236 | dependency: "direct main" 237 | description: 238 | name: geocoding 239 | sha256: e1dc0ac56666d9ed1d5a9ae5543ce9eb5986db6209cc7600103487d09192059c 240 | url: "https://pub.dev" 241 | source: hosted 242 | version: "2.1.1" 243 | geocoding_android: 244 | dependency: transitive 245 | description: 246 | name: geocoding_android 247 | sha256: "609db1d71bc364dd9d0616f72a41c01e0c74f3a3807efb85e0d5a67e57baf50f" 248 | url: "https://pub.dev" 249 | source: hosted 250 | version: "2.1.2" 251 | geocoding_ios: 252 | dependency: transitive 253 | description: 254 | name: geocoding_ios 255 | sha256: "8f79e380abb640ef4d88baee8bb65390058c802601158d0813dc990b36b189d2" 256 | url: "https://pub.dev" 257 | source: hosted 258 | version: "2.1.1" 259 | geocoding_platform_interface: 260 | dependency: transitive 261 | description: 262 | name: geocoding_platform_interface 263 | sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" 264 | url: "https://pub.dev" 265 | source: hosted 266 | version: "2.0.1" 267 | geolocator: 268 | dependency: "direct main" 269 | description: 270 | name: geolocator 271 | sha256: "694ec58afe97787b5b72b8a0ab78c1a9244811c3c10e72c4362ef3c0ceb005cd" 272 | url: "https://pub.dev" 273 | source: hosted 274 | version: "11.0.0" 275 | geolocator_android: 276 | dependency: transitive 277 | description: 278 | name: geolocator_android 279 | sha256: "136f1c97e1903366393bda514c5d9e98843418baea52899aa45edae9af8a5cd6" 280 | url: "https://pub.dev" 281 | source: hosted 282 | version: "4.5.2" 283 | geolocator_apple: 284 | dependency: transitive 285 | description: 286 | name: geolocator_apple 287 | sha256: "2f2d4ee16c4df269e93c0e382be075cc01d5db6703c3196e4af20a634fe49ef4" 288 | url: "https://pub.dev" 289 | source: hosted 290 | version: "2.3.6" 291 | geolocator_platform_interface: 292 | dependency: transitive 293 | description: 294 | name: geolocator_platform_interface 295 | sha256: "009a21c4bc2761e58dccf07c24f219adaebe0ff707abdfd40b0a763d4003fab9" 296 | url: "https://pub.dev" 297 | source: hosted 298 | version: "4.2.2" 299 | geolocator_web: 300 | dependency: transitive 301 | description: 302 | name: geolocator_web 303 | sha256: "49d8f846ebeb5e2b6641fe477a7e97e5dd73f03cbfef3fd5c42177b7300fb0ed" 304 | url: "https://pub.dev" 305 | source: hosted 306 | version: "3.0.0" 307 | geolocator_windows: 308 | dependency: transitive 309 | description: 310 | name: geolocator_windows 311 | sha256: a92fae29779d5c6dc60e8411302f5221ade464968fe80a36d330e80a71f087af 312 | url: "https://pub.dev" 313 | source: hosted 314 | version: "0.2.2" 315 | google_mlkit_commons: 316 | dependency: transitive 317 | description: 318 | name: google_mlkit_commons 319 | sha256: af63771903947d5523d9e991a939a4b8bf994f11661c9b9c8a71d7d3997115f8 320 | url: "https://pub.dev" 321 | source: hosted 322 | version: "0.2.0" 323 | google_mlkit_face_detection: 324 | dependency: "direct main" 325 | description: 326 | name: google_mlkit_face_detection 327 | sha256: db3a14db32640cf279a24202140958a2b017925eedae7e2cdf69dab98e92c23b 328 | url: "https://pub.dev" 329 | source: hosted 330 | version: "0.5.0" 331 | intl: 332 | dependency: "direct main" 333 | description: 334 | name: intl 335 | sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf 336 | url: "https://pub.dev" 337 | source: hosted 338 | version: "0.19.0" 339 | js: 340 | dependency: transitive 341 | description: 342 | name: js 343 | sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 344 | url: "https://pub.dev" 345 | source: hosted 346 | version: "0.6.7" 347 | leak_tracker: 348 | dependency: transitive 349 | description: 350 | name: leak_tracker 351 | sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" 352 | url: "https://pub.dev" 353 | source: hosted 354 | version: "10.0.0" 355 | leak_tracker_flutter_testing: 356 | dependency: transitive 357 | description: 358 | name: leak_tracker_flutter_testing 359 | sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 360 | url: "https://pub.dev" 361 | source: hosted 362 | version: "2.0.1" 363 | leak_tracker_testing: 364 | dependency: transitive 365 | description: 366 | name: leak_tracker_testing 367 | sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 368 | url: "https://pub.dev" 369 | source: hosted 370 | version: "2.0.1" 371 | lints: 372 | dependency: transitive 373 | description: 374 | name: lints 375 | sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" 376 | url: "https://pub.dev" 377 | source: hosted 378 | version: "2.1.1" 379 | lottie: 380 | dependency: "direct main" 381 | description: 382 | name: lottie 383 | sha256: "1f0ce68112072d66ea271a9841994fa8d16442e23d8cf8996c9fa74174e58b4e" 384 | url: "https://pub.dev" 385 | source: hosted 386 | version: "3.0.0" 387 | matcher: 388 | dependency: transitive 389 | description: 390 | name: matcher 391 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 392 | url: "https://pub.dev" 393 | source: hosted 394 | version: "0.12.16+1" 395 | material_color_utilities: 396 | dependency: transitive 397 | description: 398 | name: material_color_utilities 399 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" 400 | url: "https://pub.dev" 401 | source: hosted 402 | version: "0.8.0" 403 | meta: 404 | dependency: transitive 405 | description: 406 | name: meta 407 | sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 408 | url: "https://pub.dev" 409 | source: hosted 410 | version: "1.11.0" 411 | path: 412 | dependency: transitive 413 | description: 414 | name: path 415 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 416 | url: "https://pub.dev" 417 | source: hosted 418 | version: "1.9.0" 419 | path_drawing: 420 | dependency: transitive 421 | description: 422 | name: path_drawing 423 | sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 424 | url: "https://pub.dev" 425 | source: hosted 426 | version: "1.0.1" 427 | path_parsing: 428 | dependency: transitive 429 | description: 430 | name: path_parsing 431 | sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf 432 | url: "https://pub.dev" 433 | source: hosted 434 | version: "1.0.1" 435 | plugin_platform_interface: 436 | dependency: transitive 437 | description: 438 | name: plugin_platform_interface 439 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" 440 | url: "https://pub.dev" 441 | source: hosted 442 | version: "2.1.8" 443 | pointycastle: 444 | dependency: transitive 445 | description: 446 | name: pointycastle 447 | sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" 448 | url: "https://pub.dev" 449 | source: hosted 450 | version: "3.7.4" 451 | sky_engine: 452 | dependency: transitive 453 | description: flutter 454 | source: sdk 455 | version: "0.0.99" 456 | source_span: 457 | dependency: transitive 458 | description: 459 | name: source_span 460 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 461 | url: "https://pub.dev" 462 | source: hosted 463 | version: "1.10.0" 464 | sprintf: 465 | dependency: transitive 466 | description: 467 | name: sprintf 468 | sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" 469 | url: "https://pub.dev" 470 | source: hosted 471 | version: "7.0.0" 472 | stack_trace: 473 | dependency: transitive 474 | description: 475 | name: stack_trace 476 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 477 | url: "https://pub.dev" 478 | source: hosted 479 | version: "1.11.1" 480 | stream_channel: 481 | dependency: transitive 482 | description: 483 | name: stream_channel 484 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 485 | url: "https://pub.dev" 486 | source: hosted 487 | version: "2.1.2" 488 | stream_transform: 489 | dependency: transitive 490 | description: 491 | name: stream_transform 492 | sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" 493 | url: "https://pub.dev" 494 | source: hosted 495 | version: "2.1.0" 496 | string_scanner: 497 | dependency: transitive 498 | description: 499 | name: string_scanner 500 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 501 | url: "https://pub.dev" 502 | source: hosted 503 | version: "1.2.0" 504 | term_glyph: 505 | dependency: transitive 506 | description: 507 | name: term_glyph 508 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 509 | url: "https://pub.dev" 510 | source: hosted 511 | version: "1.2.1" 512 | test_api: 513 | dependency: transitive 514 | description: 515 | name: test_api 516 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" 517 | url: "https://pub.dev" 518 | source: hosted 519 | version: "0.6.1" 520 | typed_data: 521 | dependency: transitive 522 | description: 523 | name: typed_data 524 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 525 | url: "https://pub.dev" 526 | source: hosted 527 | version: "1.3.2" 528 | uuid: 529 | dependency: transitive 530 | description: 531 | name: uuid 532 | sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 533 | url: "https://pub.dev" 534 | source: hosted 535 | version: "4.3.3" 536 | vector_math: 537 | dependency: transitive 538 | description: 539 | name: vector_math 540 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 541 | url: "https://pub.dev" 542 | source: hosted 543 | version: "2.1.4" 544 | vm_service: 545 | dependency: transitive 546 | description: 547 | name: vm_service 548 | sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 549 | url: "https://pub.dev" 550 | source: hosted 551 | version: "13.0.0" 552 | web: 553 | dependency: transitive 554 | description: 555 | name: web 556 | sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 557 | url: "https://pub.dev" 558 | source: hosted 559 | version: "0.3.0" 560 | sdks: 561 | dart: ">=3.2.4 <4.0.0" 562 | flutter: ">=3.16.6" 563 | -------------------------------------------------------------------------------- /lib/page/absen/absen_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:absensi_flutter/page/absen/camera_page.dart'; 4 | import 'package:absensi_flutter/page/main_page.dart'; 5 | import 'package:camera/camera.dart'; 6 | import 'package:cloud_firestore/cloud_firestore.dart'; 7 | import 'package:dotted_border/dotted_border.dart'; 8 | import 'package:flutter/material.dart'; 9 | import 'package:geocoding/geocoding.dart'; 10 | import 'package:geolocator/geolocator.dart'; 11 | import 'package:intl/intl.dart'; 12 | 13 | class AbsenPage extends StatefulWidget { 14 | final XFile? image; 15 | 16 | const AbsenPage({super.key, this.image}); 17 | 18 | @override 19 | State createState() => _AbsenPageState(this.image); 20 | } 21 | 22 | class _AbsenPageState extends State { 23 | _AbsenPageState(this.image); 24 | 25 | XFile? image; 26 | String strAlamat = "", strDate = "", strTime = "", strDateTime = "", strStatus = "Absen Masuk"; 27 | bool isLoading = false; 28 | double dLat = 0.0, dLong = 0.0; 29 | int dateHours = 0, dateMinutes = 0; 30 | final controllerName = TextEditingController(); 31 | final CollectionReference dataCollection = FirebaseFirestore.instance.collection('absensi'); 32 | 33 | @override 34 | void initState() { 35 | handleLocationPermission(); 36 | setDateTime(); 37 | setStatusAbsen(); 38 | 39 | if (image != null) { 40 | isLoading = true; 41 | getGeoLocationPosition(); 42 | } 43 | super.initState(); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | Size size = MediaQuery.of(context).size; 49 | 50 | return Scaffold( 51 | backgroundColor: Colors.white, 52 | appBar: AppBar( 53 | elevation: 0, 54 | backgroundColor: Colors.pinkAccent, 55 | leading: IconButton( 56 | icon: const Icon(Icons.arrow_back_ios, color: Colors.white), 57 | onPressed: () => Navigator.of(context).pop(), 58 | ), 59 | title: const Text( 60 | "Menu Absensi", 61 | style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white), 62 | ), 63 | ), 64 | body: SingleChildScrollView( 65 | child: Card( 66 | color: Colors.white, 67 | margin: const EdgeInsets.fromLTRB(10, 10, 10, 30), 68 | shape: RoundedRectangleBorder( 69 | borderRadius: BorderRadius.circular(10), 70 | ), 71 | elevation: 5, 72 | child: Column( 73 | crossAxisAlignment: CrossAxisAlignment.start, 74 | children: [ 75 | Container( 76 | height: 50, 77 | decoration: const BoxDecoration( 78 | borderRadius: BorderRadius.only( 79 | topLeft: Radius.circular(10), 80 | topRight: Radius.circular(10)), 81 | color: Colors.pinkAccent, 82 | ), 83 | child: const Row( 84 | children: [ 85 | SizedBox( 86 | width: 12, 87 | ), 88 | Icon(Icons.face_retouching_natural_outlined, color: Colors.white), 89 | SizedBox( 90 | width: 12, 91 | ), 92 | Text( 93 | "Absen Foto Selfie ya!", 94 | style: TextStyle( 95 | fontSize: 18, 96 | fontWeight: FontWeight.bold, 97 | color: Colors.white), 98 | ), 99 | ], 100 | ), 101 | ), 102 | const Padding( 103 | padding: EdgeInsets.fromLTRB(10, 20, 0, 20), 104 | child: Text( 105 | "Ambil Foto", 106 | style: TextStyle( 107 | fontSize: 16, 108 | fontWeight: FontWeight.bold, 109 | color: Colors.black), 110 | ), 111 | ), 112 | GestureDetector( 113 | onTap: () { 114 | Navigator.push( 115 | context, 116 | MaterialPageRoute(builder: (context) => const CameraAbsenPage())); 117 | }, 118 | child: Container( 119 | margin: const EdgeInsets.fromLTRB(10, 0, 10, 20), 120 | width: size.width, 121 | height: 150, 122 | child: DottedBorder( 123 | radius: const Radius.circular(10), 124 | borderType: BorderType.RRect, 125 | color: Colors.pinkAccent, 126 | strokeWidth: 1, 127 | dashPattern: const [5, 5], 128 | child: SizedBox.expand( 129 | child: FittedBox( 130 | child: image != null 131 | ? Image.file(File(image!.path), fit: BoxFit.cover) 132 | : const Icon( 133 | Icons.camera_enhance_outlined, 134 | color: Colors.pinkAccent, 135 | ), 136 | ), 137 | ), 138 | ), 139 | ), 140 | ), 141 | Padding( 142 | padding: const EdgeInsets.all(10), 143 | child: TextField( 144 | textInputAction: TextInputAction.done, 145 | keyboardType: TextInputType.text, 146 | controller: controllerName, 147 | decoration: InputDecoration( 148 | contentPadding: const EdgeInsets.symmetric(horizontal: 10), 149 | labelText: "Masukan Nama Anda", 150 | hintText: "Nama Anda", 151 | hintStyle: const TextStyle( 152 | fontSize: 14, 153 | color: Colors.grey), 154 | labelStyle: const TextStyle( 155 | fontSize: 14, 156 | color: Colors.black), 157 | border: OutlineInputBorder( 158 | borderRadius: BorderRadius.circular(10), 159 | borderSide: const BorderSide(color: Colors.pinkAccent), 160 | ), 161 | enabledBorder: OutlineInputBorder( 162 | borderRadius: BorderRadius.circular(10), 163 | borderSide: const BorderSide(color: Colors.pinkAccent), 164 | ), 165 | ), 166 | ), 167 | ), 168 | const Padding( 169 | padding: EdgeInsets.fromLTRB(10, 10, 10, 10), 170 | child: Text( 171 | "Lokasi Anda", 172 | style: TextStyle( 173 | fontSize: 16, 174 | fontWeight: FontWeight.bold, 175 | color: Colors.black), 176 | ), 177 | ), 178 | isLoading 179 | ? const Center(child: CircularProgressIndicator(color: Colors.pinkAccent,)) 180 | : Padding( 181 | padding: const EdgeInsets.all(10), 182 | child: SizedBox( 183 | height: 5 * 24, 184 | child: TextField( 185 | enabled: false, 186 | maxLines: 5, 187 | decoration: InputDecoration( 188 | alignLabelWithHint: true, 189 | disabledBorder: OutlineInputBorder( 190 | borderRadius: BorderRadius.circular(10), 191 | borderSide: const BorderSide(color: Colors.pinkAccent), 192 | ), 193 | hintText: strAlamat != null 194 | ? strAlamat 195 | : strAlamat = 'Lokasi Kamu', 196 | hintStyle: const TextStyle( 197 | fontSize: 14, color: Colors.grey), 198 | fillColor: Colors.transparent, 199 | filled: true, 200 | ), 201 | ), 202 | ), 203 | ), 204 | Container( 205 | alignment: Alignment.center, 206 | margin: const EdgeInsets.all(30), 207 | child: Material( 208 | elevation: 3, 209 | borderRadius: BorderRadius.circular(20), 210 | child: Container( 211 | width: size.width, 212 | height: 50, 213 | decoration: BoxDecoration( 214 | borderRadius: BorderRadius.circular(20), 215 | color: Colors.white), 216 | child: Material( 217 | borderRadius: BorderRadius.circular(20), 218 | color: Colors.pinkAccent, 219 | child: InkWell( 220 | splashColor: Colors.pink, 221 | borderRadius: BorderRadius.circular(20), 222 | onTap: () { 223 | if (image == null || controllerName.text.isEmpty) { 224 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 225 | content: Row( 226 | children: [ 227 | Icon( 228 | Icons.info_outline, 229 | color: Colors.white, 230 | ), 231 | SizedBox(width: 10), 232 | Text("Ups, foto dan inputan tidak boleh kosong!", 233 | style: TextStyle(color: Colors.white)) 234 | ], 235 | ), 236 | backgroundColor: Colors.redAccent, 237 | shape: StadiumBorder(), 238 | behavior: SnackBarBehavior.floating, 239 | )); 240 | } else { 241 | submitAbsen(strAlamat, controllerName.text.toString(), strStatus); 242 | } 243 | }, 244 | child: const Center( 245 | child: Text( 246 | "Absen Sekarang", 247 | style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), 248 | ), 249 | ), 250 | ), 251 | ), 252 | ), 253 | )), 254 | ], 255 | )), 256 | ), 257 | ); 258 | } 259 | 260 | //get realtime location 261 | Future getGeoLocationPosition() async { 262 | Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low); 263 | setState(() { 264 | isLoading = false; 265 | getAddressFromLongLat(position); 266 | }); 267 | } 268 | 269 | //get address by lat long 270 | Future getAddressFromLongLat(Position position) async { 271 | List placemarks = await placemarkFromCoordinates(position.latitude, position.longitude); 272 | print(placemarks); 273 | Placemark place = placemarks[0]; 274 | setState(() { 275 | dLat = double.parse('${position.latitude}'); 276 | dLat = double.parse('${position.longitude}'); 277 | strAlamat = 278 | "${place.street}, ${place.subLocality}, ${place.locality}, ${place.postalCode}, ${place.country}"; 279 | }); 280 | } 281 | 282 | //permission location 283 | Future handleLocationPermission() async { 284 | bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); 285 | if (!serviceEnabled) { 286 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 287 | content: Row( 288 | children: [ 289 | Icon( 290 | Icons.location_off, 291 | color: Colors.white, 292 | ), 293 | SizedBox(width: 10), 294 | Text("Location services are disabled. Please enable the services.", 295 | style: TextStyle(color: Colors.white), 296 | ) 297 | ], 298 | ), 299 | backgroundColor: Colors.redAccent, 300 | shape: StadiumBorder(), 301 | behavior: SnackBarBehavior.floating, 302 | )); 303 | return false; 304 | } 305 | 306 | LocationPermission permission = await Geolocator.checkPermission(); 307 | if (permission == LocationPermission.denied) { 308 | permission = await Geolocator.requestPermission(); 309 | if (permission == LocationPermission.denied) { 310 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 311 | content: Row( 312 | children: [ 313 | Icon( 314 | Icons.location_off, 315 | color: Colors.white, 316 | ), 317 | SizedBox(width: 10), 318 | Text("Location permission denied.", 319 | style: TextStyle(color: Colors.white), 320 | ) 321 | ], 322 | ), 323 | backgroundColor: Colors.redAccent, 324 | shape: StadiumBorder(), 325 | behavior: SnackBarBehavior.floating, 326 | )); 327 | return false; 328 | } 329 | } 330 | 331 | if (permission == LocationPermission.deniedForever) { 332 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 333 | content: Row( 334 | children: [ 335 | Icon( 336 | Icons.location_off, 337 | color: Colors.white, 338 | ), 339 | SizedBox(width: 10), 340 | Text("Location permission denied forever, we cannot access.", 341 | style: TextStyle(color: Colors.white), 342 | ) 343 | ], 344 | ), 345 | backgroundColor: Colors.redAccent, 346 | shape: StadiumBorder(), 347 | behavior: SnackBarBehavior.floating, 348 | )); 349 | return false; 350 | } 351 | return true; 352 | } 353 | 354 | //show progress dialog 355 | showLoaderDialog(BuildContext context) { 356 | AlertDialog alert = AlertDialog( 357 | content: Row( 358 | children: [ 359 | const CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.pinkAccent)), 360 | Container( 361 | margin: const EdgeInsets.only(left: 20), 362 | child: const Text("sedang memeriksa data..."), 363 | ), 364 | ], 365 | ), 366 | ); 367 | showDialog( 368 | barrierDismissible: false, 369 | context: context, 370 | builder: (BuildContext context) { 371 | return alert; 372 | }, 373 | ); 374 | } 375 | 376 | //check format date time 377 | void setDateTime() async { 378 | var dateNow = DateTime.now(); 379 | var dateFormat = DateFormat('dd MMMM yyyy'); 380 | var dateTime = DateFormat('HH:mm:ss'); 381 | var dateHour = DateFormat('HH'); 382 | var dateMinute = DateFormat('mm'); 383 | 384 | setState(() { 385 | strDate = dateFormat.format(dateNow); 386 | strTime = dateTime.format(dateNow); 387 | strDateTime = "$strDate | $strTime"; 388 | 389 | dateHours = int.parse(dateHour.format(dateNow)); 390 | dateMinutes = int.parse(dateMinute.format(dateNow)); 391 | }); 392 | } 393 | 394 | //check status absent 395 | void setStatusAbsen() { 396 | if (dateHours < 8 || (dateHours == 8 && dateMinutes <= 30)) { 397 | strStatus = "Absen Masuk"; 398 | } 399 | else if ((dateHours > 8 && dateHours < 18) || (dateHours == 8 && dateMinutes >= 31)) { 400 | strStatus = "Absen Telat"; 401 | } 402 | else { 403 | strStatus = "Absen Keluar"; 404 | } 405 | } 406 | 407 | //submit data absent to firebase 408 | Future submitAbsen(String alamat, String nama, String status) async { 409 | showLoaderDialog(context); 410 | dataCollection.add({'alamat': alamat, 'nama': nama, 411 | 'keterangan': status, 'datetime': strDateTime}).then((result) { 412 | setState(() { 413 | Navigator.of(context).pop(); 414 | try { 415 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 416 | content: Row( 417 | children: [ 418 | Icon( 419 | Icons.check_circle_outline, 420 | color: Colors.white, 421 | ), 422 | SizedBox(width: 10), 423 | Text("Yeay! Absen berhasil!", style: TextStyle(color: Colors.white)) 424 | ], 425 | ), 426 | backgroundColor: Colors.green, 427 | shape: StadiumBorder(), 428 | behavior: SnackBarBehavior.floating, 429 | )); 430 | Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const MainPage())); 431 | } 432 | catch (e) { 433 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 434 | content: Row( 435 | children: [ 436 | const Icon( 437 | Icons.info_outline, 438 | color: Colors.white, 439 | ), 440 | const SizedBox(width: 10), 441 | Expanded( 442 | child: Text("Ups, $e", style: const TextStyle(color: Colors.white)), 443 | ), 444 | ], 445 | ), 446 | backgroundColor: Colors.redAccent, 447 | shape: const StadiumBorder(), 448 | behavior: SnackBarBehavior.floating, 449 | )); 450 | } 451 | }); 452 | }).catchError((error) { 453 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 454 | content: Row( 455 | children: [ 456 | const Icon( 457 | Icons.error_outline, 458 | color: Colors.white, 459 | ), 460 | const SizedBox(width: 10), 461 | Expanded( 462 | child: Text("Ups, $error", style: const TextStyle(color: Colors.white)) 463 | ) 464 | ], 465 | ), 466 | backgroundColor: Colors.redAccent, 467 | shape: const StadiumBorder(), 468 | behavior: SnackBarBehavior.floating, 469 | )); 470 | Navigator.of(context).pop(); 471 | }); 472 | } 473 | 474 | } 475 | -------------------------------------------------------------------------------- /lib/page/leave/leave_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:absensi_flutter/page/main_page.dart'; 2 | import 'package:cloud_firestore/cloud_firestore.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:intl/intl.dart'; 5 | 6 | class LeavePage extends StatefulWidget { 7 | 8 | const LeavePage({super.key}); 9 | 10 | @override 11 | State createState() => _LeavePageState(); 12 | } 13 | 14 | class _LeavePageState extends State { 15 | 16 | String strAlamat = '', strDate = '', strTime = '', strDateTime = ''; 17 | double dLat = 0.0, dLong = 0.0; 18 | int dateHours = 0, dateMinutes = 0; 19 | final controllerName = TextEditingController(); 20 | final fromController = TextEditingController(); 21 | final toController = TextEditingController(); 22 | String dropValueCategories = "Pilih:"; 23 | var categoriesList = [ 24 | "Pilih:", "Cuti", "Izin", "Sakit" 25 | ]; 26 | final CollectionReference dataCollection = FirebaseFirestore.instance.collection('absensi'); 27 | 28 | @override 29 | void initState() { 30 | super.initState(); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | Size size = MediaQuery.of(context).size; 36 | 37 | return Scaffold( 38 | backgroundColor: Colors.white, 39 | appBar: AppBar( 40 | elevation: 0, 41 | backgroundColor: Colors.pinkAccent, 42 | leading: IconButton( 43 | icon: const Icon(Icons.arrow_back_ios, color: Colors.white), 44 | onPressed: () => Navigator.of(context).pop(), 45 | ), 46 | title: const Text( 47 | "Menu Pengajuan Cuti / Izin", 48 | style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white), 49 | ), 50 | ), 51 | body: SingleChildScrollView( 52 | child: Card( 53 | color: Colors.white, 54 | margin: const EdgeInsets.fromLTRB(10, 10, 10, 30), 55 | shape: RoundedRectangleBorder( 56 | borderRadius: BorderRadius.circular(10), 57 | ), 58 | elevation: 5, 59 | child: Column( 60 | crossAxisAlignment: CrossAxisAlignment.start, 61 | children: [ 62 | Container( 63 | height: 50, 64 | decoration: const BoxDecoration( 65 | borderRadius: BorderRadius.only( 66 | topLeft: Radius.circular(10), 67 | topRight: Radius.circular(10)), 68 | color: Colors.pinkAccent, 69 | ), 70 | child: const Row( 71 | children: [ 72 | SizedBox( 73 | width: 12, 74 | ), 75 | Icon(Icons.maps_home_work_outlined, color: Colors.white), 76 | SizedBox( 77 | width: 12, 78 | ), 79 | Text( 80 | "Isi From Sesuai Pengajuan ya!", 81 | style: TextStyle( 82 | fontSize: 18, 83 | fontWeight: FontWeight.bold, 84 | color: Colors.white), 85 | ), 86 | ], 87 | ), 88 | ), 89 | Padding( 90 | padding: const EdgeInsets.fromLTRB(10, 20, 10, 20), 91 | child: TextField( 92 | textInputAction: TextInputAction.next, 93 | keyboardType: TextInputType.text, 94 | controller: controllerName, 95 | decoration: InputDecoration( 96 | contentPadding: const EdgeInsets.symmetric(horizontal: 10), 97 | labelText: "Masukan Nama Anda", 98 | hintText: "Nama Anda", 99 | hintStyle: const TextStyle( 100 | fontSize: 14, 101 | color: Colors.grey), 102 | labelStyle: const TextStyle( 103 | fontSize: 14, 104 | color: Colors.black), 105 | border: OutlineInputBorder( 106 | borderRadius: BorderRadius.circular(10), 107 | borderSide: const BorderSide(color: Colors.pinkAccent), 108 | ), 109 | enabledBorder: OutlineInputBorder( 110 | borderRadius: BorderRadius.circular(10), 111 | borderSide: const BorderSide(color: Colors.pinkAccent), 112 | ), 113 | ), 114 | ), 115 | ), 116 | const Padding( 117 | padding: EdgeInsets.fromLTRB(10, 10, 10, 10), 118 | child: Text( 119 | "Keterangan", 120 | style: TextStyle( 121 | fontSize: 16, 122 | fontWeight: FontWeight.bold, 123 | color: Colors.black), 124 | ), 125 | ), 126 | Padding( 127 | padding: const EdgeInsets.all(10), 128 | child: Container( 129 | padding: const EdgeInsets.symmetric(horizontal: 10), 130 | decoration: BoxDecoration( 131 | borderRadius: BorderRadius.circular(10), 132 | border: Border.all(color: Colors.pinkAccent, style: BorderStyle.solid, width: 1), 133 | ), 134 | child: DropdownButton( 135 | dropdownColor: Colors.white, 136 | value: dropValueCategories, 137 | onChanged: (value) { 138 | setState(() { 139 | dropValueCategories = value.toString(); 140 | }); 141 | }, 142 | items: categoriesList.map((value) { 143 | return DropdownMenuItem( 144 | value: value.toString(), 145 | child: Text(value.toString(), 146 | style: const TextStyle( 147 | fontSize: 14, 148 | color: Colors.black)), 149 | ); 150 | }).toList(), 151 | icon: const Icon(Icons.arrow_drop_down), 152 | iconSize: 24, 153 | elevation: 16, 154 | style: const TextStyle(color: Colors.black, fontSize: 14), 155 | underline: Container( 156 | height: 2, 157 | color: Colors.transparent, 158 | ), 159 | isExpanded: true, 160 | ), 161 | ), 162 | ), 163 | Padding( 164 | padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), 165 | child: Row(children: [ 166 | Expanded( 167 | child: Row( 168 | children: [ 169 | const Text("From: ", 170 | style: TextStyle( 171 | fontSize: 16, 172 | fontWeight: FontWeight.bold, 173 | color: Colors.black), 174 | ), 175 | Expanded( 176 | child: TextField( 177 | readOnly: true, 178 | onTap: () async { 179 | DateTime? pickedDate = await showDatePicker( 180 | builder: (BuildContext context, Widget? child) { 181 | return Theme( 182 | data: Theme.of(context).copyWith( 183 | colorScheme: const ColorScheme.light(onPrimary: Colors.white, 184 | onBackground: Colors.white, primary: Colors.pinkAccent), 185 | datePickerTheme: const DatePickerThemeData( 186 | headerBackgroundColor: Colors.pinkAccent, 187 | backgroundColor: Colors.white, 188 | headerForegroundColor: Colors.white, 189 | surfaceTintColor: Colors.white, 190 | ), 191 | ), 192 | child: child!, 193 | ); 194 | }, 195 | context: context, 196 | initialDate: DateTime.now(), 197 | firstDate: DateTime(1900), 198 | lastDate: DateTime(9999), 199 | ); 200 | if (pickedDate != null) { 201 | fromController.text = DateFormat('dd/M/yyyy').format(pickedDate); 202 | } 203 | }, 204 | style: const TextStyle( 205 | color: Colors.black, 206 | fontSize: 16, 207 | ), 208 | controller: fromController, 209 | decoration: const InputDecoration( 210 | contentPadding: EdgeInsets.all(8), 211 | hintText: "Starting From", 212 | hintStyle: 213 | TextStyle(color: Colors.grey, fontSize: 16), 214 | ), 215 | ), 216 | ), 217 | ], 218 | ), 219 | ), 220 | const SizedBox( 221 | width: 14, 222 | ), 223 | Expanded( 224 | child: Row( 225 | children: [ 226 | const Text("Until: ", 227 | style: TextStyle( 228 | fontSize: 16, 229 | fontWeight: FontWeight.bold, 230 | color: Colors.black), 231 | ), 232 | Expanded( 233 | child: TextField( 234 | readOnly: true, 235 | onTap: () async { 236 | DateTime? pickedDate = await showDatePicker( 237 | builder: (BuildContext context, Widget? widget) { 238 | return Theme( 239 | data: Theme.of(context).copyWith( 240 | colorScheme: const ColorScheme.light(onPrimary: Colors.white, 241 | onBackground: Colors.white, primary: Colors.pinkAccent), 242 | datePickerTheme: const DatePickerThemeData( 243 | headerBackgroundColor: Colors.pinkAccent, 244 | backgroundColor: Colors.white, 245 | headerForegroundColor: Colors.white, 246 | surfaceTintColor: Colors.white, 247 | ), 248 | ), 249 | child: widget!, 250 | ); 251 | }, 252 | context: context, 253 | initialDate: DateTime.now(), 254 | firstDate: DateTime(1900), 255 | lastDate: DateTime(9999)); 256 | if (pickedDate != null) { 257 | toController.text = DateFormat('dd/M/yyyy').format(pickedDate); 258 | } 259 | }, 260 | style: const TextStyle( 261 | color: Colors.black, 262 | fontSize: 16, 263 | ), 264 | controller: toController, 265 | decoration: const InputDecoration( 266 | contentPadding: EdgeInsets.all(8), 267 | hintText: "Until", 268 | hintStyle: 269 | TextStyle(color: Colors.grey, fontSize: 16), 270 | ), 271 | ), 272 | ), 273 | ], 274 | ), 275 | ), 276 | ]), 277 | ), 278 | Container( 279 | alignment: Alignment.center, 280 | margin: const EdgeInsets.all(30), 281 | child: Material( 282 | elevation: 3, 283 | borderRadius: BorderRadius.circular(20), 284 | child: Container( 285 | width: size.width, 286 | height: 50, 287 | decoration: BoxDecoration( 288 | borderRadius: BorderRadius.circular(20), 289 | color: Colors.white), 290 | child: Material( 291 | borderRadius: BorderRadius.circular(20), 292 | color: Colors.pinkAccent, 293 | child: InkWell( 294 | splashColor: Colors.pink, 295 | borderRadius: BorderRadius.circular(20), 296 | onTap: () { 297 | if (controllerName.text.isEmpty || dropValueCategories == "Pilih:" 298 | || fromController.text.isEmpty || toController.text.isEmpty) { 299 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 300 | content: Row( 301 | children: [ 302 | Icon( 303 | Icons.info_outline, 304 | color: Colors.white, 305 | ), 306 | SizedBox(width: 10), 307 | Text("Ups, inputan tidak boleh kosong!", 308 | style: TextStyle(color: Colors.white), 309 | ) 310 | ], 311 | ), 312 | backgroundColor: Colors.redAccent, 313 | shape: StadiumBorder(), 314 | behavior: SnackBarBehavior.floating, 315 | )); 316 | } else { 317 | submitAbsen(controllerName.text.toString(), dropValueCategories.toString(), 318 | fromController.text, toController.text); 319 | } 320 | }, 321 | child: const Center( 322 | child: Text( 323 | "Ajukan Sekarang", 324 | style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold), 325 | ), 326 | ), 327 | ), 328 | ), 329 | ), 330 | )), 331 | ], 332 | )), 333 | ), 334 | ); 335 | } 336 | 337 | //show progress dialog 338 | showLoaderDialog(BuildContext context) { 339 | AlertDialog alert = AlertDialog( 340 | content: Row( 341 | children: [ 342 | const CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.pinkAccent)), 343 | Container( 344 | margin: const EdgeInsets.only(left: 20), 345 | child: const Text("Mohon tunggu..."), 346 | ), 347 | ], 348 | ), 349 | ); 350 | showDialog( 351 | barrierDismissible: false, 352 | context: context, 353 | builder: (BuildContext context) { 354 | return alert; 355 | }, 356 | ); 357 | } 358 | 359 | //submit data absent to firebase 360 | Future submitAbsen(String nama, String keterangan, String from, String until) async { 361 | showLoaderDialog(context); 362 | dataCollection.add({'alamat': '-', 'nama': nama, 363 | 'keterangan': keterangan, 'datetime': '$from-$until'}).then((result) { 364 | setState(() { 365 | Navigator.of(context).pop(); 366 | try { 367 | ScaffoldMessenger.of(context).showSnackBar(const SnackBar( 368 | content: Row( 369 | children: [ 370 | Icon( 371 | Icons.check_circle_outline, 372 | color: Colors.white, 373 | ), 374 | SizedBox(width: 10), 375 | Text("Yeay! Absen berhasil!", 376 | style: TextStyle(color: Colors.white), 377 | ) 378 | ], 379 | ), 380 | backgroundColor: Colors.green, 381 | shape: StadiumBorder(), 382 | behavior: SnackBarBehavior.floating, 383 | )); 384 | Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const MainPage())); 385 | } 386 | catch (e) { 387 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 388 | content: Row( 389 | children: [ 390 | const Icon( 391 | Icons.info_outline, 392 | color: Colors.white, 393 | ), 394 | const SizedBox(width: 10), 395 | Expanded( 396 | child: Text("Ups, $e", style: const TextStyle(color: Colors.white)), 397 | ), 398 | ], 399 | ), 400 | backgroundColor: Colors.redAccent, 401 | shape: const StadiumBorder(), 402 | behavior: SnackBarBehavior.floating, 403 | )); 404 | } 405 | }); 406 | }).catchError((error) { 407 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 408 | content: Row( 409 | children: [ 410 | const Icon( 411 | Icons.error_outline, 412 | color: Colors.white, 413 | ), 414 | const SizedBox(width: 10), 415 | Expanded( 416 | child: Text("Ups, $error", 417 | style: const TextStyle(color: Colors.white), 418 | ) 419 | ) 420 | ], 421 | ), 422 | backgroundColor: Colors.redAccent, 423 | shape: const StadiumBorder(), 424 | behavior: SnackBarBehavior.floating, 425 | )); 426 | Navigator.of(context).pop(); 427 | }); 428 | } 429 | 430 | } 431 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = 97C146ED1CF9000F007C117D; 25 | remoteInfo = Runner; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXCopyFilesBuildPhase section */ 30 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 31 | isa = PBXCopyFilesBuildPhase; 32 | buildActionMask = 2147483647; 33 | dstPath = ""; 34 | dstSubfolderSpec = 10; 35 | files = ( 36 | ); 37 | name = "Embed Frameworks"; 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXCopyFilesBuildPhase section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 44 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 45 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 46 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 47 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 48 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 49 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 50 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 51 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 57 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 9740EEB11CF90186004384FC /* Flutter */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 75 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 76 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 77 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 78 | ); 79 | name = Flutter; 80 | sourceTree = ""; 81 | }; 82 | 331C8082294A63A400263BE5 /* RunnerTests */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 331C807B294A618700263BE5 /* RunnerTests.swift */, 86 | ); 87 | path = RunnerTests; 88 | sourceTree = ""; 89 | }; 90 | 97C146E51CF9000F007C117D = { 91 | isa = PBXGroup; 92 | children = ( 93 | 9740EEB11CF90186004384FC /* Flutter */, 94 | 97C146F01CF9000F007C117D /* Runner */, 95 | 97C146EF1CF9000F007C117D /* Products */, 96 | 331C8082294A63A400263BE5 /* RunnerTests */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 97C146EF1CF9000F007C117D /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 97C146EE1CF9000F007C117D /* Runner.app */, 104 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | 97C146F01CF9000F007C117D /* Runner */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 113 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 114 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 115 | 97C147021CF9000F007C117D /* Info.plist */, 116 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 117 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 118 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 119 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 120 | ); 121 | path = Runner; 122 | sourceTree = ""; 123 | }; 124 | /* End PBXGroup section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 331C8080294A63A400263BE5 /* RunnerTests */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 130 | buildPhases = ( 131 | 331C807D294A63A400263BE5 /* Sources */, 132 | 331C807E294A63A400263BE5 /* Frameworks */, 133 | 331C807F294A63A400263BE5 /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | 331C8086294A63A400263BE5 /* PBXTargetDependency */, 139 | ); 140 | name = RunnerTests; 141 | productName = RunnerTests; 142 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; 143 | productType = "com.apple.product-type.bundle.unit-test"; 144 | }; 145 | 97C146ED1CF9000F007C117D /* Runner */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 148 | buildPhases = ( 149 | 9740EEB61CF901F6004384FC /* Run Script */, 150 | 97C146EA1CF9000F007C117D /* Sources */, 151 | 97C146EB1CF9000F007C117D /* Frameworks */, 152 | 97C146EC1CF9000F007C117D /* Resources */, 153 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 154 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | ); 160 | name = Runner; 161 | productName = Runner; 162 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 163 | productType = "com.apple.product-type.application"; 164 | }; 165 | /* End PBXNativeTarget section */ 166 | 167 | /* Begin PBXProject section */ 168 | 97C146E61CF9000F007C117D /* Project object */ = { 169 | isa = PBXProject; 170 | attributes = { 171 | BuildIndependentTargetsInParallel = YES; 172 | LastUpgradeCheck = 1430; 173 | ORGANIZATIONNAME = ""; 174 | TargetAttributes = { 175 | 331C8080294A63A400263BE5 = { 176 | CreatedOnToolsVersion = 14.0; 177 | TestTargetID = 97C146ED1CF9000F007C117D; 178 | }; 179 | 97C146ED1CF9000F007C117D = { 180 | CreatedOnToolsVersion = 7.3.1; 181 | LastSwiftMigration = 1100; 182 | }; 183 | }; 184 | }; 185 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 186 | compatibilityVersion = "Xcode 9.3"; 187 | developmentRegion = en; 188 | hasScannedForEncodings = 0; 189 | knownRegions = ( 190 | en, 191 | Base, 192 | ); 193 | mainGroup = 97C146E51CF9000F007C117D; 194 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 195 | projectDirPath = ""; 196 | projectRoot = ""; 197 | targets = ( 198 | 97C146ED1CF9000F007C117D /* Runner */, 199 | 331C8080294A63A400263BE5 /* RunnerTests */, 200 | ); 201 | }; 202 | /* End PBXProject section */ 203 | 204 | /* Begin PBXResourcesBuildPhase section */ 205 | 331C807F294A63A400263BE5 /* Resources */ = { 206 | isa = PBXResourcesBuildPhase; 207 | buildActionMask = 2147483647; 208 | files = ( 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | 97C146EC1CF9000F007C117D /* Resources */ = { 213 | isa = PBXResourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 217 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 218 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 219 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXResourcesBuildPhase section */ 224 | 225 | /* Begin PBXShellScriptBuildPhase section */ 226 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 227 | isa = PBXShellScriptBuildPhase; 228 | alwaysOutOfDate = 1; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | ); 232 | inputPaths = ( 233 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 234 | ); 235 | name = "Thin Binary"; 236 | outputPaths = ( 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | shellPath = /bin/sh; 240 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 241 | }; 242 | 9740EEB61CF901F6004384FC /* Run Script */ = { 243 | isa = PBXShellScriptBuildPhase; 244 | alwaysOutOfDate = 1; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | ); 248 | inputPaths = ( 249 | ); 250 | name = "Run Script"; 251 | outputPaths = ( 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | shellPath = /bin/sh; 255 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 256 | }; 257 | /* End PBXShellScriptBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | 331C807D294A63A400263BE5 /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | 97C146EA1CF9000F007C117D /* Sources */ = { 269 | isa = PBXSourcesBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 273 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | /* End PBXSourcesBuildPhase section */ 278 | 279 | /* Begin PBXTargetDependency section */ 280 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { 281 | isa = PBXTargetDependency; 282 | target = 97C146ED1CF9000F007C117D /* Runner */; 283 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; 284 | }; 285 | /* End PBXTargetDependency section */ 286 | 287 | /* Begin PBXVariantGroup section */ 288 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 289 | isa = PBXVariantGroup; 290 | children = ( 291 | 97C146FB1CF9000F007C117D /* Base */, 292 | ); 293 | name = Main.storyboard; 294 | sourceTree = ""; 295 | }; 296 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 297 | isa = PBXVariantGroup; 298 | children = ( 299 | 97C147001CF9000F007C117D /* Base */, 300 | ); 301 | name = LaunchScreen.storyboard; 302 | sourceTree = ""; 303 | }; 304 | /* End PBXVariantGroup section */ 305 | 306 | /* Begin XCBuildConfiguration section */ 307 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 308 | isa = XCBuildConfiguration; 309 | buildSettings = { 310 | ALWAYS_SEARCH_USER_PATHS = NO; 311 | CLANG_ANALYZER_NONNULL = YES; 312 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 313 | CLANG_CXX_LIBRARY = "libc++"; 314 | CLANG_ENABLE_MODULES = YES; 315 | CLANG_ENABLE_OBJC_ARC = YES; 316 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 317 | CLANG_WARN_BOOL_CONVERSION = YES; 318 | CLANG_WARN_COMMA = YES; 319 | CLANG_WARN_CONSTANT_CONVERSION = YES; 320 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 328 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 331 | CLANG_WARN_STRICT_PROTOTYPES = YES; 332 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | GCC_C_LANGUAGE_STANDARD = gnu99; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 344 | GCC_WARN_UNDECLARED_SELECTOR = YES; 345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 346 | GCC_WARN_UNUSED_FUNCTION = YES; 347 | GCC_WARN_UNUSED_VARIABLE = YES; 348 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 349 | MTL_ENABLE_DEBUG_INFO = NO; 350 | SDKROOT = iphoneos; 351 | SUPPORTED_PLATFORMS = iphoneos; 352 | TARGETED_DEVICE_FAMILY = "1,2"; 353 | VALIDATE_PRODUCT = YES; 354 | }; 355 | name = Profile; 356 | }; 357 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 358 | isa = XCBuildConfiguration; 359 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 360 | buildSettings = { 361 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 362 | CLANG_ENABLE_MODULES = YES; 363 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 364 | ENABLE_BITCODE = NO; 365 | INFOPLIST_FILE = Runner/Info.plist; 366 | LD_RUNPATH_SEARCH_PATHS = ( 367 | "$(inherited)", 368 | "@executable_path/Frameworks", 369 | ); 370 | PRODUCT_BUNDLE_IDENTIFIER = com.azhar.absensi.absensiFlutter; 371 | PRODUCT_NAME = "$(TARGET_NAME)"; 372 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 373 | SWIFT_VERSION = 5.0; 374 | VERSIONING_SYSTEM = "apple-generic"; 375 | }; 376 | name = Profile; 377 | }; 378 | 331C8088294A63A400263BE5 /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; 381 | buildSettings = { 382 | BUNDLE_LOADER = "$(TEST_HOST)"; 383 | CODE_SIGN_STYLE = Automatic; 384 | CURRENT_PROJECT_VERSION = 1; 385 | GENERATE_INFOPLIST_FILE = YES; 386 | MARKETING_VERSION = 1.0; 387 | PRODUCT_BUNDLE_IDENTIFIER = com.azhar.absensi.absensiFlutter.RunnerTests; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 390 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 391 | SWIFT_VERSION = 5.0; 392 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 393 | }; 394 | name = Debug; 395 | }; 396 | 331C8089294A63A400263BE5 /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; 399 | buildSettings = { 400 | BUNDLE_LOADER = "$(TEST_HOST)"; 401 | CODE_SIGN_STYLE = Automatic; 402 | CURRENT_PROJECT_VERSION = 1; 403 | GENERATE_INFOPLIST_FILE = YES; 404 | MARKETING_VERSION = 1.0; 405 | PRODUCT_BUNDLE_IDENTIFIER = com.azhar.absensi.absensiFlutter.RunnerTests; 406 | PRODUCT_NAME = "$(TARGET_NAME)"; 407 | SWIFT_VERSION = 5.0; 408 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 409 | }; 410 | name = Release; 411 | }; 412 | 331C808A294A63A400263BE5 /* Profile */ = { 413 | isa = XCBuildConfiguration; 414 | baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; 415 | buildSettings = { 416 | BUNDLE_LOADER = "$(TEST_HOST)"; 417 | CODE_SIGN_STYLE = Automatic; 418 | CURRENT_PROJECT_VERSION = 1; 419 | GENERATE_INFOPLIST_FILE = YES; 420 | MARKETING_VERSION = 1.0; 421 | PRODUCT_BUNDLE_IDENTIFIER = com.azhar.absensi.absensiFlutter.RunnerTests; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | SWIFT_VERSION = 5.0; 424 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 425 | }; 426 | name = Profile; 427 | }; 428 | 97C147031CF9000F007C117D /* Debug */ = { 429 | isa = XCBuildConfiguration; 430 | buildSettings = { 431 | ALWAYS_SEARCH_USER_PATHS = NO; 432 | CLANG_ANALYZER_NONNULL = YES; 433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 434 | CLANG_CXX_LIBRARY = "libc++"; 435 | CLANG_ENABLE_MODULES = YES; 436 | CLANG_ENABLE_OBJC_ARC = YES; 437 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_COMMA = YES; 440 | CLANG_WARN_CONSTANT_CONVERSION = YES; 441 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 442 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 443 | CLANG_WARN_EMPTY_BODY = YES; 444 | CLANG_WARN_ENUM_CONVERSION = YES; 445 | CLANG_WARN_INFINITE_RECURSION = YES; 446 | CLANG_WARN_INT_CONVERSION = YES; 447 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 448 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 449 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 451 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 452 | CLANG_WARN_STRICT_PROTOTYPES = YES; 453 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 454 | CLANG_WARN_UNREACHABLE_CODE = YES; 455 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 456 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 457 | COPY_PHASE_STRIP = NO; 458 | DEBUG_INFORMATION_FORMAT = dwarf; 459 | ENABLE_STRICT_OBJC_MSGSEND = YES; 460 | ENABLE_TESTABILITY = YES; 461 | GCC_C_LANGUAGE_STANDARD = gnu99; 462 | GCC_DYNAMIC_NO_PIC = NO; 463 | GCC_NO_COMMON_BLOCKS = YES; 464 | GCC_OPTIMIZATION_LEVEL = 0; 465 | GCC_PREPROCESSOR_DEFINITIONS = ( 466 | "DEBUG=1", 467 | "$(inherited)", 468 | ); 469 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 470 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 471 | GCC_WARN_UNDECLARED_SELECTOR = YES; 472 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 473 | GCC_WARN_UNUSED_FUNCTION = YES; 474 | GCC_WARN_UNUSED_VARIABLE = YES; 475 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 476 | MTL_ENABLE_DEBUG_INFO = YES; 477 | ONLY_ACTIVE_ARCH = YES; 478 | SDKROOT = iphoneos; 479 | TARGETED_DEVICE_FAMILY = "1,2"; 480 | }; 481 | name = Debug; 482 | }; 483 | 97C147041CF9000F007C117D /* Release */ = { 484 | isa = XCBuildConfiguration; 485 | buildSettings = { 486 | ALWAYS_SEARCH_USER_PATHS = NO; 487 | CLANG_ANALYZER_NONNULL = YES; 488 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 489 | CLANG_CXX_LIBRARY = "libc++"; 490 | CLANG_ENABLE_MODULES = YES; 491 | CLANG_ENABLE_OBJC_ARC = YES; 492 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 493 | CLANG_WARN_BOOL_CONVERSION = YES; 494 | CLANG_WARN_COMMA = YES; 495 | CLANG_WARN_CONSTANT_CONVERSION = YES; 496 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 497 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 498 | CLANG_WARN_EMPTY_BODY = YES; 499 | CLANG_WARN_ENUM_CONVERSION = YES; 500 | CLANG_WARN_INFINITE_RECURSION = YES; 501 | CLANG_WARN_INT_CONVERSION = YES; 502 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 503 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 504 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 505 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 506 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 507 | CLANG_WARN_STRICT_PROTOTYPES = YES; 508 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 509 | CLANG_WARN_UNREACHABLE_CODE = YES; 510 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 511 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 512 | COPY_PHASE_STRIP = NO; 513 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 514 | ENABLE_NS_ASSERTIONS = NO; 515 | ENABLE_STRICT_OBJC_MSGSEND = YES; 516 | GCC_C_LANGUAGE_STANDARD = gnu99; 517 | GCC_NO_COMMON_BLOCKS = YES; 518 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 519 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 520 | GCC_WARN_UNDECLARED_SELECTOR = YES; 521 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 522 | GCC_WARN_UNUSED_FUNCTION = YES; 523 | GCC_WARN_UNUSED_VARIABLE = YES; 524 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 525 | MTL_ENABLE_DEBUG_INFO = NO; 526 | SDKROOT = iphoneos; 527 | SUPPORTED_PLATFORMS = iphoneos; 528 | SWIFT_COMPILATION_MODE = wholemodule; 529 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 530 | TARGETED_DEVICE_FAMILY = "1,2"; 531 | VALIDATE_PRODUCT = YES; 532 | }; 533 | name = Release; 534 | }; 535 | 97C147061CF9000F007C117D /* Debug */ = { 536 | isa = XCBuildConfiguration; 537 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 538 | buildSettings = { 539 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 540 | CLANG_ENABLE_MODULES = YES; 541 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 542 | ENABLE_BITCODE = NO; 543 | INFOPLIST_FILE = Runner/Info.plist; 544 | LD_RUNPATH_SEARCH_PATHS = ( 545 | "$(inherited)", 546 | "@executable_path/Frameworks", 547 | ); 548 | PRODUCT_BUNDLE_IDENTIFIER = com.azhar.absensi.absensiFlutter; 549 | PRODUCT_NAME = "$(TARGET_NAME)"; 550 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 551 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 552 | SWIFT_VERSION = 5.0; 553 | VERSIONING_SYSTEM = "apple-generic"; 554 | }; 555 | name = Debug; 556 | }; 557 | 97C147071CF9000F007C117D /* Release */ = { 558 | isa = XCBuildConfiguration; 559 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 560 | buildSettings = { 561 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 562 | CLANG_ENABLE_MODULES = YES; 563 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 564 | ENABLE_BITCODE = NO; 565 | INFOPLIST_FILE = Runner/Info.plist; 566 | LD_RUNPATH_SEARCH_PATHS = ( 567 | "$(inherited)", 568 | "@executable_path/Frameworks", 569 | ); 570 | PRODUCT_BUNDLE_IDENTIFIER = com.azhar.absensi.absensiFlutter; 571 | PRODUCT_NAME = "$(TARGET_NAME)"; 572 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 573 | SWIFT_VERSION = 5.0; 574 | VERSIONING_SYSTEM = "apple-generic"; 575 | }; 576 | name = Release; 577 | }; 578 | /* End XCBuildConfiguration section */ 579 | 580 | /* Begin XCConfigurationList section */ 581 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 582 | isa = XCConfigurationList; 583 | buildConfigurations = ( 584 | 331C8088294A63A400263BE5 /* Debug */, 585 | 331C8089294A63A400263BE5 /* Release */, 586 | 331C808A294A63A400263BE5 /* Profile */, 587 | ); 588 | defaultConfigurationIsVisible = 0; 589 | defaultConfigurationName = Release; 590 | }; 591 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 592 | isa = XCConfigurationList; 593 | buildConfigurations = ( 594 | 97C147031CF9000F007C117D /* Debug */, 595 | 97C147041CF9000F007C117D /* Release */, 596 | 249021D3217E4FDB00AE95B9 /* Profile */, 597 | ); 598 | defaultConfigurationIsVisible = 0; 599 | defaultConfigurationName = Release; 600 | }; 601 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 602 | isa = XCConfigurationList; 603 | buildConfigurations = ( 604 | 97C147061CF9000F007C117D /* Debug */, 605 | 97C147071CF9000F007C117D /* Release */, 606 | 249021D4217E4FDB00AE95B9 /* Profile */, 607 | ); 608 | defaultConfigurationIsVisible = 0; 609 | defaultConfigurationName = Release; 610 | }; 611 | /* End XCConfigurationList section */ 612 | }; 613 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 614 | } 615 | --------------------------------------------------------------------------------