commit fb10375183253368c3b3aaa18c3dca41883b28b2 Author: Ryan Ariana Date: Mon Mar 25 14:37:46 2024 +0700 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24476c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..25aed65 --- /dev/null +++ b/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + channel: master + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + - platform: android + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + - platform: ios + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + - platform: linux + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + - platform: macos + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + - platform: web + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + - platform: windows + create_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + base_revision: 025ce117b7eda83a1402c2b74372a290cfa6da4e + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e0f15db --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0b8a603 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# bbm_tracking + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..1411db2 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +# include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..53e8295 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,87 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '3' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '3.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + +android { + compileSdkVersion 33 + // compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.allbestsistem.bbmtracking" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion 31 + targetSdkVersion flutter.targetSdkVersion + versionCode 2 + versionName '2.0' + } + + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.release + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..20e336d --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9e2422a --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/bbm_tracking/MainActivity.kt b/android/app/src/main/kotlin/com/example/bbm_tracking/MainActivity.kt new file mode 100644 index 0000000..a174c03 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/bbm_tracking/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.bbm_tracking + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..7c12a89 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..be0e0c4 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..731a851 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..49ed705 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..fe4188b Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..20e336d --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..6a63477 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,32 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.google.gms:google-services:4.3.8' + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/fonts/OFL.txt b/assets/fonts/OFL.txt new file mode 100644 index 0000000..76df3b5 --- /dev/null +++ b/assets/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/fonts/Poppins-Black.ttf b/assets/fonts/Poppins-Black.ttf new file mode 100644 index 0000000..71c0f99 Binary files /dev/null and b/assets/fonts/Poppins-Black.ttf differ diff --git a/assets/fonts/Poppins-BlackItalic.ttf b/assets/fonts/Poppins-BlackItalic.ttf new file mode 100644 index 0000000..7aeb58b Binary files /dev/null and b/assets/fonts/Poppins-BlackItalic.ttf differ diff --git a/assets/fonts/Poppins-Bold.ttf b/assets/fonts/Poppins-Bold.ttf new file mode 100644 index 0000000..00559ee Binary files /dev/null and b/assets/fonts/Poppins-Bold.ttf differ diff --git a/assets/fonts/Poppins-BoldItalic.ttf b/assets/fonts/Poppins-BoldItalic.ttf new file mode 100644 index 0000000..e61e8e8 Binary files /dev/null and b/assets/fonts/Poppins-BoldItalic.ttf differ diff --git a/assets/fonts/Poppins-ExtraBold.ttf b/assets/fonts/Poppins-ExtraBold.ttf new file mode 100644 index 0000000..df70936 Binary files /dev/null and b/assets/fonts/Poppins-ExtraBold.ttf differ diff --git a/assets/fonts/Poppins-ExtraBoldItalic.ttf b/assets/fonts/Poppins-ExtraBoldItalic.ttf new file mode 100644 index 0000000..14d2b37 Binary files /dev/null and b/assets/fonts/Poppins-ExtraBoldItalic.ttf differ diff --git a/assets/fonts/Poppins-ExtraLight.ttf b/assets/fonts/Poppins-ExtraLight.ttf new file mode 100644 index 0000000..e76ec69 Binary files /dev/null and b/assets/fonts/Poppins-ExtraLight.ttf differ diff --git a/assets/fonts/Poppins-ExtraLightItalic.ttf b/assets/fonts/Poppins-ExtraLightItalic.ttf new file mode 100644 index 0000000..89513d9 Binary files /dev/null and b/assets/fonts/Poppins-ExtraLightItalic.ttf differ diff --git a/assets/fonts/Poppins-Italic.ttf b/assets/fonts/Poppins-Italic.ttf new file mode 100644 index 0000000..12b7b3c Binary files /dev/null and b/assets/fonts/Poppins-Italic.ttf differ diff --git a/assets/fonts/Poppins-Light.ttf b/assets/fonts/Poppins-Light.ttf new file mode 100644 index 0000000..bc36bcc Binary files /dev/null and b/assets/fonts/Poppins-Light.ttf differ diff --git a/assets/fonts/Poppins-LightItalic.ttf b/assets/fonts/Poppins-LightItalic.ttf new file mode 100644 index 0000000..9e70be6 Binary files /dev/null and b/assets/fonts/Poppins-LightItalic.ttf differ diff --git a/assets/fonts/Poppins-Medium.ttf b/assets/fonts/Poppins-Medium.ttf new file mode 100644 index 0000000..6bcdcc2 Binary files /dev/null and b/assets/fonts/Poppins-Medium.ttf differ diff --git a/assets/fonts/Poppins-MediumItalic.ttf b/assets/fonts/Poppins-MediumItalic.ttf new file mode 100644 index 0000000..be67410 Binary files /dev/null and b/assets/fonts/Poppins-MediumItalic.ttf differ diff --git a/assets/fonts/Poppins-Regular.ttf b/assets/fonts/Poppins-Regular.ttf new file mode 100644 index 0000000..9f0c71b Binary files /dev/null and b/assets/fonts/Poppins-Regular.ttf differ diff --git a/assets/fonts/Poppins-SemiBold.ttf b/assets/fonts/Poppins-SemiBold.ttf new file mode 100644 index 0000000..74c726e Binary files /dev/null and b/assets/fonts/Poppins-SemiBold.ttf differ diff --git a/assets/fonts/Poppins-SemiBoldItalic.ttf b/assets/fonts/Poppins-SemiBoldItalic.ttf new file mode 100644 index 0000000..3e6c942 Binary files /dev/null and b/assets/fonts/Poppins-SemiBoldItalic.ttf differ diff --git a/assets/fonts/Poppins-Thin.ttf b/assets/fonts/Poppins-Thin.ttf new file mode 100644 index 0000000..03e7366 Binary files /dev/null and b/assets/fonts/Poppins-Thin.ttf differ diff --git a/assets/fonts/Poppins-ThinItalic.ttf b/assets/fonts/Poppins-ThinItalic.ttf new file mode 100644 index 0000000..e26db5d Binary files /dev/null and b/assets/fonts/Poppins-ThinItalic.ttf differ diff --git a/assets/images/Logo.png b/assets/images/Logo.png new file mode 100644 index 0000000..a959b0d Binary files /dev/null and b/assets/images/Logo.png differ diff --git a/assets/images/about_person.png b/assets/images/about_person.png new file mode 100644 index 0000000..5882a0d Binary files /dev/null and b/assets/images/about_person.png differ diff --git a/assets/images/arrow-right.png b/assets/images/arrow-right.png new file mode 100644 index 0000000..7e8572e Binary files /dev/null and b/assets/images/arrow-right.png differ diff --git a/assets/images/calendaradd.png b/assets/images/calendaradd.png new file mode 100644 index 0000000..45dd0ed Binary files /dev/null and b/assets/images/calendaradd.png differ diff --git a/assets/images/car.png b/assets/images/car.png new file mode 100644 index 0000000..f382519 Binary files /dev/null and b/assets/images/car.png differ diff --git a/assets/images/card.png b/assets/images/card.png new file mode 100644 index 0000000..e6751b5 Binary files /dev/null and b/assets/images/card.png differ diff --git a/assets/images/card_empty.png b/assets/images/card_empty.png new file mode 100644 index 0000000..e58e66c Binary files /dev/null and b/assets/images/card_empty.png differ diff --git a/assets/images/compass.png b/assets/images/compass.png new file mode 100644 index 0000000..617af12 Binary files /dev/null and b/assets/images/compass.png differ diff --git a/assets/images/dollarsquare.png b/assets/images/dollarsquare.png new file mode 100644 index 0000000..8d73b81 Binary files /dev/null and b/assets/images/dollarsquare.png differ diff --git a/assets/images/eceran.png b/assets/images/eceran.png new file mode 100644 index 0000000..0f6fa73 Binary files /dev/null and b/assets/images/eceran.png differ diff --git a/assets/images/edit.png b/assets/images/edit.png new file mode 100644 index 0000000..cd5eb76 Binary files /dev/null and b/assets/images/edit.png differ diff --git a/assets/images/emptywallet.png b/assets/images/emptywallet.png new file mode 100644 index 0000000..5c1272f Binary files /dev/null and b/assets/images/emptywallet.png differ diff --git a/assets/images/error_kendaraan.png b/assets/images/error_kendaraan.png new file mode 100644 index 0000000..4d89f19 Binary files /dev/null and b/assets/images/error_kendaraan.png differ diff --git a/assets/images/firstIcon.png b/assets/images/firstIcon.png new file mode 100644 index 0000000..f134f5a Binary files /dev/null and b/assets/images/firstIcon.png differ diff --git a/assets/images/frmAdd.png b/assets/images/frmAdd.png new file mode 100644 index 0000000..cfa059d Binary files /dev/null and b/assets/images/frmAdd.png differ diff --git a/assets/images/frmImage.png b/assets/images/frmImage.png new file mode 100644 index 0000000..a3b2aad Binary files /dev/null and b/assets/images/frmImage.png differ diff --git a/assets/images/frmImage1.png b/assets/images/frmImage1.png new file mode 100644 index 0000000..8bb87e9 Binary files /dev/null and b/assets/images/frmImage1.png differ diff --git a/assets/images/gas-pump.png b/assets/images/gas-pump.png new file mode 100644 index 0000000..4d49c18 Binary files /dev/null and b/assets/images/gas-pump.png differ diff --git a/assets/images/help-circle.png b/assets/images/help-circle.png new file mode 100644 index 0000000..566b86d Binary files /dev/null and b/assets/images/help-circle.png differ diff --git a/assets/images/img_empty.png b/assets/images/img_empty.png new file mode 100644 index 0000000..18e0265 Binary files /dev/null and b/assets/images/img_empty.png differ diff --git a/assets/images/logoMesinPom.png b/assets/images/logoMesinPom.png new file mode 100644 index 0000000..705a579 Binary files /dev/null and b/assets/images/logoMesinPom.png differ diff --git a/assets/images/motor.png b/assets/images/motor.png new file mode 100644 index 0000000..2eab920 Binary files /dev/null and b/assets/images/motor.png differ diff --git a/assets/images/pertamina.png b/assets/images/pertamina.png new file mode 100644 index 0000000..169752e Binary files /dev/null and b/assets/images/pertamina.png differ diff --git a/assets/images/radar.png b/assets/images/radar.png new file mode 100644 index 0000000..67c9699 Binary files /dev/null and b/assets/images/radar.png differ diff --git a/assets/images/sad_person.png b/assets/images/sad_person.png new file mode 100644 index 0000000..159ddc2 Binary files /dev/null and b/assets/images/sad_person.png differ diff --git a/assets/images/shell.png b/assets/images/shell.png new file mode 100644 index 0000000..fa86005 Binary files /dev/null and b/assets/images/shell.png differ diff --git a/assets/images/success.png b/assets/images/success.png new file mode 100644 index 0000000..847ae3b Binary files /dev/null and b/assets/images/success.png differ diff --git a/assets/images/timer.png b/assets/images/timer.png new file mode 100644 index 0000000..59ba0fd Binary files /dev/null and b/assets/images/timer.png differ diff --git a/assets/images/titikpoint.png b/assets/images/titikpoint.png new file mode 100644 index 0000000..edb9d09 Binary files /dev/null and b/assets/images/titikpoint.png differ diff --git a/assets/images/user.png b/assets/images/user.png new file mode 100644 index 0000000..892ebed Binary files /dev/null and b/assets/images/user.png differ diff --git a/assets/images/vivo.png b/assets/images/vivo.png new file mode 100644 index 0000000..324a535 Binary files /dev/null and b/assets/images/vivo.png differ diff --git a/assets/images/wifi-off.png b/assets/images/wifi-off.png new file mode 100644 index 0000000..08ec613 Binary files /dev/null and b/assets/images/wifi-off.png differ diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..0f26cfc --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,612 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807E294A63A400263BE5 /* Frameworks */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..e42adcb --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..6ed2d93 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cd7b00 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..fe73094 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..502f463 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..e9f5fea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..0467bf1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..aa2c90c --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Bbm Tracking + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + bbm_tracking + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/app.dart b/lib/app.dart new file mode 100644 index 0000000..7a8f7c8 --- /dev/null +++ b/lib/app.dart @@ -0,0 +1,33 @@ +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/pages/onBoard/on_board_start.dart'; +import 'package:bbm_tracking/pages/onBoard/splash_screen.dart'; +import 'package:bbm_tracking/repository/kendaraan/kendaraan_repository.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class App extends StatelessWidget { + const App({super.key}); + + @override + Widget build(BuildContext context) { + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle( + statusBarColor: Color(0xffE3EAEA), + ), + ); + return BlocProvider( + create: (context) => BbmBloc( + kendaraanRepository: KendaraanRepository(), + transaksiRepository: TransaksiRepository(), + )..add( + BBMStarted(), + ), + child: MaterialApp( + debugShowCheckedModeBanner: false, + home: const SplsScreen(), + ), + ); + } +} diff --git a/lib/bloc/bbm_bloc.dart b/lib/bloc/bbm_bloc.dart new file mode 100644 index 0000000..e7e8fde --- /dev/null +++ b/lib/bloc/bbm_bloc.dart @@ -0,0 +1,239 @@ +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/photo_m.dart'; +import 'package:bbm_tracking/model/transaksiPerMonth_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/repository/kendaraan/kendaraan_repository.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:bbm_tracking/resource/data-bensin/data-bensin.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +part 'bbm_event.dart'; +part 'bbm_state.dart'; + +class BbmBloc extends Bloc { + final KendaraanRepository kendaraanRepository; + final TransaksiRepository transaksiRepository; + + BbmBloc( + {required this.kendaraanRepository, required this.transaksiRepository}) + : super(BbmInitial()) { + on(_onBBMStarted); + on(_onBBMKendaraanAdded); + on(_onBBMKendaraanUpdated); + on(_onBBMChangeStatusKendaraan); + on(_onBBMGetDataKendaraan); + on(_onBBMInsertTransaksi); + on(_onBBMGetAllKendaraan); + on(_onBBMChangeDataTransaction); + } + + Future _onBBMChangeDataTransaction( + BBMChangeDataTransaction event, + Emitter emit, + ) async { + try { + List dataKendaraan = + await kendaraanRepository.loadKendaraan(); + List dataTransaksi = + await transaksiRepository.loadTransaksi(); + List dataTransaksiThisMonth = + await transaksiRepository.loadTransaksiThisMonth(event.selectedDate); + + emit(BBMLoaded(dataKendaraan, dataTransaksi, dataTransaksiThisMonth)); + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMGetDataKendaraan( + BBMDataKendaraan event, + Emitter emit, + ) async { + final state = this.state; + try { + if (state is BBMLoaded) { + late KendaraanModel dataKendaraan; + state.kendaraan.forEach((element) { + if (element.id == event.kendaraanModel.id) { + dataKendaraan = element; + } + }); + emit(BBMSingleData(kendaraan: dataKendaraan)); + } + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMGetAllKendaraan( + BBMAllDataKendaraan event, + Emitter emit, + ) async { + try { + List dataKendaraan = + await kendaraanRepository.loadKendaraan(); + emit(BBMKendaraanLoaded(kendaraan: dataKendaraan)); + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMChangeStatusKendaraan( + BBMChangeStatusKendaraan event, + Emitter emit, + ) async { + final state = this.state; + try { + if (state is BBMLoaded) { + await kendaraanRepository.changeStatuKendaraan(event.id, event.status); + state.kendaraan.forEach((element) { + element.status = 0; + }); + state.kendaraan + .elementAt( + state.kendaraan.indexWhere((element) => element.id == event.id)) + .status = event.status; + // List dataKendaraan = state.kendaraan; + // List dataTransaksi = state.transaksi; + // print("data dari bloc = "+dataKendaraan[0].status.toString()); + // emit(BBMLoaded(dataKendaraan, dataTransaksi, dataTransaksi)); + } + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMKendaraanAdded( + BBMDataKendaraanAdded event, + Emitter emit, + ) async { + final state = this.state; + try { + if (state is BBMLoaded) { + await kendaraanRepository.addedKendaraan(event.kendaraanModel); + List dataKendaraan = state.kendaraan; + event.kendaraanModel.id = state.kendaraan.length + 1; + dataKendaraan.add(event.kendaraanModel); + List dataTransaksi = state.transaksi; + List dataTransaksiThisMonth = + await transaksiRepository.loadTransaksiThisMonth( + DateFormat("yyyy-MM-dd") + .parse(DateTime.now().toString()) + .toString()); + emit( + BBMLoaded(dataKendaraan, dataTransaksi, dataTransaksiThisMonth), + ); + } + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMKendaraanUpdated( + BBMDataKendaraanUpdated event, + Emitter emit, + ) async { + final state = this.state; + try { + if (state is BBMLoaded) { + await kendaraanRepository.updateDataKendaraan(event.kendaraanModel); + List dataKendaraan = state.kendaraan; + // event.kendaraanModel.id = state.kendaraan.length + 1; + // dataKendaraan.add(event.kendaraanModel); + // dataKendaraan.removeWhere((element) => element.id == event.kendaraanModel.id); + dataKendaraan[dataKendaraan.indexWhere((element) => element.id == event.kendaraanModel.id)] = event.kendaraanModel; + List dataTransaksi = state.transaksi; + List dataTransaksiThisMonth = + await transaksiRepository.loadTransaksiThisMonth( + DateFormat("yyyy-MM-dd") + .parse(DateTime.now().toString()) + .toString()); + emit( + BBMLoaded(dataKendaraan, dataTransaksi, dataTransaksiThisMonth), + ); + } + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMStarted( + BBMStarted event, + Emitter emit, + ) async { + try { + List dataKendaraan = + await kendaraanRepository.loadKendaraan(); + List dataTransaksi = + await transaksiRepository.loadTransaksi(); + List dataTransaksiThisMonth = + await transaksiRepository.loadTransaksiThisMonth( + DateFormat("yyyy-MM-dd") + .parse(DateTime.now().toString()) + .toString()); + + emit(BBMLoaded(dataKendaraan, dataTransaksi, dataTransaksiThisMonth)); + } catch (e) { + print("hit here = " + e.toString()); + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } + + Future _onBBMInsertTransaksi( + BBMInsertTransaksion event, + Emitter emit, + ) async { + try { + final state = this.state; + + if (state is BBMLoaded) { + await transaksiRepository.insertTransaksi(event.transaksi); + for (PhotoModel element in event.photo) { + await transaksiRepository.insertPhoto(element); + } + + List dataKendaraan = + await kendaraanRepository.loadKendaraan(); + List dataTransaksi = state.transaksi; + event.transaksi.id = dataTransaksi.length + 1; + dataTransaksi.add(event.transaksi); + // await transaksiRepository.loadTransaksi(); + List dataTransaksiThisMonth = + state.transaksiThisMonth; + // await transaksiRepository.loadTransaksiThisMonth( + // DateFormat("yyyy-MM-dd") + // .parse(DateTime.now().toString()) + // .toString()); + // state.transaksiThisMonth; + var data = event.transaksi; + TransaksiPerMonthModel dtIni = new TransaksiPerMonthModel( + totalLiter: double.parse(data.totalLiter), + totalBayar: data.totalBayar, + kendaraanId: data.kendaraanId, + tanggalTransaksi: data.tanggalTransaksi, + ); + if (data.tanggalTransaksi.month == DateTime.now().month) { + int i = 0; + dataTransaksiThisMonth.forEach((element) { + if (element.tanggalTransaksi.day == dtIni.tanggalTransaksi.day) { + element.totalBayar += dtIni.totalBayar; + element.totalLiter += dtIni.totalLiter; + state.transaksiThisMonth[i].totalBayar += element.totalBayar; + state.transaksiThisMonth[i].totalLiter += element.totalLiter; + } else { + dataTransaksiThisMonth.add(dtIni); + } + }); + } + + emit(BBMLoaded(dataKendaraan, dataTransaksi, dataTransaksiThisMonth)); + } + } catch (e) { + emit(BBMError(message: "Something Error, ${e}, We Will Fix it")); + } + } +} diff --git a/lib/bloc/bbm_event.dart b/lib/bloc/bbm_event.dart new file mode 100644 index 0000000..bd6e35b --- /dev/null +++ b/lib/bloc/bbm_event.dart @@ -0,0 +1,63 @@ +part of 'bbm_bloc.dart'; + +abstract class BbmEvent extends Equatable { + const BbmEvent(); + + @override + List get props => []; +} + +class BBMStarted extends BbmEvent{} + +class BBMDataKendaraanAdded extends BbmEvent{ + const BBMDataKendaraanAdded(this.kendaraanModel); + final KendaraanModel kendaraanModel; + + @override + List get props => [kendaraanModel]; +} + +class BBMDataKendaraanUpdated extends BbmEvent{ + const BBMDataKendaraanUpdated(this.kendaraanModel); + final KendaraanModel kendaraanModel; + + @override + List get props => [kendaraanModel]; +} + +class BBMDataKendaraan extends BbmEvent{ + final KendaraanModel kendaraanModel; + const BBMDataKendaraan({required this.kendaraanModel}); + + @override + List get props => [kendaraanModel]; +} + +class BBMAllDataKendaraan extends BbmEvent{} + +class BBMChangeStatusKendaraan extends BbmEvent{ + final int id; + final int status; + const BBMChangeStatusKendaraan(this.id, this.status); + + @override + List get props => [id, status]; +} + +class BBMInsertTransaksion extends BbmEvent{ + final TransaksiModel transaksi; + final List photo; + const BBMInsertTransaksion({required this.transaksi, required this.photo}); + + @override + List get props => [transaksi]; +} + +class BBMChangeDataTransaction extends BbmEvent{ + final String selectedDate; + + const BBMChangeDataTransaction({required this.selectedDate}); + + @override + List get props => [selectedDate]; +} \ No newline at end of file diff --git a/lib/bloc/bbm_state.dart b/lib/bloc/bbm_state.dart new file mode 100644 index 0000000..cb40ed4 --- /dev/null +++ b/lib/bloc/bbm_state.dart @@ -0,0 +1,44 @@ +part of 'bbm_bloc.dart'; + +abstract class BbmState extends Equatable { + const BbmState(); + + @override + List get props => []; +} + +class BbmInitial extends BbmState {} + +class BBMSingleData extends BbmState{ + final KendaraanModel kendaraan; + BBMSingleData({required this.kendaraan}); +} + +class BBMLoaded extends BbmState{ + final List kendaraan; + final List transaksi; + final List transaksiThisMonth; + late List bensin = listBensin; + + BBMLoaded(this.kendaraan, this.transaksi, this.transaksiThisMonth); +} + +class BBMChangeStatus extends BbmState{ + final List kendaraan; + final List transaksi; + late List bensin = listBensin; + + BBMChangeStatus({required this.kendaraan, required this.transaksi}); +} + +class BBMKendaraanLoaded extends BbmState{ + final List kendaraan; + + BBMKendaraanLoaded({required this.kendaraan}); +} + + +class BBMError extends BbmState{ + final String message; + BBMError({required this.message}); +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..20ffdad --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,9 @@ +import 'package:bbm_tracking/app.dart'; +import 'package:bbm_tracking/simple_bloc_observer.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter/material.dart'; + +void main() { + Bloc.observer = const SimpleBlocObserver(); + runApp(const App()); +} diff --git a/lib/model/Kendaraan_model.dart b/lib/model/Kendaraan_model.dart new file mode 100644 index 0000000..2209475 --- /dev/null +++ b/lib/model/Kendaraan_model.dart @@ -0,0 +1,17 @@ +class Kendaraan { + int id; + String jenisKendaraan; + String namaKendaraan; + String nomorPlat; + String bahanBakar; + bool status; + + Kendaraan({ + required this.id, + required this.jenisKendaraan, + required this.namaKendaraan, + required this.nomorPlat, + required this.bahanBakar, + required this.status, + }); +} diff --git a/lib/model/MapKendaraanPhoto_m.dart b/lib/model/MapKendaraanPhoto_m.dart new file mode 100644 index 0000000..be4686f --- /dev/null +++ b/lib/model/MapKendaraanPhoto_m.dart @@ -0,0 +1,72 @@ +import 'package:bbm_tracking/model/photo_m.dart'; + +class TransaksiModel { + int id; + String kendaraanId; + String bensinId; + String kodeTransaksi; + DateTime tanggalTransaksi; + String lokasiPertamina; + String totalLiter; + int hargaPerLiter; + int totalBayar; + String odometer; + String catatan; + String lat; + String lang; + int status; + List dataPhoto; + + TransaksiModel({ + required this.id, + required this.kendaraanId, + required this.bensinId, + required this.kodeTransaksi, + required this.tanggalTransaksi, + required this.lokasiPertamina, + required this.totalLiter, + required this.hargaPerLiter, + required this.totalBayar, + required this.odometer, + required this.catatan, + required this.lat, + required this.lang, + required this.status, + required this.dataPhoto, + }); + + TransaksiModel.fromJson(Map json) + : id = json['id'], + kendaraanId = json['kendaraanId'], + bensinId = json['bensinId'], + kodeTransaksi = json['kodeTransaksi'], + tanggalTransaksi = json['tanggalTransaksi'], + lokasiPertamina = json['lokasiPertamina'], + totalLiter = json['totalLiter'], + hargaPerLiter = json['hargaPerLiter'], + totalBayar = json['totalBayar'], + odometer = json['odometer'], + catatan = json['catatan'], + lat = json['lat'], + lang = json['lang'], + status = json['status'], + dataPhoto = json['dataPhoto']; + + Map toJson() => { + 'id': id, + 'kendaraanId': kendaraanId, + 'bensinId': bensinId, + 'kodeTransaksi': kodeTransaksi, + 'tanggalTransaksi': tanggalTransaksi, + 'lokasiPertamina': lokasiPertamina, + 'totalLiter': totalLiter, + 'hargaPerLiter': hargaPerLiter, + 'totalBayar': totalBayar, + 'odometer': odometer, + 'catatan': catatan, + 'lat': lat, + 'lang': lang, + 'status': status, + 'dataPhoto': dataPhoto, + }; +} diff --git a/lib/model/bensin_m.dart b/lib/model/bensin_m.dart new file mode 100644 index 0000000..25c007f --- /dev/null +++ b/lib/model/bensin_m.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class BensinModel { + int id; + String value; + String text; + String perusahaan; + int harga; + + BensinModel({ + required this.id, + required this.value, + required this.text, + required this.perusahaan, + required this.harga, + }); + + BensinModel.fromJson(Map json) + : id = json['id'], + value = json['value'], + text = json['text'], + perusahaan = json['perusahaan'], + harga = json['harga']; + + Map toJson() => { + 'id': id, + 'value': value, + 'text': text, + 'perusahaan': perusahaan, + 'harga': harga + }; +} diff --git a/lib/model/kendaraan_m.dart b/lib/model/kendaraan_m.dart new file mode 100644 index 0000000..b248518 --- /dev/null +++ b/lib/model/kendaraan_m.dart @@ -0,0 +1,46 @@ +class KendaraanModel { + int id; + String bahanBakar; + String jenisKendaraan; + String namaKendaraan; + String nomorPlat; + int cc; + String odometer; + String kepemilikan; + int status; + + KendaraanModel({ + required this.id, + required this.jenisKendaraan, + required this.namaKendaraan, + required this.nomorPlat, + required this.bahanBakar, + required this.cc, + required this.odometer, + required this.kepemilikan, + required this.status, + }); + + KendaraanModel.fromJson(Map json) + : id = json['id'], + jenisKendaraan = json['jenisKendaraan'], + namaKendaraan = json['namaKendaraan'], + nomorPlat = json['nomorPlat'], + bahanBakar = json['bahanBakar'], + cc = json['cc'], + odometer = json['odometer'], + kepemilikan = json['kepemilikan'], + status = json['status']; + + Map toJson() => { + 'id': id, + 'jenisKendaraan': jenisKendaraan, + 'namaKendaraan': namaKendaraan, + 'nomorPlat': nomorPlat, + 'bahanBakar': bahanBakar, + 'cc': cc, + 'odometer': odometer, + 'kepemilikan': kepemilikan, + 'status': status + }; +} diff --git a/lib/model/photo_m.dart b/lib/model/photo_m.dart new file mode 100644 index 0000000..a7904f5 --- /dev/null +++ b/lib/model/photo_m.dart @@ -0,0 +1,25 @@ +class PhotoModel { + int id; + String transaksi_id; + String linkPhoto; + String namePhoto; + + PhotoModel( + {required this.id, + required this.transaksi_id, + required this.linkPhoto, + required this.namePhoto}); + + PhotoModel.fromJson(Map json) + : id = json['id'], + transaksi_id = json['transaksi_id'], + linkPhoto = json['linkPhoto'], + namePhoto = json['namePhoto']; + + Map toJson() => { + 'id': id, + 'transaksi_id': transaksi_id, + 'linkPhoto': linkPhoto, + 'namePhoto': namePhoto + }; +} diff --git a/lib/model/status_m.dart b/lib/model/status_m.dart new file mode 100644 index 0000000..4dacca6 --- /dev/null +++ b/lib/model/status_m.dart @@ -0,0 +1,17 @@ +class StatusModel { + int id; + int status; + + StatusModel( + {required this.id, + required this.status}); + + StatusModel.fromJson(Map json) + : id = json['id'], + status = json['status']; + + Map toJson() => { + 'id': id, + 'status': status + }; +} diff --git a/lib/model/transaksiPerMonth_m.dart b/lib/model/transaksiPerMonth_m.dart new file mode 100644 index 0000000..a488e96 --- /dev/null +++ b/lib/model/transaksiPerMonth_m.dart @@ -0,0 +1,27 @@ +class TransaksiPerMonthModel{ + double totalLiter; + int totalBayar; + String kendaraanId; + DateTime tanggalTransaksi; + + TransaksiPerMonthModel({ + required this.totalLiter, + required this.totalBayar, + required this.kendaraanId, + required this.tanggalTransaksi + }); + + TransaksiPerMonthModel.fromJson(Map json) + : totalBayar = json['totalBayar'], + totalLiter = json['totalLiter'], + kendaraanId = json['kendaraanId'], + tanggalTransaksi = json['tanggalTransaksi']; + + Map toJson() => { + 'totalBayar' : totalBayar, + 'totalLiter' : totalLiter, + 'kendaraanId' : kendaraanId, + 'tanggalTransaksi' : tanggalTransaksi + }; + +} \ No newline at end of file diff --git a/lib/model/transaksi_m.dart b/lib/model/transaksi_m.dart new file mode 100644 index 0000000..76a465b --- /dev/null +++ b/lib/model/transaksi_m.dart @@ -0,0 +1,70 @@ +class TransaksiModel { + int id; + String kendaraanId; + String bensinId; + String kodeTransaksi; + DateTime tanggalTransaksi; + DateTime waktuTransaksi; + String lokasiPertamina; + String totalLiter; + int hargaPerLiter; + int totalBayar; + String odometer; + String catatan; + String lat; + String lang; + int status; + + TransaksiModel({ + required this.id, + required this.kendaraanId, + required this.bensinId, + required this.kodeTransaksi, + required this.tanggalTransaksi, + required this.waktuTransaksi, + required this.lokasiPertamina, + required this.totalLiter, + required this.hargaPerLiter, + required this.totalBayar, + required this.odometer, + required this.catatan, + required this.lat, + required this.lang, + required this.status, + }); + + TransaksiModel.fromJson(Map json) + : id = json['id'], + kendaraanId = json['kendaraanId'], + bensinId = json['bensinId'], + kodeTransaksi = json['kodeTransaksi'], + tanggalTransaksi = json['tanggalTransaksi'], + waktuTransaksi = json['waktuTransaksi'], + lokasiPertamina = json['lokasiPertamina'], + totalLiter = json['totalLiter'], + hargaPerLiter = json['hargaPerLiter'], + totalBayar = json['totalBayar'], + odometer = json['odometer'], + catatan = json['catatan'], + lat = json['lat'], + lang = json['lang'], + status = json['status']; + + Map toJson() => { + 'id': id, + 'kendaraanId': kendaraanId, + 'bensinId': bensinId, + 'kodeTransaksi': kodeTransaksi, + 'tanggalTransaksi': tanggalTransaksi, + 'waktuTransaksi': waktuTransaksi, + 'lokasiPertamina': lokasiPertamina, + 'totalLiter': totalLiter, + 'hargaPerLiter': hargaPerLiter, + 'totalBayar': totalBayar, + 'odometer': odometer, + 'catatan': catatan, + 'lat': lat, + 'lang': lang, + 'status': status, + }; +} diff --git a/lib/pages/AboutApps/component/about.dart b/lib/pages/AboutApps/component/about.dart new file mode 100644 index 0000000..8f442ef --- /dev/null +++ b/lib/pages/AboutApps/component/about.dart @@ -0,0 +1,191 @@ +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; + +class About extends StatefulWidget { + const About({super.key}); + + @override + State createState() => _AboutState(); +} + +class _AboutState extends State { + TextStyle styles = TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w200, + ); + TextStyle styles1 = TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w700, + ); + + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: Container( + child: SingleChildScrollView( + reverse: true, + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height: 55, + ), + Container( + child: InkWell( + onTap: () => Navigator.pop(context), + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + ), + SizedBox( + height: 1, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Tentang Aplikasi", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 17, + color: Color(0xff1A0F0F), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + top: 20, + bottom: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Image.asset( + "assets/images/logoMesinPom.png", + width: 35, + height: 40, + ), + ), + SizedBox( + width: 6, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "BBM", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w700, + color: Color(0xFF3B3C48), + ), + ), + Text( + "Tracking", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w500, + color: Color(0xFF3B3C48), + ), + ) + ], + ), + ), + ], + ), + ), + Container( + child: Text( + about1, + style: styles, + ), + ), + SizedBox( + height: 30, + ), + Container( + child: Text( + about2, + style: styles, + ), + ), + SizedBox( + height: 30, + ), + Container( + child: Text( + about3, + style: styles, + ), + ), + SizedBox( + height: 40, + ), + Container( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Text( + Salam1, + style: styles, + ), + ), + Container( + child: Text( + Salam2, + style: styles1, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/AboutApps/component/kebijakan.dart b/lib/pages/AboutApps/component/kebijakan.dart new file mode 100644 index 0000000..1866d9b --- /dev/null +++ b/lib/pages/AboutApps/component/kebijakan.dart @@ -0,0 +1,191 @@ +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; + +class Kebijakan extends StatefulWidget { + const Kebijakan({super.key}); + + @override + State createState() => _KebijakanState(); +} + +class _KebijakanState extends State { + TextStyle styles = TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w200, + ); + TextStyle styles1 = TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w700, + ); + + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: Container( + child: SingleChildScrollView( + reverse: true, + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height: 55, + ), + Container( + child: InkWell( + onTap: () => Navigator.pop(context), + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + ), + SizedBox( + height: 1, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Kebijakan & Privasi", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 17, + color: Color(0xff1A0F0F), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + Container( + margin: EdgeInsets.only( + top: 20, + bottom: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Image.asset( + "assets/images/logoMesinPom.png", + width: 35, + height: 40, + ), + ), + SizedBox( + width: 6, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "BBM", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w700, + color: Color(0xFF3B3C48), + ), + ), + Text( + "Tracking", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w500, + color: Color(0xFF3B3C48), + ), + ) + ], + ), + ), + ], + ), + ), + Container( + child: Text( + Kebijakan1, + style: styles, + ), + ), + SizedBox( + height: 30, + ), + Container( + child: Text( + Kebijakan2, + style: styles, + ), + ), + SizedBox( + height: 30, + ), + Container( + child: Text( + Kebijakan3, + style: styles, + ), + ), + SizedBox( + height: 40, + ), + Container( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Text( + Salam1, + style: styles, + ), + ), + Container( + child: Text( + Salam2, + style: styles1, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/AboutApps/index.dart b/lib/pages/AboutApps/index.dart new file mode 100644 index 0000000..35d9e5e --- /dev/null +++ b/lib/pages/AboutApps/index.dart @@ -0,0 +1,161 @@ +import 'package:bbm_tracking/pages/AboutApps/component/about.dart'; +import 'package:bbm_tracking/pages/AboutApps/component/kebijakan.dart'; +import 'package:flutter/material.dart'; + +class AboutApps extends StatefulWidget { + const AboutApps({super.key}); + + @override + State createState() => _AboutAppsState(); +} + +class _AboutAppsState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: Container( + child: Column( + children: [ + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Tentang Aplikasi", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 17, + color: Color(0xff1A0F0F), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 20, + ), + card("kebijakan"), + SizedBox( + height: 5, + ), + card("tentang"), + SizedBox( + height: 100, + ), + Column( + children: [ + Container( + child: Image.asset("assets/images/about_person.png"), + ), + Container( + child: Text( + "Ada Yang Bisa Kami Bantu ?", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + fontSize: 13, + color: Color(0xFF3B3C48), + ), + ), + ) + ], + ) + ], + ), + ), + ); + } + + Widget card(tujuan) { + return InkWell( + onTap: () { + tujuan == "kebijakan" + ? Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => Kebijakan(), + ), + ) + : Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => About(), + ), + ); + }, + child: Container( + width: double.infinity, + height: 60, + margin: EdgeInsets.all(5), + padding: EdgeInsets.only( + left: 15, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: const Offset( + 0.5, + 2.0, + ), + blurRadius: 3.0, + spreadRadius: 2.0, + ) + ], + ), + child: Row( + children: [ + Container( + child: Image.asset( + tujuan == "kebijakan" + ? "assets/images/help-circle.png" + : "assets/images/user.png", + width: 30, + height: 30, + ), + ), + SizedBox( + width: 10, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + tujuan == "kebijakan" + ? "Kebijakan & Privasi" + : "Tentang Aplikasi", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w400, + fontSize: 13, + color: Color(0xFF455A64), + ), + ), + Text( + tujuan == "kebijakan" + ? "Baca informasi selengkapnya..." + : "Selengkapnya...", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + fontSize: 11, + color: Color(0xFF3B3C48), + ), + ), + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/Performa/index.dart b/lib/pages/Performa/index.dart new file mode 100644 index 0000000..27afeb7 --- /dev/null +++ b/lib/pages/Performa/index.dart @@ -0,0 +1,273 @@ +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/simulation/index.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; + +class Performa extends StatefulWidget { + const Performa({super.key}); + + @override + State createState() => _PerformaState(); +} + +class _PerformaState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Container( + margin: EdgeInsets.only(top: 54), + child: SingleChildScrollView( + child: Column( + children: [ + Container( + child: InkWell( + onTap: () {}, + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ) + ], + ), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Performa Kendaraan", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 10, + ), + // MainCardKendaraan(), + InkWell( + onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => SimulationScreen())), + child: Align( + alignment: Alignment.topRight, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 13, + vertical: 15, + ), + decoration: BoxDecoration( + color: Color(0xFFF1C40F), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Text( + "Buat Simulasi Kendaraan Anda", + style: TextStyle( + color: Color(0xFF1C7A44), + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + width: double.infinity, + margin: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Color(0xffE3EAEA), + borderRadius: BorderRadius.all(Radius.circular(8)), + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: const Offset( + 0.5, + 2.0, + ), + blurRadius: 5.0, + spreadRadius: 2.0, + ) + ], + ), + child: Padding( + padding: EdgeInsets.all(9), + child: Column( + children: [ + SizedBox( + height: 20, + ), + Container( + width: double.infinity, + height: 190, + // child: BarChartSample3(), + ), + SizedBox( + height: 10, + ), + Container( + child: Text( + "Bulan : Januari 2023", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + color: Color(0xFF1A0F0F), + ), + ), + ), + ], + ), + ), + ), + SizedBox( + height: 8, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Status Performa Kendaraan Anda minggu ini", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w500, + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Status Performa", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 8, + fontWeight: FontWeight.w500, + ), + ), + ), + SizedBox( + height: 10, + ), + itemData("Status", "Baik"), + SizedBox( + height: 10, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Detail Informasi", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 8, + fontWeight: FontWeight.w500, + ), + ), + ), + SizedBox( + height: 10, + ), + itemData("Merek kendaraan", "Honda Beat"), + itemData("Jumlah biaya", "Rp. 600.000"), + itemData("Jumlah liter bensin", "6 Liter"), + itemData("Cubicle Centimeter", "250"), + itemData("Jenis Bahan Bakar", "Pertalite"), + itemData("Odometer", "304761,25 km"), + itemData("Km Tempuh per hari", "8.5 km"), + itemData("Total Km Tempuh", "318 km"), + itemData("Priode pemakaian", "01 Januari 2023 - 31 Januari 2023") + ], + ), + ), + ), + ), + ), + ); + } + + Widget itemData(key, value) { + return Container( + margin: EdgeInsets.symmetric(vertical: 5), + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + margin: EdgeInsets.symmetric(horizontal: 6), + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 12, + ), + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFFD9D9D9), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Text( + key, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + Flexible( + flex: 1, + child: Container( + padding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 12, + ), + margin: EdgeInsets.symmetric(horizontal: 6), + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFFBFE5DF), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Text( + value, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/component/custom_dialog_box.dart b/lib/pages/component/custom_dialog_box.dart new file mode 100644 index 0000000..7ecb064 --- /dev/null +++ b/lib/pages/component/custom_dialog_box.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; + +class CustomeDialogBox extends StatefulWidget { + String title, description, positiveText, negativeText, screen; + final Function onChangeStatus; + + CustomeDialogBox({ + super.key, + required this.title, + required this.description, + required this.positiveText, + required this.negativeText, + required this.screen, + required this.onChangeStatus, + }); + + @override + State createState() => _CustomeDialogBoxState(); +} + +class _CustomeDialogBoxState extends State { + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + contentBox(context) { + return Container( + height: 200, + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: const Offset( + 0.5, + 2.0, + ), + blurRadius: 3.0, + spreadRadius: 2.0, + ) + ], + ), + child: Column( + children: [ + Container( + width: double.infinity, + child: Text( + widget.title, + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + fontSize: 14, + color: Color(0xFF29170B), + ), + textAlign: TextAlign.center, + ), + ), + SizedBox( + height: 10, + ), + Container( + width: double.infinity, + child: Text( + widget.description, + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w400, + fontSize: 11, + color: Color(0xFF080705), + ), + textAlign: TextAlign.center, + ), + ), + SizedBox( + height: 35, + ), + Container( + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + onTap: () { + Navigator.of(context).pop(); + }, + child: Container( + margin: EdgeInsets.only(left: 15), + child: Text( + widget.negativeText, + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + fontSize: 12, + color: Color(0xFF29170B), + ), + ), + ), + ), + InkWell( + onTap: () { + Navigator.of(context).pop(); + widget.onChangeStatus(); + }, + child: Container( + width: 115, + padding: EdgeInsets.fromLTRB( + 10, + 10, + 10, + 10, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Color(0xFF2ECC71), + ), + child: Text( + widget.positiveText, + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + fontSize: 12, + color: Color(0xFFFFFFFF), + ), + textAlign: TextAlign.center, + ), + ), + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/component/dropdown.dart b/lib/pages/component/dropdown.dart new file mode 100644 index 0000000..143dbf5 --- /dev/null +++ b/lib/pages/component/dropdown.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class Dropdown extends StatefulWidget { + const Dropdown({super.key}); + + @override + State createState() => _DropdownState(); +} + +class _DropdownState extends State { + @override + Widget build(BuildContext context) { + return Container(); + } +} \ No newline at end of file diff --git a/lib/pages/component/success_dialog_box.dart b/lib/pages/component/success_dialog_box.dart new file mode 100644 index 0000000..1d6727c --- /dev/null +++ b/lib/pages/component/success_dialog_box.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; + +class SuccessDialogBox extends StatefulWidget { + String deskripsi; + SuccessDialogBox({ + super.key, + required this.deskripsi, + }); + + @override + State createState() => _SuccessDialogBoxState(); +} + +class _SuccessDialogBoxState extends State { + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: Container( + height: 160, + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Color(0xFF2ECC71), + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: const Offset( + 0.5, + 2.0, + ), + blurRadius: 3.0, + spreadRadius: 2.0, + ) + ], + ), + child: Column( + children: [ + Image.asset('assets/images/success.png'), + SizedBox( + height: 10, + ), + Text( + "BERHASIL", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + fontSize: 16, + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: 10, + ), + Text( + widget.deskripsi, + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + fontSize: 10, + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/form-tambah-data-bensin/displayImage.dart b/lib/pages/form-tambah-data-bensin/displayImage.dart new file mode 100644 index 0000000..c5afcda --- /dev/null +++ b/lib/pages/form-tambah-data-bensin/displayImage.dart @@ -0,0 +1,119 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; + +class DisplayImage extends StatefulWidget { + final File imagePath; + const DisplayImage({super.key, required this.imagePath}); + + @override + State createState() => _DisplayImageState(); +} + +class _DisplayImageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: Container( + margin: EdgeInsets.only( + top: 50, + ), + child: Column( + children: [ + Container( + child: BackButton(), + margin: EdgeInsets.only( + left: 10, + ), + ), + SizedBox( + height: 20, + ), + Expanded( + flex: 4, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 5, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + color: Colors.amber), + child: Image.file( + File(widget.imagePath.path), + fit: BoxFit.cover, + ), + ), + ), + ), + SizedBox( + height: 20, + ), + InkWell( + onTap: () { + Navigator.pop(context, widget.imagePath); + }, + child: Container( + height: 33, + width: 100, + decoration: BoxDecoration( + color: Color(0xFFE74C3C), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10), + child: Container( + child: Text( + "Hapus", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + color: Colors.white, + fontSize: 11, + ), + ), + ), + ), + ), + ), + SizedBox( + height: 20, + ), + ], + ), + ), + ); + } + + Widget BackButton() { + return InkWell( + onTap: () => Navigator.pop(context, null), + child: Container( + child: Container( + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/form-tambah-data-bensin/index.dart b/lib/pages/form-tambah-data-bensin/index.dart new file mode 100644 index 0000000..26eb253 --- /dev/null +++ b/lib/pages/form-tambah-data-bensin/index.dart @@ -0,0 +1,1495 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:math'; + +import 'package:animated_custom_dropdown/custom_dropdown.dart'; +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/photo_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/pages/component/success_dialog_box.dart'; +import 'package:bbm_tracking/pages/form-tambah-data-bensin/displayImage.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/resource/popup/popup.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +// import 'package:geolocator/geolocator.dart'; +import 'package:intl/intl.dart'; +import 'package:currency_text_input_formatter/currency_text_input_formatter.dart'; +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'dart:developer' as developer; +import 'package:geolocator/geolocator.dart'; +import 'package:location/location.dart'; +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:uri_to_file/uri_to_file.dart'; + +class FormTamabahDataBensin extends StatefulWidget { + KendaraanModel kendaraanModel; + // TransaksiModel transaksiModel; + final CameraDescription camera; + + FormTamabahDataBensin( + {required this.kendaraanModel, required this.camera, Key? key}) + : super(key: key); + // FormTamabahDataBensin(this.transaksiModel, {required this.kendaraanModel, required this.camera}); + + @override + State createState() => _FormTamabahDataBensinState(); +} + +class _FormTamabahDataBensinState extends State + with RestorationMixin { + ConnectivityResult _connectionStatus = ConnectivityResult.none; + final Connectivity _connectivity = Connectivity(); + late StreamSubscription _connectivitySubscription; + + late KendaraanModel dataKendaraan; + var formatDate = DateFormat("yyyy-MM-dd"); + DateTime dateNow = DateTime.now(); + late String selectedDate = formatDate.format(dateNow).toString(); + late TimeOfDay _time = TimeOfDay(hour: dateNow.hour, minute: dateNow.minute); + late bool conditionBbm = false; + + late String literTxt = ''; + late String hargaPerLiterTxt = ''; + late String totalBiayaTxt = ''; + + final String wifiOff = + "Maps tidak dapat dibuka, Anda saat ini sedang di luar jaringan. Silakan periksa jaringan internet Anda"; + final String gpsOff = "Maps tidak dapat dibuka, GPS tidak aktif"; + + final odometerController = TextEditingController(); + final bbmController = TextEditingController(); + final dateController = TextEditingController(); + final timeController = TextEditingController(); + final literController = TextEditingController(); + final totalBiayaController = TextEditingController(); + final alamatController = TextEditingController(); + final catatanController = TextEditingController(); + final hargaPerLiterController = TextEditingController(); + final lokasiController = TextEditingController(); + + GoogleMapController? _controllerMap; + Location currentLocation = Location(); + static const CameraPosition initialCameraPosition = CameraPosition( + target: LatLng(37.42796133580664, -122.085749655962), zoom: 14); + + late bool _gpsEnable = false; + late bool _internetEnable = false; + + Set _markers = {}; + + late CameraController _cameraController; + late Future _initializeControllerFuture; + + List _image = []; + File? tryImage; + + bool _submittedForm = false; + + BensinModel? dtBensin; + + String latitude = "0"; + String langitude = "0"; + + List dataPhoto = []; + + bool _isButtonDisabled = false; + + bool isLoading = false; + + + bool markerLoading = false; + + @override + void initState() { + // TODO: implement initState + super.initState(); + Future.delayed(Duration.zero, () { + timeController.text = _time.format(context).toString(); + dateController.text = selectedDate; + }); + + initConnectivity(); + // checkGPS(); + _connectivitySubscription = + _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + + dataKendaraan = widget.kendaraanModel; + + bbmController.addListener(() { + if (bbmController.text == "") { + conditionBbm == true; + } else { + conditionBbm = false; + dtBensin = listBensin + .firstWhere((element) => element.text == bbmController.text); + hargaPerLiterController.text = + CurrencyFormat.convertToIdr(dtBensin!.harga, 0); + hargaPerLiterTxt = dtBensin!.harga.toString(); + } + }); + + totalBiayaController.addListener(() { + var txt = _replaceFormat(totalBiayaController.text); + totalBiayaTxt = txt; + _counter(); + }); + + hargaPerLiterController.addListener(() { + var txt = _replaceFormat(hargaPerLiterController.text); + hargaPerLiterTxt = txt; + _counter(); + }); + + setState(() { + initialLocation(); + isLoading = true; + // getLocation(); + }); + + _cameraController = CameraController( + widget.camera, + ResolutionPreset.medium, + ); + + _initializeControllerFuture = _cameraController.initialize(); + + } + + @override + void dispose() { + super.dispose(); + _controllerMap!.dispose(); + _connectivitySubscription.cancel(); + _cameraController.dispose(); + odometerController.dispose(); + bbmController.dispose(); + dateController.dispose(); + timeController.dispose(); + literController.dispose(); + totalBiayaController.dispose(); + alamatController.dispose(); + catatanController.dispose(); + hargaPerLiterController.dispose(); + lokasiController.dispose(); + } + + void initialLocation() async { + Position position = await checkGPS(); + + _controllerMap?.animateCamera( + CameraUpdate.newCameraPosition( + CameraPosition( + target: LatLng( + position.latitude, + position.longitude, + ), + zoom: 16, + ), + ), + ); + _markers.clear(); + latitude = position.latitude.toString(); + langitude = position.longitude.toString(); + + setState(() { + _markers.add( + Marker( + markerId: const MarkerId('currentLocation'), + position: LatLng(position.latitude, position.longitude), + ), + ); + markerLoading = true; + }); + } + + Future checkGPS() async { + bool serviceEnabled; + LocationPermission permission; + + // Test if location services are enabled. + serviceEnabled = await Geolocator.isLocationServiceEnabled(); + + if (!serviceEnabled) { + // Location services are not enabled don't continue + // accessing the position and request users of the + // App to enable the location services. + return Future.error('Location services are disabled.'); + } else { + _gpsEnable = true; + } + + permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + // Permissions are denied, next time you could try + // requesting permissions again (this is also where + // Android's shouldShowRequestPermissionRationale + // returned true. According to Android guidelines + // your App should show an explanatory UI now. + return Future.error('Location permissions are denied'); + } + } + + if (permission == LocationPermission.deniedForever) { + // Permissions are denied forever, handle appropriately. + return Future.error( + 'Location permissions are permanently denied, we cannot request permissions.'); + } + // When we reach here, permissions are granted and we can + // continue accessing the position of the device. + return await Geolocator.getCurrentPosition(); + } + + Future initConnectivity() async { + late ConnectivityResult result; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + result = await _connectivity.checkConnectivity(); + } on PlatformException catch (e) { + developer.log('Couldn\'t check connectivity status', error: e); + return; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) { + return Future.value(null); + } + + return _updateConnectionStatus(result); + } + + Future _updateConnectionStatus(ConnectivityResult result) async { + setState(() { + if (result != ConnectivityResult.none) { + _internetEnable = true; + } + _connectionStatus = result; + }); + } + + List listNamaBensin = List.from(listBensin.map((e) => e.text)); + RangeLabels labels = RangeLabels('1', "10"); + RangeValues _rangeValues = RangeValues(1, 10); + + @override + String? get restorationId => 'main'; + + final RestorableDateTime _selectedDate = RestorableDateTime(DateTime.now()); + late final RestorableRouteFuture _restorableDatePickerRouteFuture = + RestorableRouteFuture( + onComplete: _selectDate, + onPresent: (NavigatorState navigator, Object? arguments) { + return navigator.restorablePush( + _datePickerRoute, + arguments: _selectedDate.value.millisecondsSinceEpoch, + ); + }, + ); + + static Route _datePickerRoute( + BuildContext context, + Object? arguments, + ) { + return DialogRoute( + context: context, + builder: (BuildContext context) { + return DatePickerDialog( + restorationId: 'date_picker_dialog', + initialEntryMode: DatePickerEntryMode.calendarOnly, + initialDate: DateTime.fromMillisecondsSinceEpoch(arguments! as int), + firstDate: DateTime(2000), + lastDate: DateTime.now(), + ); + }, + ); + } + + @override + void restoreState(RestorationBucket? oldBucket, bool initialRestore) { + registerForRestoration(_selectedDate, 'selected_date'); + registerForRestoration( + _restorableDatePickerRouteFuture, 'date_picker_route_future'); + } + + void _selectDate(DateTime? newSelectedDate) { + if (newSelectedDate != null) { + setState(() { + _selectedDate.value = newSelectedDate; + dateController.text = + DateFormat("yyyy-MM-dd").format(newSelectedDate).toString(); + selectedDate = + DateFormat("yyyy-MM-dd").format(newSelectedDate).toString(); + }); + } + } + + void _selectTime() async { + TimeOfDay? newTime = await showTimePicker( + context: context, + initialTime: _time, + ); + if (newTime != null) { + setState(() { + _time = newTime; + timeController.text = _time.format(context).toString(); + }); + } + } + + String _replaceFormat(String data) { + var txt = data.replaceAll("Rp. ", ''); + txt = txt.replaceAll(".", ''); + return txt; + } + + void _counter() { + if (bbmController.text == "") { + showDialog( + context: context, + builder: (BuildContext context) { + return PopUp( + text: "Maaf, Silakan pilih jenis BBM terlebih dahulu", + param: "negative", + ); + }, + ); + } else { + double res = 0; + hargaPerLiterTxt != '' && totalBiayaTxt != '' + ? res = int.parse(totalBiayaTxt) / int.parse(hargaPerLiterTxt) + : res = 0; + + // BensinModel dtBensin = listBensin + // .firstWhere((element) => element.text == bbmController.text); + if (res == 0) { + literController.text = ''; + literTxt = ''; + } else { + literController.text = res.toStringAsFixed(2).toString(); + literTxt = res.toStringAsFixed(2).toString(); + } + } + } + + void _checkBBMselected() { + conditionBbm == true + ? showDialog( + context: context, + builder: (BuildContext context) { + return PopUp( + text: "Maaf, Silakan pilih jenis BBM terlebih dahulu", + param: "negative", + ); + }, + ) + : null; + } + + String _setFormat(data) { + return CurrencyFormat.convertToIdr(data, 0); + } + + Future _navigateAndDisplayImage( + BuildContext context, + File file, + ) async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DisplayImage(imagePath: file), + ), + ); + if (!mounted) return; + + if (result != null) { + setState(() { + _image.remove(result); + }); + print(_image); + } + } + + void _submitted() async { + setState(() { + _isButtonDisabled = true; + }); + var rng = Random(); + String _kodeTransaksi = + "BBM-T/F0001/${bbmController.text}/XIII/${rng.nextInt(999999)}"; + + final dateNow = DateTime.now().toString(); + print("printing"); + await insertedImageToGallery(dateNow, _kodeTransaksi); + + Future.delayed(Duration(seconds: 2), () { + insertedTransaksi(_kodeTransaksi); + }); + } + + Future insertedTransaksi(String _kodeTransaksi) async { + String strsub; + if (timeController.text.toString()[4] == " ") { + strsub = timeController.text.substring(0, 4) + ":00"; + } else { + strsub = timeController.text.substring(0, 5) + ":00"; + } + + TransaksiModel transaksiModel = TransaksiModel( + id: 0, + kendaraanId: dataKendaraan.id.toString(), + bensinId: dtBensin!.id.toString(), + kodeTransaksi: _kodeTransaksi, + tanggalTransaksi: DateFormat("yyyy-MM-dd").parse(dateController.text), + waktuTransaksi: DateFormat("HH:mm:ss").parse(strsub), + lokasiPertamina: lokasiController.text, + totalLiter: literController.text, + hargaPerLiter: int.parse(hargaPerLiterTxt), + totalBayar: int.parse(totalBiayaTxt), + odometer: odometerController.text, + catatan: catatanController.text, + lat: latitude, + lang: langitude, + status: 1, + ); + context + .read() + .add(BBMInsertTransaksion(transaksi: transaksiModel, photo: dataPhoto)); + setState(() { + BlocProvider.of(context).add(BBMStarted()); + }); + Navigator.pop(context); + showDialog( + context: context, + builder: (BuildContext context) { + return SuccessDialogBox(deskripsi: "Berhasil Menambah Data"); + }, + ); + } + + Future insertedImageToGallery( + String dateNow, String _kodeTransaksi) async { + _image.forEach((element) async { + final result = await ImageGallerySaver.saveImage( + Uint8List.fromList(element!.readAsBytesSync()), + quality: 60, + name: dateNow, + ); + // File file = await toFile(Uri.parse(result['filePath']).toString()); + // print("files = "+file.path.toString()); + PhotoModel modelPhoto = PhotoModel( + id: 0, + transaksi_id: _kodeTransaksi, + linkPhoto: result['filePath'], + namePhoto: dateNow, + ); + setState(() { + dataPhoto.add(modelPhoto); + }); + }); + } + + String? _errorText(TextEditingController controller) { + var val = controller.value.text.isEmpty ? "Tidak Boleh Kosong" : null; + return val; + } + + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return isLoading ? WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: SingleChildScrollView( + child: Container( + margin: EdgeInsets.only( + top: 50, + ), + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + BackButton(), + SizedBox( + height: 10, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Pengisian Bahan Bakar", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 15, + ), + Card(dataKendaraan), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Masukan Data Pengisian Bahan Bakar", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 13, + color: Color(0xff1A0F0F), + ), + ), + ), + SizedBox( + height: 5, + ), + formPengisian(), + SizedBox( + height: 10, + ), + formLokasiSPBU(), + SizedBox( + height: 10, + ), + formGambar(), + SizedBox( + height: 10, + ), + formCatatan(), + SizedBox( + height: 15, + ), + SizedBox( + height: 25, + ), + ButtonSave(), + ], + ), + ), + ), + ), + ), + ) : Container(); + } + + Widget ButtonSave() { + return InkWell( + onTap: () { + _isButtonDisabled ? null : _submitted(); + }, + child: Container( + alignment: Alignment.topRight, + child: Container( + width: 80, + height: 35, + // alignment: Alignment.topRight, + padding: EdgeInsets.only(top: 9, left: 9), + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Color(0xFF2ECC71), + ), + child: Text( + "Tambahkan", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ), + ), + ); + } + + Widget Card(KendaraanModel dataKendaraan) { + return Container( + height: 75, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Color(0xFFFC8D05), + ), + child: Row( + children: [ + SizedBox( + width: 20, + ), + Image.asset( + dataKendaraan.jenisKendaraan == "motor" + ? "assets/images/motor.png" + : "assets/images/car.png", + width: 50, + height: 50, + ), + SizedBox( + width: 20, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 15, + ), + Text( + "Tipe Kendaraan : ", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + color: Color(0xFF3B3C48), + ), + ), + SizedBox( + height: 5, + ), + Text( + dataKendaraan.namaKendaraan, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w700, + color: Colors.white, + ), + ), + ], + ), + ], + ), + ); + } + + Widget BackButton() { + return InkWell( + onTap: () => Navigator.pop(context), + child: Container( + child: Container( + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ) + ], + ), + ), + ), + ); + } + + Widget formCatatan() { + return Container( + child: Column( + children: [ + Container( + padding: EdgeInsets.only( + left: 10, + top: 3, + ), + width: double.infinity, + height: 25, + decoration: BoxDecoration( + color: Color(0xFF677D81), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + child: Text( + "Optional", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 11, + color: Color(0xffFFFFFF), + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Row( + children: [ + Container( + child: Image.asset( + "assets/images/edit.png", + width: 34, + height: 34, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Container( + child: TextField( + controller: catatanController, + maxLines: 5, + keyboardType: TextInputType.text, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: "Catatan (optional)", + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + ], + ), + ) + ], + ), + ); + } + + Widget formGambar() { + return Container( + child: Column( + children: [ + Container( + padding: EdgeInsets.only( + left: 10, + top: 3, + ), + width: double.infinity, + height: 25, + decoration: BoxDecoration( + color: Color(0xFF677D81), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + child: Text( + "Gambar", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 11, + color: Color(0xffFFFFFF), + ), + ), + ), + SizedBox( + height: 10, + ), + Row( + children: [ + Container( + child: Image.asset( + "assets/images/frmImage1.png", + width: 34, + height: 34, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Color(0xFF677D81), + width: 1, + ), + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + InkWell( + onTap: () async { + try { + final pickedImage = await ImagePicker() + .pickImage(source: ImageSource.camera); + + setState(() { + _image.add(File(pickedImage!.path)); + }); + } catch (e) { + // If an error occurs, log the error to the console. + print(e); + } + }, + child: Container( + child: Image.asset( + "assets/images/frmAdd.png", + width: 34, + height: 34, + ), + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Container( + height: 34, + child: ListView.builder( + itemCount: _image.length, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context, int index) { + return Container( + margin: EdgeInsets.symmetric(horizontal: 5), + child: InkWell( + onTap: () { + _navigateAndDisplayImage( + context, _image[index]!); + }, + child: Container( + child: Image.file( + File( + _image[index]!.path, + ), + width: 35, + fit: BoxFit.fill, + ), + ), + ), + ); + }, + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ], + ), + ); + } + + Widget formLokasiSPBU() { + return Column( + children: [ + Container( + padding: EdgeInsets.only( + left: 10, + top: 3, + ), + width: double.infinity, + height: 25, + decoration: BoxDecoration( + color: Color(0xFF677D81), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + child: Text( + "Lokasi SPBU", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 11, + color: Color(0xffFFFFFF), + ), + ), + ), + SizedBox( + height: 10, + ), + SizedBox( + height: 10, + ), + _internetEnable == false + ? frameNegativeMaps(wifiOff) + : _gpsEnable == false + ? frameNegativeMaps(gpsOff) + : framePositiveMaps(), + SizedBox( + height: 10, + ), + Row( + children: [ + Container( + margin: EdgeInsets.only( + top: 10, + ), + child: Image.asset( + "assets/images/titikpoint.png", + width: 24, + height: 24, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Container( + child: TextField( + controller: lokasiController, + keyboardType: TextInputType.text, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: "Lokasi/Nama SPBU (optional)", + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ), + ], + ), + ], + ); + } + + Widget framePositiveMaps() { + return Container( + height: 150, + width: double.infinity, + child: GoogleMap( + initialCameraPosition: CameraPosition( + target: LatLng(48.8561, 2.2930), + zoom: 15, + ), + markers: markerLoading ? _markers : {}, + zoomControlsEnabled: false, + mapType: MapType.normal, + onMapCreated: (GoogleMapController controller) { + _controllerMap = controller; + }, + ), + ); + } + + Widget frameNegativeMaps(text) { + return Container( + height: 150, + width: double.infinity, + decoration: BoxDecoration( + border: Border.all(color: Color(0xFFAEAEAE)), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Column( + children: [ + SizedBox( + height: 40, + ), + Image.asset( + "assets/images/wifi-off.png", + width: 40, + ), + Container( + width: 250, + child: Text( + text, + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFF828282), + fontSize: 9, + fontWeight: FontWeight.w400, + ), + ), + ), + ], + ), + ); + } + + Widget formPengisian() { + return Container( + width: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: EdgeInsets.only( + left: 10, + top: 3, + ), + width: double.infinity, + height: 25, + decoration: BoxDecoration( + color: Color(0xFF677D81), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + child: Text( + "Pengisian", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 11, + color: Color(0xffFFFFFF), + ), + ), + ), + SizedBox( + height: 10, + ), + formPengisianKendaraan(), + formTanggalPengisian(), + SizedBox( + height: 10, + ), + formJumlahBensin() + ], + ), + ); + } + + Widget formPengisianKendaraan() { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only( + top: 10, + ), + child: Image.asset( + "assets/images/radar.png", + width: 24, + height: 24, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Container( + // decoration: BoxDecoration(color: Colors.greenAccent), + child: Column( + children: [ + TextField( + controller: odometerController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: "Odometer (km)", + errorText: + _submittedForm ? _errorText(odometerController) : null, + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ), + SizedBox( + height: 10, + ), + CustomDropdown.search( + fillColor: Color(0xffE3EAEA), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + hintStyle: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + ), + // errorText: _submitted + // ? _errorText(controller) + // : null, + items: listNamaBensin, + controller: bbmController, + hintText: "Tipe Bahan Bakar", + errorText: _submittedForm ? _errorText(bbmController) : null, + ), + SizedBox( + height: 10, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Perkiraan Bensin Saat ini", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ), + ), + SizedBox( + height: 5, + ), + Container( + child: RangeSlider( + divisions: 10, + activeColor: Color(0xFFFC8D05), + inactiveColor: Color(0xFFDDB05E), + min: 1, + max: 10, + labels: RangeLabels( + _rangeValues.start.round().toString(), + _rangeValues.end.round().toString(), + ), + values: _rangeValues, + onChanged: (RangeValues val) { + if (val.start == 1) { + setState(() { + _rangeValues = val; + }); + } + }, + ), + ), + ], + ), + ), + ), + ], + ); + } + + Widget formTanggalPengisian() { + return Row( + children: [ + Container( + child: Image.asset( + "assets/images/calendaradd.png", + width: 24, + height: 24, + ), + ), + SizedBox( + width: 10, + ), + Expanded( + child: Container( + child: Row( + children: [ + Flexible( + flex: 5, + child: Container( + child: TextField( + controller: dateController, + readOnly: true, + onTap: () { + _restorableDatePickerRouteFuture.present(); + }, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: selectedDate, + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Colors.black, + fontSize: 15, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + Flexible( + flex: 1, + child: Container( + margin: EdgeInsets.only( + left: 5, + right: 5, + ), + child: Image.asset( + "assets/images/timer.png", + width: 24, + height: 24, + ), + ), + ), + Flexible( + flex: 5, + child: Container( + child: TextField( + controller: timeController, + readOnly: true, + onTap: () { + _selectTime(); + }, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: _time.format(context), + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Colors.black, + fontSize: 15, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ], + ); + } + + Widget formJumlahBensin() { + return Row( + children: [ + Container( + child: Image.asset( + "assets/images/dollarsquare.png", + width: 24, + height: 24, + ), + ), + SizedBox( + width: 10, + ), + Container( + child: Expanded( + child: Row( + children: [ + Flexible( + flex: 2, + child: TextField( + controller: literController, + keyboardType: TextInputType.number, + onTap: () => _checkBBMselected(), + readOnly: true, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: "Liter", + errorText: + _submittedForm ? _errorText(literController) : null, + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + SizedBox( + width: 10, + ), + Flexible( + flex: 3, + child: TextField( + inputFormatters: [ + CurrencyTextInputFormatter( + locale: 'id', + symbol: 'Rp. ', + decimalDigits: 0, + ), + ], + controller: hargaPerLiterController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + errorText: _submittedForm + ? _errorText(hargaPerLiterController) + : null, + hintText: "Harga/Liter", + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + SizedBox( + width: 10, + ), + Flexible( + flex: 3, + child: TextField( + inputFormatters: [ + CurrencyTextInputFormatter( + locale: 'id', + symbol: 'Rp. ', + decimalDigits: 0, + ), + ], + controller: totalBiayaController, + keyboardType: TextInputType.number, + onTap: () => _checkBBMselected(), + // readOnly: !conditionBbm, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: "Total Biaya", + errorText: _submittedForm + ? _errorText(totalBiayaController) + : null, + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/pages/home.dart b/lib/pages/home.dart new file mode 100644 index 0000000..ef27266 --- /dev/null +++ b/lib/pages/home.dart @@ -0,0 +1,259 @@ +import 'dart:io'; + +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/pages/AboutApps/index.dart'; +import 'package:bbm_tracking/pages/form-tambah-data-bensin/index.dart'; +import 'package:bbm_tracking/pages/kendaraan/form-tambah-kendaraan/form.dart'; +import 'package:bbm_tracking/pages/kendaraan/index_kendaraan.dart'; +import 'package:bbm_tracking/repository/kendaraan/kendaraan_repository.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:bbm_tracking/resource/component-bersama/chart.dart'; +import 'package:bbm_tracking/pages/mainMenu/component/item_bensin.dart'; +import 'package:bbm_tracking/pages/mainMenu/index.dart'; +import 'package:bbm_tracking/pages/riwayat/index.dart'; +import 'package:bbm_tracking/resource/popup/popup.dart'; +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:pandabar/main.view.dart'; +import 'package:pandabar/model.dart'; + +class Home extends StatefulWidget { + final String screen; + final String param; + + Home(this.screen, this.param); + + @override + State createState() => _HomeState(); +} + +class _HomeState extends State { + late String screen = 'home'; + late String param; + late List dataKendaraan; + late KendaraanModel dt; + late bool paramKendaran = false; + late int paramText = 0; + late bool cond = false; + var firstCamera; + + late bool _gpsEnable; + void ButtonAddTransaksi() { + if (dataKendaraan != null || dataKendaraan.length != 0) { + for (KendaraanModel element in dataKendaraan) { + if (element.status == 1) { + paramKendaran = true; + dt = element; + cond = true; + paramText = 2; + break; + } + paramKendaran = false; + paramText = 1; + } + } else { + paramKendaran = false; + paramText = 0; + } + + paramKendaran + ? Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => FormTamabahDataBensin( + kendaraanModel: dt, + camera: firstCamera, + key: UniqueKey(), + ), + ), + ) + : showDialog( + context: context, + builder: (BuildContext context) { + return PopUp( + text: paramText == 1 + ? "Maaf, Silakan aktifkan kendaraan Anda terlebih dahulu" + : "Maaf, Silakan tambahkan kendaraan Anda terlebih dahulu", + param: "negative", + ); + }, + ); + } + + @override + void initState() { + // TODO: implement initState + super.initState(); + screen = widget.screen; + param = widget.param; + + context.read()..add(BBMStarted()); + // setState(() { + // widget.screen != null ? screen = "${widget.screen}" : screen = "home"; + // }); + initilizeCamera(); + checkGPS(); + } + + Future checkGPS() async { + bool serviceEnabled; + LocationPermission permission; + + // Test if location services are enabled. + serviceEnabled = await Geolocator.isLocationServiceEnabled(); + + if (!serviceEnabled) { + // Location services are not enabled don't continue + // accessing the position and request users of the + // App to enable the location services. + return Future.error('Location services are disabled.'); + } else { + _gpsEnable = true; + } + + permission = await Geolocator.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await Geolocator.requestPermission(); + if (permission == LocationPermission.denied) { + // Permissions are denied, next time you could try + // requesting permissions again (this is also where + // Android's shouldShowRequestPermissionRationale + // returned true. According to Android guidelines + // your App should show an explanatory UI now. + return Future.error('Location permissions are denied'); + } + } + + if (permission == LocationPermission.deniedForever) { + // Permissions are denied forever, handle appropriately. + return Future.error( + 'Location permissions are permanently denied, we cannot request permissions.'); + } + // When we reach here, permissions are granted and we can + // continue accessing the position of the device. + return await Geolocator.getCurrentPosition(); + } + + Future initilizeCamera() async { + WidgetsFlutterBinding.ensureInitialized(); + + // Obtain a list of the available cameras on the device. + final cameras = await availableCameras(); + + // Get a specific camera from the list of available cameras. + setState(() { + firstCamera = cameras.first; + }); + } + + Future _onWillPop() async { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: new Text('Apa Kamu Yakin?'), + content: new Text('Kamu ingin Keluar Aplikasi'), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: new Text('No'), + ), + TextButton( + onPressed: () => SystemNavigator.pop(), + child: new Text('Yes'), + ), + ], + ); + }, + ); + return false; + } + + // String page = 'home'; + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + bottomNavigationBar: PandaBar( + backgroundColor: Color(0xFFD2E1E1), + buttonSelectedColor: Color(0xFFFC8D05), + fabColors: [Color(0xFFFC8D05), Color(0xFFDDB05E)], + buttonData: [ + PandaBarButtonData( + id: 'home', + icon: Icons.home, + title: 'Home', + ), + PandaBarButtonData( + id: 'kendaraan', + icon: Icons.directions_car_filled_outlined, + title: 'Kendaraan', + ), + PandaBarButtonData( + id: 'riwayat', + icon: Icons.account_balance_wallet_outlined, + title: 'Riwayat', + ), + PandaBarButtonData( + id: 'tentang', + icon: Icons.assignment_late_outlined, + title: 'Tentang', + ), + ], + onChange: (id) { + setState(() { + screen = id; + }); + }, + onFabButtonPressed: () { + ButtonAddTransaksi(); + }, + ), + body: BlocBuilder( + builder: (context, state) { + if (state is BBMLoaded) { + dataKendaraan = state.kendaraan; + return WillPopScope( + onWillPop: () => _onWillPop(), + child: SafeArea( + child: Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Builder( + builder: (context) { + // print("screen = " + param); + switch (screen) { + case 'home': + return IndexMainMenu(); + case 'kendaraan': + // context.read().add(BBMAllDataKendaraan()); + return IndexKendaraan(); + case 'riwayat': + return Riwayat( + dataKendaraan, + key: UniqueKey(), + data: state.transaksi, + ); + case 'tentang': + return AboutApps(); + default: + return IndexMainMenu(); + } + }, + ), + ), + ), + ); + } + return Container(); + }, + ), + ); + } +} diff --git a/lib/pages/kendaraan/component/card-kendaraan.dart b/lib/pages/kendaraan/component/card-kendaraan.dart new file mode 100644 index 0000000..12fb268 --- /dev/null +++ b/lib/pages/kendaraan/component/card-kendaraan.dart @@ -0,0 +1,282 @@ +import 'package:bbm_tracking/model/Kendaraan_model.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/pages/component/custom_dialog_box.dart'; +import 'package:bbm_tracking/repository/kendaraan/kendaraan_repository.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; + +class CardKendaraan extends StatefulWidget { + final KendaraanModel kendaraan; + final Function onChangeStatus; + final Function onDelete; + final Function onUpdate; + CardKendaraan( + {required this.kendaraan, required this.onChangeStatus, required this.onDelete, required this.onUpdate, Key? key}) + : super(key: key); + + @override + State createState() => _CardKendaraanState(); +} + +class _CardKendaraanState extends State { + late KendaraanModel kendaraan; + late Function onChangeStatus; + late Function onDelete; + late Function onUpdate; + @override + void initState() { + super.initState(); + kendaraan = widget.kendaraan; + onChangeStatus = widget.onChangeStatus; + onDelete = widget.onDelete; + onUpdate = widget.onUpdate; + } + + int count = 0; + changeStatus(id, status) { + onChangeStatus(id, status); + } + + TextStyle styleText = TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w700, + color: Color(0xFF3B3C48), + ); + + TextStyle cardTitle = TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w700, + color: Color(0xFF3B3C48), + ); + + TextStyle cardData = TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + fontWeight: FontWeight.w400, + color: Color(0xFFFFFFFF), + ); + + void deleteData() async { + onDelete(kendaraan.id); + } + + void updateData() async { + onUpdate(kendaraan); + } + + @override + Widget build(BuildContext context) { + return Slidable( + // Specify a key if the Slidable is dismissible. + key: const ValueKey(0), + + // The start action pane is the one at the left or the top side. + startActionPane: ActionPane( + // A motion is a widget used to control how the pane animates. + motion: const DrawerMotion(), + + // A pane can dismiss the Slidable. + // dismissible: DismissiblePane(onDismissed: () {}), + + // All actions are defined in the children parameter. + children: [ + // A SlidableAction can have an icon and/or a label. + SlidableAction( + backgroundColor: Color(0xFFFE4A49), + foregroundColor: Colors.white, + icon: Icons.delete, + label: 'Delete', + onPressed: (context) => deleteData(), + ), + SlidableAction( + onPressed: (context) => updateData(), + backgroundColor: Color(0xFF21B7CA), + foregroundColor: Colors.white, + icon: Icons.share, + label: 'Update', + ), + ], + ), + + child: Container( + width: double.infinity, + height: 145, + margin: EdgeInsets.only( + top: 8, + bottom: 8, + ), + decoration: BoxDecoration( + color: kendaraan.status == 1 ? Color(0xFFFC8D05) : Color(0xFFDDB05E), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Column( + children: [ + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.all(10), + child: Text( + kendaraan.status == 1 + ? "Kendaraan Anda Saat ini" + : "Kendaraan Lainnya", + style: styleText, + ), + ), + Container( + // padding: EdgeInsets.all(10), + child: Switch( + activeColor: Color(0xFFDDB05E), + activeTrackColor: Colors.white, + inactiveThumbColor: Color(0xFFE3EAEA), + inactiveTrackColor: Colors.white, + splashRadius: 50, + value: kendaraan.status == 0 ? false : true, + onChanged: (value) { + kendaraan.status == 0 + ? showDialog( + context: context, + builder: (BuildContext context) { + return CustomeDialogBox( + title: 'Aktifkan Kendaraan?', + description: + 'Anda dapat melihat semua detail data kendaraan ketika status kendaraan sudah aktif kembali', + positiveText: "Ya, Aktifkan", + negativeText: "Batalkan", + screen: "cardKendaraan", + onChangeStatus: () => { + changeStatus(kendaraan.id, 1), + }, + ); + }, + ) + : changeStatus(kendaraan.id, 0); + }, + ), + ), + ], + ), + ), + Container( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + // crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tipe Kendaraan : ", + style: cardTitle, + ), + Text( + "${kendaraan.namaKendaraan}", + style: cardData, + ), + ], + ), + ), + SizedBox( + width: 20, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Nomor Plat : ", + style: cardTitle, + ), + Text( + "${kendaraan.nomorPlat}", + style: cardData, + ), + ], + ), + ), + ], + ), + SizedBox( + height: 15, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Bahan Bakar saat ini ", + style: cardTitle, + ), + Text( + "${kendaraan.bahanBakar}", + style: cardData, + ), + ], + ), + ), + ], + ), + Container( + child: Image.asset( + kendaraan.jenisKendaraan == "mobil" + ? "assets/images/car.png" + : "assets/images/motor.png", + width: 80, + height: 80, + ), + ), + ], + ), + ), + ], + ), + ), + ); + } + + Dialog showDialogError() { + return Dialog( + elevation: 1, + backgroundColor: Colors.white, + child: Container( + height: 230, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset("assets/images/error_kendaraan.png"), + SizedBox( + height: 25, + ), + Text( + "Maaf, Anda menonaktifkan kendaraan ini", + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 12, + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + ), + textAlign: TextAlign.center, + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/kendaraan/form-tambah-kendaraan/form.dart b/lib/pages/kendaraan/form-tambah-kendaraan/form.dart new file mode 100644 index 0000000..8a5ebba --- /dev/null +++ b/lib/pages/kendaraan/form-tambah-kendaraan/form.dart @@ -0,0 +1,415 @@ +import 'package:animated_custom_dropdown/custom_dropdown.dart'; +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/pages/component/success_dialog_box.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/mainMenu/index.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; + +class FormKendaraan extends StatefulWidget { + String kendaraan; + FormKendaraan({super.key, required this.kendaraan}); + + @override + State createState() => _FormKendaraanState(); +} + +class _FormKendaraanState extends State { + late String kendaraan; + late String selectedValueBensin; + late KendaraanModel kendaraanModel; + + bool _submitted = false; + + final tipeKendaraanController = TextEditingController(); + final dateController = TextEditingController(); + final kilometerController = TextEditingController(); + final jenisBBMController = TextEditingController(); + final kepemilikanController = TextEditingController(); + final nomorPlatController = TextEditingController(); + final ccController = TextEditingController(); + + @override + void initState() { + super.initState(); + kendaraan = widget.kendaraan; + } + + void _submit() { + setState(() { + _submitted = true; + }); + if (tipeKendaraanController.value.text != "" && + dateController.value.text != "" && + kilometerController.value.text != "" && + jenisBBMController.value.text != "" && + kepemilikanController.value.text != "" && + nomorPlatController.value.text != "" && + ccController.value.text != "") { + print("success"); + kendaraanModel = KendaraanModel( + id: 0, + jenisKendaraan: kendaraan, + namaKendaraan: tipeKendaraanController.value.text, + nomorPlat: nomorPlatController.value.text, + bahanBakar: jenisBBMController.value.text, + cc: int.parse(ccController.value.text), + odometer: kilometerController.value.text, + kepemilikan: kepemilikanController.value.text, + status: 0, + ); + context.read().add(BBMDataKendaraanAdded(kendaraanModel)); + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => Home("", ""), + )); + showDialog( + context: context, + builder: (BuildContext context) { + return SuccessDialogBox(deskripsi: "Berhasil Menambah Data"); + }, + ); + } else { + print("faield"); + } + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + tipeKendaraanController.dispose(); + dateController.dispose(); + kilometerController.dispose(); + jenisBBMController.dispose(); + kepemilikanController.dispose(); + nomorPlatController.dispose(); + ccController.dispose(); + } + + List listNamaBensin = List.from(listBensin.map((e) => e.text)); + List listKepemilikan = [ + 'Pribadi', + 'Perusahaan', + 'Sewa', + 'Lainnya', + ]; + // listBensin.map + + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height: 55, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Data Pribadi Kendaraan Anda", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 15, + ), + Card(), + SizedBox( + height: 15, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + inputField( + "Tipe Kendaraan", + "Type Of Brand", + "text", + tipeKendaraanController, + ), + dropdownField( + "Jenis Bahan Bakar", + listNamaBensin, + jenisBBMController, + ), + dropdownField( + "Kepemilikan", + listKepemilikan, + kepemilikanController, + ), + inputField( + "Data Penerimaan Kendaraan", + "MM/DD/YYYY", + "date", + dateController, + ), + inputField( + "Kilometers Kendaraan", + "0 Km", + "number", + kilometerController, + ), + inputField( + "CC Kendaraan", + "CC", + "number", + ccController, + ), + inputField( + "Nomor Plat Kendaraan", + "Contoh : XX XXXX XXX", + "text", + nomorPlatController, + ), + SaveButton(), + Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ); + } + + String? _errorText(TextEditingController controller) { + var val = controller.value.text.isEmpty ? "Tidak Boleh Kosong" : null; + return val; + } + + Widget Card() { + return Container( + height: 75, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Color(0xFFDDB05E), + ), + child: Row( + children: [ + SizedBox( + width: 20, + ), + Image.asset( + kendaraan == "motor" + ? "assets/images/motor.png" + : "assets/images/car.png", + width: 50, + height: 50, + ), + SizedBox( + width: 20, + ), + Text( + kendaraan == "motor" ? "Motor" : "Mobil", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 15, + color: Color(0xFF1A0F0F), + ), + ) + ], + ), + ); + } + + Widget SaveButton() { + return InkWell( + onTap: _submit, + child: Container( + width: 90, + height: 35, + margin: EdgeInsets.only( + top: 10, + ), + padding: EdgeInsets.only( + top: 7, + ), + decoration: BoxDecoration( + color: Color(0xFF2ECC71), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Text( + "Save Data", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + color: Colors.white, + fontSize: 15, + ), + textAlign: TextAlign.center, + ), + ), + ); + } + + Widget dropdownField(title, data, TextEditingController controller) { + return Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 10, + ), + Text( + title, + style: TextStyle( + color: Color(0xFF1A0F0F), + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + title != "Kepemilikan" + ? CustomDropdown.search( + fillColor: Color(0xffE3EAEA), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + hintStyle: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + ), + errorText: _submitted ? _errorText(controller) : null, + items: data, + controller: controller, + ) + : CustomDropdown( + fillColor: Color(0xffE3EAEA), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + hintStyle: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + ), + items: data, + controller: controller, + ), + ], + ), + ); + } + + Widget inputField(title, hint, typeField, TextEditingController controller) { + return Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 10, + ), + Text( + title, + style: TextStyle( + color: Color(0xFF1A0F0F), + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + TextField( + textCapitalization: title == "Nomor Plat Kendaraan" + ? TextCapitalization.characters + : title == "Kendaraan" + ? TextCapitalization.characters + : TextCapitalization.none, + maxLength: title == "Nomor Plat Kendaraan" ? 11 : 100, + controller: controller, + readOnly: typeField == "date" && true, + keyboardType: typeField != "date" && typeField != "text" + ? TextInputType.number + : TextInputType.text, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: hint, + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + errorText: _submitted ? _errorText(controller) : null, + ), + onTap: () async { + if (typeField == "date") { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2024), + ); + if (pickedDate != null) { + String formattedDate = + DateFormat('yyyy-MM-dd').format(pickedDate); + + setState( + () { + controller.text = + formattedDate; //set foratted date to TextField value. + }, + ); + } + } + }, + ), + ], + ), + ); + } +} diff --git a/lib/pages/kendaraan/form-update-kendaraan/form-update.dart b/lib/pages/kendaraan/form-update-kendaraan/form-update.dart new file mode 100644 index 0000000..6e07f79 --- /dev/null +++ b/lib/pages/kendaraan/form-update-kendaraan/form-update.dart @@ -0,0 +1,420 @@ +import 'package:animated_custom_dropdown/custom_dropdown.dart'; +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/pages/component/success_dialog_box.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/mainMenu/index.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; + +class FormUpdateKendaraan extends StatefulWidget { + KendaraanModel kendaraan; + FormUpdateKendaraan({super.key, required this.kendaraan}); + + @override + State createState() => _FormUpdateKendaraanState(); +} + +class _FormUpdateKendaraanState extends State { + late KendaraanModel kendaraan; + late String selectedValueBensin; + late KendaraanModel kendaraanModel; + + bool _submitted = false; + + final tipeKendaraanController = TextEditingController(); + final dateController = TextEditingController(); + final kilometerController = TextEditingController(); + final jenisBBMController = TextEditingController(); + final kepemilikanController = TextEditingController(); + final nomorPlatController = TextEditingController(); + final ccController = TextEditingController(); + + @override + void initState() { + super.initState(); + kendaraan = widget.kendaraan; + tipeKendaraanController.text = kendaraan.namaKendaraan; + kilometerController.text = kendaraan.odometer; + jenisBBMController.text = kendaraan.bahanBakar; + kepemilikanController.text = kendaraan.kepemilikan; + nomorPlatController.text = kendaraan.nomorPlat; + ccController.text = kendaraan.cc.toString(); + print(kendaraan.jenisKendaraan); + + } + + void _submit() { + setState(() { + _submitted = true; + }); + if (tipeKendaraanController.value.text != "" && + dateController.value.text != "" && + kilometerController.value.text != "" && + jenisBBMController.value.text != "" && + kepemilikanController.value.text != "" && + nomorPlatController.value.text != "" && + ccController.value.text != "") { + kendaraanModel = KendaraanModel( + id: kendaraan.id, + jenisKendaraan: kendaraan.jenisKendaraan, + namaKendaraan: tipeKendaraanController.value.text, + nomorPlat: nomorPlatController.value.text, + bahanBakar: jenisBBMController.value.text, + cc: int.parse(ccController.value.text), + odometer: kilometerController.value.text, + kepemilikan: kepemilikanController.value.text, + status: kendaraan.status, + ); + context.read().add(BBMDataKendaraanUpdated(kendaraanModel)); + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (context) => Home("", ""), + )); + showDialog( + context: context, + builder: (BuildContext context) { + return SuccessDialogBox(deskripsi: "Berhasil Mengubah Data"); + }, + ); + } + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + tipeKendaraanController.dispose(); + dateController.dispose(); + kilometerController.dispose(); + jenisBBMController.dispose(); + kepemilikanController.dispose(); + nomorPlatController.dispose(); + ccController.dispose(); + } + + List listNamaBensin = List.from(listBensin.map((e) => e.text)); + List listKepemilikan = [ + 'Pribadi', + 'Perusahaan', + 'Sewa', + 'Lainnya', + ]; + // listBensin.map + + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height: 55, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Data Pribadi Kendaraan Anda", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 15, + ), + Card(), + SizedBox( + height: 15, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + inputField( + "Tipe Kendaraan", + "Type Of Brand", + "text", + tipeKendaraanController, + ), + dropdownField( + "Jenis Bahan Bakar", + listNamaBensin, + jenisBBMController, + ), + dropdownField( + "Kepemilikan", + listKepemilikan, + kepemilikanController, + ), + inputField( + "Data Penerimaan Kendaraan", + "MM/DD/YYYY", + "date", + dateController, + ), + inputField( + "Kilometers Kendaraan", + "0 Km", + "number", + kilometerController, + ), + inputField( + "CC Kendaraan", + "CC", + "number", + ccController, + ), + inputField( + "Nomor Plat Kendaraan", + "Contoh : XX XXXX XXX", + "text", + nomorPlatController, + ), + SaveButton(), + Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ), + ); + } + + String? _errorText(TextEditingController controller) { + var val = controller.value.text.isEmpty ? "Tidak Boleh Kosong" : null; + return val; + } + + Widget Card() { + return Container( + height: 75, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: Color(0xFFDDB05E), + ), + child: Row( + children: [ + SizedBox( + width: 20, + ), + Image.asset( + kendaraan.jenisKendaraan == "motor" + ? "assets/images/motor.png" + : "assets/images/car.png", + width: 50, + height: 50, + ), + SizedBox( + width: 20, + ), + Text( + kendaraan.jenisKendaraan == "motor" ? "Motor" : "Mobil", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 15, + color: Color(0xFF1A0F0F), + ), + ) + ], + ), + ); + } + + Widget SaveButton() { + return InkWell( + onTap: _submit, + child: Container( + width: 90, + height: 35, + margin: EdgeInsets.only( + top: 10, + ), + padding: EdgeInsets.only( + top: 7, + ), + decoration: BoxDecoration( + color: Color(0xFF2ECC71), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Text( + "Save Data", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + color: Colors.white, + fontSize: 15, + ), + textAlign: TextAlign.center, + ), + ), + ); + } + + Widget dropdownField(title, data, TextEditingController controller) { + return Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 10, + ), + Text( + title, + style: TextStyle( + color: Color(0xFF1A0F0F), + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + title != "Kepemilikan" + ? CustomDropdown.search( + fillColor: Color(0xffE3EAEA), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + hintStyle: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + ), + errorText: _submitted ? _errorText(controller) : null, + items: data, + controller: controller, + ) + : CustomDropdown( + fillColor: Color(0xffE3EAEA), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + hintStyle: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + ), + items: data, + controller: controller, + ), + ], + ), + ); + } + + Widget inputField(title, hint, typeField, TextEditingController controller) { + return Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 10, + ), + Text( + title, + style: TextStyle( + color: Color(0xFF1A0F0F), + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + TextField( + textCapitalization: title == "Nomor Plat Kendaraan" + ? TextCapitalization.characters + : title == "Kendaraan" + ? TextCapitalization.characters + : TextCapitalization.none, + maxLength: title == "Nomor Plat Kendaraan" ? 11 : 100, + controller: controller, + readOnly: typeField == "date" && true, + keyboardType: typeField != "date" && typeField != "text" + ? TextInputType.number + : TextInputType.text, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(12), + ), + borderSide: BorderSide( + color: Color(0xFF677D81), + ), + ), + // border: BoxDecoration(border:), + contentPadding: EdgeInsets.only( + top: 4, + bottom: 4, + left: 15, + right: 15, + ), + hintText: hint, + hintStyle: TextStyle( + fontFamily: 'Poppins', + color: Color(0xFFAEAEAE), + fontSize: 10, + fontWeight: FontWeight.w400, + ), + errorText: _submitted ? _errorText(controller) : null, + ), + onTap: () async { + if (typeField == "date") { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2024), + ); + if (pickedDate != null) { + String formattedDate = + DateFormat('yyyy-MM-dd').format(pickedDate); + + setState( + () { + controller.text = + formattedDate; //set foratted date to TextField value. + }, + ); + } + } + }, + ), + ], + ), + ); + } +} diff --git a/lib/pages/kendaraan/index_kendaraan.dart b/lib/pages/kendaraan/index_kendaraan.dart new file mode 100644 index 0000000..d441f34 --- /dev/null +++ b/lib/pages/kendaraan/index_kendaraan.dart @@ -0,0 +1,385 @@ + +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/model/Kendaraan_model.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/pages/Performa/index.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/kendaraan/component/card-kendaraan.dart'; +import 'package:bbm_tracking/pages/kendaraan/form-tambah-kendaraan/form.dart'; +import 'package:bbm_tracking/pages/kendaraan/form-update-kendaraan/form-update.dart'; +import 'package:bbm_tracking/repository/kendaraan/kendaraan_repository.dart'; +import 'package:bbm_tracking/resource/popup/popup.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class IndexKendaraan extends StatefulWidget { + const IndexKendaraan({super.key}); + + @override + State createState() => _IndexKendaraanState(); +} + +class _IndexKendaraanState extends State { + List dataKendaraan = []; + int counter = 0; + + void changeStatuKendaraan(int id, int status) { + context.read().add(BBMChangeStatusKendaraan(id, status)); + dataKendaraan.forEach((element) { + element.status = 0; + }); + dataKendaraan + .elementAt(dataKendaraan.indexWhere((element) => element.id == id)) + .status = status; + setState(() { + counter++; + }); + } + + void deleteDataKendaraan(int id) async { + await KendaraanRepository().deleteDataKendaraan(id); + dataKendaraan.removeWhere((element) => element.id == id); + setState(() { + counter++; + }); + } + + void updateKendaraan(KendaraanModel data) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => FormUpdateKendaraan( + kendaraan: data, + key: UniqueKey(), + ), + ), + ); + } + + void checkKendaraan(List data) { + bool cond = false; + for (var i = 0; i < data.length; i++) { + if (data[i].status == 1) { + cond = true; + } + } + if (cond == true) { + // Navigator.of(context) + // .push(MaterialPageRoute(builder: (context) => Performa())); + showDialog( + context: context, + builder: (BuildContext context) { + return PopUp( + text: "Masih dalam Tahap Pengembangan", + param: "negative", + ); + }, + ); + } else { + showDialog( + context: context, + builder: (BuildContext context) { + return PopUp( + text: data.isEmpty + ? "Maaf, belum ada kendaraan yang Anda tambahkan" + : "Silahkan Aktifkan Salah Satu Kendaraan Anda", + param: "negative", + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + floatingActionButton: FloatingActionButton( + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return showDialogKendaraan(); + }, + ); + }, + backgroundColor: Color(0xFF677D81), + child: Icon( + Icons.add, + ), + ), + body: Container( + child: BlocBuilder( + builder: (context, state) { + if (state is BbmInitial) { + return Container( + child: Center(child: CircularProgressIndicator()), + ); + } + if (state is BBMError) { + return Container( + child: Center(child: Text(state.message.toString())), + ); + } + if (state is BBMLoaded) { + dataKendaraan = state.kendaraan; + return SingleChildScrollView( + child: Container( + child: Stack( + children: [ + Container( + child: Padding( + padding: EdgeInsets.all(5), + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Container(), + Container( + child: InkWell( + onTap: () => + checkKendaraan(state.kendaraan), + child: Text( + "Performa Kendaraan", + style: TextStyle( + fontSize: 13, + fontFamily: 'Poppins', + color: Color(0xff25A35A), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Data Pribadi Kendaraan Anda", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 15, + ), + Container( + child: ListView.builder( + physics: NeverScrollableScrollPhysics(), + itemCount: dataKendaraan.length, + shrinkWrap: true, + itemBuilder: + (BuildContext context, int index) { + return CardKendaraan( + kendaraan: dataKendaraan.elementAt(index), + onChangeStatus: (int id, int status) { + changeStatuKendaraan(id, status); + }, + onDelete: (int id) { + deleteDataKendaraan(id); + }, + onUpdate: (KendaraanModel kendaraan) { + updateKendaraan(kendaraan); + }, + key: UniqueKey(), + ); + }, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + } + return Container(); + }, + ), + ), + ); + } + + // Widget ListDataKendaraan() { + // return Container( + // child: ListView.builder( + // scrollDirection: Axis.vertical, + // itemCount: _dataKendaraan.length, + // shrinkWrap: true, + // itemBuilder: (BuildContext context, int index) { + // return CardKendaraan( + // kendaraan: _dataKendaraan[index], + // onChangeStatus: (int id, bool status) { + // changeStatuKendaraan(id, status); + // }, + // ); + // }, + // ), + // ); + // } + + Widget backButton() { + return Container( + child: InkWell( + onTap: () => Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (context) => Home("home", ""), + ), + ), + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + ); + } + + Dialog showNotif(txt) { + return Dialog( + elevation: 1, + backgroundColor: Color(0xffE3EAEA), + child: Container( + height: 200, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + "assets/images/sad_person.png", + width: 70, + ), + SizedBox( + height: 10, + ), + Text( + txt, + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 13, + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + } + + Dialog showDialogKendaraan() { + return Dialog( + elevation: 1, + backgroundColor: Color(0xffE3EAEA), + child: Container( + height: 230, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Pilih Kendaraan", + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 18, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: 25, + ), + InkWell( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => FormKendaraan(kendaraan: "motor"), + ), + ); + }, + child: chooseKendaraan( + "assets/images/motor.png", + "Motor", + ), + ), + SizedBox( + height: 7, + ), + Divider( + color: Color(0xFFECDEDE), + height: 2, + thickness: 2, + ), + SizedBox( + height: 7, + ), + InkWell( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => FormKendaraan(kendaraan: "mobil"), + ), + ); + }, + child: chooseKendaraan("assets/images/car.png", "Mobil"), + ), + ], + ), + ), + ); + } + + Container chooseKendaraan(image, text) { + return Container( + margin: EdgeInsets.only(left: 20), + child: Row( + children: [ + Image.asset( + image, + width: 50, + height: 50, + ), + SizedBox( + width: 20, + ), + Text( + text, + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 15, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/mainMenu/component/item_bensin.dart b/lib/pages/mainMenu/component/item_bensin.dart new file mode 100644 index 0000000..248677e --- /dev/null +++ b/lib/pages/mainMenu/component/item_bensin.dart @@ -0,0 +1,104 @@ +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:bbm_tracking/resource/convert_money/convert_money.dart'; +import 'package:flutter/material.dart'; + +class ItemBensin extends StatelessWidget { + final BensinModel data; + + const ItemBensin({ + super.key, + required this.data, + }); + + @override + Widget build(BuildContext context) { + return Container( + width: 180, + height: 75, + decoration: BoxDecoration( + border: Border.all( + color: Color(0xFF677D81), + width: 1.0, + ), + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + ), + child: Padding( + padding: EdgeInsets.all(7), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + data.text, + style: TextStyle( + fontSize: 15, + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + color: Color(0xFF677D81), + ), + ), + Container( + decoration: BoxDecoration( + border: Border.all( + color: Colors.white, + width: 2.0, + ), + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Container( + decoration: BoxDecoration( + color: Color(0xFF677D81), + ), + child: Icon( + Icons.add, + color: Colors.white, + ), + ), + ), + ], + ), + Row( + children: [ + Image.asset( + "assets/images/gas-pump.png", + ), + SizedBox( + width: 10, + ), + Text( + "${CurrencyFormat.convertToIdr(data.harga,0)} /Liter", + style: TextStyle( + fontSize: 11, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + color: Color(0xFF677D81), + ), + ), + ], + ), + SizedBox( + height: 3, + ), + Container( + width: double.maxFinite, + child: Text( + "Update on Juli 24, 2023", + style: TextStyle( + fontSize: 9, + fontFamily: 'Poppins', + fontWeight: FontWeight.w300, + color: Color(0xFF677D81), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/mainMenu/index.dart b/lib/pages/mainMenu/index.dart new file mode 100644 index 0000000..1d0aa22 --- /dev/null +++ b/lib/pages/mainMenu/index.dart @@ -0,0 +1,542 @@ +import 'package:bbm_tracking/bloc/bbm_bloc.dart'; +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/transaksiPerMonth_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/repository/kendaraan/kendaraan_repository.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:bbm_tracking/resource/component-bersama/chart.dart'; +import 'package:bbm_tracking/pages/mainMenu/component/item_bensin.dart'; +import 'package:bbm_tracking/resource/component-bersama/card_kendaraan.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/date_symbol_data_local.dart'; +// import 'package:month_year_picker/month_year_picker.dart'; +import 'package:simple_month_year_picker/simple_month_year_picker.dart'; +import 'package:intl/intl.dart'; + +class IndexMainMenu extends StatefulWidget { + const IndexMainMenu({super.key}); + + @override + State createState() => _IndexMainMenuState(); +} + +class _IndexMainMenuState extends State { + String _toggle = "Harga"; + DateTime _selected = DateTime.now(); + int totalPengeluaran = 0; + double totalBBM = 0; + late int count; + + late List dataTransaksiThisMonth = []; + late List dataKendaraan = []; + late List dataTransaksi = []; + KendaraanModel? dataKendaraanObject; + bool isLoading = false; + @override + void initState() { + context.read()..add(BBMStarted()); + initializeDateFormatting(); + count = 0; + loadData(_selected); + super.initState(); + } + + Future loadData(DateTime date) async { + List dtKendaraan = + await KendaraanRepository().loadKendaraan(); + setState(() { + dataKendaraan.addAll(dtKendaraan); + }); + + bool cond = false; + int i = 0; + + for (int i = 0; i < dtKendaraan.length; i++) { + if (cond == false) { + if (dataKendaraan[i].status == 1) { + setState(() { + dataKendaraanObject = dataKendaraan[i]; + }); + cond = true; + } + } + } + + List dt = await TransaksiRepository() + .loadTransaksiThisMonth( + DateFormat("yyyy-MM-dd").parse(date.toString()).toString()); + dataTransaksiThisMonth.clear(); + dt.forEach((element) { + if (element.kendaraanId == dataKendaraanObject?.id.toString()) { + setState(() { + dataTransaksiThisMonth.add(element); + }); + } + }); + + List dtM = await TransaksiRepository().loadTransaksi(); + dtM.forEach((element) { + if (dataKendaraanObject?.status == 1) { + totalPengeluaran += element.totalBayar.toInt(); + totalBBM += double.parse(element.totalLiter); + } + }); + dataTransaksi.addAll(dtM); + + setState(() { + isLoading = true; + }); + } + + TextStyle styleData = TextStyle( + fontFamily: 'Poppins', + fontSize: 6, + color: Color(0xFF3B3C48), + fontWeight: FontWeight.w500, + ); + + void selectedDate(DateTime time) { + setState(() { + _selected = time; + loadData(time); + }); + } + + void selectedToggle(String toogle) { + setState(() { + count++; + _toggle = toogle; + }); + } + + // String _month = 0; + // int _year = 0; + + Future _onWillPop() async { + return (await showDialog( + context: context, + builder: (context) => new AlertDialog( + title: new Text('Apa Kamu Yakin?'), + content: new Text('Kamu ingin Keluar Aplikasi'), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: new Text('No'), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: new Text('Yes'), + ), + ], + ), + )) ?? + false; + } + + @override + Widget build(BuildContext context) { + return isLoading + ? Container( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: 10), + child: Stack( + children: [ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Hallo,", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + color: Color(0xFF1A0F0F), + fontWeight: FontWeight.w600, + ), + ), + Text( + "Selamat datang di Aplikasi BBM-Tracking", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + color: Color(0xFF1A0F0F), + ), + ), + SizedBox( + height: 10, + ), + MainCardKendaraan(dataKendaraanObject), + SecondWidget(), + SizedBox( + height: 5, + ), + SizedBox( + height: 15, + ), + ItemListBensin(listBensin), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "Pembaruan,", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 8, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.w700, + ), + ), + Text( + " 24 Juli 2023", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 8, + ), + ) + ], + ), + ), + SizedBox( + height: 15, + ), + DatePerforma(dataTransaksiThisMonth), + SizedBox( + height: 10, + ), + ], + ), + ), + ], + ), + ), + ), + ) + : Container(); + } + + Widget DatePerforma(dataTransaksiThisMonth) { + return Container( + width: double.infinity, + height: 350, + margin: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Color(0xffE3EAEA), + borderRadius: BorderRadius.all(Radius.circular(8)), + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: const Offset( + 0.5, + 2.0, + ), + blurRadius: 5.0, + spreadRadius: 2.0, + ) + ], + ), + child: Padding( + padding: EdgeInsets.all(9), + child: Column( + children: [ + Container( + child: Text( + "Grafik Pengisian Bahan Bakar", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 16, + color: Color(0xFF1A0F0F), + ), + ), + ), + SizedBox( + height: 10, + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 10, + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + InkWell( + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return MonthPicker( + onChangeDate: (bulan, tahun) { + setState(() { + _selected = + DateTime.parse("${tahun}-${bulan}-01"); + selectedDate(_selected); + }); + }, + ); + }, + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8)), + border: Border.all( + width: 2, + color: Color(0xffDDB05E), + ), + ), + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 20, + vertical: 5, + ), + child: Text( + DateFormat( + "MMMM yyyy", + "id_ID", + ).format(_selected), + // _selected.toString(), + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + color: Color(0xFF1A0F0F), + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + SizedBox( + width: 10, + ), + Container( + width: 130, + height: 30, + alignment: Alignment.topRight, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Row( + children: [ + InkWell( + onTap: () => selectedToggle("Harga"), + child: Container( + width: 65, + height: 30, + decoration: BoxDecoration( + color: _toggle == "Harga" + ? Color(0xFF677D81) + : Color(0xFFffffff), + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Container( + margin: EdgeInsets.only(top: 7), + child: Text( + "Harga", + style: TextStyle( + fontSize: 12, + fontFamily: 'Poppins', + color: _toggle == "Harga" + ? Colors.white + : Colors.black, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + InkWell( + onTap: () => selectedToggle("Liter"), + child: Container( + width: 65, + height: 30, + decoration: BoxDecoration( + color: _toggle == "Harga" + ? Color(0xFFffffff) + : Color(0xFF677D81), + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Container( + margin: EdgeInsets.only(top: 7), + child: Text( + "Liter", + style: TextStyle( + fontSize: 12, + fontFamily: 'Poppins', + color: _toggle == "Harga" + ? Colors.black + : Colors.white, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + SizedBox( + height: 20, + ), + Container( + width: double.infinity, + height: 190, + child: BarChartSample3( + key: UniqueKey(), + dataTransaksi: dataTransaksiThisMonth, + param: _toggle, + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Text( + "Bulan : ${DateFormat('MMMM').format(DateTime(0, _selected.month.toInt()))} ${_selected.year.toString()}", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + color: Color(0xFF1A0F0F), + ), + ), + ), + ], + ), + ), + ); + } + + Widget SecondWidget() { + return Container( + margin: EdgeInsets.symmetric( + vertical: 0, + horizontal: 4, + ), + width: double.infinity, + height: 58, + decoration: BoxDecoration( + color: Color(0xFF677D81), + borderRadius: BorderRadius.all(Radius.circular(8)), + boxShadow: [ + BoxShadow( + color: Colors.grey, + offset: const Offset( + 0.5, + 2.0, + ), + blurRadius: 3.0, + spreadRadius: 2.0, + ) + ], + ), + child: Padding( + padding: EdgeInsets.all(8), + child: Row( + children: [ + ItemTotalLiterUang("Total Pengeluaran", "pengeluaran"), + SizedBox( + width: 10, + ), + ItemTotalLiterUang("Total Bahan Bakar", "liter"), + ], + ), + ), + ); + } + + Widget ItemTotalLiterUang(text, param) { + return Expanded( + flex: 1, + child: Container( + height: 45, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Padding( + padding: EdgeInsets.only( + left: 7, + top: 3, + bottom: 3, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + text, + style: TextStyle( + fontSize: 12, + fontFamily: 'Poppins', + color: Color(0xFF1A0F0F), + ), + ), + Row( + children: [ + Image.asset( + param == "pengeluaran" + ? "assets/images/compass.png" + : "assets/images/gas-pump.png", + ), + SizedBox( + width: 10, + ), + Text( + param == "pengeluaran" + ? "${CurrencyFormat.convertToIdr(totalPengeluaran, 0)}" + : "${totalBBM.toStringAsFixed(2)} Liter", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xFF1A0F0F), + ), + ) + ], + ), + ], + ), + ), + ), + ); + } + + Widget ItemListBensin(List dataModel) { + return Container( + width: double.infinity, + height: 80, + child: Expanded( + child: ListView.builder( + itemCount: dataModel.length, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context, int index) { + return Container( + margin: EdgeInsets.only(right: 10), + child: ItemBensin(data: dataModel.elementAt(index)), + ); + }, + ), + ), + ); + } +} diff --git a/lib/pages/onBoard/on_board_start.dart b/lib/pages/onBoard/on_board_start.dart new file mode 100644 index 0000000..673e624 --- /dev/null +++ b/lib/pages/onBoard/on_board_start.dart @@ -0,0 +1,248 @@ +import 'package:bbm_tracking/model/status_m.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:flutter/material.dart'; +import 'package:path/path.dart'; + +class OnBoardStart extends StatefulWidget { + const OnBoardStart({super.key}); + + @override + State createState() => _OnBoardStartState(); +} + +class _OnBoardStartState extends State { + bool isFirst = true; + bool isLoading = true; + + @override + void initState() { + super.initState(); + print("object"); + loadData(); + } + + Future loadData() async { + List dt = await TransaksiRepository().getStatusIn(); + if (dt.isNotEmpty) { + setState(() { + isFirst = false; + isLoading = false; + }); + } else { + setState(() { + isLoading = false; + }); + } + } + + Future updateFirstIn() async { + await TransaksiRepository().insertStatusIn(); + } + + @override + Widget build(BuildContext context) { + return isLoading + ? Container() + : Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + // mainAxisAlignment: , + children: [ + Image.asset('assets/images/firstIcon.png'), + Text( + "BBM", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 40, + fontWeight: FontWeight.w700, + color: Colors.black, + ), + ), + Column( + children: [ + Text( + "Lacak & Pantau bahan bakar", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 20, + fontWeight: FontWeight.w600, + fontStyle: FontStyle.italic, + color: Color(0xFF1A0F0F), + ), + ), + Text( + "Kendaraan Anda", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 20, + fontWeight: FontWeight.w600, + fontStyle: FontStyle.italic, + color: Color(0xFF1A0F0F), + ), + ), + ], + ), + SizedBox( + height: 20, + ), + Text( + "Dapat dengan mudah memantau penggunaan bahan bakar atau BBM yang kendaraan Anda gunakan ", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + color: Color(0xFF3B3C48), + ), + ), + SizedBox( + height: 20, + ), + InkWell( + onTap: () { + isFirst + ? showDialog( + context: context, + builder: (BuildContext context) { + updateFirstIn(); + return showDialogKendaraan(context); + }, + ) + : Navigator.of(context).pushReplacement( + _createRoute(), + ); + // print("object"); + }, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + margin: EdgeInsets.only( + left: 100, + right: 100, + ), + decoration: BoxDecoration( + border: Border.all( + color: Color(0xFFFC8D05), + width: 25.0, + ), + borderRadius: BorderRadius.all( + Radius.circular(30), + ), + ), + ), + Image.asset( + 'assets/images/arrow-right.png', + width: 40, + height: 40, + ) + ], + ), + ), + ], + ), + ), + ); + } +} + +Dialog showDialogKendaraan(BuildContext context) { + return Dialog( + elevation: 1, + backgroundColor: Color(0xffE3EAEA), + child: Container( + height: 400, + padding: EdgeInsets.all(15), + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "This app accesses your device's location to record your location while refueling. This location information is used exclusively to provide a better service in recording your refueling history. Your privacy is our priority, and your location data will not be used for any other purpose or shared with third parties without your permission.", + style: TextStyle(fontSize: 16.0), + ), + SizedBox(height: 16.0), + Text( + 'when the app/location is running in the background or when the app is closed, location/system does not retrieve your location data. Location will only be used when you actively want to log detailed gas station locations using coordinates.', + style: TextStyle(fontSize: 16.0), + ), + SizedBox(height: 16.0), + Text( + 'The main features of apps that use device location are:', + style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), + ), + SizedBox(height: 8.0), + Text( + '- Location Logging Feature: The feature that uses location is when you add gas filling data on the gas filling form.', + style: TextStyle(fontSize: 16.0), + ), + SizedBox(height: 16.0), + Text( + 'We value your trust and are committed to maintaining the security and privacy of your data.', + style: TextStyle(fontSize: 16.0), + ), + SizedBox(height: 20), + Text( + "Thank you for using BBM Tracking application", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 20), + Text( + "Management System", + style: TextStyle( + fontStyle: FontStyle.italic, + ), + ), + SizedBox( + height: 7, + ), + InkWell( + onTap: () { + Navigator.of(context).pushReplacement( + _createRoute(), + ); + }, + child: Text( + "I Accept", + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 14, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + ); +} + +Route _createRoute() { + return PageRouteBuilder( + pageBuilder: (context, animation, secondaryAnimation) => Home("", ""), + transitionsBuilder: (context, animation, secondaryAnimation, child) { + const begin = Offset(4.0, 3.0); + const end = Offset.zero; + const curve = Curves.ease; + + var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); + + return SlideTransition( + position: animation.drive(tween), + child: child, + ); + }, + ); +} diff --git a/lib/pages/onBoard/splash_screen.dart b/lib/pages/onBoard/splash_screen.dart new file mode 100644 index 0000000..28ae7de --- /dev/null +++ b/lib/pages/onBoard/splash_screen.dart @@ -0,0 +1,62 @@ +import 'dart:async'; + +import 'package:bbm_tracking/pages/onBoard/on_board_start.dart'; +import 'package:flutter/material.dart'; + +class SplsScreen extends StatefulWidget { + const SplsScreen({super.key}); + + @override + State createState() => _SplsScreen(); +} + +class _SplsScreen extends State { + @override + Widget build(BuildContext context) { + @override + void initState() { + super.initState(); + } + + Timer( + Duration(seconds: 3), + () { + Navigator.of(context).pushReplacement( + _createRoute(), + ); + }, + ); + + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: Container( + child: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [Image.asset("assets/images/Logo.png")], + ), + ), + ), + ); + } +} + +Route _createRoute() { + return PageRouteBuilder( + pageBuilder: (context, animation, secondaryAnimation) => + const OnBoardStart(), + transitionsBuilder: (context, animation, secondaryAnimation, child) { + const begin = Offset(4.0, 3.0); + const end = Offset.zero; + const curve = Curves.ease; + + var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); + + return SlideTransition( + position: animation.drive(tween), + child: child, + ); + }, + ); +} diff --git a/lib/pages/riwayat/component/item-history.dart b/lib/pages/riwayat/component/item-history.dart new file mode 100644 index 0000000..f4b6671 --- /dev/null +++ b/lib/pages/riwayat/component/item-history.dart @@ -0,0 +1,241 @@ +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/riwayat/riwayat-detail/riwayat-detail.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; + +class ItemHistory extends StatefulWidget { + TransaksiModel data; + KendaraanModel kendaraan; + ItemHistory({super.key, required this.data, required this.kendaraan}); + + @override + State createState() => _ItemHistoryState(); +} + +class _ItemHistoryState extends State { + TransaksiModel? data; + List dataBensin = listBensin; + KendaraanModel? kendaraan; + + @override + void initState() { + super.initState(); + data = widget.data; + kendaraan = widget.kendaraan; + } + + String reformatDate(DateTime date) { + String data = ""; + for (int i = 0; i < bulan.length; i++) { + if (i + 1 == date.month) { + data += "${bulan[i].substring(0, 3)}, ${date.day} ${date.year}"; + } + } + return data; + } + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(vertical: 5), + child: InkWell( + onTap: () => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => RiwayatDetail( + data: data!, + key: UniqueKey(), + kendaraan: kendaraan!, + ), + ), + ), + child: Container( + decoration: BoxDecoration( + border: Border.all(width: 1, color: Color(0xFF677D81)), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + child: Column( + children: [ + Container( + decoration: BoxDecoration(color: Color(0xFFE1E1E1)), + height: 42, + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + margin: EdgeInsets.only( + left: 10, + top: 5, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Pengisian", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w400, + fontSize: 11, + color: Colors.black, + ), + ), + Row( + children: [ + Text( + dataBensin[int.parse(data!.bensinId) - 1] + .text + .toString(), + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 10, + color: Colors.black, + ), + ), + SizedBox( + width: 5, + ), + Text( + "Data : ${reformatDate(data!.tanggalTransaksi)}", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 10, + color: Colors.black, + ), + ), + ], + ) + ], + ), + ), + ), + Flexible( + flex: 1, + child: Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: EdgeInsets.all(5), + child: Image.asset( + "assets/images/${dataBensin[int.parse(data!.bensinId) - 1].perusahaan.toLowerCase()}.png"), + ), + Container( + margin: EdgeInsets.all(5), + padding: EdgeInsets.only(top: 6), + width: 50, + height: 25, + decoration: BoxDecoration( + color: data?.status == 1 + ? Color(0xFF58D68D) + : Color(0XFFFC8D05), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + // alignment: Alignment.topRight, + child: Text( + data?.status == 1 ? "selesai" : "draft", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + color: Colors.white, + ), + ), + ) + ], + ), + ), + ), + ], + ), + ), + Container( + height: 35, + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + margin: EdgeInsets.only( + left: 10, + top: 5, + ), + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Total Harga:", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + Text( + CurrencyFormat.convertToIdr(data?.totalBayar, 0), + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ), + ), + Flexible( + flex: 1, + child: Container( + margin: EdgeInsets.only( + left: 10, + top: 5, + ), + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Lokasi SPBU:", + textAlign: TextAlign.center, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w400, + ), + ), + Text( + "${data?.lokasiPertamina}", + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w700, + color: Color(0xFF3B3C48), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/riwayat/component/makePdf.dart b/lib/pages/riwayat/component/makePdf.dart new file mode 100644 index 0000000..40d30c4 --- /dev/null +++ b/lib/pages/riwayat/component/makePdf.dart @@ -0,0 +1,413 @@ +import 'dart:typed_data'; + +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/photo_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:bbm_tracking/resource/convert_money/convert_money.dart'; +import 'package:bbm_tracking/resource/data-bensin/data-bensin.dart'; +import 'package:bbm_tracking/resource/data-tanggal/bulan.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; +import 'package:printing/printing.dart'; +import 'dart:io'; + +class MakePdf extends StatelessWidget { + TransaksiModel transaksi; + KendaraanModel kendaraan; + MakePdf({super.key, required this.transaksi, required this.kendaraan}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("PDF Preview"), + ), + body: PdfPreview( + build: (context) => makePdf(transaksi, kendaraan), + ), + ); + } + + List photos = []; + List imagesUint8list = []; + List pdfImagesWidget = []; + + Future> loadPhoto(param) async { + List photo = await TransaksiRepository().getPhoto(param); + return photo; + } + + String reformatDate(DateTime date) { + String data = ""; + for (int i = 0; i < bulan.length; i++) { + if (i + 1 == date.month) { + data += "${date.day} ${bulan[i]} ${date.year}"; + } + } + return data; + } + + Future makePdf( + TransaksiModel transaksi, + KendaraanModel kendaraan, + ) async { + final pdf = pw.Document(); + photos = await loadPhoto(transaksi.kodeTransaksi); + + photos.forEach((element) async { + var replace = "/storage/emulated/0/Pictures/" + + element.namePhoto.replaceAll(RegExp(':'), '_') + + ".jpg"; + Uri myUri = Uri.parse(replace); + File imageFile = new File.fromUri(myUri); + // final ByteData bytes = await imageFile.readAsBytes(); + final Uint8List byteList = imageFile.readAsBytesSync(); + + imagesUint8list.add(byteList); + }); + + pdfImagesWidget = imagesUint8list.map( + (image) { + return pw.Padding( + padding: pw.EdgeInsets.symmetric(vertical: 20, horizontal: 10), + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.center, + mainAxisSize: pw.MainAxisSize.max, + children: [ + pw.SizedBox(height: 10), + pw.Image( + pw.MemoryImage( + image, + ), + height: 400, + fit: pw.BoxFit.fitHeight), + ], + ), + ); + }, + ).toList(); + + + final fontData = await rootBundle.load("assets/fonts/Poppins-Medium.ttf"); + final ttf = pw.Font.ttf(fontData.buffer.asByteData()); + pdf.addPage( + pw.Page( + margin: pw.EdgeInsets.all(10), + pageFormat: PdfPageFormat.a4, + build: (context) { + return pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + pw.Text( + "Detail Transaksi", + style: pw.TextStyle( + font: ttf, + fontSize: 16, + color: PdfColor.fromInt(0xff3B3C48), + ), + ), + pw.Divider(borderStyle: pw.BorderStyle.dashed), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Kode Transaksi", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + transaksi.kodeTransaksi, + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Divider(borderStyle: pw.BorderStyle.dashed), + pw.Text( + "Tipe Kendaraan", + style: pw.TextStyle( + font: ttf, + fontSize: 16, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + kendaraan.namaKendaraan, + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + kendaraan.nomorPlat, + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Divider(borderStyle: pw.BorderStyle.dashed), + pw.Text( + "Detail", + style: pw.TextStyle( + font: ttf, + fontSize: 16, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Padding( + padding: pw.EdgeInsets.symmetric(horizontal: 50), + child: pw.Column( + children: [ + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Center( + child: pw.Text( + "Tipe Transaksi", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ), + pw.Center( + child: pw.Text( + "Pengisian Bahan Bakar", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Align( + alignment: pw.Alignment.topLeft, + child: pw.Text( + "Data Transaksi", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ), + pw.Align( + alignment: pw.Alignment.topRight, + child: pw.Text( + reformatDate(transaksi.tanggalTransaksi), + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Waktu", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + "${transaksi.tanggalTransaksi.hour}:${transaksi.tanggalTransaksi.minute} WIB", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Jenis Bahan Bakar", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + listBensin[int.parse(transaksi.bensinId) - 1].text, + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Alamat SPBU", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + transaksi.lokasiPertamina, + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Total Liter", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + "${transaksi.totalLiter} Liter", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Harga / Liter", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + "${CurrencyFormat.convertToIdr(listBensin[int.parse(transaksi.bensinId) - 1].harga, 0)}", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Total Pembayaran", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + CurrencyFormat.convertToIdr(transaksi.totalBayar, 0), + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Odometer", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + "${transaksi.odometer} KM", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text( + "Catatan", + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + pw.Text( + transaksi.catatan, + style: pw.TextStyle( + font: ttf, + fontSize: 13, + color: PdfColor.fromInt(0xff000000), + ), + ), + ], + ), + ], + ), + ), + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.center, + mainAxisSize: pw.MainAxisSize.max, + children: pdfImagesWidget, + ) + ], + ); + }, + ), + ); + + return pdf.save(); + } +} diff --git a/lib/pages/riwayat/component/viewImage.dart b/lib/pages/riwayat/component/viewImage.dart new file mode 100644 index 0000000..8dfcbad --- /dev/null +++ b/lib/pages/riwayat/component/viewImage.dart @@ -0,0 +1,138 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; + +class ViewImage extends StatefulWidget { + final List imagePath; + const ViewImage({super.key, required this.imagePath}); + + @override + State createState() => _ViewImageState(); +} + +class _ViewImageState extends State { + late List dataPhoto; + bool loading = false; + // List _files = new List(); + + @override + void initState() { + load(); + // TODO: implement initState + super.initState(); + } + + Future load() async { + dataPhoto = widget.imagePath; + setState(() { + loading = true; + }); + } + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: loading + ? Container( + margin: EdgeInsets.only( + top: 50, + ), + child: Column( + children: [ + Container( + child: BackButton(), + margin: EdgeInsets.only( + left: 10, + ), + ), + SizedBox( + height: 20, + ), + Container( + child: Expanded( + child: ListView.builder( + // shrinkWrap: true, + itemCount: dataPhoto.length, + itemBuilder: (BuildContext context, int index) { + var replace = "/storage/emulated/0/Pictures/" + + dataPhoto[index].replaceAll(RegExp(':'), '_')+".jpg"; + print("counting ${dataPhoto.length.toString()}, path = ${replace}"); + return ScreenImage( + replace, + ); + }, + ), + ), + ), + ], + ), + ) + : Container(), + ), + ); + } + + Widget ScreenImage(param) { + print("counting data ${param}"); + return Container( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: 5, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + color: Colors.amber), + child: Image.file( + File(param), + fit: BoxFit.cover, + ), + ), + ), + SizedBox( + height: 20, + ) + ], + ), + ); + } + + Widget BackButton() { + return InkWell( + onTap: () => Navigator.pop(context), + child: Container( + child: Container( + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/riwayat/index.dart b/lib/pages/riwayat/index.dart new file mode 100644 index 0000000..e457faa --- /dev/null +++ b/lib/pages/riwayat/index.dart @@ -0,0 +1,300 @@ +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/riwayat/component/item-history.dart'; +import 'package:bbm_tracking/resource/popup/popup.dart'; +import 'package:flutter/material.dart'; + +class Riwayat extends StatefulWidget { + List data; + List kendaraan; + Riwayat(this.kendaraan, {super.key, required this.data}); + + @override + State createState() => _RiwayatState(); +} + +class _RiwayatState extends State { + KendaraanModel? kendaraan; + // String kendaraan = 'motor'; + late String _tab = 'selesai'; + late List data; + + @override + void initState() { + // TODO: implement initState + super.initState(); + data = widget.data; + print("counting ${data.length}"); + loadDataKendaraan(); + } + + void loadDataKendaraan() { + for (KendaraanModel element in widget.kendaraan) { + if (element.status == 1) { + kendaraan = element; + break; + } + } + } + + @override + Widget build(BuildContext context) { + return Container( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(bottom: 10), + child: Column( + children: [ + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Riwayat Transaksi Pengisian Anda", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 17, + color: Color(0xff1A0F0F), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 10, + ), + Container( + height: 75, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(8), + ), + color: + kendaraan != null ? Color(0xFFFC8D05) : Color(0xFFAEAEAE), + ), + child: Row( + children: [ + SizedBox( + width: 20, + ), + Image.asset( + kendaraan != null + ? kendaraan?.jenisKendaraan == "motor" + ? "assets/images/motor.png" + : "assets/images/car.png" + : "assets/images/img_empty.png", + width: 50, + height: 50, + ), + SizedBox( + width: 20, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 15, + ), + Text( + "Tipe Kendaraan : ", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + color: Color(0xFF3B3C48), + ), + ), + SizedBox( + height: 5, + ), + Text( + kendaraan != null + ? "${kendaraan?.namaKendaraan} / ${kendaraan?.nomorPlat}" + : "- / -", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 15, + fontWeight: FontWeight.w700, + color: Colors.white, + ), + ), + ], + ), + ], + ), + ), + // Container( + // alignment: Alignment.topRight, + // child: Text( + // "Ganti Kendaraan", + // style: TextStyle( + // fontSize: 11, + // color: Color(0xFF1C7A44), + // fontFamily: 'Poppins', + // fontWeight: FontWeight.w400, + // fontStyle: FontStyle.italic, + // ), + // ), + // ), + SizedBox( + height: 15, + ), + Container( + child: Row( + children: [ + Flexible( + flex: 1, + child: Container( + child: InkWell( + onTap: () { + // setState(() { + // _tab = 'selesai'; + // }); + }, + child: Column( + children: [ + Text( + "Selesai", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: _tab == 'selesai' + ? Color(0xFF58D68D) + : Colors.transparent, + height: 2, + thickness: 2, + ), + ], + ), + ), + ), + ), + SizedBox( + width: 5, + ), + Flexible( + flex: 1, + child: Container( + child: InkWell( + onTap: () { + // setState(() { + // _tab = 'draft'; + // }); + showDialog( + context: context, + builder: (BuildContext context) { + return PopUp( + text: "Masih dalam Tahap Pengembangan", + param: "negative", + ); + }, + ); + }, + child: Column( + children: [ + Text( + "Draft", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + SizedBox( + height: 5, + ), + Divider( + color: _tab == 'draft' + ? Color(0xFF58D68D) + : Colors.transparent, + height: 2, + thickness: 2, + ), + ], + ), + ), + ), + ) + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Anda memiliki ${kendaraan != null ? data.length.toString() : 0} data transaksi", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + fontWeight: FontWeight.w400, + color: Color(0xFF828282), + ), + ), + ), + SizedBox( + height: 7, + ), + kendaraan != null + ? Container( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: Expanded( + child: ListView.builder( + padding: EdgeInsets.only(bottom: 400), + shrinkWrap: true, + itemCount: data.length, + itemBuilder: (BuildContext context, int index) { + return ItemHistory( + data: data.elementAt(index), + kendaraan: kendaraan!, + ); + }, + ), + ), + ) + : Container( + child: Column( + children: [ + SizedBox( + height: 80, + ), + Image.asset( + "assets/images/sad_person.png", + width: 70, + ), + SizedBox( + height: 10, + ), + Text( + "Anda masih belum memiliki data", + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 13, + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/riwayat/riwayat-detail/riwayat-detail.dart b/lib/pages/riwayat/riwayat-detail/riwayat-detail.dart new file mode 100644 index 0000000..86e6772 --- /dev/null +++ b/lib/pages/riwayat/riwayat-detail/riwayat-detail.dart @@ -0,0 +1,321 @@ +import 'dart:io'; + +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/photo_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/pages/home.dart'; +import 'package:bbm_tracking/pages/riwayat/component/makePdf.dart'; +import 'package:bbm_tracking/pages/riwayat/component/viewImage.dart'; +import 'package:bbm_tracking/repository/transaksi/transaksi_repository.dart'; +import 'package:flutter/material.dart'; +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:path_provider/path_provider.dart'; + +import 'package:permission_handler/permission_handler.dart'; + +class RiwayatDetail extends StatefulWidget { + TransaksiModel data; + KendaraanModel kendaraan; + RiwayatDetail({super.key, required this.data, required this.kendaraan}); + + @override + State createState() => _RiwayatDetailState(); +} + +class _RiwayatDetailState extends State { + late TransaksiModel data; + late KendaraanModel kendaraan; + + @override + void initState() { + super.initState(); + data = widget.data; + kendaraan = widget.kendaraan; + } + + Future> loadPhoto(param) async { + List photo = await TransaksiRepository().getPhoto(param); + return photo; + } + + _showImage(path) async { + List photo = await loadPhoto(path); + List data = []; + photo.forEach((element) { + data.add(element.namePhoto); + }); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ViewImage(imagePath: data), + ), + ); + } + + String reformatDate(DateTime date) { + String data = ""; + for (int i = 0; i < bulan.length; i++) { + if (i + 1 == date.month) { + data += "${date.day} ${bulan[i]} ${date.year}"; + } + } + return data; + } + + TextStyle style = TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w400, + ); + + Future _onWillPop() async { + Navigator.pop(context); + return false; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () => _onWillPop(), + child: Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: SingleChildScrollView( + child: Container( + margin: EdgeInsets.only( + top: 50, + ), + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height: 10, + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Detail Transaksi", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 10, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Transaksi Berhasil", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 15, + fontWeight: FontWeight.w500, + color: Color(0xFF25A35A), + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + flex: 2, + child: Container( + child: Text( + data.kodeTransaksi, + style: style, + ), + ), + ), + Flexible( + flex: 1, + child: InkWell( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => MakePdf( + transaksi: data, + kendaraan: kendaraan), + ), + ); + }, + child: Container( + child: Text( + "Download", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w400, + color: Color(0xFF1C7A44), + fontStyle: FontStyle.italic, + ), + ), + ), + ), + ), + ], + ) + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + decoration: BoxDecoration( + border: Border.all(width: 1, color: Color(0xFF677D81)), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + padding: EdgeInsets.all(5), + alignment: Alignment.topLeft, + child: Text( + "Tipe Kendaraan", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + height: 10, + ), + itemDetail(kendaraan.namaKendaraan, kendaraan.nomorPlat), + SizedBox( + height: 10, + ), + Container( + decoration: BoxDecoration( + border: Border.all(width: 1, color: Color(0xFF677D81)), + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + ), + padding: EdgeInsets.all(5), + alignment: Alignment.topLeft, + child: Text( + "Details", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + itemDetail("Tipe transaksi", "Pengisian Bahan Bakar"), + itemDetail( + "Data Transaksi", reformatDate(data.tanggalTransaksi)), + itemDetail("Waktu", + "${data.tanggalTransaksi.hour}:${data.tanggalTransaksi.minute} WIB"), + itemDetail("Jenis Bahan Bakar", + listBensin[int.parse(data.bensinId) - 1].text), + itemDetail("Total Liter", "${data.totalLiter} Liter"), + itemDetail("Harga/Liter", + "${CurrencyFormat.convertToIdr(listBensin[int.parse(data.bensinId) - 1].harga, 0)}"), + itemDetail("Total Pembayaran", + "${CurrencyFormat.convertToIdr(data.totalBayar, 0)}"), + itemDetail("Odometer/km", "${data.odometer} km"), + itemDetaill("Gambar", "Lihat Gambar", data.kodeTransaksi), + itemDetail("Catatan Tambahan", data.catatan), + ], + ), + ), + ), + ), + ), + ); + } + + Widget itemDetaill(item, value, val) { + return Container( + margin: EdgeInsets.symmetric(vertical: 5), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + flex: 1, + child: Container( + child: Text( + item, + style: style, + ), + ), + ), + Flexible( + flex: 1, + child: InkWell( + onTap: () { + _showImage(val); + }, + child: Container( + child: Text( + value, + textAlign: TextAlign.right, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 13, + fontWeight: FontWeight.w400, + color: Color(0xFF25A35A), + ), + ), + ), + ), + ), + ], + ), + ), + ); + } + + Widget itemDetail(item, value) { + return Container( + margin: EdgeInsets.symmetric(vertical: 5), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + flex: 1, + child: Container( + child: Text( + item, + style: style, + ), + ), + ), + Flexible( + flex: 1, + child: Container( + child: Text( + value, + textAlign: TextAlign.right, + style: style, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/simulation/index.dart b/lib/pages/simulation/index.dart new file mode 100644 index 0000000..b61a50e --- /dev/null +++ b/lib/pages/simulation/index.dart @@ -0,0 +1,294 @@ +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; + +class SimulationScreen extends StatefulWidget { + const SimulationScreen({super.key}); + + @override + State createState() => _SimulationScreenState(); +} + +class _SimulationScreenState extends State { + List tipe_kendaraan = ["Motor", "Mobil"]; + List merek_kendaraan = ["Beat", "NMax", "PCX", "Ninja"]; + + bool toogleTipe = false; + bool toogleMerek = false; + bool toogleBBM = false; + bool tooglePriode = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Color(0xffE3EAEA), + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(10), + child: Container( + margin: EdgeInsets.only(top: 52), + child: Column( + children: [ + Align( + alignment: Alignment.topLeft, + child: Container( + width: 70, + child: InkWell( + onTap: () {}, + child: Row( + children: [ + Icon( + Icons.arrow_back_ios, + size: 15, + ), + Text( + "Kembali", + style: TextStyle( + fontSize: 10, + fontFamily: 'Poppins', + color: Color(0xff1A0F0F), + fontWeight: FontWeight.w400, + ), + ) + ], + ), + ), + ), + ), + Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10), + child: Text( + "Simulasi Pemakaian", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 16, + color: Color(0xff3B3C48), + ), + ), + ), + Divider( + color: Color(0xFF1A0F0F3D), + height: 2, + thickness: 2, + ), + SizedBox( + height: 6, + ), + Container( + alignment: Alignment.topLeft, + child: Text( + "Simulasi Performa Bahan Bakar Kendaraan", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w500, + fontSize: 12, + color: Colors.black, + ), + ), + ), + SizedBox( + height: 10, + ), + FormField("-- Pilih Tipe Kendaraan --", tipe_kendaraan, + toogleTipe, "tipe"), + SizedBox( + height: 5, + ), + FormField("-- Pilih Kendaraan --", merek_kendaraan, toogleMerek, + "merek"), + SizedBox( + height: 5, + ), + FormField("-- Pilih Jenis Bahan Bakar --", listBensin, + toogleBBM, "bbm"), + SizedBox( + height: 5, + ), + FormField("-- Pilih Periode --", null, tooglePriode, "periode"), + ], + ), + ), + ), + ), + ); + } + + Widget FormField( + txtTitle, + data, + toogle, + toogleParam, + ) { + return Container( + child: Column( + children: [ + Container( + decoration: BoxDecoration( + color: Color(0xFFBFE5DF), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + padding: EdgeInsets.all(10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: Text( + txtTitle, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + color: Color(0xFF677D81), + ), + ), + ), + InkWell( + onTap: () { + setState(() { + toogleParam == "tipe" + ? toogleTipe = !toogleTipe + : toogleParam == "merek" + ? toogleMerek = !toogleMerek + : toogleParam == "bbm" + ? toogleBBM = !toogleBBM + : toogleParam == "peride" + ? tooglePriode = !tooglePriode + : null; + }); + // print(toogleTipe); + }, + child: Container( + child: Icon( + Icons.arrow_circle_down, + color: Color(0xFFAEAEAE), + ), + ), + ) + ], + ), + ), + AnimatedContainer( + duration: Duration(seconds: 1), + width: double.infinity, + height: toogleParam == "tipe" + ? toogleTipe == true + ? (36 * data.length).toDouble() + : 0 + : toogleParam == "merek" + ? toogleMerek == true + ? (36 * data.length).toDouble() + : 0 + : toogleParam == "bbm" + ? toogleBBM == true + ? (26 * data.length).toDouble() + : 0 + : toogleParam == "periode" + ? tooglePriode == true + ? 30 + : 0 + : 0, + curve: Curves.fastOutSlowIn, + child: toogleParam != "periode" + ? listBuilderWidget(data, toogleParam) + : formPeriode(), + ), + SizedBox( + height: 10, + ), + ], + ), + ); + } + + Widget formPeriode() { + return Container( + height: 20, + width: 20, + child: Column( + children: [ + Row( + children: [ + Container( + width: 40, + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 22), + margin: EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: Color(0xFFBFE5DF), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + child: Row( + children: [ + Icon(Icons.calendar_month_outlined), + Text( + "Awal", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + color: Color(0xFF677D81), + ), + ) + ], + ), + ), + SizedBox( + width: 15, + ), + Container( + width: double.infinity, + height: 10, + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 22), + margin: EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: Color(0xFFBFE5DF), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + ) + ], + ) + ], + ), + ); + } + + Widget listBuilderWidget(data, toogleParam) { + return ListView.builder( + padding: EdgeInsets.zero, + itemCount: data.length, + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemBuilder: (BuildContext context, int index) { + return toogleParam != "bbm" + ? itemDropDown(data.elementAt(index)) + : itemDropDown(listBensin[index].text); + }, + ); + } + + Widget itemDropDown(key) { + return Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 22), + margin: EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: Color(0xFFBFE5DF), + borderRadius: BorderRadius.all( + Radius.circular(10), + ), + ), + child: Text( + key, + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 10, + color: Color(0xFF677D81), + ), + ), + ); + } +} diff --git a/lib/repository/kendaraan/kendaraan_repository.dart b/lib/repository/kendaraan/kendaraan_repository.dart new file mode 100644 index 0000000..c79b50f --- /dev/null +++ b/lib/repository/kendaraan/kendaraan_repository.dart @@ -0,0 +1,36 @@ + +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/services/databases.dart'; + +// const _delay = Duration(milliseconds: 800); + +class KendaraanRepository{ + + DatabasesMain service = DatabasesMain(); + + Future> loadKendaraan() { + return service.getAllKendaraan(); + } + + Future addedKendaraan(KendaraanModel kendaraan) + { + return service.insertDataKendaraan(kendaraan); + } + + Future changeStatuKendaraan(int id, int status) + { + return service.updateStatusAktifKendaraan(id, status); + } + + Future deleteDataKendaraan(int id) async + { + await service.deleteDataKendaraan(id); + } + + Future updateDataKendaraan(KendaraanModel data) async + { + await service.updateDataKendaraan(data); + } + +} \ No newline at end of file diff --git a/lib/repository/transaksi/transaksi_repository.dart b/lib/repository/transaksi/transaksi_repository.dart new file mode 100644 index 0000000..5b9a45a --- /dev/null +++ b/lib/repository/transaksi/transaksi_repository.dart @@ -0,0 +1,45 @@ +import 'package:bbm_tracking/model/photo_m.dart'; +import 'package:bbm_tracking/model/status_m.dart'; +import 'package:bbm_tracking/model/transaksiPerMonth_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:bbm_tracking/services/databases.dart'; + +class TransaksiRepository +{ + DatabasesMain service = DatabasesMain(); + Future> loadTransaksi() + { + return service.getAllTransaksiStatusSuccessfull(); + } + + Future> loadTransaksiThisMonth(String datetime) + { + return service.getAllTransaksiStatusSuccessfullThisMonth(datetime); + } + + Future insertTransaksi(TransaksiModel model) async + { + await service.insertDataTransaksi(model); + } + + //photo + Future insertPhoto(PhotoModel model) async + { + await service.insertDataPhoto(model); + } + + Future> getPhoto(String param) async{ + return service.getAllPhoto(param); + } + + //status + Future insertStatusIn() async + { + await service.insertDataStatus(); + } + + Future> getStatusIn() async{ + return service.getStatusIn(); + } + +} \ No newline at end of file diff --git a/lib/resource/component-bersama/card_kendaraan.dart b/lib/resource/component-bersama/card_kendaraan.dart new file mode 100644 index 0000000..3150872 --- /dev/null +++ b/lib/resource/component-bersama/card_kendaraan.dart @@ -0,0 +1,190 @@ +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:flutter/material.dart'; + +class MainCardKendaraan extends StatelessWidget { + final KendaraanModel? kendaraanModel; + + MainCardKendaraan(this.kendaraanModel); + + @override + Widget build(BuildContext context) { + return Container( + child: Stack( + children: [ + kendaraanModel != null + ? Image.asset( + "assets/images/card.png", + width: double.infinity, + fit: BoxFit.fill, + ) + : Image.asset( + "assets/images/card_empty.png", + width: double.infinity, + fit: BoxFit.fill, + ), + Container( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + Container( + width: double.infinity, + child: Text( + "Data Pribadi Kendaraan Anda", + style: TextStyle( + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + fontSize: 16, + color: Color(0xFF3B3C48), + ), + ), + ), + Container( + child: Row( + children: [ + kendaraanModel != null + ? kendaraanModel?.jenisKendaraan != "motor" + ? Image.asset( + "assets/images/car.png", + width: 110, + height: 110, + ) + : Image.asset( + "assets/images/motor.png", + width: 110, + height: 110, + ) + : Image.asset( + "assets/images/img_empty.png", + width: 110, + height: 110, + ), + SizedBox( + width: 10, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + // width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Tipe Kendaraan : ", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + color: Color(0xFF25235B), + ), + ), + SizedBox( + height: 5, + ), + Text( + kendaraanModel != null + ? kendaraanModel!.namaKendaraan + : "-", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + fontWeight: FontWeight.w700, + color: Color(0xFFffffff), + ), + ), + ], + ), + ), + SizedBox( + width: 20, + ), + Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Nomor Plat :", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + color: Color(0xFF25235B), + ), + ), + SizedBox( + height: 5, + ), + Text( + kendaraanModel != null + ? kendaraanModel!.nomorPlat + : "-", + // "AS 7713 JJA", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + fontWeight: FontWeight.w700, + color: Color(0xFFffffff), + ), + ), + ], + ), + ), + ], + ), + ), + SizedBox( + height: 10, + ), + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Bahan Bakar saat ini", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 11, + fontWeight: FontWeight.w400, + color: Color(0xFF25235B), + ), + ), + // SizedBox( + // height: 5, + // ), + Text( + kendaraanModel != null + ? kendaraanModel!.bahanBakar + : "-", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 14, + fontWeight: FontWeight.w700, + color: Color(0xFFffffff), + ), + ), + ], + ), + ) + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/resource/component-bersama/chart.dart b/lib/resource/component-bersama/chart.dart new file mode 100644 index 0000000..039ef28 --- /dev/null +++ b/lib/resource/component-bersama/chart.dart @@ -0,0 +1,92 @@ +// import 'package:fl_chart_app/presentation/resources/app_resources.dart'; +// import 'package:fl_chart_app/util/extensions/color_extensions.dart'; +import 'package:bbm_tracking/model/transaksiPerMonth_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:syncfusion_flutter_charts/sparkcharts.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class BarChartSample3 extends StatefulWidget { + List dataTransaksi; + String param; + BarChartSample3({required this.dataTransaksi, required this.param, Key? key}): super(key: key); + + @override + State createState() => BarChartSample3State(); +} + +class BarChartSample3State extends State { + List dtTotalBayar = []; + List dtTotalLiter = []; + late List dtTransaksi; + DateTime today = DateTime.now(); + @override + void initState() { + // TODO: implement initState + super.initState(); + dtTransaksi = widget.dataTransaksi; + final daysInMonth = DateTime(today.year, today.month + 1, 0).day; + + for (var i = 1; i <= daysInMonth; i++) { + if (dtTransaksi.length > 0) { + for(int j = 0; j < dtTransaksi.length; j++) + { + if(i == dtTransaksi[j].tanggalTransaksi.day) + { + dtTotalBayar.add(dtTransaksi[j].totalBayar.toDouble()); + dtTotalLiter.add(dtTransaksi[j].totalLiter); + break; + }else{ + dtTotalBayar.add(0); + dtTotalLiter.add(0); + break; + } + } + } else { + dtTotalBayar.add(0); + dtTotalLiter.add(0); + } + } + } + + @override + Widget build(BuildContext context) { + print(widget.param); + return AspectRatio( + aspectRatio: 1.6, + child: widget.param == "Harga" + ? SfSparkLineChart( + //Enable the trackball + trackball: SparkChartTrackball( + activationMode: SparkChartActivationMode.tap, + color: Colors.black, + ), + //Enable marker + marker: SparkChartMarker( + displayMode: SparkChartMarkerDisplayMode.all, + color: Colors.black), + //Enable data label + labelDisplayMode: SparkChartLabelDisplayMode.none, + color: Color(0xFFFC8D05), + // dashArray: [], + data: dtTotalBayar, + ) + : SfSparkLineChart( + //Enable the trackball + trackball: SparkChartTrackball( + activationMode: SparkChartActivationMode.tap, + color: Colors.black, + ), + //Enable marker + marker: SparkChartMarker( + displayMode: SparkChartMarkerDisplayMode.all, + color: Colors.black), + //Enable data label + labelDisplayMode: SparkChartLabelDisplayMode.none, + color: Color(0xFFFC8D05), + // dashArray: [], + data: dtTotalLiter, + ), + ); + } +} diff --git a/lib/resource/convert_money/convert_money.dart b/lib/resource/convert_money/convert_money.dart new file mode 100644 index 0000000..21deb60 --- /dev/null +++ b/lib/resource/convert_money/convert_money.dart @@ -0,0 +1,11 @@ +import 'package:intl/intl.dart'; +class CurrencyFormat { + static String convertToIdr(dynamic number, int decimalDigit) { + NumberFormat currencyFormatter = NumberFormat.currency( + locale: 'id', + symbol: 'Rp. ', + decimalDigits: decimalDigit, + ); + return currencyFormatter.format(number); + } +} \ No newline at end of file diff --git a/lib/resource/data-bensin/data-bensin.dart b/lib/resource/data-bensin/data-bensin.dart new file mode 100644 index 0000000..afebb7a --- /dev/null +++ b/lib/resource/data-bensin/data-bensin.dart @@ -0,0 +1,103 @@ +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:flutter/material.dart'; + +List listBensin = [ + BensinModel( + id: 1, + value: "pertalite", + text: "Pertalite", + perusahaan: "Pertamina", + harga: 10000, + ), + BensinModel( + id: 2, + value: "pertamax", + text: "Pertamax", + perusahaan: "Pertamina", + harga: 12400, + ), + BensinModel( + id: 3, + value: "pertamax_turbo", + text: "Pertamax Turbo", + perusahaan: "Pertamina", + harga: 14000, + ), + BensinModel( + id: 4, + value: "pertamina_dex", + text: "Pertamina Dex", + perusahaan: "Pertamina", + harga: 13550, + ), + BensinModel( + id: 5, + value: "dexlite", + text: "Dexlite", + perusahaan: "Pertamina", + harga: 13150, + ), + BensinModel( + id: 6, + value: "solar", + text: "Solar", + perusahaan: "Pertamina", + harga: 6800, + ), + BensinModel( + id: 7, + value: "shell_v_power_nitro", + text: "Shell V-Power Nitro+", + perusahaan: "Shell", + harga: 14120, + ), + BensinModel( + id: 8, + value: "shell_v_power", + text: "Shell V-Power", + perusahaan: "Shell", + harga: 13780, + ), + BensinModel( + id: 9, + value: "shell_super", + text: "Shell Super", + perusahaan: "Shell", + harga: 12920, + ), + BensinModel( + id: 10, + value: "shell_v_power_diesel", + text: "Shell V-Power Diesel", + perusahaan: "Shell", + harga: 13590, + ), + BensinModel( + id: 11, + value: "shell_diesel_extra", + text: "Shell Diesel Extra", + perusahaan: "Shell", + harga: 13160, + ), + BensinModel( + id: 12, + value: "revvo_90", + text: "Revvo 90", + perusahaan: "Revvo", + harga: 11200, + ), + BensinModel( + id: 13, + value: "revvo_92", + text: "Revvo 92", + perusahaan: "Revvo", + harga: 12400, + ), + BensinModel( + id: 14, + value: "revvo_95", + text: "Revvo 95", + perusahaan: "Revvo", + harga: 13200, + ), +]; diff --git a/lib/resource/data-tanggal/bulan.dart b/lib/resource/data-tanggal/bulan.dart new file mode 100644 index 0000000..125e8b9 --- /dev/null +++ b/lib/resource/data-tanggal/bulan.dart @@ -0,0 +1 @@ +List bulan = ["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"]; \ No newline at end of file diff --git a/lib/resource/data-tanggal/tahun.dart b/lib/resource/data-tanggal/tahun.dart new file mode 100644 index 0000000..b055035 --- /dev/null +++ b/lib/resource/data-tanggal/tahun.dart @@ -0,0 +1 @@ +List tahun = ["2023","2024","2025","2026","2027","2028","2029","2030"]; \ No newline at end of file diff --git a/lib/resource/dialog-pickdate/month-pickcer.dart b/lib/resource/dialog-pickdate/month-pickcer.dart new file mode 100644 index 0000000..26b6f08 --- /dev/null +++ b/lib/resource/dialog-pickdate/month-pickcer.dart @@ -0,0 +1,180 @@ +import 'package:bbm_tracking/resource/resource.dart'; +import 'package:flutter/material.dart'; + +class MonthPicker extends StatefulWidget { + // final Function onChangeNextMonth; + final Function onChangeDate; + // final String bulan; + + const MonthPicker({ + super.key, + required this.onChangeDate, + // required this.onChangBeforeMonth, + // required this.bulan + }); + + @override + State createState() => _MonthPickerState(); +} + +class _MonthPickerState extends State { + late Function onChangeDate; + + int _month = 0; + int _year = 2023; + String mon = ""; + + @override + void initState() { + super.initState(); + onChangeDate = widget.onChangeDate; + } + + void nextMonth() { + setState(() { + _month == 11 ? _month = 0 : _month = _month + 1; + }); + // print(bulan.elementAt(_month)); + } + + void beforeMonth() { + setState(() { + _month == 0 ? _month = 11 : _month = _month - 1; + }); + // print(bulan.elementAt(_month)); + } + + void nextYear() { + setState(() { + _year = _year + 1; + }); + // print(bulan.elementAt(_month)); + } + + void beforeYear() { + setState(() { + _year > 2023 ? _year = _year - 1 : null; + }); + // print(bulan.elementAt(_month)); + } + + @override + Widget build(BuildContext context) { + return Dialog( + elevation: 1, + backgroundColor: Color(0xffE3EAEA), + child: Container( + height: 250, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + "Pilih Tanggal", + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 18, + fontFamily: 'Poppins', + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: 20, + ), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Column( + children: [ + InkWell( + onTap: () => nextMonth(), + child: Icon( + Icons.arrow_drop_up, + size: 50, + ), + ), + Text( + bulan.elementAt(_month), + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + InkWell( + onTap: () => beforeMonth(), + child: Icon( + Icons.arrow_drop_down, + size: 50, + ), + ), + ], + ), + Column( + children: [ + InkWell( + onTap: () => nextYear(), + child: Icon( + Icons.arrow_drop_up, + size: 50, + ), + ), + Text( + _year.toString(), + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + InkWell( + onTap: () => beforeYear(), + child: Icon( + Icons.arrow_drop_down, + size: 50, + ), + ), + ], + ), + ], + ), + ), + SizedBox( + height: 16, + ), + InkWell( + onTap: () { + if (_month < 10) { + mon = "0" + (_month + 1).toString(); + } + onChangeDate(mon.toString(), _year.toString()); + Navigator.of(context).pop(); + }, + child: Container( + padding: EdgeInsets.symmetric( + vertical: 10, + horizontal: 17, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9)), + color: Color(0xFF2ECC71), + ), + child: Text( + "Selesai", + style: TextStyle( + fontFamily: 'Poppins', + fontSize: 12, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/resource/popup/popup.dart b/lib/resource/popup/popup.dart new file mode 100644 index 0000000..0b5c07c --- /dev/null +++ b/lib/resource/popup/popup.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +class PopUp extends StatefulWidget { + String text, param; + PopUp({super.key, required this.text, required this.param}); + + @override + State createState() => _PopUpState(); +} + +class _PopUpState extends State { + + @override + Widget build(BuildContext context) { + return Dialog( + elevation: 1, + backgroundColor: Color(0xffE3EAEA), + child: Container( + height: 200, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.asset( + widget.param == "negative" ? "assets/images/sad_person.png" : "assets/images/about_person.png", + width: 70, + ), + SizedBox( + height: 10, + ), + Text( + widget.text, + style: TextStyle( + color: Color(0xFF677D81), + fontSize: 13, + fontFamily: 'Poppins', + fontWeight: FontWeight.w600, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/resource/resource.dart b/lib/resource/resource.dart new file mode 100644 index 0000000..78654ef --- /dev/null +++ b/lib/resource/resource.dart @@ -0,0 +1,9 @@ +export 'data-bensin/data-bensin.dart'; +export 'text/text-kebijakan.dart'; +export 'component-bersama/card_kendaraan.dart'; +export 'component-bersama/chart.dart'; +export 'data-tanggal/bulan.dart'; +export 'data-tanggal/tahun.dart'; +export 'dialog-pickdate/month-pickcer.dart'; + +export 'convert_money/convert_money.dart'; \ No newline at end of file diff --git a/lib/resource/text/text-kebijakan.dart b/lib/resource/text/text-kebijakan.dart new file mode 100644 index 0000000..6728d93 --- /dev/null +++ b/lib/resource/text/text-kebijakan.dart @@ -0,0 +1,11 @@ +String Kebijakan1 = "BBM-Tracking menghormati segala sesuatu yang berhubungan dengan privasi Anda. Kami menyusun kebijakan privasi ini untuk membantu Anda memahami data apa pun yang diperoleh, dikumpulkan, diproses, dianalisis, digunakan, dikirim, ditampilkan, diumumkan, diperluas, dihapus, dikirim, dan dimusnahkan pada data pribadi Anda yang disediakan di Aplikasi ini."; +String Kebijakan2 = "Data yang disebutkan di atas diatur sesuai dengan kebijakan privasi di aplikasi ini dan disesuaikan kembali dengan peraturan perundang-undangan yang berlaku."; +String Kebijakan3 = "Kami berharap Anda benar-benar membaca dan memahami kebijakan privasi ini dengan seksama sehingga Anda mengertikan bagaimana kami mengelola dan melindungi data yang Anda simpan. Dengan menggunakan BBM-Tracking, Anda mengakui bahwa Anda telah membaca dan memahami semua ketentuan yang terdapat dalam kebijakan dan privasi aplikasi ini."; + +String about1 = "Dengan BBM-Tracking App Anda dapat menyimpan riwayat bahan bakar kendaraan yang sedang Anda gunakan. Aplikasi ini membantu Anda memantau setiap kebutuhan kendaraan secara akurat dan tentunya lebih efisien."; +String about2 = "Aplikasi BBM-Tracking mencatat semua bahan bakar yang digunakan, biaya dan pelacak jarak tempuh kendaraan yang digunakan. Konsumsi bahan bakar dapat diprediksi sehingga penghematan biaya kendaraan Anda akan jauh lebih baik."; +String about3 = "Ayo download aplikasi BBM-Tracking sekarang juga dan nikmati kemudahan tracking BBM kendaraan Anda."; + + +String Salam1 = "Salam Hormat,"; +String Salam2 = "Management System"; \ No newline at end of file diff --git a/lib/services/databases.dart b/lib/services/databases.dart new file mode 100644 index 0000000..3a41473 --- /dev/null +++ b/lib/services/databases.dart @@ -0,0 +1,318 @@ +import 'package:bbm_tracking/model/bensin_m.dart'; +import 'package:bbm_tracking/model/kendaraan_m.dart'; +import 'package:bbm_tracking/model/photo_m.dart'; +import 'package:bbm_tracking/model/status_m.dart'; +import 'package:bbm_tracking/model/transaksiPerMonth_m.dart'; +import 'package:bbm_tracking/model/transaksi_m.dart'; +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/widgets.dart'; +import 'package:intl/intl.dart'; +import 'package:path/path.dart'; +// import 'package:sqflite/sqflite.dart'; +import 'package:flutter/foundation.dart'; +import 'package:sqflite/sqflite.dart' as sql; +import 'package:sqflite/sqlite_api.dart'; + +class DatabasesMain { + Future createTablesBensin(sql.Database database) async { + await database.execute("""CREATE TABLE bensin( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + value TEXT, + text TEXT, + perusahaan TEXT, + harga INTEGER + ) + """); + } + + Future createTablesTransaksi(sql.Database database) async { + await database.execute("""CREATE TABLE transaksi( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + kendaraanId TEXT, + bensinId TEXT, + kodeTransaksi TEXT, + tanggalTransaksi DATETIME, + waktuTransaksi DATETIME, + lokasiPertamina TEXT, + totalLiter TEXT, + hargaPerLiter INTEGER, + totalBayar INTEGER, + odometer TEXT, + catatan TEXT, + latitude TEXT, + longitude TEXT, + status INTEGER + ) + """); + } + + Future createTablesKendaraan(sql.Database database) async { + await database.execute("""CREATE TABLE kendaraan( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + bahanBakar TEXT, + jenisKendaraan TEXT, + namaKendaraan TEXT, + nomorPlat TEXT, + cc INTEGER, + odometer TEXT, + kepemilikan TEXT, + status INTEGER + ) + """); + } + + Future createTablesFirstIn(sql.Database database) async { + await database.execute("""CREATE TABLE firstIn( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + status INTEGER + ) + """); + } + + Future createTableMapPhotoTransaction(sql.Database database) async { + await database.execute("""CREATE TABLE photo( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + transaksi_id TEXT, + linkPhoto TEXT, + namePhoto TEXT + )"""); + } + + Future dbs() async { + return sql.openDatabase( + join(await sql.getDatabasesPath(), 'bbmtracking1.db'), + version: 1, + onCreate: (sql.Database database, int version) async { + await createTablesBensin(database); + await createTablesTransaksi(database); + await createTablesKendaraan(database); + await createTablesFirstIn(database); + await createTableMapPhotoTransaction(database); + }, + ); + } + + //kendaraan + Future> getStatusIn() async { + final db = await dbs(); + + final List> maps = await db.query('firstIn'); + return List.generate(maps.length, (index) { + return StatusModel( + id: maps[index]['id'], + status: maps[index]['status'], + ); + }); + } + + Future insertDataStatus() async { + final db = await dbs(); + await db.rawInsert("INSERT INTO firstIn(status) VALUES(1)"); + } + + //bensin + Future> getAllBensin() async { + final db = await dbs(); + + final List> maps = await db.query('bensin'); + return List.generate(maps.length, (index) { + return BensinModel( + id: maps[index]['id'], + value: maps[index]['value'], + text: maps[index]['text'], + perusahaan: maps[index]['perusahaan'], + harga: maps[index]['harga'], + ); + }); + } + + //kendaraan + Future> getAllKendaraan() async { + final db = await dbs(); + + final List> maps = await db.query('kendaraan'); + return List.generate(maps.length, (index) { + return KendaraanModel( + id: maps[index]['id'], + jenisKendaraan: maps[index]['jenisKendaraan'], + namaKendaraan: maps[index]['namaKendaraan'], + nomorPlat: maps[index]['nomorPlat'], + bahanBakar: maps[index]['bahanBakar'], + cc: maps[index]['cc'], + odometer: maps[index]['odometer'], + kepemilikan: maps[index]['kepemilikan'], + status: maps[index]['status'], + ); + }); + } + + Future insertDataKendaraan(KendaraanModel kendaraan) async { + final db = await dbs(); + await db.rawInsert( + "INSERT INTO kendaraan(bahanBakar,jenisKendaraan,namaKendaraan,nomorPlat,cc,odometer,kepemilikan,status) VALUES('${kendaraan.bahanBakar}','${kendaraan.jenisKendaraan}','${kendaraan.namaKendaraan}','${kendaraan.nomorPlat}','${kendaraan.cc}','${kendaraan.odometer}','${kendaraan.kepemilikan}','${kendaraan.status}')"); + } + + Future updateDataKendaraan(KendaraanModel kendaraan) async { + final db = await dbs(); + db.rawUpdate( + "UPDATE kendaraan SET bahanBakar=?, jenisKendaraan = ?, namaKendaraan = ?, nomorPlat = ?, cc = ?, odometer = ?, kepemilikan = ? WHERE id = ?", + [ + kendaraan.bahanBakar, + kendaraan.jenisKendaraan, + kendaraan.namaKendaraan, + kendaraan.nomorPlat, + kendaraan.cc, + kendaraan.odometer, + kendaraan.kepemilikan, + kendaraan.id, + ], + ); + } + + Future deleteDataKendaraan(int id) async { + final db = await dbs(); + await db.rawDelete("DELETE FROM kendaraan WHERE id = ${id}"); + } + + Future updateStatusAktifKendaraan(int id, int status) async { + final db = await dbs(); + await db.rawUpdate("UPDATE kendaraan SET status = 0"); + await db + .rawUpdate("UPDATE kendaraan SET status = ${status} WHERE id = ${id}"); + } + + // transaksi + Future> getAllTransaksiStatusSuccessfull() async { + final db = await dbs(); + + final List> maps = + await db.query('transaksi', where: "status = 1"); + + return List.generate(maps.length, (index) { + return TransaksiModel( + id: maps[index]['id'], + kendaraanId: maps[index]['kendaraanId'], + bensinId: maps[index]['bensinId'], + kodeTransaksi: maps[index]['kodeTransaksi'], + tanggalTransaksi: maps[index]['tanggalTransaksi'] != null + ? DateTime.parse(maps[index]['tanggalTransaksi']) + : DateTime.now(), + waktuTransaksi: maps[index]['waktuTransaksi'] != null + ? DateTime.parse(maps[index]['waktuTransaksi']) + : DateTime.now(), + lokasiPertamina: maps[index]['lokasiPertamina'] != null + ? maps[index]['lokasiPertamina'] + : "-", + totalLiter: + maps[index]['totalLiter'] != null ? maps[index]['totalLiter'] : "0", + hargaPerLiter: maps[index]['hargaPerLiter'] != null + ? maps[index]['hargaPerLiter'] + : 0, + totalBayar: + maps[index]['totalBayar'] != null ? maps[index]['totalBayar'] : 0, + odometer: + maps[index]['odometer'] != null ? maps[index]['odometer'] : "0", + catatan: maps[index]['catatan'] != null ? maps[index]['catatan'] : "-", + lat: maps[index]['latitude'] != null ? maps[index]['latitude'] : "0", + lang: maps[index]['longitude'] != null ? maps[index]['longitude'] : "0", + status: maps[index]['status'], + ); + }); + } + + Future> getAllPhoto(param) async { + final db = await dbs(); + + final List> maps = + await db.query('photo', where: "transaksi_id = '${param}'"); + + return List.generate(maps.length, (index) { + return PhotoModel( + id: maps[index]['id'], + transaksi_id: maps[index]['transaksi_id'], + linkPhoto: maps[index]['linkPhoto'], + namePhoto: maps[index]['namePhoto'], + ); + }); + } + + Future> + getAllTransaksiStatusSuccessfullThisMonth(String datetime) async { + final db = await dbs(); + + final List> maps = await db.rawQuery( + "SELECT kendaraanId, SUM(totalLiter) as totalLiter, SUM(totalBayar) as totalBayar, tanggalTransaksi FROM transaksi WHERE (strftime('%m', tanggalTransaksi) = strftime('%m', '${datetime}')) AND status = 1 GROUP BY tanggalTransaksi ORDER BY tanggalTransaksi ASC"); + + return List.generate(maps.length, (index) { + return TransaksiPerMonthModel( + kendaraanId: maps[index]['kendaraanId'], + totalLiter: + maps[index]['totalLiter'] != null ? maps[index]['totalLiter'] : 0, + totalBayar: + maps[index]['totalBayar'] != null ? maps[index]['totalBayar'] : 0, + tanggalTransaksi: maps[index]['tanggalTransaksi'] != null + ? DateTime.parse(maps[index]['tanggalTransaksi']) + : DateTime.now(), + ); + }); + } + + Future> getAllTransaksiStatusDraft() async { + final db = await dbs(); + + final List> maps = + await db.query('transaksi', where: "status = 0"); + + return List.generate(maps.length, (index) { + return TransaksiModel( + id: maps[index]['id'], + kendaraanId: maps[index]['kendaraanId'], + bensinId: maps[index]['bensinId'], + kodeTransaksi: maps[index]['kodeTransaksi'], + tanggalTransaksi: maps[index]['tanggalTransaksi'] != null + ? DateTime.parse(maps[index]['tanggalTransaksi']) + : DateTime.now(), + waktuTransaksi: maps[index]['waktuTransaksi'] != null + ? DateTime.parse(maps[index]['waktuTransaksi']) + : DateTime.now(), + lokasiPertamina: maps[index]['lokasiPertamina'] != null + ? maps[index]['lokasiPertamina'] + : "-", + totalLiter: + maps[index]['totalLiter'] != null ? maps[index]['totalLiter'] : "0", + hargaPerLiter: maps[index]['hargaPerLiter'] != null + ? maps[index]['hargaPerLiter'] + : 0, + totalBayar: + maps[index]['totalBayar'] != null ? maps[index]['totalBayar'] : 0, + odometer: + maps[index]['odometer'] != null ? maps[index]['odometer'] : "0", + catatan: maps[index]['catatan'] != null ? maps[index]['catatan'] : "-", + lat: maps[index]['latitude'] != null ? maps[index]['latitude'] : "0", + lang: maps[index]['longitude'] != null ? maps[index]['longitude'] : "0", + status: maps[index]['status'], + ); + }); + } + + Future insertDataTransaksi(TransaksiModel model) async { + final db = await dbs(); + + final DateFormat formatter = DateFormat('yyyy-MM-dd'); + final String formatted = formatter.format(model.tanggalTransaksi); + final qry = + "INSERT INTO transaksi(kendaraanId,bensinId,kodeTransaksi,tanggalTransaksi,waktuTransaksi,lokasiPertamina,totalLiter,HargaPerliter,totalBayar,odometer,catatan,latitude,longitude,status) " + + "VALUES('${model.kendaraanId}','${model.bensinId}','${model.kodeTransaksi}','${model.tanggalTransaksi.toString()}','${model.waktuTransaksi.toString()}','${model.lokasiPertamina}','${model.totalLiter}','${model.hargaPerLiter}','${model.totalBayar}','${model.odometer}','${model.catatan}','${model.lat}','${model.lang}','${model.status}')"; + await db.rawInsert(qry); + // print(qry); + } + + // photo + Future insertDataPhoto(PhotoModel model) async { + final db = await dbs(); + await db.rawInsert( + "INSERT INTO photo(transaksi_id,linkPhoto,namePhoto) VALUES('${model.transaksi_id}','${model.linkPhoto}','${model.namePhoto}')"); + } +} diff --git a/lib/simple_bloc_observer.dart b/lib/simple_bloc_observer.dart new file mode 100644 index 0000000..d24b5b7 --- /dev/null +++ b/lib/simple_bloc_observer.dart @@ -0,0 +1,28 @@ +import 'dart:developer'; + +import 'package:bloc/bloc.dart'; + +class SimpleBlocObserver extends BlocObserver { + const SimpleBlocObserver(); + + @override + void onEvent(Bloc bloc, Object? event) { + super.onEvent(bloc, event); + log('${bloc.runtimeType} $event'); + } + + @override + void onError(BlocBase bloc, Object error, StackTrace stackTrace) { + log('${bloc.runtimeType} $error'); + super.onError(bloc, error, stackTrace); + } + + @override + void onTransition( + Bloc bloc, + Transition transition, + ) { + super.onTransition(bloc, transition); + log('$transition'); + } +} \ No newline at end of file diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..a2ee626 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,138 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "bbm_tracking") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.bbm_tracking") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..ce0e550 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) printing_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "PrintingPlugin"); + printing_plugin_register_with_registrar(printing_registrar); +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..0c2c3c3 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + printing +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/main.cc b/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/my_application.cc b/linux/my_application.cc new file mode 100644 index 0000000..a6e131e --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "bbm_tracking"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "bbm_tracking"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..92d3e78 --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,22 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import connectivity_plus +import geolocator_apple +import location +import path_provider_foundation +import printing +import sqflite + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) + LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + PrintingPlugin.register(with: registry.registrar(forPlugin: "PrintingPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) +} diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..df469df --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,695 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* bbm_tracking.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "bbm_tracking.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* bbm_tracking.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* bbm_tracking.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/bbm_tracking.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/bbm_tracking"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/bbm_tracking.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/bbm_tracking"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/bbm_tracking.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/bbm_tracking"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..94af319 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..82b6f9d Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..13b35eb Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..0a3f5fa Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bdb5722 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..f083318 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..326c0e7 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..2f1632c Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..a1e1383 --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = bbm_tracking + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.bbmTracking + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..2722837 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..5418c9f --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..91b3d99 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1138 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "8880b4cfe7b5b17d57c052a5a3a8cc1d4f546261c7cc8fbd717bd53f48db0568" + url: "https://pub.dev" + source: hosted + version: "59.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: a89627f49b0e70e068130a36571409726b04dab12da7e5625941d2c8ec278b96 + url: "https://pub.dev" + source: hosted + version: "5.11.1" + animated_custom_dropdown: + dependency: "direct main" + description: + name: animated_custom_dropdown + sha256: a1ce14dd584dc73891da4c29047bc41a7520781d58c9169ccf7b0e1516f531bf + url: "https://pub.dev" + source: hosted + version: "1.4.0" + archive: + dependency: transitive + description: + name: archive + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + url: "https://pub.dev" + source: hosted + version: "3.3.7" + args: + dependency: transitive + description: + name: args + sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + url: "https://pub.dev" + source: hosted + version: "2.4.1" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + barcode: + dependency: transitive + description: + name: barcode + sha256: "789f898eef0bd88312470bdb2cc996f895ad7dd5f89e9adde84b204546a90b45" + url: "https://pub.dev" + source: hosted + version: "2.2.4" + bidi: + dependency: transitive + description: + name: bidi + sha256: "6794b226bc939731308b8539c49bb6c2fdbf0e78c3a65e9b9e81e727c256dfe6" + url: "https://pub.dev" + source: hosted + version: "2.0.7" + bloc: + dependency: "direct main" + description: + name: bloc + sha256: "658a5ae59edcf1e58aac98b000a71c762ad8f46f1394c34a52050cafb3e11a80" + url: "https://pub.dev" + source: hosted + version: "8.1.1" + bloc_test: + dependency: "direct dev" + description: + name: bloc_test + sha256: ffbb60c17ee3d8e3784cb78071088e353199057233665541e8ac6cd438dca8ad + url: "https://pub.dev" + source: hosted + version: "9.1.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + camera: + dependency: "direct main" + description: + name: camera + sha256: "309b823e61f15ff6b5b2e4c0ff2e1512ea661cad5355f71fc581e510ae5b26bb" + url: "https://pub.dev" + source: hosted + version: "0.10.5" + camera_android: + dependency: transitive + description: + name: camera_android + sha256: e0f9b7eea2d1f4d4f5460f178522f0d02c095d2ae00b01a77419ce61c4184bfe + url: "https://pub.dev" + source: hosted + version: "0.10.7" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "7ac8b950672716722af235eed7a7c37896853669800b7da706bb0a9fd41d3737" + url: "https://pub.dev" + source: hosted + version: "0.9.13+1" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: "525017018d116c5db8c4c43ec2d9b1663216b369c9f75149158280168a7ce472" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: d77965f32479ee6d8f48205dcf10f845d7210595c6c00faa51eab265d1cae993 + url: "https://pub.dev" + source: hosted + version: "0.3.1+3" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + connectivity_plus: + dependency: "direct main" + description: + name: connectivity_plus + sha256: b74247fad72c171381dbe700ca17da24deac637ab6d43c343b42867acb95c991 + url: "https://pub.dev" + source: hosted + version: "3.0.6" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + url: "https://pub.dev" + source: hosted + version: "1.2.4" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + url: "https://pub.dev" + source: hosted + version: "1.6.3" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" + source: hosted + version: "0.3.3+4" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + currency_text_input_formatter: + dependency: "direct main" + description: + name: currency_text_input_formatter + sha256: c7ceefbfda7d279c489fcc00b4515795ae1e5657968bfd32b4129a6488558e95 + url: "https://pub.dev" + source: hosted + version: "2.1.8" + dbus: + dependency: transitive + description: + name: dbus + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" + source: hosted + version: "0.7.8" + diff_match_patch: + dependency: transitive + description: + name: diff_match_patch + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" + url: "https://pub.dev" + source: hosted + version: "0.4.1" + equatable: + dependency: "direct main" + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "155556c4aba56c8474308d51b4e5446b80a07db9ab66a3cb74aff05c110df982" + url: "https://pub.dev" + source: hosted + version: "0.60.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: "434951eea948dbe87f737b674281465f610b8259c16c097b8163ce138749a775" + url: "https://pub.dev" + source: hosted + version: "8.1.2" + flutter_lints: + dependency: "direct main" + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_neumorphic: + dependency: "direct main" + description: + name: flutter_neumorphic + sha256: "02606d937a3ceaa497b8a7c25f3efa95188bf93d77ebf0bd6552e432db4c2ec6" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0" + url: "https://pub.dev" + source: hosted + version: "2.0.14" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + sha256: cc4231579e3eae41ae166660df717f4bad1359c87f4a4322ad8ba1befeb3d2be + url: "https://pub.dev" + source: hosted + version: "3.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "2f9c4d3f4836421f7067a28f8939814597b27614e021da9d63e5d3fb6e212d25" + url: "https://pub.dev" + source: hosted + version: "8.2.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + geolocator: + dependency: "direct main" + description: + name: geolocator + sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8" + url: "https://pub.dev" + source: hosted + version: "9.0.2" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + sha256: "2ba24690aee0a3e1b6b7bd47c2711a50c874e95e4c758346589d35194adf6d6a" + url: "https://pub.dev" + source: hosted + version: "4.1.7" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: "22b60ca3b8c0f58e6a9688ff855ee39ab813ca3f0c0609a48d282f6631266f2e" + url: "https://pub.dev" + source: hosted + version: "2.2.5" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: af4d69231452f9620718588f41acc4cb58312368716bfff2e92e770b46ce6386 + url: "https://pub.dev" + source: hosted + version: "4.0.7" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: f68a122da48fcfff68bbc9846bb0b74ef651afe84a1b1f6ec20939de4d6860e1 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: f5911c88e23f48b598dd506c7c19eff0e001645bdc03bb6fecb9f4549208354d + url: "https://pub.dev" + source: hosted + version: "0.1.1" + glob: + dependency: transitive + description: + name: glob + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + google_maps_flutter: + dependency: "direct main" + description: + name: google_maps_flutter + sha256: "0a7e0bd1dfe594bc86892d2e69062e3f80b267e378042d82e6b87a8efc798013" + url: "https://pub.dev" + source: hosted + version: "2.2.6" + google_maps_flutter_android: + dependency: transitive + description: + name: google_maps_flutter_android + sha256: b1aeab571b33e983ced9977f2f0eca2b25925f6319e99e3901cfc1675e1b5ada + url: "https://pub.dev" + source: hosted + version: "2.4.13" + google_maps_flutter_ios: + dependency: transitive + description: + name: google_maps_flutter_ios + sha256: e9ad74415a222573625a2c1717adc1e375b18e8ce660fc12db734d1bda1132d4 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + google_maps_flutter_platform_interface: + dependency: transitive + description: + name: google_maps_flutter_platform_interface + sha256: a07811d2b82055815ede75e1fe4b7b76f71a0b4820b26f71bdaddd157d6a3e20 + url: "https://pub.dev" + source: hosted + version: "2.2.6" + http: + dependency: transitive + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + url: "https://pub.dev" + source: hosted + version: "4.0.17" + image_gallery_saver: + dependency: "direct main" + description: + name: image_gallery_saver + sha256: be812580c7a320d3bf583af89cac6b376f170d48000aca75215a73285a3223a0 + url: "https://pub.dev" + source: hosted + version: "1.7.1" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "3da954c3b8906d82ecb50fd5e2b5401758f06d5678904eed6cbc06172283a263" + url: "https://pub.dev" + source: hosted + version: "0.8.7+4" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "271e0448e82268b3fa1cb2a48e4a911cbc2135587123d7df8e7ca703c5b10da2" + url: "https://pub.dev" + source: hosted + version: "0.8.6+11" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c" + url: "https://pub.dev" + source: hosted + version: "2.1.12" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: a1546ff5861fc15812953d4733b520c3d371cec3d2859a001ff04c46c4d81883 + url: "https://pub.dev" + source: hosted + version: "0.8.7+3" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8" + url: "https://pub.dev" + source: hosted + version: "2.6.3" + intl: + dependency: "direct main" + description: + name: intl + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" + source: hosted + version: "0.17.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + location: + dependency: "direct main" + description: + name: location + sha256: "9051959f6f2ccadd887b28b66e9cbbcc25b6838e37cf9e894c421ccc0ebf80b5" + url: "https://pub.dev" + source: hosted + version: "4.4.0" + location_platform_interface: + dependency: transitive + description: + name: location_platform_interface + sha256: "62eeaf1658e92e4459b727f55a3c328eccbac8ba043fa6d262ac5286ad48384c" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + location_web: + dependency: transitive + description: + name: location_web + sha256: "6c08c408a040534c0269c4ff9fe17eebb5a36dea16512fbaf116b9c8bc21545b" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: "direct main" + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + mocktail: + dependency: "direct dev" + description: + name: mocktail + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" + source: hosted + version: "0.3.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + pandabar: + dependency: "direct main" + description: + name: pandabar + sha256: bb5f394bc1c1c6779af042c3b3edc09a2610b146a0b3e06a9f1f67bd35bd33c0 + url: "https://pub.dev" + source: hosted + version: "0.1.2" + path: + dependency: "direct main" + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + url: "https://pub.dev" + source: hosted + version: "2.0.15" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + url: "https://pub.dev" + source: hosted + version: "2.0.27" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + url: "https://pub.dev" + source: hosted + version: "2.1.10" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" + source: hosted + version: "2.0.6" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 + url: "https://pub.dev" + source: hosted + version: "2.1.6" + pdf: + dependency: "direct main" + description: + name: pdf + sha256: "9f75fc7f5580ea5e635b5724de58fb27f684c9ad03ed46fdc1aac768e4557315" + url: "https://pub.dev" + source: hosted + version: "3.10.4" + pdf_widget_wrapper: + dependency: transitive + description: + name: pdf_widget_wrapper + sha256: "754867bf32c4683da29ccc6bf31250905431fb0818a7258c153e21cd627b3212" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" + url: "https://pub.dev" + source: hosted + version: "10.4.3" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: c0c9754479a4c4b1c1f3862ddc11930c9b3f03bef2816bb4ea6eed1e13551d6f + url: "https://pub.dev" + source: hosted + version: "10.3.2" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" + url: "https://pub.dev" + source: hosted + version: "9.1.4" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" + url: "https://pub.dev" + source: hosted + version: "3.11.3" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 + url: "https://pub.dev" + source: hosted + version: "0.1.3" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + printing: + dependency: "direct main" + description: + name: printing + sha256: "6aa86779d51f1c60608defee7b231e1133ab9b00f63b3b71abfa85cb39898571" + url: "https://pub.dev" + source: hosted + version: "5.10.4" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + provider: + dependency: transitive + description: + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" + source: hosted + version: "6.0.5" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + qr: + dependency: transitive + description: + name: qr + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + quiver: + dependency: transitive + description: + name: quiver + sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + url: "https://pub.dev" + source: hosted + version: "3.2.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + simple_month_year_picker: + dependency: "direct main" + description: + name: simple_month_year_picker + sha256: a0e871a441ed578c597d1071f3f3f0325c1ba97a3a4c6564cd9d7ba404998fd1 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: "3a82c9a216b46b88617e3714dd74227eaca20c501c4abcc213e56db26b9caa00" + url: "https://pub.dev" + source: hosted + version: "2.2.8+2" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 + url: "https://pub.dev" + source: hosted + version: "2.4.5" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + syncfusion_flutter_charts: + dependency: "direct main" + description: + name: syncfusion_flutter_charts + sha256: "0222ac9d8cb6c671f014effe9bd5c0aef35eadb16471355345ba87cc0ac007b3" + url: "https://pub.dev" + source: hosted + version: "20.4.54" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "3979f0b1c5a97422cadae52d476c21fa3e0fb671ef51de6cae1d646d8b99fe1f" + url: "https://pub.dev" + source: hosted + version: "20.4.54" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" + url: "https://pub.dev" + source: hosted + version: "1.24.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + test_core: + dependency: transitive + description: + name: test_core + sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + uri_to_file: + dependency: "direct main" + description: + name: uri_to_file + sha256: "84afd633b1492fc465c768141e1a29edd519061bf99935b6b4d0d5de8ec7c108" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + very_good_analysis: + dependency: "direct dev" + description: + name: very_good_analysis + sha256: "4815adc7ded57657038d2bb2a7f332c50e3c8152f7d3c6acf8f6b7c0cc81e5e2" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: d1ba6ce3fa60807433511f943b51607bd7073f8fe5c14286d66fec8e05c8d24c + url: "https://pub.dev" + source: hosted + version: "11.5.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + url: "https://pub.dev" + source: hosted + version: "4.1.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.0-77.0.dev <4.0.0" + flutter: ">=3.7.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..ae73e08 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,129 @@ +name: bbm_tracking +description: A new Flutter project. +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 4.0.4+7 + +environment: + sdk: '>=3.0.0-77.0.dev <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + bloc: ^8.1.0 + equatable: ^2.0.3 + flutter: + sdk: flutter + flutter_bloc: ^8.1.1 + meta: ^1.8.0 + pandabar: ^0.1.1 + syncfusion_flutter_charts: ^20.4.50 + fl_chart: ^0.60.0 + flutter_lints: ^2.0.1 + fluttertoast: ^8.2.1 + animated_custom_dropdown: 1.4.0 + flutter_neumorphic: ^3.0.3 + simple_month_year_picker: ^0.0.2 + sqflite: + path: + intl: ^0.17.0 + currency_text_input_formatter: + # month_picker_dialog: ^1.0.0 + # month_year_picker: ^0.2.0+2 + # flutter_localizations: + # sdk: flutter + # intl: ^0.17.0 + # intl: 0.17.0-nullsafety.2 + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + google_maps_flutter: ^2.2.6 + geolocator: ^9.0.2 + connectivity_plus: ^3.0.6 + location: ^4.3.0 + camera: + path_provider: + image_picker: + image_gallery_saver: '^1.7.1' + permission_handler: + uri_to_file: + pdf: + printing: + flutter_slidable: ^3.0.0 + # uri_to_file: ^0.2.0 + +dev_dependencies: + bloc_test: ^9.0.0 + flutter_test: + sdk: flutter + mocktail: ^0.3.0 + very_good_analysis: ^3.1.0 + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/ + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + fonts: + - family: Poppins + fonts: + - asset: assets/fonts/Poppins-Medium.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..8eac22c --- /dev/null +++ b/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + bbm_tracking + + + + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..4a70b41 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "bbm_tracking", + "short_name": "bbm_tracking", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..ce3b76b --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,101 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(bbm_tracking LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "bbm_tracking") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..930d207 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,104 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..61c84a7 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,23 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + ConnectivityPlusWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + GeolocatorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("GeolocatorWindows")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + PrintingPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PrintingPlugin")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..183b0b5 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,27 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + connectivity_plus + geolocator_windows + permission_handler_windows + printing +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..c85bcb9 --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "bbm_tracking" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "bbm_tracking" "\0" + VALUE "LegalCopyright", "Copyright (C) 2023 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "bbm_tracking.exe" "\0" + VALUE "ProductName", "bbm_tracking" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..b25e363 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,66 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..f8d47d8 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"bbm_tracking", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/windows/runner/resources/app_icon.ico differ diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..a42ea76 --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..f5bf9fa --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..041a385 --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..c86632d --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_