@ -0,0 +1,45 @@ |
|||
# Miscellaneous |
|||
*.class |
|||
*.log |
|||
*.pyc |
|||
*.swp |
|||
.DS_Store |
|||
.atom/ |
|||
.build/ |
|||
.buildlog/ |
|||
.history |
|||
.svn/ |
|||
.swiftpm/ |
|||
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 |
|||
.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 |
|||
@ -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 and should not be manually edited. |
|||
|
|||
version: |
|||
revision: "c23637390482d4cf9598c3ce3f2be31aa7332daf" |
|||
channel: "stable" |
|||
|
|||
project_type: app |
|||
|
|||
# Tracks metadata for the flutter migrate command |
|||
migration: |
|||
platforms: |
|||
- platform: root |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
- platform: android |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
- platform: ios |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
- platform: linux |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
- platform: macos |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
- platform: web |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
- platform: windows |
|||
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf |
|||
|
|||
# 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' |
|||
@ -0,0 +1,16 @@ |
|||
# guycom |
|||
|
|||
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. |
|||
@ -0,0 +1,28 @@ |
|||
# 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.dev/lints. |
|||
# |
|||
# 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 |
|||
@ -0,0 +1,14 @@ |
|||
gradle-wrapper.jar |
|||
/.gradle |
|||
/captures/ |
|||
/gradlew |
|||
/gradlew.bat |
|||
/local.properties |
|||
GeneratedPluginRegistrant.java |
|||
.cxx/ |
|||
|
|||
# Remember to never publicly share your keystore. |
|||
# See https://flutter.dev/to/reference-keystore |
|||
key.properties |
|||
**/*.keystore |
|||
**/*.jks |
|||
@ -0,0 +1,44 @@ |
|||
plugins { |
|||
id("com.android.application") |
|||
id("kotlin-android") |
|||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. |
|||
id("dev.flutter.flutter-gradle-plugin") |
|||
} |
|||
|
|||
android { |
|||
namespace = "com.example.my_app" |
|||
compileSdk = flutter.compileSdkVersion |
|||
ndkVersion = flutter.ndkVersion |
|||
|
|||
compileOptions { |
|||
sourceCompatibility = JavaVersion.VERSION_11 |
|||
targetCompatibility = JavaVersion.VERSION_11 |
|||
} |
|||
|
|||
kotlinOptions { |
|||
jvmTarget = JavaVersion.VERSION_11.toString() |
|||
} |
|||
|
|||
defaultConfig { |
|||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). |
|||
applicationId = "com.example.my_app" |
|||
// You can update the following values to match your application needs. |
|||
// For more information, see: https://flutter.dev/to/review-gradle-config. |
|||
minSdk = flutter.minSdkVersion |
|||
targetSdk = flutter.targetSdkVersion |
|||
versionCode = flutter.versionCode |
|||
versionName = flutter.versionName |
|||
} |
|||
|
|||
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.getByName("debug") |
|||
} |
|||
} |
|||
} |
|||
|
|||
flutter { |
|||
source = "../.." |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<!-- The INTERNET permission is required for development. Specifically, |
|||
the Flutter tool needs it to communicate with the running application |
|||
to allow setting breakpoints, to provide hot reload, etc. |
|||
--> |
|||
<uses-permission android:name="android.permission.INTERNET"/> |
|||
</manifest> |
|||
@ -0,0 +1,45 @@ |
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<application |
|||
android:label="my_app" |
|||
android:name="${applicationName}" |
|||
android:icon="@mipmap/ic_launcher"> |
|||
<activity |
|||
android:name=".MainActivity" |
|||
android:exported="true" |
|||
android:launchMode="singleTop" |
|||
android:taskAffinity="" |
|||
android:theme="@style/LaunchTheme" |
|||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" |
|||
android:hardwareAccelerated="true" |
|||
android:windowSoftInputMode="adjustResize"> |
|||
<!-- Specifies an Android theme to apply to this Activity as soon as |
|||
the Android process has started. This theme is visible to the user |
|||
while the Flutter UI initializes. After that, this theme continues |
|||
to determine the Window background behind the Flutter UI. --> |
|||
<meta-data |
|||
android:name="io.flutter.embedding.android.NormalTheme" |
|||
android:resource="@style/NormalTheme" |
|||
/> |
|||
<intent-filter> |
|||
<action android:name="android.intent.action.MAIN"/> |
|||
<category android:name="android.intent.category.LAUNCHER"/> |
|||
</intent-filter> |
|||
</activity> |
|||
<!-- Don't delete the meta-data below. |
|||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> |
|||
<meta-data |
|||
android:name="flutterEmbedding" |
|||
android:value="2" /> |
|||
</application> |
|||
<!-- Required to query activities that can process text, see: |
|||
https://developer.android.com/training/package-visibility and |
|||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT. |
|||
|
|||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. --> |
|||
<queries> |
|||
<intent> |
|||
<action android:name="android.intent.action.PROCESS_TEXT"/> |
|||
<data android:mimeType="text/plain"/> |
|||
</intent> |
|||
</queries> |
|||
</manifest> |
|||
@ -0,0 +1,5 @@ |
|||
package com.example.my_app |
|||
|
|||
import io.flutter.embedding.android.FlutterActivity |
|||
|
|||
class MainActivity : FlutterActivity() |
|||
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- Modify this file to customize your launch splash screen --> |
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<item android:drawable="?android:colorBackground" /> |
|||
|
|||
<!-- You can insert your own image assets here --> |
|||
<!-- <item> |
|||
<bitmap |
|||
android:gravity="center" |
|||
android:src="@mipmap/launch_image" /> |
|||
</item> --> |
|||
</layer-list> |
|||
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- Modify this file to customize your launch splash screen --> |
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<item android:drawable="@android:color/white" /> |
|||
|
|||
<!-- You can insert your own image assets here --> |
|||
<!-- <item> |
|||
<bitmap |
|||
android:gravity="center" |
|||
android:src="@mipmap/launch_image" /> |
|||
</item> --> |
|||
</layer-list> |
|||
|
After Width: | Height: | Size: 544 B |
|
After Width: | Height: | Size: 442 B |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<resources> |
|||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on --> |
|||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> |
|||
<!-- Show a splash screen on the activity. Automatically removed when |
|||
the Flutter engine draws its first frame --> |
|||
<item name="android:windowBackground">@drawable/launch_background</item> |
|||
</style> |
|||
<!-- Theme applied to the Android Window as soon as the process has started. |
|||
This theme determines the color of the Android Window while your |
|||
Flutter UI initializes, as well as behind your Flutter UI while its |
|||
running. |
|||
|
|||
This Theme is only used starting with V2 of Flutter's Android embedding. --> |
|||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> |
|||
<item name="android:windowBackground">?android:colorBackground</item> |
|||
</style> |
|||
</resources> |
|||
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<resources> |
|||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> |
|||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> |
|||
<!-- Show a splash screen on the activity. Automatically removed when |
|||
the Flutter engine draws its first frame --> |
|||
<item name="android:windowBackground">@drawable/launch_background</item> |
|||
</style> |
|||
<!-- Theme applied to the Android Window as soon as the process has started. |
|||
This theme determines the color of the Android Window while your |
|||
Flutter UI initializes, as well as behind your Flutter UI while its |
|||
running. |
|||
|
|||
This Theme is only used starting with V2 of Flutter's Android embedding. --> |
|||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar"> |
|||
<item name="android:windowBackground">?android:colorBackground</item> |
|||
</style> |
|||
</resources> |
|||
@ -0,0 +1,7 @@ |
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<!-- The INTERNET permission is required for development. Specifically, |
|||
the Flutter tool needs it to communicate with the running application |
|||
to allow setting breakpoints, to provide hot reload, etc. |
|||
--> |
|||
<uses-permission android:name="android.permission.INTERNET"/> |
|||
</manifest> |
|||
@ -0,0 +1,21 @@ |
|||
allprojects { |
|||
repositories { |
|||
google() |
|||
mavenCentral() |
|||
} |
|||
} |
|||
|
|||
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() |
|||
rootProject.layout.buildDirectory.value(newBuildDir) |
|||
|
|||
subprojects { |
|||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) |
|||
project.layout.buildDirectory.value(newSubprojectBuildDir) |
|||
} |
|||
subprojects { |
|||
project.evaluationDependsOn(":app") |
|||
} |
|||
|
|||
tasks.register<Delete>("clean") { |
|||
delete(rootProject.layout.buildDirectory) |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError |
|||
android.useAndroidX=true |
|||
android.enableJetifier=true |
|||
@ -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-8.10.2-all.zip |
|||
@ -0,0 +1,25 @@ |
|||
pluginManagement { |
|||
val flutterSdkPath = run { |
|||
val properties = java.util.Properties() |
|||
file("local.properties").inputStream().use { properties.load(it) } |
|||
val flutterSdkPath = properties.getProperty("flutter.sdk") |
|||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } |
|||
flutterSdkPath |
|||
} |
|||
|
|||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") |
|||
|
|||
repositories { |
|||
google() |
|||
mavenCentral() |
|||
gradlePluginPortal() |
|||
} |
|||
} |
|||
|
|||
plugins { |
|||
id("dev.flutter.flutter-plugin-loader") version "1.0.0" |
|||
id("com.android.application") version "8.7.0" apply false |
|||
id("org.jetbrains.kotlin.android") version "1.8.22" apply false |
|||
} |
|||
|
|||
include(":app") |
|||
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,3 @@ |
|||
description: This file stores settings for Dart & Flutter DevTools. |
|||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states |
|||
extensions: |
|||
@ -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 |
|||
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>en</string> |
|||
<key>CFBundleExecutable</key> |
|||
<string>App</string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>io.flutter.flutter.app</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundleName</key> |
|||
<string>App</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>FMWK</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>1.0</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1.0</string> |
|||
<key>MinimumOSVersion</key> |
|||
<string>12.0</string> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,2 @@ |
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" |
|||
#include "Generated.xcconfig" |
|||
@ -0,0 +1,2 @@ |
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" |
|||
#include "Generated.xcconfig" |
|||
@ -0,0 +1,46 @@ |
|||
# Uncomment this line to define a global platform for your project |
|||
# platform :ios, '12.0' |
|||
|
|||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. |
|||
ENV['COCOAPODS_DISABLE_STATS'] = 'true' |
|||
|
|||
project 'Runner', { |
|||
'Debug' => :debug, |
|||
'Profile' => :release, |
|||
'Release' => :release, |
|||
} |
|||
|
|||
|
|||
def flutter_root |
|||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) |
|||
unless File.exist?(generated_xcode_build_settings_path) |
|||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" |
|||
end |
|||
|
|||
File.foreach(generated_xcode_build_settings_path) do |line| |
|||
matches = line.match(/FLUTTER_ROOT\=(.*)/) |
|||
return matches[1].strip if matches |
|||
end |
|||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" |
|||
end |
|||
|
|||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) |
|||
|
|||
flutter_ios_podfile_setup |
|||
|
|||
target 'Runner' do |
|||
use_frameworks! |
|||
use_modular_headers! |
|||
# Add This Line |
|||
pod 'PhoneNumberKit', '~> 4.0.1' |
|||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) |
|||
# target 'RunnerTests' do |
|||
# inherit! :search_paths |
|||
# end |
|||
end |
|||
|
|||
post_install do |installer| |
|||
installer.pods_project.targets.each do |target| |
|||
flutter_additional_ios_build_settings(target) |
|||
end |
|||
end |
|||
@ -0,0 +1,129 @@ |
|||
PODS: |
|||
- charset_converter (0.0.1): |
|||
- Flutter |
|||
- DKImagePickerController/Core (4.3.9): |
|||
- DKImagePickerController/ImageDataManager |
|||
- DKImagePickerController/Resource |
|||
- DKImagePickerController/ImageDataManager (4.3.9) |
|||
- DKImagePickerController/PhotoGallery (4.3.9): |
|||
- DKImagePickerController/Core |
|||
- DKPhotoGallery |
|||
- DKImagePickerController/Resource (4.3.9) |
|||
- DKPhotoGallery (0.0.19): |
|||
- DKPhotoGallery/Core (= 0.0.19) |
|||
- DKPhotoGallery/Model (= 0.0.19) |
|||
- DKPhotoGallery/Preview (= 0.0.19) |
|||
- DKPhotoGallery/Resource (= 0.0.19) |
|||
- SDWebImage |
|||
- SwiftyGif |
|||
- DKPhotoGallery/Core (0.0.19): |
|||
- DKPhotoGallery/Model |
|||
- DKPhotoGallery/Preview |
|||
- SDWebImage |
|||
- SwiftyGif |
|||
- DKPhotoGallery/Model (0.0.19): |
|||
- SDWebImage |
|||
- SwiftyGif |
|||
- DKPhotoGallery/Preview (0.0.19): |
|||
- DKPhotoGallery/Model |
|||
- DKPhotoGallery/Resource |
|||
- SDWebImage |
|||
- SwiftyGif |
|||
- DKPhotoGallery/Resource (0.0.19): |
|||
- SDWebImage |
|||
- SwiftyGif |
|||
- file_picker (0.0.1): |
|||
- DKImagePickerController/PhotoGallery |
|||
- Flutter |
|||
- Flutter (1.0.0) |
|||
- flutter_pdfview (1.0.2): |
|||
- Flutter |
|||
- image_picker_ios (0.0.1): |
|||
- Flutter |
|||
- libphonenumber_plugin (0.0.1): |
|||
- Flutter |
|||
- PhoneNumberKit |
|||
- open_file_ios (0.0.1): |
|||
- Flutter |
|||
- path_provider_foundation (0.0.1): |
|||
- Flutter |
|||
- FlutterMacOS |
|||
- PhoneNumberKit (4.0.1): |
|||
- PhoneNumberKit/PhoneNumberKitCore (= 4.0.1) |
|||
- PhoneNumberKit/UIKit (= 4.0.1) |
|||
- PhoneNumberKit/PhoneNumberKitCore (4.0.1) |
|||
- PhoneNumberKit/UIKit (4.0.1): |
|||
- PhoneNumberKit/PhoneNumberKitCore |
|||
- SDWebImage (5.21.0): |
|||
- SDWebImage/Core (= 5.21.0) |
|||
- SDWebImage/Core (5.21.0) |
|||
- sqflite_darwin (0.0.4): |
|||
- Flutter |
|||
- FlutterMacOS |
|||
- SwiftyGif (5.4.5) |
|||
- url_launcher_ios (0.0.1): |
|||
- Flutter |
|||
|
|||
DEPENDENCIES: |
|||
- charset_converter (from `.symlinks/plugins/charset_converter/ios`) |
|||
- file_picker (from `.symlinks/plugins/file_picker/ios`) |
|||
- Flutter (from `Flutter`) |
|||
- flutter_pdfview (from `.symlinks/plugins/flutter_pdfview/ios`) |
|||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) |
|||
- libphonenumber_plugin (from `.symlinks/plugins/libphonenumber_plugin/ios`) |
|||
- open_file_ios (from `.symlinks/plugins/open_file_ios/ios`) |
|||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) |
|||
- PhoneNumberKit (~> 4.0.1) |
|||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) |
|||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) |
|||
|
|||
SPEC REPOS: |
|||
trunk: |
|||
- DKImagePickerController |
|||
- DKPhotoGallery |
|||
- PhoneNumberKit |
|||
- SDWebImage |
|||
- SwiftyGif |
|||
|
|||
EXTERNAL SOURCES: |
|||
charset_converter: |
|||
:path: ".symlinks/plugins/charset_converter/ios" |
|||
file_picker: |
|||
:path: ".symlinks/plugins/file_picker/ios" |
|||
Flutter: |
|||
:path: Flutter |
|||
flutter_pdfview: |
|||
:path: ".symlinks/plugins/flutter_pdfview/ios" |
|||
image_picker_ios: |
|||
:path: ".symlinks/plugins/image_picker_ios/ios" |
|||
libphonenumber_plugin: |
|||
:path: ".symlinks/plugins/libphonenumber_plugin/ios" |
|||
open_file_ios: |
|||
:path: ".symlinks/plugins/open_file_ios/ios" |
|||
path_provider_foundation: |
|||
:path: ".symlinks/plugins/path_provider_foundation/darwin" |
|||
sqflite_darwin: |
|||
:path: ".symlinks/plugins/sqflite_darwin/darwin" |
|||
url_launcher_ios: |
|||
:path: ".symlinks/plugins/url_launcher_ios/ios" |
|||
|
|||
SPEC CHECKSUMS: |
|||
charset_converter: 82bc1d2e3c70dcb51bf769e9772e3ae5b2571695 |
|||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c |
|||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 |
|||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be |
|||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 |
|||
flutter_pdfview: 32bf27bda6fd85b9dd2c09628a824df5081246cf |
|||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a |
|||
libphonenumber_plugin: d134f173b22bfa5ede50887071f087f309277f8c |
|||
open_file_ios: 5ff7526df64e4394b4fe207636b67a95e83078bb |
|||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 |
|||
PhoneNumberKit: a74155066daa6450475f6a029068eb919fb00d5d |
|||
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 |
|||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 |
|||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 |
|||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d |
|||
|
|||
PODFILE CHECKSUM: a28aa98e3ca7183648527da64078769adf630e89 |
|||
|
|||
COCOAPODS: 1.16.2 |
|||
@ -0,0 +1,555 @@ |
|||
// !$*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 */; }; |
|||
ACFB5868BBA6B74A992E1A41 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF94D6584D2E8A3F6BBFAD2 /* Pods_Runner.framework */; }; |
|||
/* End PBXBuildFile 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 = "<group>"; }; |
|||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; |
|||
1FF94D6584D2E8A3F6BBFAD2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
|||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; |
|||
700DD0757496908A05DEFAD8 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; |
|||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; |
|||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; |
|||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; |
|||
886ED87D91BD7C88314D0336 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; |
|||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; |
|||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; |
|||
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 = "<group>"; }; |
|||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; |
|||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; |
|||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
|||
F33AC98EB80D167B1D458E07 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; }; |
|||
/* End PBXFileReference section */ |
|||
|
|||
/* Begin PBXFrameworksBuildPhase section */ |
|||
97C146EB1CF9000F007C117D /* Frameworks */ = { |
|||
isa = PBXFrameworksBuildPhase; |
|||
buildActionMask = 2147483647; |
|||
files = ( |
|||
ACFB5868BBA6B74A992E1A41 /* Pods_Runner.framework in Frameworks */, |
|||
); |
|||
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 = "<group>"; |
|||
}; |
|||
97C146E51CF9000F007C117D = { |
|||
isa = PBXGroup; |
|||
children = ( |
|||
9740EEB11CF90186004384FC /* Flutter */, |
|||
97C146F01CF9000F007C117D /* Runner */, |
|||
97C146EF1CF9000F007C117D /* Products */, |
|||
C2405E9D8DA19A1A863D1EDF /* Pods */, |
|||
A35EC737372E19786CB8B8AD /* Frameworks */, |
|||
); |
|||
sourceTree = "<group>"; |
|||
}; |
|||
97C146EF1CF9000F007C117D /* Products */ = { |
|||
isa = PBXGroup; |
|||
children = ( |
|||
97C146EE1CF9000F007C117D /* Runner.app */, |
|||
); |
|||
name = Products; |
|||
sourceTree = "<group>"; |
|||
}; |
|||
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 = "<group>"; |
|||
}; |
|||
A35EC737372E19786CB8B8AD /* Frameworks */ = { |
|||
isa = PBXGroup; |
|||
children = ( |
|||
1FF94D6584D2E8A3F6BBFAD2 /* Pods_Runner.framework */, |
|||
); |
|||
name = Frameworks; |
|||
sourceTree = "<group>"; |
|||
}; |
|||
C2405E9D8DA19A1A863D1EDF /* Pods */ = { |
|||
isa = PBXGroup; |
|||
children = ( |
|||
F33AC98EB80D167B1D458E07 /* Pods-Runner.debug.xcconfig */, |
|||
886ED87D91BD7C88314D0336 /* Pods-Runner.release.xcconfig */, |
|||
700DD0757496908A05DEFAD8 /* Pods-Runner.profile.xcconfig */, |
|||
); |
|||
name = Pods; |
|||
path = Pods; |
|||
sourceTree = "<group>"; |
|||
}; |
|||
/* End PBXGroup section */ |
|||
|
|||
/* Begin PBXNativeTarget section */ |
|||
97C146ED1CF9000F007C117D /* Runner */ = { |
|||
isa = PBXNativeTarget; |
|||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; |
|||
buildPhases = ( |
|||
40AEFA2DCA57AF98219D4A74 /* [CP] Check Pods Manifest.lock */, |
|||
9740EEB61CF901F6004384FC /* Run Script */, |
|||
97C146EA1CF9000F007C117D /* Sources */, |
|||
97C146EB1CF9000F007C117D /* Frameworks */, |
|||
97C146EC1CF9000F007C117D /* Resources */, |
|||
9705A1C41CF9048500538489 /* Embed Frameworks */, |
|||
3B06AD1E1E4923F5004D2608 /* Thin Binary */, |
|||
731B87E0F0D7405841DD9A9D /* [CP] Embed Pods Frameworks */, |
|||
); |
|||
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 = 1510; |
|||
ORGANIZATIONNAME = ""; |
|||
TargetAttributes = { |
|||
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 */, |
|||
); |
|||
}; |
|||
/* End PBXProject section */ |
|||
|
|||
/* Begin PBXResourcesBuildPhase section */ |
|||
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 = ( |
|||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", |
|||
); |
|||
name = "Thin Binary"; |
|||
outputPaths = ( |
|||
); |
|||
runOnlyForDeploymentPostprocessing = 0; |
|||
shellPath = /bin/sh; |
|||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; |
|||
}; |
|||
40AEFA2DCA57AF98219D4A74 /* [CP] Check Pods Manifest.lock */ = { |
|||
isa = PBXShellScriptBuildPhase; |
|||
buildActionMask = 2147483647; |
|||
files = ( |
|||
); |
|||
inputFileListPaths = ( |
|||
); |
|||
inputPaths = ( |
|||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock", |
|||
"${PODS_ROOT}/Manifest.lock", |
|||
); |
|||
name = "[CP] Check Pods Manifest.lock"; |
|||
outputFileListPaths = ( |
|||
); |
|||
outputPaths = ( |
|||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", |
|||
); |
|||
runOnlyForDeploymentPostprocessing = 0; |
|||
shellPath = /bin/sh; |
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; |
|||
showEnvVarsInLog = 0; |
|||
}; |
|||
731B87E0F0D7405841DD9A9D /* [CP] Embed Pods Frameworks */ = { |
|||
isa = PBXShellScriptBuildPhase; |
|||
buildActionMask = 2147483647; |
|||
files = ( |
|||
); |
|||
inputFileListPaths = ( |
|||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", |
|||
); |
|||
name = "[CP] Embed Pods Frameworks"; |
|||
outputFileListPaths = ( |
|||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", |
|||
); |
|||
runOnlyForDeploymentPostprocessing = 0; |
|||
shellPath = /bin/sh; |
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; |
|||
showEnvVarsInLog = 0; |
|||
}; |
|||
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 */ |
|||
97C146EA1CF9000F007C117D /* Sources */ = { |
|||
isa = PBXSourcesBuildPhase; |
|||
buildActionMask = 2147483647; |
|||
files = ( |
|||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, |
|||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, |
|||
); |
|||
runOnlyForDeploymentPostprocessing = 0; |
|||
}; |
|||
/* End PBXSourcesBuildPhase section */ |
|||
|
|||
/* Begin PBXVariantGroup section */ |
|||
97C146FA1CF9000F007C117D /* Main.storyboard */ = { |
|||
isa = PBXVariantGroup; |
|||
children = ( |
|||
97C146FB1CF9000F007C117D /* Base */, |
|||
); |
|||
name = Main.storyboard; |
|||
sourceTree = "<group>"; |
|||
}; |
|||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { |
|||
isa = PBXVariantGroup; |
|||
children = ( |
|||
97C147001CF9000F007C117D /* Base */, |
|||
); |
|||
name = LaunchScreen.storyboard; |
|||
sourceTree = "<group>"; |
|||
}; |
|||
/* 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 = 12.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)"; |
|||
DEVELOPMENT_TEAM = J39VHLWJ99; |
|||
ENABLE_BITCODE = NO; |
|||
INFOPLIST_FILE = Runner/Info.plist; |
|||
LD_RUNPATH_SEARCH_PATHS = ( |
|||
"$(inherited)", |
|||
"@executable_path/Frameworks", |
|||
); |
|||
PRODUCT_BUNDLE_IDENTIFIER = com.example.youmazgestion; |
|||
PRODUCT_NAME = "$(TARGET_NAME)"; |
|||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
|||
SWIFT_VERSION = 5.0; |
|||
VERSIONING_SYSTEM = "apple-generic"; |
|||
}; |
|||
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 = 12.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 = 12.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)"; |
|||
DEVELOPMENT_TEAM = J39VHLWJ99; |
|||
ENABLE_BITCODE = NO; |
|||
INFOPLIST_FILE = Runner/Info.plist; |
|||
LD_RUNPATH_SEARCH_PATHS = ( |
|||
"$(inherited)", |
|||
"@executable_path/Frameworks", |
|||
); |
|||
PRODUCT_BUNDLE_IDENTIFIER = com.example.youmazgestion; |
|||
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)"; |
|||
DEVELOPMENT_TEAM = J39VHLWJ99; |
|||
ENABLE_BITCODE = NO; |
|||
INFOPLIST_FILE = Runner/Info.plist; |
|||
LD_RUNPATH_SEARCH_PATHS = ( |
|||
"$(inherited)", |
|||
"@executable_path/Frameworks", |
|||
); |
|||
PRODUCT_BUNDLE_IDENTIFIER = com.example.youmazgestion; |
|||
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 */ |
|||
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 */; |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<Workspace |
|||
version = "1.0"> |
|||
<FileRef |
|||
location = "self:"> |
|||
</FileRef> |
|||
</Workspace> |
|||
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>IDEDidComputeMac32BitWarning</key> |
|||
<true/> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>PreviewsEnabled</key> |
|||
<false/> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,88 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<Scheme |
|||
LastUpgradeVersion = "1510" |
|||
version = "1.3"> |
|||
<BuildAction |
|||
parallelizeBuildables = "YES" |
|||
buildImplicitDependencies = "YES"> |
|||
<BuildActionEntries> |
|||
<BuildActionEntry |
|||
buildForTesting = "YES" |
|||
buildForRunning = "YES" |
|||
buildForProfiling = "YES" |
|||
buildForArchiving = "YES" |
|||
buildForAnalyzing = "YES"> |
|||
<BuildableReference |
|||
BuildableIdentifier = "primary" |
|||
BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
|||
BuildableName = "Runner.app" |
|||
BlueprintName = "Runner" |
|||
ReferencedContainer = "container:Runner.xcodeproj"> |
|||
</BuildableReference> |
|||
</BuildActionEntry> |
|||
</BuildActionEntries> |
|||
</BuildAction> |
|||
<TestAction |
|||
buildConfiguration = "Debug" |
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
|||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
|||
shouldUseLaunchSchemeArgsEnv = "YES"> |
|||
<MacroExpansion> |
|||
<BuildableReference |
|||
BuildableIdentifier = "primary" |
|||
BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
|||
BuildableName = "Runner.app" |
|||
BlueprintName = "Runner" |
|||
ReferencedContainer = "container:Runner.xcodeproj"> |
|||
</BuildableReference> |
|||
</MacroExpansion> |
|||
<Testables> |
|||
</Testables> |
|||
</TestAction> |
|||
<LaunchAction |
|||
buildConfiguration = "Debug" |
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
|||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
|||
launchStyle = "0" |
|||
useCustomWorkingDirectory = "NO" |
|||
ignoresPersistentStateOnLaunch = "NO" |
|||
debugDocumentVersioning = "YES" |
|||
debugServiceExtension = "internal" |
|||
enableGPUValidationMode = "1" |
|||
allowLocationSimulation = "YES"> |
|||
<BuildableProductRunnable |
|||
runnableDebuggingMode = "0"> |
|||
<BuildableReference |
|||
BuildableIdentifier = "primary" |
|||
BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
|||
BuildableName = "Runner.app" |
|||
BlueprintName = "Runner" |
|||
ReferencedContainer = "container:Runner.xcodeproj"> |
|||
</BuildableReference> |
|||
</BuildableProductRunnable> |
|||
</LaunchAction> |
|||
<ProfileAction |
|||
buildConfiguration = "Profile" |
|||
shouldUseLaunchSchemeArgsEnv = "YES" |
|||
savedToolIdentifier = "" |
|||
useCustomWorkingDirectory = "NO" |
|||
debugDocumentVersioning = "YES"> |
|||
<BuildableProductRunnable |
|||
runnableDebuggingMode = "0"> |
|||
<BuildableReference |
|||
BuildableIdentifier = "primary" |
|||
BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
|||
BuildableName = "Runner.app" |
|||
BlueprintName = "Runner" |
|||
ReferencedContainer = "container:Runner.xcodeproj"> |
|||
</BuildableReference> |
|||
</BuildableProductRunnable> |
|||
</ProfileAction> |
|||
<AnalyzeAction |
|||
buildConfiguration = "Debug"> |
|||
</AnalyzeAction> |
|||
<ArchiveAction |
|||
buildConfiguration = "Release" |
|||
revealArchiveInOrganizer = "YES"> |
|||
</ArchiveAction> |
|||
</Scheme> |
|||
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<Workspace |
|||
version = "1.0"> |
|||
<FileRef |
|||
location = "group:Runner.xcodeproj"> |
|||
</FileRef> |
|||
<FileRef |
|||
location = "group:Pods/Pods.xcodeproj"> |
|||
</FileRef> |
|||
</Workspace> |
|||
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>IDEDidComputeMac32BitWarning</key> |
|||
<true/> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>PreviewsEnabled</key> |
|||
<false/> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1,13 @@ |
|||
import UIKit |
|||
import Flutter |
|||
|
|||
@main |
|||
@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) |
|||
} |
|||
} |
|||
@ -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" |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 295 B |
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 450 B |
|
After Width: | Height: | Size: 282 B |
|
After Width: | Height: | Size: 462 B |
|
After Width: | Height: | Size: 704 B |
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 586 B |
|
After Width: | Height: | Size: 862 B |
|
After Width: | Height: | Size: 862 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 762 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
@ -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" |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
@ -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. |
|||
@ -0,0 +1,37 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> |
|||
<dependencies> |
|||
<deployment identifier="iOS"/> |
|||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> |
|||
</dependencies> |
|||
<scenes> |
|||
<!--View Controller--> |
|||
<scene sceneID="EHf-IW-A2E"> |
|||
<objects> |
|||
<viewController id="01J-lp-oVM" sceneMemberID="viewController"> |
|||
<layoutGuides> |
|||
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/> |
|||
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/> |
|||
</layoutGuides> |
|||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> |
|||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
|||
<subviews> |
|||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> |
|||
</imageView> |
|||
</subviews> |
|||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
|||
<constraints> |
|||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/> |
|||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/> |
|||
</constraints> |
|||
</view> |
|||
</viewController> |
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> |
|||
</objects> |
|||
<point key="canvasLocation" x="53" y="375"/> |
|||
</scene> |
|||
</scenes> |
|||
<resources> |
|||
<image name="LaunchImage" width="168" height="185"/> |
|||
</resources> |
|||
</document> |
|||
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> |
|||
<dependencies> |
|||
<deployment identifier="iOS"/> |
|||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> |
|||
</dependencies> |
|||
<scenes> |
|||
<!--Flutter View Controller--> |
|||
<scene sceneID="tne-QT-ifu"> |
|||
<objects> |
|||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController"> |
|||
<layoutGuides> |
|||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> |
|||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> |
|||
</layoutGuides> |
|||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> |
|||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/> |
|||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
|||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> |
|||
</view> |
|||
</viewController> |
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> |
|||
</objects> |
|||
</scene> |
|||
</scenes> |
|||
</document> |
|||
@ -0,0 +1,51 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>$(DEVELOPMENT_LANGUAGE)</string> |
|||
<key>CFBundleDisplayName</key> |
|||
<string>Youmazgestion</string> |
|||
<key>CFBundleExecutable</key> |
|||
<string>$(EXECUTABLE_NAME)</string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundleName</key> |
|||
<string>youmazgestion</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>APPL</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>$(FLUTTER_BUILD_NAME)</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>$(FLUTTER_BUILD_NUMBER)</string> |
|||
<key>LSRequiresIPhoneOS</key> |
|||
<true/> |
|||
<key>UILaunchStoryboardName</key> |
|||
<string>LaunchScreen</string> |
|||
<key>UIMainStoryboardFile</key> |
|||
<string>Main</string> |
|||
<key>UISupportedInterfaceOrientations</key> |
|||
<array> |
|||
<string>UIInterfaceOrientationPortrait</string> |
|||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|||
<string>UIInterfaceOrientationLandscapeRight</string> |
|||
</array> |
|||
<key>UISupportedInterfaceOrientations~ipad</key> |
|||
<array> |
|||
<string>UIInterfaceOrientationPortrait</string> |
|||
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
|||
<string>UIInterfaceOrientationLandscapeLeft</string> |
|||
<string>UIInterfaceOrientationLandscapeRight</string> |
|||
</array> |
|||
<key>UIViewControllerBasedStatusBarAppearance</key> |
|||
<false/> |
|||
<key>CADisableMinimumFrameDurationOnPhone</key> |
|||
<true/> |
|||
<key>UIApplicationSupportsIndirectInputEvents</key> |
|||
<true/> |
|||
</dict> |
|||
</plist> |
|||
@ -0,0 +1 @@ |
|||
#import "GeneratedPluginRegistrant.h" |
|||
@ -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. |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
class OrderedProduct { |
|||
String name; |
|||
int quantity; |
|||
double price; |
|||
|
|||
OrderedProduct({required this.name, required this.quantity, required this.price}); |
|||
} |
|||
@ -0,0 +1,213 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:shared_preferences/shared_preferences.dart'; |
|||
import 'package:youmazgestion/Views/historique.dart'; |
|||
|
|||
import '../Views/addProduct.dart'; |
|||
import '../Views/bilanMois.dart'; |
|||
import '../Views/gestionProduct.dart'; |
|||
import '../Views/gestionStock.dart'; |
|||
import '../Views/listUser.dart'; |
|||
import '../Views/loginPage.dart'; |
|||
import '../Views/registrationPage.dart'; |
|||
import '../accueil.dart'; |
|||
import '../controller/userController.dart'; |
|||
|
|||
class CustomDrawer extends StatelessWidget { |
|||
final UserController userController = Get.find<UserController>(); |
|||
Future<void> clearUserData() async { |
|||
final prefs = await SharedPreferences.getInstance(); |
|||
await prefs.remove('username'); |
|||
await prefs.remove('role'); |
|||
} |
|||
CustomDrawer({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Drawer( |
|||
backgroundColor: Colors.white, |
|||
child: ListView( |
|||
children: [ |
|||
GetBuilder<UserController>( |
|||
builder: (controller) => UserAccountsDrawerHeader( |
|||
accountEmail: Text(controller.email), |
|||
accountName: Text(controller.name), |
|||
currentAccountPicture: const CircleAvatar( |
|||
backgroundImage: AssetImage("assets/youmaz2.png"), |
|||
), |
|||
decoration: const BoxDecoration( |
|||
gradient: LinearGradient( |
|||
colors: [Colors.white, const Color.fromARGB(255, 4, 54, 95)], |
|||
begin: Alignment.topLeft, |
|||
end: Alignment.bottomRight, |
|||
), |
|||
)), |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.home), |
|||
iconColor: Colors.lightBlueAccent, |
|||
title: const Text("Accueil"), |
|||
onTap: () { |
|||
// Action lorsque l'utilisateur clique sur "Accueil" |
|||
Get.to(const AccueilPage()); |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.person_add), |
|||
iconColor: Colors.green, |
|||
title: const Text("Ajouter un utilisateur"), |
|||
onTap: () { |
|||
if (userController.role == "admin") { |
|||
Get.to(const RegistrationPage()); |
|||
} else { |
|||
Get.snackbar( |
|||
"Accés refusé", |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
icon: const Icon(Icons.error), |
|||
duration: const Duration(seconds: 3), |
|||
snackPosition: SnackPosition.TOP, |
|||
"Vous n'avez pas les droits pour ajouter un utilisateur"); |
|||
} |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.supervised_user_circle), |
|||
iconColor: const Color.fromARGB(255, 4, 54, 95), |
|||
title: const Text("Modifier/Supprimer un utilisateur"), |
|||
onTap: () { |
|||
// Action lorsque l'utilisateur clique sur "Modifier/Supprimer un utilisateur" |
|||
if (userController.role == "admin") { |
|||
Get.to(const ListUserPage()); |
|||
} else { |
|||
Get.snackbar( |
|||
"Accés refusé", |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
icon: const Icon(Icons.error), |
|||
duration: const Duration(seconds: 3), |
|||
snackPosition: SnackPosition.TOP, |
|||
"Vous n'avez pas les droits pour modifier/supprimer un utilisateur"); |
|||
} |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.add), |
|||
iconColor: Colors.indigoAccent, |
|||
title: const Text("Ajouter un produit"), |
|||
onTap: () { |
|||
if (userController.role == "admin") { |
|||
// Action lorsque l'utilisateur clique sur "Ajouter un produit" |
|||
Get.to(const AddProductPage()); |
|||
} else { |
|||
Get.snackbar( |
|||
"Accés refusé", |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
icon: const Icon(Icons.error), |
|||
duration: const Duration(seconds: 3), |
|||
snackPosition: SnackPosition.TOP, |
|||
"Vous n'avez pas les droits pour ajouter un produit"); |
|||
} |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.edit), |
|||
iconColor: Colors.redAccent, |
|||
title: const Text("Modifier/Supprimer un produit"), |
|||
onTap: () { |
|||
if (userController.role == "admin") { |
|||
// Action lorsque l'utilisateur clique sur "Modifier/Supprimer un produit" |
|||
Get.to(GestionProduit()); |
|||
} else { |
|||
Get.snackbar( |
|||
"Accés refusé", |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
icon: const Icon(Icons.error), |
|||
duration: const Duration(seconds: 3), |
|||
snackPosition: SnackPosition.TOP, |
|||
"Vous n'avez pas les droits pour modifier/supprimer un produit"); |
|||
} |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.bar_chart), |
|||
title: const Text("Bilan"), |
|||
onTap: () { |
|||
if (userController.role == "admin") { |
|||
Get.to(const BilanMois()); |
|||
} else { |
|||
Get.snackbar( |
|||
"Accés refusé", |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
icon: const Icon(Icons.error_outline_outlined), |
|||
duration: const Duration(seconds: 3), |
|||
snackPosition: SnackPosition.TOP, |
|||
"Vous n'avez pas les droits pour accéder au bilan"); |
|||
} |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.inventory), |
|||
iconColor: Colors.blueAccent, |
|||
title: const Text("Gestion de stock"), |
|||
onTap: () { |
|||
if (userController.role == "admin") { |
|||
// Action lorsque l'utilisateur clique sur "Gestion de stock" |
|||
Get.to(const GestionStockPage()); |
|||
} else { |
|||
Get.snackbar( |
|||
"Accés refusé", |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
icon: const Icon(Icons.error), |
|||
duration: const Duration(seconds: 3), |
|||
snackPosition: SnackPosition.TOP, |
|||
"Vous n'avez pas les droits pour accéder à la gestion de stock"); |
|||
} |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.history), |
|||
iconColor: Colors.blue, |
|||
title: const Text("Historique"), |
|||
onTap: () { |
|||
// Action lorsque l'utilisateur clique sur "Historique" |
|||
Get.to(HistoryPage()); |
|||
}, |
|||
), |
|||
ListTile( |
|||
leading: const Icon(Icons.logout), |
|||
iconColor: Colors.red, |
|||
title: const Text("Déconnexion"), |
|||
onTap: () { |
|||
// Action lorsque l'utilisateur clique sur "Déconnexion" |
|||
// display confirmation dialog |
|||
Get.defaultDialog( |
|||
title: "Déconnexion", |
|||
content: const Text("Voulez-vous vraiment vous déconnecter ?"), |
|||
actions: [ |
|||
ElevatedButton( |
|||
child: const Text("Oui"), |
|||
onPressed: () { |
|||
clearUserData(); |
|||
Get.offAll(const LoginPage()); |
|||
}, |
|||
), |
|||
ElevatedButton( |
|||
child: const Text("Non"), |
|||
onPressed: () { |
|||
Get.back(); |
|||
}, |
|||
) |
|||
], |
|||
); |
|||
}, |
|||
) |
|||
], |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
import 'package:flutter/material.dart'; |
|||
|
|||
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { |
|||
final String title; |
|||
|
|||
const CustomAppBar({Key? key, required this.title}) : super(key: key); |
|||
|
|||
@override |
|||
Size get preferredSize => const Size.fromHeight(kToolbarHeight); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return AppBar( |
|||
backgroundColor: Colors.transparent, |
|||
elevation: 5, |
|||
flexibleSpace: Container( |
|||
decoration: const BoxDecoration( |
|||
gradient: LinearGradient( |
|||
colors: [Colors.white, const Color.fromARGB(255, 4, 54, 95)], |
|||
begin: Alignment.topLeft, |
|||
end: Alignment.bottomRight, |
|||
), |
|||
), |
|||
child: Row( |
|||
children: [ |
|||
const Spacer(), |
|||
Align( |
|||
alignment: Alignment.center, |
|||
child: Text( |
|||
title, |
|||
style: const TextStyle( |
|||
fontSize: 25, |
|||
color: Colors.white, |
|||
), |
|||
), |
|||
), |
|||
const Spacer(), |
|||
Padding( |
|||
padding: const EdgeInsets.only(right: 10.0), |
|||
child: Align( |
|||
alignment: Alignment.centerRight, |
|||
child: Image.asset( |
|||
'assets/youmaz2.png', |
|||
width: 100, |
|||
height: 50, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
import '../Models/produit.dart'; |
|||
|
|||
class CartItem { |
|||
final Product product; |
|||
int quantity; |
|||
|
|||
CartItem(this.product, this.quantity); |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:quantity_input/quantity_input.dart'; |
|||
import 'cartItem.dart'; |
|||
|
|||
class PanierPage extends StatelessWidget { |
|||
final List<CartItem> selectedProducts; |
|||
final Function() saveOrderToDatabase; |
|||
|
|||
const PanierPage({ |
|||
super.key, |
|||
required this.selectedProducts, |
|||
required this.saveOrderToDatabase, |
|||
}); |
|||
|
|||
double calculateTotalPrice() { |
|||
double totalPrice = 0; |
|||
for (final cartItem in selectedProducts) { |
|||
totalPrice += cartItem.product.price * cartItem.quantity; |
|||
} |
|||
return totalPrice; |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: const Text('Panier'), |
|||
), |
|||
body: Container( |
|||
padding: const EdgeInsets.all(16), |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
const Text( |
|||
'Produits sélectionnés', |
|||
style: TextStyle( |
|||
fontSize: 20, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
const SizedBox(height: 16), |
|||
Expanded( |
|||
child: ListView.builder( |
|||
itemCount: selectedProducts.length, |
|||
itemBuilder: (context, index) { |
|||
final cartItem = selectedProducts[index]; |
|||
final product = cartItem.product; |
|||
final quantity = cartItem.quantity; |
|||
|
|||
return ListTile( |
|||
title: Text(product.name), |
|||
subtitle: Text(product.category), |
|||
trailing: Row( |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: [ |
|||
Text('${product.price.toStringAsFixed(2)} fcfa'), |
|||
const SizedBox(width: 8), |
|||
Text('x $quantity'), |
|||
const SizedBox(width: 8), |
|||
QuantityInput( |
|||
value: quantity, |
|||
minValue: 1, |
|||
maxValue: 100, |
|||
step: 1, |
|||
buttonColor: Colors.orange, |
|||
onChanged: (value) {}, |
|||
), |
|||
], |
|||
), |
|||
); |
|||
}, |
|||
), |
|||
), |
|||
const SizedBox(height: 16), |
|||
ElevatedButton( |
|||
onPressed: saveOrderToDatabase, |
|||
child: Text('Valider la commande (${selectedProducts.length})'), |
|||
), |
|||
const SizedBox(height: 16), |
|||
Text( |
|||
'Total: ${calculateTotalPrice().toStringAsFixed(2)} fcfa', |
|||
style: const TextStyle( |
|||
fontSize: 16, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
class Order { |
|||
final int id; |
|||
final double totalPrice; |
|||
final String dateTime; |
|||
final DateTime? startDate; |
|||
final String? user; |
|||
|
|||
Order({ |
|||
required this.id, |
|||
required this.totalPrice, |
|||
required this.dateTime, |
|||
this.startDate, |
|||
this.user, |
|||
}); |
|||
|
|||
Map<String, dynamic> toMap() { |
|||
return { |
|||
'id': id, |
|||
'total_price': totalPrice, |
|||
'date_time': dateTime, |
|||
'start_date': startDate?.toIso8601String(), |
|||
'user': user, |
|||
}; |
|||
} |
|||
|
|||
factory Order.fromMap(Map<String, dynamic> map) { |
|||
return Order( |
|||
id: map['id'], |
|||
totalPrice: map['total_price'], |
|||
dateTime: map['date_time'], |
|||
startDate: |
|||
map['start_date'] != null ? DateTime.parse(map['start_date']) : null, |
|||
user: map['user'], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
class Work { |
|||
final int? id; |
|||
final String date; |
|||
|
|||
Work({ |
|||
this.id, |
|||
required this.date, |
|||
}); |
|||
|
|||
Work copy({ |
|||
int? id, |
|||
String? date, |
|||
}) => |
|||
Work( |
|||
id: id ?? this.id, |
|||
date: date ?? this.date, |
|||
); |
|||
|
|||
factory Work.fromJson(Map<String, dynamic> json) => Work( |
|||
id: json['id'] as int?, |
|||
date: json['date'] as String, |
|||
); |
|||
|
|||
Map<String, dynamic> toJson() => { |
|||
'id': id, |
|||
'date': date, |
|||
}; |
|||
} |
|||
@ -0,0 +1,61 @@ |
|||
class Product { |
|||
final int? id; |
|||
final String name; |
|||
final double price; |
|||
String image; |
|||
final String category; |
|||
int? stock; // Paramètre optionnel pour le stock |
|||
String? description; // Nouveau champ |
|||
String? qrCode; // Nouveau champ |
|||
String? reference; |
|||
|
|||
Product({ |
|||
this.id, |
|||
required this.name, |
|||
required this.price, |
|||
required this.image, |
|||
required this.category, |
|||
this.stock = 0, |
|||
this.description, |
|||
this.qrCode, |
|||
this.reference, |
|||
}); |
|||
|
|||
// Vérifie si le stock est défini |
|||
bool isStockDefined() { |
|||
if (stock != null) { |
|||
print("stock is defined : $stock $name"); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
Map<String, dynamic> toMap() { |
|||
return { |
|||
'id': id, |
|||
'name': name, |
|||
'price': price, |
|||
'image': image, |
|||
'category': category, |
|||
'stock': stock, |
|||
'description': description, |
|||
'qrCode': qrCode, |
|||
'reference':reference |
|||
}; |
|||
} |
|||
|
|||
factory Product.fromMap(Map<String, dynamic> map) { |
|||
return Product( |
|||
id: map['id'], |
|||
name: map['name'], |
|||
price: map['price'], |
|||
image: map['image'], |
|||
category: map['category'], |
|||
stock: map['stock'], |
|||
description: map['description'], |
|||
qrCode: map['qrCode'], |
|||
reference:map['reference'] |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
class Users { |
|||
int id; |
|||
String name; |
|||
String lastName; |
|||
String email; |
|||
String password; |
|||
String username; |
|||
String role; |
|||
|
|||
Users({ |
|||
required this.id, |
|||
required this.name, |
|||
required this.lastName, |
|||
required this.email, |
|||
required this.password, |
|||
required this.username, |
|||
required this.role, |
|||
}); |
|||
|
|||
Map<String, dynamic> toMap() { |
|||
return { |
|||
'id': id, |
|||
'name': name, |
|||
'lastName': lastName, |
|||
'email': email, |
|||
'password': password, |
|||
'username': username, |
|||
'role': role, |
|||
}; |
|||
} |
|||
|
|||
factory Users.fromMap(Map<String, dynamic> map) { |
|||
return Users( |
|||
id: map['id'], |
|||
name: map['name'], |
|||
lastName: map['lastname'], |
|||
email: map['email'], |
|||
password: map['password'], |
|||
username: map['username'], |
|||
role: map['role'] |
|||
); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,285 @@ |
|||
import 'package:path/path.dart'; |
|||
import 'package:path_provider/path_provider.dart'; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart' as sqflite_ffi; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart'; |
|||
import 'package:intl/intl.dart'; |
|||
import '../Models/Order.dart'; |
|||
import 'dart:io'; |
|||
import 'package:flutter/services.dart'; |
|||
|
|||
class OrderDatabase { |
|||
static final OrderDatabase instance = OrderDatabase._init(); |
|||
late Database _database; |
|||
|
|||
OrderDatabase._init() { |
|||
sqflite_ffi.sqfliteFfiInit(); |
|||
} |
|||
|
|||
Future<void> initDatabase() async { |
|||
_database = await _initDB('orderdb.db'); |
|||
await _createDB(_database, 1); |
|||
} |
|||
|
|||
Future<Database> get database async { |
|||
if (_database.isOpen) return _database; |
|||
|
|||
_database = await _initDB('orderdb.db'); |
|||
return _database; |
|||
} |
|||
|
|||
Future<Database> _initDB(String filePath) async { |
|||
// Obtenez le répertoire de stockage local de l'application |
|||
final documentsDirectory = await getApplicationDocumentsDirectory(); |
|||
final path = join(documentsDirectory.path, filePath); |
|||
|
|||
// Vérifiez si le fichier de base de données existe déjà dans le répertoire de stockage local |
|||
bool dbExists = await File(path).exists(); |
|||
if (!dbExists) { |
|||
// Si le fichier n'existe pas, copiez-le depuis le dossier assets/database |
|||
ByteData data = await rootBundle.load('assets/database/$filePath'); |
|||
List<int> bytes = |
|||
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); |
|||
await File(path).writeAsBytes(bytes); |
|||
} |
|||
|
|||
// Ouvrez la base de données |
|||
return await databaseFactoryFfi.openDatabase(path); |
|||
} |
|||
|
|||
Future<void> _createDB(Database db, int version) async { |
|||
final resultOrders = await db.rawQuery( |
|||
"SELECT name FROM sqlite_master WHERE type='table' AND name='orders'"); |
|||
final resultOrderItems = await db.rawQuery( |
|||
"SELECT name FROM sqlite_master WHERE type='table' AND name='order_items'"); |
|||
|
|||
if (resultOrders.isEmpty) { |
|||
await db.execute(''' |
|||
CREATE TABLE orders ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|||
total_price REAL, |
|||
date_time TEXT, |
|||
start_date TEXT, |
|||
user TEXT, |
|||
) |
|||
'''); |
|||
} |
|||
|
|||
if (resultOrderItems.isEmpty) { |
|||
await db.execute(''' |
|||
CREATE TABLE order_items ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|||
order_id INTEGER, |
|||
product_name TEXT, |
|||
quantity INTEGER, |
|||
price REAL, |
|||
FOREIGN KEY (order_id) REFERENCES orders (id) |
|||
) |
|||
'''); |
|||
} |
|||
} |
|||
|
|||
Future<int> insertOrder( |
|||
double totalPrice, |
|||
String dateTime, |
|||
DateTime? startDate, |
|||
String user, |
|||
) async { |
|||
final db = await database; |
|||
final formattedStartDate = DateFormat('yyyy-MM-dd').format(startDate!); |
|||
print("formattedStartDate1 : $formattedStartDate"); |
|||
final orderId = await db.insert( |
|||
'orders', |
|||
{ |
|||
'total_price': totalPrice, |
|||
'date_time': dateTime, |
|||
'start_date': formattedStartDate, |
|||
'user': user, |
|||
}, |
|||
); |
|||
return orderId; |
|||
} |
|||
|
|||
Future<void> insertOrderItem( |
|||
int orderId, |
|||
String productName, |
|||
int quantity, |
|||
double price, |
|||
) async { |
|||
final db = await database; |
|||
await db.insert( |
|||
'order_items', |
|||
{ |
|||
'order_id': orderId, |
|||
'product_name': productName, |
|||
'quantity': quantity, |
|||
'price': price, |
|||
}, |
|||
); |
|||
} |
|||
|
|||
Future<List<Map<String, dynamic>>> getAllOrders() async { |
|||
final db = await database; |
|||
return db.query('orders'); |
|||
} |
|||
|
|||
Future<List<Order>> getOrderHistory() async { |
|||
final orderData = await getAllOrders(); |
|||
|
|||
return orderData.map((orderMap) { |
|||
return Order( |
|||
id: orderMap['id'], |
|||
totalPrice: orderMap['total_price'], |
|||
dateTime: orderMap['date_time'], |
|||
startDate: orderMap['start_date'] != null |
|||
? DateTime.parse(orderMap['start_date']) |
|||
: null, |
|||
user: orderMap['user'], |
|||
); |
|||
}).toList(); |
|||
} |
|||
|
|||
Future<List<Map<String, dynamic>>> getOrderItems(int orderId) async { |
|||
final db = await database; |
|||
return db.query( |
|||
'order_items', |
|||
where: 'order_id = ?', |
|||
whereArgs: [orderId], |
|||
); |
|||
} |
|||
|
|||
Future<List<Order>> getOrdersByStartDate(DateTime startDate) async { |
|||
final db = await database; |
|||
final formattedStartDate = DateFormat('yyyy-MM-dd').format(startDate); |
|||
print("formattedStartDate dans la base: $formattedStartDate"); |
|||
final orderData = await db.query( |
|||
'orders', |
|||
where: 'start_date = ?', |
|||
whereArgs: [formattedStartDate], |
|||
); |
|||
|
|||
return orderData.map((orderMap) { |
|||
return Order( |
|||
id: orderMap['id'] as int, |
|||
totalPrice: orderMap['total_price'] as double, |
|||
dateTime: orderMap['date_time'] as String, |
|||
startDate: orderMap['start_date'] != null |
|||
? DateTime.parse(orderMap['start_date'] as String) |
|||
: null, |
|||
user: orderMap['user'] as String, |
|||
); |
|||
}).toList(); |
|||
} |
|||
|
|||
Future<Map<String, int>> getProductQuantitiesByDate(DateTime date) async { |
|||
final db = await database; |
|||
final formattedDate = DateFormat('yyyy-MM-dd').format(date); |
|||
|
|||
final result = await db.rawQuery(''' |
|||
SELECT product_name, SUM(quantity) AS total_quantity |
|||
FROM order_items |
|||
INNER JOIN orders ON order_items.order_id = orders.id |
|||
WHERE orders.start_date = ? |
|||
GROUP BY product_name |
|||
''', [formattedDate]); |
|||
|
|||
final productQuantities = <String, int>{}; |
|||
for (final row in result) { |
|||
final productName = row['product_name'] as String; |
|||
final quantity = row['total_quantity'] as int; |
|||
productQuantities[productName] = quantity; |
|||
} |
|||
|
|||
return productQuantities; |
|||
} |
|||
|
|||
Future<Map<String, int>> getProductQuantitiesByMonth(DateTime date) async { |
|||
final db = await database; |
|||
final formattedDate = DateFormat('yyyy-MM').format(date); |
|||
|
|||
final result = await db.rawQuery(''' |
|||
SELECT product_name, SUM(quantity) AS total_quantity |
|||
FROM order_items |
|||
INNER JOIN orders ON order_items.order_id = orders.id |
|||
WHERE strftime('%Y-%m', orders.start_date) = ? |
|||
GROUP BY product_name |
|||
''', [formattedDate]); |
|||
|
|||
final productQuantities = <String, int>{}; |
|||
for (final row in result) { |
|||
final productName = row['product_name'] as String; |
|||
final quantity = row['total_quantity'] as int; |
|||
productQuantities[productName] = quantity; |
|||
} |
|||
|
|||
return productQuantities; |
|||
} |
|||
|
|||
Future<List<Order>> getOrdersByMonth(DateTime date) async { |
|||
final db = await database; |
|||
final formattedDate = DateFormat('yyyy-MM').format(date); |
|||
|
|||
final orderData = await db.rawQuery(''' |
|||
SELECT id, total_price, date_time, start_date, user |
|||
FROM orders |
|||
WHERE strftime('%Y-%m', start_date) = ? |
|||
''', [formattedDate]); |
|||
|
|||
return orderData.map((orderMap) { |
|||
return Order( |
|||
id: orderMap['id'] as int, |
|||
totalPrice: orderMap['total_price'] as double, |
|||
dateTime: orderMap['date_time'] as String, |
|||
startDate: orderMap['start_date'] != null |
|||
? DateTime.parse(orderMap['start_date'] as String) |
|||
: null, |
|||
user: orderMap['user'] as String, |
|||
); |
|||
}).toList(); |
|||
} |
|||
|
|||
// maintenant je vais recuperer les commande par semaine en utilisant les semaines de l'année |
|||
Future<List<Order>> getOrdersByWeekNumber(int weekNumber) async { |
|||
final db = await database; |
|||
|
|||
final orderData = await db.rawQuery(''' |
|||
SELECT id, total_price, date_time, start_date |
|||
FROM orders |
|||
WHERE strftime('%W', start_date) = ? |
|||
''', [(weekNumber - 1).toString()]); |
|||
|
|||
return orderData.map((orderMap) { |
|||
return Order( |
|||
id: orderMap['id'] as int, |
|||
totalPrice: orderMap['total_price'] as double, |
|||
dateTime: orderMap['date_time'] as String, |
|||
startDate: orderMap['start_date'] != null |
|||
? DateTime.parse(orderMap['start_date'] as String) |
|||
: null, |
|||
user: orderMap['user'] as String, |
|||
); |
|||
}).toList(); |
|||
} |
|||
|
|||
Future<List<Order>> getOrdersByYear(DateTime date) async { |
|||
final db = await database; |
|||
final formattedDate = DateFormat('yyyy').format(date); |
|||
|
|||
final orderData = await db.rawQuery(''' |
|||
SELECT id, total_price, date_time, start_date |
|||
FROM orders |
|||
WHERE strftime('%Y', start_date) = ? |
|||
''', [formattedDate]); |
|||
|
|||
return orderData.map((orderMap) { |
|||
return Order( |
|||
id: orderMap['id'] as int, |
|||
totalPrice: orderMap['total_price'] as double, |
|||
dateTime: orderMap['date_time'] as String, |
|||
startDate: orderMap['start_date'] != null |
|||
? DateTime.parse(orderMap['start_date'] as String) |
|||
: null, |
|||
user: orderMap['user'] as String, |
|||
); |
|||
}).toList(); |
|||
} |
|||
} |
|||
@ -0,0 +1,147 @@ |
|||
import 'package:flutter/services.dart'; |
|||
import 'package:path/path.dart'; |
|||
import 'package:path_provider/path_provider.dart'; |
|||
import 'package:sqflite/sqflite.dart'; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart' as sqflite_ffi; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart'; |
|||
import 'package:youmazgestion/Models/users.dart'; |
|||
import 'dart:io'; |
|||
|
|||
class AuthDatabase { |
|||
static final AuthDatabase instance = AuthDatabase._init(); |
|||
late Database _database; |
|||
|
|||
AuthDatabase._init() { |
|||
sqflite_ffi.sqfliteFfiInit(); |
|||
} |
|||
|
|||
Future<void> initDatabase() async { |
|||
_database = await _initDB('usersDb.db'); |
|||
await _createDB(_database, 1); |
|||
} |
|||
|
|||
Future<Database> get database async { |
|||
if (_database.isOpen) return _database; |
|||
|
|||
_database = await _initDB('usersDb.db'); |
|||
return _database; |
|||
} |
|||
|
|||
Future<Database> _initDB(String filePath) async { |
|||
// Obtenez le répertoire de stockage local de l'application |
|||
final documentsDirectory = await getApplicationDocumentsDirectory(); |
|||
final path = join(documentsDirectory.path, filePath); |
|||
|
|||
// Vérifiez si le fichier de base de données existe déjà dans le répertoire de stockage local |
|||
bool dbExists = await File(path).exists(); |
|||
if (!dbExists) { |
|||
// Si le fichier n'existe pas, copiez-le depuis le dossier assets/database |
|||
ByteData data = await rootBundle.load('assets/database/$filePath'); |
|||
List<int> bytes = |
|||
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); |
|||
await File(path).writeAsBytes(bytes); |
|||
} |
|||
|
|||
// Ouvrez la base de données |
|||
return await databaseFactoryFfi.openDatabase(path); |
|||
} |
|||
|
|||
Future<void> _createDB(Database db, int version) async { |
|||
final resultUsers = await db.rawQuery( |
|||
"SELECT name FROM sqlite_master WHERE type='table' AND name='users'"); |
|||
|
|||
if (resultUsers.isEmpty) { |
|||
await db.execute(''' |
|||
CREATE TABLE users ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|||
name TEXT, |
|||
lastname TEXT, |
|||
email TEXT, |
|||
password TEXT, |
|||
username TEXT, |
|||
role TEXT |
|||
) |
|||
'''); |
|||
} |
|||
} |
|||
|
|||
Future<int> createUser(Users user) async { |
|||
final db = await database; |
|||
return await db.insert('users', user.toMap()); |
|||
} |
|||
|
|||
Future<int> deleteUser(int id) async { |
|||
final db = await database; |
|||
return await db.delete('users', where: 'id = ?', whereArgs: [id]); |
|||
} |
|||
|
|||
Future<int> updateUser(Users user) async { |
|||
final db = await database; |
|||
return await db |
|||
.update('users', user.toMap(), where: 'id = ?', whereArgs: [user.id]); |
|||
} |
|||
|
|||
Future<int> getUserCount() async { |
|||
final db = await database; |
|||
List<Map<String, dynamic>> x = |
|||
await db.rawQuery('SELECT COUNT (*) from users'); |
|||
int result = Sqflite.firstIntValue(x)!; |
|||
return result; |
|||
} |
|||
|
|||
// verify username and password existe |
|||
Future<bool> verifyUser(String username, String password) async { |
|||
final db = await database; |
|||
List<Map<String, dynamic>> x = await db.rawQuery( |
|||
'SELECT COUNT (*) from users WHERE username = ? AND password = ?', |
|||
[username, password]); |
|||
int result = Sqflite.firstIntValue(x)!; |
|||
if (result == 1) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
//recuperer un user grace a son username |
|||
Future<Users> getUser(String username) async { |
|||
try { |
|||
final db = await database; |
|||
List<Map<String, dynamic>> x = await db |
|||
.rawQuery('SELECT * from users WHERE username = ?', [username]); |
|||
print(x.first); |
|||
Users user = Users.fromMap(x.first); |
|||
print(user); |
|||
return user; |
|||
} catch (e) { |
|||
print(e); |
|||
rethrow; |
|||
} |
|||
} |
|||
|
|||
Future<Map<String, String>?> getUserCredentials(String username, String password) async { |
|||
final db = await database; |
|||
|
|||
List<Map<String, dynamic>> result = await db.rawQuery( |
|||
'SELECT username, role FROM users WHERE username = ? AND password = ?', |
|||
[username, password], |
|||
); |
|||
|
|||
if (result.isNotEmpty) { |
|||
print('username '+result[0]['username']); |
|||
return { |
|||
'username': result[0]['username'], |
|||
'role': result[0]['role'], |
|||
}; |
|||
} else { |
|||
return null; // Aucun utilisateur trouvé |
|||
} |
|||
} |
|||
|
|||
Future<List<Users>> getAllUsers() async { |
|||
final db = await database; |
|||
const orderBy = 'id ASC'; |
|||
final result = await db.query('users', orderBy: orderBy); |
|||
return result.map((json) => Users.fromMap(json)).toList(); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
import 'dart:convert'; |
|||
import 'package:shelf/shelf.dart'; |
|||
import 'package:shelf_router/shelf_router.dart'; |
|||
import 'OrderDatabase.dart'; |
|||
|
|||
class OrderApi { |
|||
final Router _router = Router(); |
|||
late OrderDatabase _orderDatabase; |
|||
|
|||
OrderApi() { |
|||
_orderDatabase = OrderDatabase.instance; |
|||
_router.get('/orders', _getAllOrders); |
|||
// Ajoutez d'autres routes nécessaires |
|||
} |
|||
|
|||
Router get router => _router; |
|||
|
|||
Future<Response> _getAllOrders(Request request) async { |
|||
await _orderDatabase.initDatabase(); |
|||
final orders = await _orderDatabase.getAllOrders(); |
|||
|
|||
final ordersJson = jsonEncode(orders); |
|||
|
|||
return Response.ok(ordersJson, |
|||
headers: {'content-type': 'application/json'}); |
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
import 'dart:async'; |
|||
import 'dart:io'; |
|||
import 'package:flutter/services.dart'; |
|||
import 'package:path/path.dart'; |
|||
import 'package:path_provider/path_provider.dart'; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart'; |
|||
import '../Models/produit.dart'; |
|||
|
|||
class ProductDatabase { |
|||
static final ProductDatabase instance = ProductDatabase._init(); |
|||
late Database _database; |
|||
|
|||
ProductDatabase._init() { |
|||
sqfliteFfiInit(); |
|||
} |
|||
|
|||
ProductDatabase(); |
|||
|
|||
Future<Database> get database async { |
|||
if (_database.isOpen) return _database; |
|||
_database = await _initDB('products2.db'); |
|||
return _database; |
|||
} |
|||
|
|||
Future<void> initDatabase() async { |
|||
_database = await _initDB('products2.db'); |
|||
await _createDB(_database, 1); |
|||
} |
|||
|
|||
Future<Database> _initDB(String filePath) async { |
|||
final documentsDirectory = await getApplicationDocumentsDirectory(); |
|||
final path = join(documentsDirectory.path, filePath); |
|||
|
|||
bool dbExists = await File(path).exists(); |
|||
if (!dbExists) { |
|||
ByteData data = await rootBundle.load('assets/database/$filePath'); |
|||
List<int> bytes = |
|||
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); |
|||
await File(path).writeAsBytes(bytes); |
|||
} |
|||
|
|||
return await databaseFactoryFfi.openDatabase(path); |
|||
} |
|||
|
|||
Future<void> _createDB(Database db, int version) async { |
|||
// Récupère la liste des colonnes de la table "products" |
|||
final tables = await db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'"); |
|||
final tableNames = tables.map((row) => row['name'] as String).toList(); |
|||
|
|||
// Si la table "products" n'existe pas encore, on la crée entièrement |
|||
if (!tableNames.contains('products')) { |
|||
await db.execute(''' |
|||
CREATE TABLE products( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|||
name TEXT, |
|||
price REAL, |
|||
image TEXT, |
|||
category TEXT, |
|||
stock INTEGER, |
|||
description TEXT, |
|||
qrCode TEXT |
|||
reference TEXT |
|||
) |
|||
'''); |
|||
print("Table 'products' créée avec toutes les colonnes."); |
|||
} else { |
|||
// Vérifie si les colonnes "description" et "qrCode" existent déjà |
|||
final columns = await db.rawQuery('PRAGMA table_info(products)'); |
|||
final columnNames = columns.map((e) => e['name'] as String).toList(); |
|||
|
|||
// Ajoute la colonne "description" si elle n'existe pas |
|||
if (!columnNames.contains('description')) { |
|||
try { |
|||
await db.execute("ALTER TABLE products ADD COLUMN description TEXT"); |
|||
print("Colonne 'description' ajoutée."); |
|||
} catch (e) { |
|||
print("Erreur ajout colonne description : $e"); |
|||
} |
|||
} |
|||
|
|||
// Ajoute la colonne "qrCode" si elle n'existe pas |
|||
if (!columnNames.contains('qrCode')) { |
|||
try { |
|||
await db.execute("ALTER TABLE products ADD COLUMN qrCode TEXT"); |
|||
print("Colonne 'qrCode' ajoutée."); |
|||
} catch (e) { |
|||
print("Erreur ajout colonne qrCode : $e"); |
|||
} |
|||
} |
|||
// Ajoute la colonne "reference" si elle n'existe pas |
|||
if (!columnNames.contains('reference')) { |
|||
try { |
|||
await db.execute("ALTER TABLE products ADD COLUMN reference TEXT"); |
|||
print("Colonne 'reference' ajoutée."); |
|||
} catch (e) { |
|||
print("Erreur ajout colonne reference : $e"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
Future<int> createProduct(Product product) async { |
|||
final db = await database; |
|||
return await db.insert('products', product.toMap()); |
|||
} |
|||
|
|||
Future<List<Product>> getProducts() async { |
|||
final db = await database; |
|||
final maps = await db.query('products'); |
|||
return List.generate(maps.length, (i) { |
|||
return Product.fromMap(maps[i]); |
|||
}); |
|||
} |
|||
|
|||
Future<int> updateProduct(Product product) async { |
|||
final db = await database; |
|||
return await db.update( |
|||
'products', |
|||
product.toMap(), |
|||
where: 'id = ?', |
|||
whereArgs: [product.id], |
|||
); |
|||
} |
|||
|
|||
Future<int> deleteProduct(int? id) async { |
|||
final db = await database; |
|||
return await db.delete( |
|||
'products', |
|||
where: 'id = ?', |
|||
whereArgs: [id], |
|||
); |
|||
} |
|||
|
|||
Future<List<String>> getCategories() async { |
|||
final db = await database; |
|||
final result = await db.rawQuery('SELECT DISTINCT category FROM products'); |
|||
return List.generate( |
|||
result.length, (index) => result[index]['category'] as String); |
|||
} |
|||
|
|||
Future<List<Product>> getProductsByCategory(String category) async { |
|||
final db = await database; |
|||
final maps = await db |
|||
.query('products', where: 'category = ?', whereArgs: [category]); |
|||
return List.generate(maps.length, (i) { |
|||
return Product.fromMap(maps[i]); |
|||
}); |
|||
} |
|||
|
|||
Future<int> updateStock(int id, int stock) async { |
|||
final db = await database; |
|||
return await db |
|||
.rawUpdate('UPDATE products SET stock = ? WHERE id = ?', [stock, id]); |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
import 'dart:io'; |
|||
|
|||
import 'package:flutter/services.dart'; |
|||
import 'package:path/path.dart'; |
|||
import 'package:path_provider/path_provider.dart'; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart' as sqflite_ffi; |
|||
import 'package:sqflite_common_ffi/sqflite_ffi.dart'; |
|||
|
|||
class WorkDatabase { |
|||
static final WorkDatabase instance = WorkDatabase._init(); |
|||
late Database _database; |
|||
|
|||
WorkDatabase._init() { |
|||
sqflite_ffi.sqfliteFfiInit(); |
|||
} |
|||
|
|||
Future<void> initDatabase() async { |
|||
_database = await _initDB('work.db'); |
|||
await _createDB(_database, 1); |
|||
} |
|||
|
|||
Future<Database> get database async { |
|||
if (_database.isOpen) return _database; |
|||
|
|||
_database = await _initDB('work.db'); |
|||
return _database; |
|||
} |
|||
|
|||
Future<Database> _initDB(String filePath) async { |
|||
// Obtenez le répertoire de stockage local de l'application |
|||
final documentsDirectory = await getApplicationDocumentsDirectory(); |
|||
final path = join(documentsDirectory.path, filePath); |
|||
|
|||
// Vérifiez si le fichier de base de données existe déjà dans le répertoire de stockage local |
|||
bool dbExists = await File(path).exists(); |
|||
if (!dbExists) { |
|||
// Si le fichier n'existe pas, copiez-le depuis le dossier assets/database |
|||
ByteData data = await rootBundle.load('assets/database/$filePath'); |
|||
List<int> bytes = |
|||
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); |
|||
await File(path).writeAsBytes(bytes); |
|||
} |
|||
|
|||
// Ouvrez la base de données |
|||
return await databaseFactoryFfi.openDatabase(path); |
|||
} |
|||
|
|||
Future<void> _createDB(Database db, int version) async { |
|||
await db.execute(''' |
|||
CREATE TABLE IF NOT EXISTS work ( |
|||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|||
date TEXT |
|||
) |
|||
'''); |
|||
} |
|||
|
|||
Future<int> insertDate(String date) async { |
|||
final db = await database; |
|||
final existingDates = |
|||
await db.query('work', where: 'date = ?', whereArgs: [date]); |
|||
|
|||
if (existingDates.isNotEmpty) { |
|||
// Date already exists, return 0 to indicate no new insertion |
|||
return 0; |
|||
} |
|||
|
|||
return await db.insert('work', {'date': date}); |
|||
} |
|||
|
|||
/*Future<List<Work>> getDates() async { |
|||
final db = await database; |
|||
final result = await db.query('work'); |
|||
|
|||
return result.map((json) => Work.fromJson(json)).toList(); |
|||
}*/ |
|||
Future<List<String>> getDates() async { |
|||
final db = await database; |
|||
final result = await db.query('work'); |
|||
return List.generate( |
|||
result.length, (index) => result[index]['date'] as String); |
|||
} |
|||
|
|||
// recuperer les dates par ordre du plus recent au plus ancien |
|||
Future<List<String>> getDatesDesc() async { |
|||
final db = await database; |
|||
final result = await db.query('work', orderBy: 'date DESC'); |
|||
return List.generate( |
|||
result.length, (index) => result[index]['date'] as String); |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
import 'package:flutter/material.dart'; |
|||
|
|||
class DemarrerCaissePage extends StatelessWidget { |
|||
const DemarrerCaissePage({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: const Text('Accueil'), |
|||
), |
|||
body: Center( |
|||
child: ElevatedButton( |
|||
onPressed: () { |
|||
// Mettre à jour la valeur de isRegisterOpen dans le HomeController |
|||
}, |
|||
child: const Text('Démarrer la caisse'), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
import 'package:flutter/material.dart'; |
|||
|
|||
class ErreurPage extends StatelessWidget { |
|||
final String dbPath; |
|||
|
|||
const ErreurPage({Key? key, required this.dbPath}) : super(key: key); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
backgroundColor: Colors.white, |
|||
appBar: AppBar( |
|||
title: const Text('Erreur'), |
|||
), |
|||
body: Center( |
|||
child: Text('Base de données introuvable : $dbPath'), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,325 @@ |
|||
import 'dart:io'; |
|||
import 'dart:ui'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:file_picker/file_picker.dart'; |
|||
import 'package:path_provider/path_provider.dart'; |
|||
import 'package:qr_flutter/qr_flutter.dart'; |
|||
|
|||
import '../Components/appDrawer.dart'; |
|||
import '../Components/app_bar.dart'; |
|||
import '../Models/produit.dart'; |
|||
import '../Services/productDatabase.dart'; |
|||
|
|||
class AddProductPage extends StatefulWidget { |
|||
const AddProductPage({super.key}); |
|||
|
|||
@override |
|||
_AddProductPageState createState() => _AddProductPageState(); |
|||
} |
|||
|
|||
class _AddProductPageState extends State<AddProductPage> { |
|||
// Controllers for text fields |
|||
final TextEditingController _nameController = TextEditingController(); |
|||
final TextEditingController _priceController = TextEditingController(); |
|||
final TextEditingController _imageController = TextEditingController(); |
|||
final TextEditingController _descriptionController = TextEditingController(); |
|||
|
|||
String? _qrData; // Variable to store QR code data |
|||
final List<String> _categories = ['Sucré', 'Salé', 'Jus', 'Gateaux']; // List of product categories |
|||
String? _selectedCategory; // Selected category |
|||
File? _pickedImage; // Variable to store the selected image file |
|||
late ProductDatabase _productDatabase; // Database instance |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
_productDatabase = ProductDatabase.instance; |
|||
_productDatabase.initDatabase(); |
|||
_nameController.addListener(_updateQrData); |
|||
} |
|||
|
|||
@override |
|||
void dispose() { |
|||
_nameController.removeListener(_updateQrData); |
|||
_nameController.dispose(); |
|||
super.dispose(); |
|||
} |
|||
|
|||
// Function to select an image from files or drop |
|||
void _selectImage() async { |
|||
final action = await showDialog( |
|||
context: context, |
|||
builder: (BuildContext context) { |
|||
return AlertDialog( |
|||
title: const Text('Sélectionner une image'), |
|||
content: const Text('Choisissez comment sélectionner une image'), |
|||
actions: [ |
|||
TextButton( |
|||
onPressed: () { |
|||
Navigator.of(context).pop('pick'); |
|||
}, |
|||
child: const Text('Choisir depuis les fichiers'), |
|||
), |
|||
TextButton( |
|||
onPressed: () { |
|||
Navigator.of(context).pop('drop'); |
|||
}, |
|||
child: const Text('Déposer une image'), |
|||
), |
|||
], |
|||
); |
|||
}, |
|||
); |
|||
|
|||
if (action == 'pick') { |
|||
final result = await FilePicker.platform.pickFiles( |
|||
type: FileType.image, |
|||
); |
|||
|
|||
if (result != null) { |
|||
setState(() { |
|||
_pickedImage = File(result.files.single.path!); |
|||
_imageController.text = _pickedImage!.path; |
|||
}); |
|||
} |
|||
} else if (action == 'drop') { |
|||
// Code to handle image drop |
|||
} |
|||
} |
|||
|
|||
// Function to update QR data based on product name |
|||
void _updateQrData() { |
|||
if (_nameController.text.isNotEmpty) { |
|||
final reference = 'PROD_PREVIEW_${_nameController.text}_${DateTime.now().millisecondsSinceEpoch}'; |
|||
setState(() { |
|||
_qrData = 'https://tonsite.com/$reference'; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
// Function to get the database location |
|||
Future<void> _getDatabaseLocation() async { |
|||
final directory = await getApplicationDocumentsDirectory(); |
|||
final dbPath = directory.path; |
|||
print('Emplacement de la base de données : $dbPath'); |
|||
} |
|||
|
|||
// Function to generate and save QR code |
|||
Future<String> _generateAndSaveQRCode(String reference) async { |
|||
final qrValidationResult = QrValidator.validate( |
|||
data: 'https://tonsite.com/$reference', |
|||
version: QrVersions.auto, |
|||
errorCorrectionLevel: QrErrorCorrectLevel.L, |
|||
); |
|||
final qrCode = qrValidationResult.qrCode; |
|||
final painter = QrPainter.withQr( |
|||
qr: qrCode!, |
|||
color: Colors.black, |
|||
emptyColor: Colors.white, |
|||
gapless: true, |
|||
); |
|||
|
|||
final tempDir = await getApplicationDocumentsDirectory(); |
|||
final file = File('${tempDir.path}/$reference.png'); |
|||
final picData = await painter.toImageData(2048, format: ImageByteFormat.png); |
|||
await file.writeAsBytes(picData!.buffer.asUint8List()); |
|||
|
|||
return file.path; |
|||
} |
|||
|
|||
// Function to add a product to the database |
|||
void _addProduct() async { |
|||
final name = _nameController.text; |
|||
final price = double.tryParse(_priceController.text) ?? 0.0; |
|||
final image = _imageController.text; |
|||
final category = _selectedCategory; |
|||
final description = _descriptionController.text; |
|||
|
|||
if (name.isNotEmpty && price > 0 && image.isNotEmpty && category != null) { |
|||
final reference = 'PROD_${DateTime.now().millisecondsSinceEpoch}'; |
|||
final qrPath = await _generateAndSaveQRCode(reference); |
|||
|
|||
final product = Product( |
|||
name: name, |
|||
price: price, |
|||
image: image, |
|||
category: category, |
|||
description: description, |
|||
qrCode: qrPath, |
|||
reference: reference, |
|||
); |
|||
|
|||
_productDatabase.createProduct(product).then((_) { |
|||
Get.snackbar('Succès', 'Produit ajouté avec succès'); |
|||
setState(() { |
|||
_nameController.clear(); |
|||
_priceController.clear(); |
|||
_imageController.clear(); |
|||
_descriptionController.clear(); |
|||
_selectedCategory = null; |
|||
_pickedImage = null; |
|||
}); |
|||
}).catchError((error) { |
|||
Get.snackbar('Erreur', 'Impossible d\'ajouter le produit : $error'); |
|||
}); |
|||
} else { |
|||
Get.snackbar( |
|||
'Saisie invalide', |
|||
'Veuillez entrer tous les champs requis.', |
|||
); |
|||
} |
|||
} |
|||
|
|||
// Function to display the selected image |
|||
Widget _displayImage() { |
|||
if (_pickedImage != null) { |
|||
return ClipRRect( |
|||
borderRadius: BorderRadius.circular(8.0), |
|||
child: Image.file( |
|||
_pickedImage!, |
|||
width: 100, |
|||
height: 100, |
|||
fit: BoxFit.cover, |
|||
), |
|||
); |
|||
} else { |
|||
return Stack( |
|||
alignment: Alignment.center, |
|||
children: [ |
|||
Container( |
|||
width: 100, |
|||
height: 100, |
|||
decoration: BoxDecoration( |
|||
color: Colors.grey[200], |
|||
borderRadius: BorderRadius.circular(8.0), |
|||
), |
|||
), |
|||
Icon( |
|||
Icons.image, |
|||
size: 48, |
|||
color: Colors.grey[400], |
|||
), |
|||
Positioned( |
|||
bottom: 4, |
|||
child: Text( |
|||
'Aucune image', |
|||
style: TextStyle( |
|||
fontSize: 12, |
|||
color: Colors.grey[400], |
|||
), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Ajouter un produit'), |
|||
drawer: CustomDrawer(), |
|||
body: Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
children: [ |
|||
const Text( |
|||
'Ajouter un produit', |
|||
style: TextStyle( |
|||
fontSize: 24, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
const SizedBox(height: 16), |
|||
TextField( |
|||
controller: _nameController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Nom du produit', |
|||
border: OutlineInputBorder(), |
|||
), |
|||
), |
|||
const SizedBox(height: 16), |
|||
TextField( |
|||
controller: _priceController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Prix', |
|||
border: OutlineInputBorder(), |
|||
), |
|||
keyboardType: const TextInputType.numberWithOptions(decimal: true), |
|||
), |
|||
const SizedBox(height: 16), |
|||
Row( |
|||
crossAxisAlignment: CrossAxisAlignment.end, |
|||
children: [ |
|||
Expanded( |
|||
child: TextField( |
|||
controller: _imageController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Image', |
|||
border: OutlineInputBorder(), |
|||
), |
|||
), |
|||
), |
|||
const SizedBox(width: 8), |
|||
ElevatedButton( |
|||
onPressed: _selectImage, |
|||
child: const Text('Sélectionner une image'), |
|||
), |
|||
], |
|||
), |
|||
const SizedBox(height: 16), |
|||
_displayImage(), |
|||
const SizedBox(height: 16), |
|||
DropdownButtonFormField<String>( |
|||
value: _selectedCategory, |
|||
onChanged: (newValue) { |
|||
setState(() { |
|||
_selectedCategory = newValue; |
|||
}); |
|||
}, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Catégorie', |
|||
border: OutlineInputBorder(), |
|||
), |
|||
items: _categories.map((category) { |
|||
return DropdownMenuItem<String>( |
|||
value: category, |
|||
child: Text(category), |
|||
); |
|||
}).toList(), |
|||
), |
|||
const SizedBox(height: 16), |
|||
if (_qrData != null) |
|||
Column( |
|||
children: [ |
|||
const SizedBox(height: 16), |
|||
const Text('Aperçu du QR Code :'), |
|||
QrImageView( |
|||
data: _qrData!, |
|||
version: QrVersions.auto, |
|||
size: 120.0, |
|||
), |
|||
], |
|||
), |
|||
const SizedBox(height: 16), |
|||
TextField( |
|||
controller: _descriptionController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Description', |
|||
border: OutlineInputBorder(), |
|||
), |
|||
maxLines: 3, |
|||
), |
|||
const SizedBox(height: 16), |
|||
ElevatedButton( |
|||
onPressed: _addProduct, |
|||
child: const Text('Ajouter le produit'), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:intl/intl.dart'; |
|||
import 'listCommandeHistory.dart'; |
|||
|
|||
class BilanDesJourne extends StatelessWidget { |
|||
final DateTime selectedDate; |
|||
|
|||
const BilanDesJourne({super.key, required this.selectedDate}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: const Text('Bilan des Journées'), |
|||
), |
|||
body: Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
const Text( |
|||
'Jours du mois', |
|||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), |
|||
), |
|||
const SizedBox(height: 10), |
|||
Expanded( |
|||
child: ListView.builder( |
|||
itemCount: |
|||
DateTime(selectedDate.year, selectedDate.month + 1, 0).day, |
|||
itemBuilder: (context, index) { |
|||
final day = index + 1; |
|||
final date = |
|||
DateTime(selectedDate.year, selectedDate.month, day); |
|||
final formattedDate = |
|||
'${date.day}-${date.month}-${date.year}'; |
|||
|
|||
return ListTile( |
|||
title: Text( |
|||
'Jour $day', |
|||
style: const TextStyle( |
|||
fontWeight: FontWeight.bold, fontSize: 18), |
|||
), |
|||
subtitle: Text(formattedDate, |
|||
style: const TextStyle(fontSize: 16)), |
|||
onTap: () { |
|||
// Handle the day selection |
|||
// You can navigate to a specific page or perform any action |
|||
navigateToDetailPage(date.toString()); |
|||
}, |
|||
); |
|||
}, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
void navigateToDetailPage(String selectedDate) { |
|||
DateTime parsedDate = DateFormat('yyyy-MM-dd').parse(selectedDate); |
|||
Get.to(() => HistoryDetailPage(selectedDate: parsedDate)); |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:youmazgestion/Components/app_bar.dart'; |
|||
import 'package:youmazgestion/controller/HistoryController.dart'; |
|||
|
|||
import 'bilanDesJourne.dart'; |
|||
|
|||
class BilanMois extends StatefulWidget { |
|||
const BilanMois({super.key}); |
|||
|
|||
@override |
|||
_BilanMoisState createState() => _BilanMoisState(); |
|||
} |
|||
|
|||
class _BilanMoisState extends State<BilanMois> { |
|||
final HistoryController controller = Get.put(HistoryController()); |
|||
DateTime selectedDate = DateTime.now(); |
|||
|
|||
void refreshData(DateTime selectedDate) { |
|||
setState(() { |
|||
this.selectedDate = selectedDate; |
|||
controller.refreshOrders(); |
|||
controller.getTotalSumOrdersByMonth(selectedDate); |
|||
controller.getOrderCountByMonth(selectedDate); |
|||
controller.getProductQuantitiesByMonth(selectedDate); |
|||
}); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Bilan du mois'), |
|||
body: Column( |
|||
children: [ |
|||
// Les 3 cartes en haut |
|||
Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
|||
children: [ |
|||
_buildInfoCard( |
|||
title: 'Chiffre réalisé', |
|||
value: '${controller.totalSum.value.toStringAsFixed(2)} fcfa', |
|||
color: Colors.green, |
|||
icon: Icons.monetization_on, |
|||
), |
|||
_buildInfoCard( |
|||
title: 'Total de commandes', |
|||
value: controller.orderQuantity.value.toString(), |
|||
color: Colors.orange, |
|||
icon: Icons.shopping_cart, |
|||
), |
|||
ElevatedButton( |
|||
onPressed: () { |
|||
// Redirect to BilanDesJourne page |
|||
Get.to(BilanDesJourne(selectedDate: selectedDate)); |
|||
}, |
|||
child: const Text('Voir les jours'), |
|||
), |
|||
], |
|||
), |
|||
// La zone déroulante |
|||
Expanded( |
|||
child: Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: SingleChildScrollView( |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.center, |
|||
children: [ |
|||
const Text( |
|||
'Detail produit :', |
|||
style: |
|||
TextStyle(fontSize: 24, fontWeight: FontWeight.bold), |
|||
), |
|||
const SizedBox(height: 10), |
|||
SizedBox( |
|||
height: MediaQuery.of(context).size.height * 0.5, |
|||
width: MediaQuery.of(context).size.width * 0.9, |
|||
child: FutureBuilder<Map<String, int>>( |
|||
future: controller |
|||
.getProductQuantitiesByMonth(selectedDate), |
|||
builder: (context, snapshot) { |
|||
if (snapshot.connectionState == |
|||
ConnectionState.waiting) { |
|||
return const Center( |
|||
child: CircularProgressIndicator()); |
|||
} else if (snapshot.hasError) { |
|||
return const Text( |
|||
'Erreur lors de la récupération des quantités de produits'); |
|||
} else { |
|||
final quantities = snapshot.data!; |
|||
return Column( |
|||
children: [ |
|||
const SizedBox(height: 20), |
|||
Expanded( |
|||
child: ListView.builder( |
|||
itemCount: quantities.length, |
|||
itemBuilder: (context, index) { |
|||
final entry = |
|||
quantities.entries.elementAt(index); |
|||
return ListTile( |
|||
leading: |
|||
const Icon(Icons.shopping_cart), |
|||
title: Text( |
|||
entry.key, |
|||
style: const TextStyle( |
|||
fontWeight: FontWeight.bold, |
|||
fontSize: 18), |
|||
), |
|||
subtitle: Text( |
|||
'Quantité : ${entry.value}', |
|||
style: |
|||
const TextStyle(fontSize: 16)), |
|||
); |
|||
}, |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
}, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
), |
|||
), |
|||
], |
|||
), |
|||
floatingActionButton: FloatingActionButton( |
|||
onPressed: () => refreshData(selectedDate), |
|||
backgroundColor: Colors.deepOrange, |
|||
focusColor: Colors.deepOrangeAccent, |
|||
hoverColor: Colors.deepOrangeAccent, |
|||
child: const Icon(Icons.refresh), |
|||
), |
|||
persistentFooterButtons: [ |
|||
TextButton( |
|||
onPressed: () async { |
|||
final DateTime? pickedDate = await showDatePicker( |
|||
context: context, |
|||
initialDate: selectedDate, |
|||
firstDate: DateTime(DateTime.now().year - 5), |
|||
lastDate: DateTime(DateTime.now().year + 5), |
|||
); |
|||
if (pickedDate != null) { |
|||
refreshData(pickedDate); |
|||
} |
|||
}, |
|||
child: const Text( |
|||
'Changer la date', |
|||
style: TextStyle(fontSize: 16), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
|
|||
Widget _buildInfoCard({ |
|||
required String title, |
|||
required String value, |
|||
required Color color, |
|||
required IconData icon, |
|||
}) { |
|||
return Card( |
|||
child: Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: Column( |
|||
children: [ |
|||
Icon( |
|||
icon, |
|||
size: 40, |
|||
color: color, |
|||
), |
|||
const SizedBox(height: 10), |
|||
Text( |
|||
title, |
|||
style: const TextStyle(fontSize: 18), |
|||
), |
|||
const SizedBox(height: 10), |
|||
Text( |
|||
value, |
|||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"model": "generic", |
|||
"type": "network", |
|||
"width": 48, |
|||
"cutter": true |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
import '../Models/Order.dart'; |
|||
import '../controller/HistoryController.dart'; |
|||
|
|||
class DetailPage extends StatelessWidget { |
|||
final Order order; |
|||
final HistoryController historyController = Get.find<HistoryController>(); |
|||
|
|||
DetailPage({super.key, required this.order}) { |
|||
historyController.fetchOrderItems(order.id); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: Text('Détails de la commande #${order.id}'), |
|||
), |
|||
body: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
Text( |
|||
'Total: ${order.totalPrice}', |
|||
style: const TextStyle( |
|||
fontSize: 18.0, |
|||
fontWeight: FontWeight.bold, |
|||
color: Colors.blue, |
|||
), |
|||
), |
|||
const SizedBox(height: 8.0), |
|||
Text( |
|||
'Date: ${order.dateTime}', |
|||
style: const TextStyle( |
|||
fontSize: 16.0, |
|||
color: Colors.grey, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
Divider( |
|||
thickness: 1.0, |
|||
color: Colors.grey[300], |
|||
), |
|||
const SizedBox(height: 16), |
|||
Obx( |
|||
() => historyController.orderItems.isEmpty |
|||
? const Center( |
|||
child: Text( |
|||
'Aucun article trouvé', |
|||
style: TextStyle( |
|||
fontSize: 16.0, |
|||
fontWeight: FontWeight.bold, |
|||
color: Colors.red, |
|||
), |
|||
), |
|||
) |
|||
: ListView.builder( |
|||
shrinkWrap: true, |
|||
itemCount: historyController.orderItems.length, |
|||
itemBuilder: (context, index) { |
|||
final item = historyController.orderItems[index]; |
|||
|
|||
return Card( |
|||
elevation: 2.0, |
|||
margin: const EdgeInsets.symmetric( |
|||
horizontal: 16.0, |
|||
vertical: 8.0, |
|||
), |
|||
color: Colors.white, |
|||
child: ListTile( |
|||
leading: const Icon( |
|||
Icons.add_shopping_cart_rounded, |
|||
color: Colors.green, |
|||
), |
|||
title: Text( |
|||
item['product_name'], |
|||
style: const TextStyle( |
|||
fontWeight: FontWeight.bold, |
|||
color: Colors.black, |
|||
), |
|||
), |
|||
subtitle: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
Text( |
|||
'Quantité: ${item['quantity']}', |
|||
style: const TextStyle( |
|||
color: Colors.grey, |
|||
), |
|||
), |
|||
Text( |
|||
'Prix: ${item['price']}', |
|||
style: const TextStyle( |
|||
color: Colors.grey, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
}, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
import '../Models/produit.dart'; |
|||
import '../Services/productDatabase.dart'; |
|||
import 'gestionProduct.dart'; |
|||
|
|||
class EditProductPage extends StatelessWidget { |
|||
final Product product; |
|||
final TextEditingController _nameController; |
|||
final TextEditingController _priceController; |
|||
final TextEditingController _categoryController; |
|||
|
|||
EditProductPage({super.key, required this.product}) |
|||
: _nameController = TextEditingController(text: product.name), |
|||
_priceController = |
|||
TextEditingController(text: product.price.toString()), |
|||
_categoryController = TextEditingController(text: product.category); |
|||
|
|||
void _saveChanges() async { |
|||
final name = _nameController.text; |
|||
final price = double.tryParse(_priceController.text) ?? 0.0; |
|||
final category = _categoryController.text; |
|||
|
|||
if (name.isNotEmpty && price > 0) { |
|||
final updatedProduct = Product( |
|||
id: product.id, |
|||
name: name, |
|||
price: price, |
|||
image: product.image, |
|||
category: category, |
|||
); |
|||
|
|||
await ProductDatabase.instance.updateProduct(updatedProduct); |
|||
|
|||
Get.to(GestionProduit()); |
|||
} else { |
|||
Get.snackbar( |
|||
'Entrée invalide', |
|||
'Veuillez entrer un nom et un prix valides', |
|||
snackPosition: SnackPosition.BOTTOM, |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
); |
|||
} |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: const Text('Modifier le produit'), |
|||
), |
|||
body: Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
children: [ |
|||
const Text( |
|||
'Modifier le produit', |
|||
style: TextStyle( |
|||
fontSize: 24, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
const SizedBox(height: 16), |
|||
TextField( |
|||
controller: _nameController, |
|||
decoration: const InputDecoration(labelText: 'Nom du produit'), |
|||
), |
|||
const SizedBox(height: 16), |
|||
TextField( |
|||
controller: _priceController, |
|||
decoration: const InputDecoration(labelText: 'Prix'), |
|||
keyboardType: |
|||
const TextInputType.numberWithOptions(decimal: true), |
|||
), |
|||
const SizedBox(height: 16), |
|||
TextField( |
|||
controller: _categoryController, |
|||
decoration: const InputDecoration(labelText: 'Catégorie'), |
|||
), |
|||
const SizedBox(height: 16), |
|||
ElevatedButton( |
|||
onPressed: _saveChanges, |
|||
child: const Text('Enregistrer les modifications'), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,186 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:youmazgestion/Models/users.dart'; |
|||
import '../Services/authDatabase.dart'; |
|||
|
|||
class EditUserPage extends StatefulWidget { |
|||
final Users user; |
|||
|
|||
const EditUserPage({super.key, required this.user}); |
|||
|
|||
@override |
|||
_EditUserPageState createState() => _EditUserPageState(); |
|||
} |
|||
|
|||
class _EditUserPageState extends State<EditUserPage> { |
|||
late TextEditingController _nameController; |
|||
late TextEditingController _lastNameController; |
|||
late TextEditingController _emailController; |
|||
late TextEditingController _usernameController; |
|||
late TextEditingController _passwordController; |
|||
String _selectedRole = ''; |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
_nameController = TextEditingController(text: widget.user.name); |
|||
_lastNameController = TextEditingController(text: widget.user.lastName); |
|||
_emailController = TextEditingController(text: widget.user.email); |
|||
_usernameController = TextEditingController(text: widget.user.username); |
|||
_passwordController = |
|||
TextEditingController(); // Leave password field empty initially |
|||
_selectedRole = widget.user.role; |
|||
} |
|||
|
|||
@override |
|||
void dispose() { |
|||
_nameController.dispose(); |
|||
_lastNameController.dispose(); |
|||
_emailController.dispose(); |
|||
_usernameController.dispose(); |
|||
_passwordController.dispose(); |
|||
super.dispose(); |
|||
} |
|||
|
|||
void _updateUser() { |
|||
final String name = _nameController.text; |
|||
final String lastName = _lastNameController.text; |
|||
final String email = _emailController.text; |
|||
final String username = _usernameController.text; |
|||
final String password = |
|||
_passwordController.text; // Get the entered password |
|||
final String role = _selectedRole; |
|||
|
|||
final Users updatedUser = Users( |
|||
id: widget.user.id, |
|||
name: name, |
|||
lastName: lastName, |
|||
email: email, |
|||
password: password.isNotEmpty |
|||
? password |
|||
: widget.user |
|||
.password, // Use entered password if not empty, otherwise keep the existing password |
|||
username: username, |
|||
role: role, |
|||
); |
|||
|
|||
AuthDatabase.instance.updateUser(updatedUser).then((value) { |
|||
// User update successful |
|||
showDialog( |
|||
context: context, |
|||
builder: (BuildContext context) { |
|||
return AlertDialog( |
|||
title: const Text('Update Successful'), |
|||
content: const Text('User information has been updated.'), |
|||
actions: <Widget>[ |
|||
ElevatedButton( |
|||
onPressed: () { |
|||
Navigator.of(context).pop(); |
|||
Navigator.pop(context, |
|||
true); // Return true to indicate successful update |
|||
}, |
|||
child: const Text('OK'), |
|||
), |
|||
], |
|||
); |
|||
}, |
|||
); |
|||
}).catchError((error) { |
|||
print(error); |
|||
// Update failed |
|||
showDialog( |
|||
context: context, |
|||
builder: (BuildContext context) { |
|||
return AlertDialog( |
|||
title: const Text('Update Failed'), |
|||
content: |
|||
const Text('An error occurred during user information update.'), |
|||
actions: <Widget>[ |
|||
ElevatedButton( |
|||
onPressed: () { |
|||
Navigator.of(context).pop(); |
|||
}, |
|||
child: const Text('OK'), |
|||
), |
|||
], |
|||
); |
|||
}, |
|||
); |
|||
}); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: const Text('Edit User'), |
|||
), |
|||
body: Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: SingleChildScrollView( |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
children: [ |
|||
TextField( |
|||
controller: _nameController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'First Name', |
|||
), |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
TextField( |
|||
controller: _lastNameController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Last Name', |
|||
), |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
TextField( |
|||
controller: _emailController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Email', |
|||
), |
|||
keyboardType: TextInputType.emailAddress, |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
TextField( |
|||
controller: _usernameController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Username', |
|||
), |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
TextField( |
|||
controller: _passwordController, |
|||
decoration: const InputDecoration( |
|||
labelText: 'Password', |
|||
), |
|||
obscureText: true, |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
DropdownButton<String>( |
|||
value: _selectedRole, |
|||
onChanged: (String? newValue) { |
|||
setState(() { |
|||
_selectedRole = newValue!; |
|||
}); |
|||
}, |
|||
items: <String>['admin', 'user'] |
|||
.map<DropdownMenuItem<String>>((String value) { |
|||
return DropdownMenuItem<String>( |
|||
value: value, |
|||
child: Text(value), |
|||
); |
|||
}).toList(), |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
ElevatedButton( |
|||
onPressed: _updateUser, |
|||
child: const Text('Update'), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:youmazgestion/Components/app_bar.dart'; |
|||
|
|||
import '../Components/appDrawer.dart'; |
|||
import '../Models/produit.dart'; |
|||
import '../Services/productDatabase.dart'; |
|||
import 'editProduct.dart'; |
|||
import 'dart:io'; |
|||
|
|||
class GestionProduit extends StatelessWidget { |
|||
final ProductDatabase _productDatabase = ProductDatabase.instance; |
|||
|
|||
const GestionProduit({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
final screenWidth = MediaQuery.of(context).size.width * 0.8; |
|||
|
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Gestion des produits'), |
|||
drawer: CustomDrawer(), |
|||
body: FutureBuilder<List<Product>>( |
|||
future: _productDatabase.getProducts(), |
|||
builder: (context, snapshot) { |
|||
if (snapshot.connectionState == ConnectionState.waiting) { |
|||
return const Center( |
|||
child: CircularProgressIndicator(), |
|||
); |
|||
} |
|||
|
|||
if (snapshot.hasError) { |
|||
return const Center( |
|||
child: Text('Une erreur s\'est produite'), |
|||
); |
|||
} |
|||
|
|||
final products = snapshot.data; |
|||
|
|||
if (products == null || products.isEmpty) { |
|||
return const Center( |
|||
child: Text('Aucun produit disponible'), |
|||
); |
|||
} |
|||
|
|||
return ListView.builder( |
|||
itemCount: products.length, |
|||
itemBuilder: (context, index) { |
|||
final product = products[index]; |
|||
return Container( |
|||
width: screenWidth, |
|||
margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 20), |
|||
decoration: BoxDecoration( |
|||
borderRadius: BorderRadius.circular(30), |
|||
border: Border.all( |
|||
color: Colors.grey, |
|||
width: 1.0, |
|||
), |
|||
), |
|||
child: ListTile( |
|||
leading: CircleAvatar( |
|||
backgroundImage: product.image != null |
|||
? FileImage(File(product.image)) as ImageProvider< |
|||
Object> // Charger l'image à partir du chemin d'accès |
|||
: const AssetImage( |
|||
'assets/placeholder_image.png'), // Image de substitution si le chemin d'accès est vide |
|||
), |
|||
title: Text(product.name), |
|||
subtitle: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
Text('Price: \$${product.price.toStringAsFixed(2)}'), |
|||
Text('Category: ${product.category}'), |
|||
], |
|||
), |
|||
trailing: Row( |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: [ |
|||
IconButton( |
|||
onPressed: () { |
|||
_productDatabase |
|||
.deleteProduct(product.id) |
|||
.then((value) { |
|||
Get.snackbar( |
|||
'Produit supprimé', |
|||
'Le produit a été supprimé avec succès', |
|||
snackPosition: SnackPosition.TOP, |
|||
duration: const Duration(seconds: 3), |
|||
backgroundColor: Colors.green, |
|||
colorText: Colors.white, |
|||
); |
|||
}); |
|||
}, |
|||
icon: const Icon(Icons.delete), |
|||
color: Colors.red, |
|||
), |
|||
IconButton( |
|||
onPressed: () { |
|||
Get.to(EditProductPage(product: product)) |
|||
?.then((result) { |
|||
if (result != null && result is Product) { |
|||
_productDatabase |
|||
.updateProduct(result) |
|||
.then((value) { |
|||
Get.snackbar( |
|||
'Produit mis à jour', |
|||
'Le produit a été mis à jour avec succès', |
|||
snackPosition: SnackPosition.TOP, |
|||
duration: const Duration(seconds: 3), |
|||
backgroundColor: Colors.green, |
|||
colorText: Colors.white, |
|||
); |
|||
}); |
|||
} |
|||
}); |
|||
}, |
|||
icon: const Icon(Icons.edit), |
|||
color: Colors.blue, |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
}, |
|||
); |
|||
}, |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,192 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:youmazgestion/Components/app_bar.dart'; |
|||
import '../Models/produit.dart'; |
|||
import '../Services/productDatabase.dart'; |
|||
|
|||
class GestionStockPage extends StatefulWidget { |
|||
const GestionStockPage({super.key}); |
|||
|
|||
@override |
|||
_GestionStockPageState createState() => _GestionStockPageState(); |
|||
} |
|||
|
|||
class _GestionStockPageState extends State<GestionStockPage> { |
|||
late Future<List<Product>> _productsFuture; |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
_loadProducts(); |
|||
} |
|||
|
|||
Future<void> _loadProducts() async { |
|||
final productDatabase = ProductDatabase.instance; |
|||
_productsFuture = productDatabase.getProducts(); |
|||
} |
|||
|
|||
Future<void> _refreshProducts() async { |
|||
final productDatabase = ProductDatabase.instance; |
|||
_productsFuture = productDatabase.getProducts(); |
|||
setState(() {}); |
|||
} |
|||
|
|||
Future<void> _updateStock(int id, int stock) async { |
|||
final productDatabase = ProductDatabase.instance; |
|||
await productDatabase.updateStock(id, stock); |
|||
_refreshProducts(); |
|||
} |
|||
|
|||
//popup pour modifier le stock |
|||
|
|||
Future<void> _showStockDialog(Product product) async { |
|||
int stock = product.stock ?? 0; |
|||
final quantityController = TextEditingController(text: stock.toString()); |
|||
|
|||
await showDialog( |
|||
context: context, |
|||
builder: (context) { |
|||
return AlertDialog( |
|||
title: const Text('Modifier le stock'), |
|||
content: Column( |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: [ |
|||
Text(product.name), |
|||
const SizedBox(height: 16), |
|||
Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
|||
children: [ |
|||
IconButton( |
|||
icon: const Icon(Icons.remove), |
|||
onPressed: () { |
|||
setState(() { |
|||
if (stock > 0) { |
|||
stock--; |
|||
quantityController.text = stock.toString(); |
|||
} |
|||
}); |
|||
}, |
|||
), |
|||
Expanded( |
|||
child: TextField( |
|||
controller: quantityController, |
|||
textAlign: TextAlign.center, |
|||
keyboardType: TextInputType.number, |
|||
onChanged: (value) { |
|||
setState(() { |
|||
stock = int.parse(value); |
|||
}); |
|||
}, |
|||
), |
|||
), |
|||
IconButton( |
|||
icon: const Icon(Icons.add), |
|||
onPressed: () { |
|||
setState(() { |
|||
stock++; |
|||
quantityController.text = stock.toString(); |
|||
}); |
|||
}, |
|||
), |
|||
], |
|||
), |
|||
], |
|||
), |
|||
actions: [ |
|||
TextButton( |
|||
child: const Text('Annuler'), |
|||
onPressed: () { |
|||
Navigator.of(context).pop(); |
|||
}, |
|||
), |
|||
ElevatedButton( |
|||
child: const Text('Enregistrer'), |
|||
onPressed: () { |
|||
// Enregistrer la nouvelle quantité dans la base de données |
|||
_updateStock(product.id!, stock); |
|||
Navigator.of(context).pop(); |
|||
}, |
|||
), |
|||
], |
|||
); |
|||
}, |
|||
); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Gestion du stock'), |
|||
body: FutureBuilder<List<Product>>( |
|||
future: _productsFuture, |
|||
builder: (context, snapshot) { |
|||
if (snapshot.connectionState == ConnectionState.waiting) { |
|||
return const Center( |
|||
child: CircularProgressIndicator(), |
|||
); |
|||
} else if (snapshot.hasError) { |
|||
return const Center( |
|||
child: Text('Une erreur s\'est produite'), |
|||
); |
|||
} else if (!snapshot.hasData || snapshot.data!.isEmpty) { |
|||
return const Center( |
|||
child: Text('Aucun produit trouvé'), |
|||
); |
|||
} else { |
|||
final products = snapshot.data!; |
|||
return ListView.builder( |
|||
itemCount: products.length, |
|||
itemBuilder: (context, index) { |
|||
final product = products[index]; |
|||
Color stockColor; |
|||
if (product.stock != null) { |
|||
if (product.stock! > 30) { |
|||
stockColor = Colors.green; |
|||
} else if (product.stock! > 10) { |
|||
stockColor = Colors.red; |
|||
} else { |
|||
stockColor = Colors.red; |
|||
} |
|||
} else { |
|||
stockColor = Colors.red; |
|||
} |
|||
|
|||
return Card( |
|||
margin: |
|||
const EdgeInsets.symmetric(vertical: 8, horizontal: 16), |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(20), |
|||
), |
|||
elevation: 4, |
|||
shadowColor: Colors.deepOrangeAccent, |
|||
child: ListTile( |
|||
leading: const Icon(Icons.shopping_basket), |
|||
title: Text( |
|||
product.name, |
|||
style: const TextStyle( |
|||
fontSize: 18, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
subtitle: Text( |
|||
'Stock: ${product.stock ?? 'Non disponible'}', |
|||
style: TextStyle( |
|||
fontSize: 16, |
|||
color: stockColor, |
|||
), |
|||
), |
|||
trailing: IconButton( |
|||
icon: const Icon(Icons.edit), |
|||
onPressed: () { |
|||
_showStockDialog(product); |
|||
}, |
|||
), |
|||
), |
|||
); |
|||
}, |
|||
); |
|||
} |
|||
}, |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,123 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:youmazgestion/Components/app_bar.dart'; |
|||
import 'package:intl/intl.dart'; |
|||
import '../Components/appDrawer.dart'; |
|||
import '../controller/HistoryController.dart'; |
|||
import 'listCommandeHistory.dart'; |
|||
|
|||
class HistoryPage extends GetView<HistoryController> { |
|||
@override |
|||
HistoryController controller = Get.put(HistoryController()); |
|||
|
|||
HistoryPage({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Historique'), |
|||
drawer: CustomDrawer(), |
|||
body: Column( |
|||
children: [ |
|||
Padding( |
|||
padding: const EdgeInsets.all(16.0), |
|||
child: ElevatedButton( |
|||
onPressed: () { |
|||
controller.refreshOrders(); |
|||
controller.onInit(); |
|||
}, |
|||
style: ElevatedButton.styleFrom( |
|||
backgroundColor: Colors.deepOrangeAccent, |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(20.0), |
|||
), |
|||
), |
|||
child: const Text( |
|||
'Rafraîchir', |
|||
style: TextStyle( |
|||
color: Colors.white, |
|||
fontSize: 16.0, |
|||
), |
|||
), |
|||
), |
|||
), |
|||
Expanded( |
|||
child: Obx( |
|||
() { |
|||
final distinctDates = controller.workDays; |
|||
|
|||
if (distinctDates.isEmpty) { |
|||
return const Center( |
|||
child: Text( |
|||
'Aucune journée de travail trouvée', |
|||
style: TextStyle( |
|||
fontSize: 18.0, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
return ListView.builder( |
|||
itemCount: distinctDates.length, |
|||
itemBuilder: (context, index) { |
|||
final date = distinctDates[index]; |
|||
return Card( |
|||
elevation: 2.0, |
|||
margin: const EdgeInsets.symmetric( |
|||
horizontal: 16.0, |
|||
vertical: 8.0, |
|||
), |
|||
child: ListTile( |
|||
title: Text( |
|||
'Journée du $date', |
|||
style: const TextStyle( |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
leading: const CircleAvatar( |
|||
backgroundColor: Colors.deepOrange, |
|||
child: Icon( |
|||
Icons.calendar_today, |
|||
color: Colors.white, |
|||
), |
|||
), |
|||
trailing: const Icon( |
|||
Icons.arrow_forward, |
|||
color: Colors.deepOrange, |
|||
), |
|||
onTap: () => navigateToDetailPage(date), |
|||
), |
|||
); |
|||
}, |
|||
); |
|||
}, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
); |
|||
} |
|||
|
|||
String formatDate(String date) { |
|||
try { |
|||
final parsedDate = DateFormat('dd-MM-yyyy').parse(date); |
|||
print('parsedDate1: $parsedDate'); |
|||
final formattedDate = DateFormat('yyyy-MM-dd').format(parsedDate); |
|||
print('formattedDate1: $formattedDate'); |
|||
return formattedDate; |
|||
} catch (e) { |
|||
print('Error parsing date: $date'); |
|||
return ''; |
|||
} |
|||
} |
|||
|
|||
// transformer string en DateTime |
|||
void navigateToDetailPage(String selectedDate) { |
|||
print('selectedDate: $selectedDate'); |
|||
DateTime parsedDate = DateFormat('yyyy-MM-dd').parse(selectedDate); |
|||
print('parsedDate: $parsedDate'); |
|||
|
|||
Get.to(() => HistoryDetailPage(selectedDate: parsedDate)); |
|||
} |
|||
} |
|||
@ -0,0 +1,219 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:youmazgestion/Components/app_bar.dart'; |
|||
import 'package:youmazgestion/Views/voirPlus.dart'; |
|||
import 'package:youmazgestion/controller/HistoryController.dart'; |
|||
import '../Models/Order.dart'; |
|||
import 'package:youmazgestion/Views/detailHistory.dart'; |
|||
|
|||
class HistoryDetailPage extends StatelessWidget { |
|||
final DateTime selectedDate; |
|||
final HistoryController controller = Get.find(); |
|||
double totalSum = 0.0; |
|||
late Future<Map<String, int>> productQuantities; |
|||
|
|||
HistoryDetailPage({super.key, required this.selectedDate}) { |
|||
calculateTotalSum(); |
|||
totalQuantity(); |
|||
} |
|||
|
|||
void calculateTotalSum() { |
|||
totalSum = controller.getTotalSumOrdersByStartDate(selectedDate); |
|||
} |
|||
|
|||
void totalQuantity() { |
|||
productQuantities = controller.getProductQuantitiesByDate(selectedDate); |
|||
print(productQuantities); |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return GetBuilder<HistoryController>( |
|||
init: controller, |
|||
builder: (controller) { |
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Historique de la journée'), |
|||
body: Column( |
|||
children: [ |
|||
Padding( |
|||
padding: const EdgeInsets.all(20.0), |
|||
child: Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceAround, |
|||
children: [ |
|||
ElevatedButton( |
|||
onPressed: () { |
|||
controller.refreshOrders(); |
|||
calculateTotalSum(); |
|||
}, |
|||
style: ElevatedButton.styleFrom( |
|||
backgroundColor: Colors.deepOrange, |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(20.0), |
|||
), |
|||
), |
|||
child: const Row( |
|||
children: [ |
|||
Icon(Icons.refresh, color: Colors.white), |
|||
SizedBox(width: 5), |
|||
Text( |
|||
'Rafraîchir', |
|||
style: TextStyle( |
|||
color: Colors.white, |
|||
fontSize: 16.0, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
ElevatedButton( |
|||
onPressed: () { |
|||
Navigator.push( |
|||
context, |
|||
MaterialPageRoute( |
|||
builder: (context) => |
|||
FutureBuilder<Map<String, int>>( |
|||
future: productQuantities, |
|||
builder: (context, snapshot) { |
|||
if (snapshot.connectionState == |
|||
ConnectionState.waiting) { |
|||
return const CircularProgressIndicator(); |
|||
} else if (snapshot.hasError) { |
|||
return Text('Error: ${snapshot.error}'); |
|||
} else { |
|||
return VoirPlusPage( |
|||
productQuantities: snapshot.data!); |
|||
} |
|||
}, |
|||
), |
|||
), |
|||
); |
|||
}, |
|||
style: ElevatedButton.styleFrom( |
|||
backgroundColor: Colors.deepOrange, |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(20.0), |
|||
), |
|||
), |
|||
child: const Row( |
|||
children: [ |
|||
Icon(Icons.feed_outlined, color: Colors.white), |
|||
SizedBox(width: 5), |
|||
Text( |
|||
'Voir Plus', |
|||
style: TextStyle( |
|||
color: Colors.white, |
|||
fontSize: 16.0, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
Text( |
|||
'Total Somme: $totalSum fcfa', |
|||
style: const TextStyle( |
|||
fontSize: 18.0, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
Expanded( |
|||
child: FutureBuilder<List<Order>>( |
|||
future: controller.getOrdersByStartDate(selectedDate), |
|||
builder: (context, snapshot) { |
|||
if (snapshot.connectionState == ConnectionState.waiting) { |
|||
return const Center( |
|||
child: CircularProgressIndicator(), |
|||
); |
|||
} |
|||
|
|||
if (snapshot.hasError) { |
|||
return const Center( |
|||
child: Text( |
|||
'Une erreur s\'est produite', |
|||
style: TextStyle( |
|||
fontSize: 18.0, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
final orders = snapshot.data; |
|||
|
|||
if (orders == null || orders.isEmpty) { |
|||
return const Center( |
|||
child: Text( |
|||
'Aucune commande trouvée pour cette journée', |
|||
style: TextStyle( |
|||
fontSize: 18.0, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
return ListView.builder( |
|||
itemCount: orders.length, |
|||
itemBuilder: (context, index) { |
|||
final order = orders[index]; |
|||
|
|||
return Card( |
|||
elevation: 4.0, |
|||
shadowColor: Colors.red, |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(20.0), |
|||
), |
|||
margin: const EdgeInsets.symmetric( |
|||
horizontal: 16.0, |
|||
vertical: 8.0, |
|||
), |
|||
child: ListTile( |
|||
title: Row( |
|||
children: [ |
|||
Text( |
|||
'Commande #${order.id}', |
|||
style: const TextStyle( |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
const SizedBox(width: 10), |
|||
Container( |
|||
padding: const EdgeInsets.symmetric( |
|||
horizontal: 8.0, vertical: 4.0), |
|||
decoration: BoxDecoration( |
|||
color: Colors.deepOrange, |
|||
borderRadius: BorderRadius.circular(10.0), |
|||
), |
|||
child: const Text( |
|||
'Terminé', |
|||
style: TextStyle( |
|||
color: Colors.white, |
|||
fontSize: 12.0, |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
), |
|||
subtitle: Text('Total: ${order.totalPrice} fcfa'), |
|||
trailing: Text('Date: ${order.dateTime}'), |
|||
leading: Text('vendeur: ${order.user}'), |
|||
onTap: () { |
|||
Get.to(() => DetailPage(order: order)); |
|||
}, |
|||
), |
|||
); |
|||
}, |
|||
); |
|||
}, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
); |
|||
}, |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:youmazgestion/Models/users.dart'; |
|||
import '../Components/app_bar.dart'; |
|||
import '../Services/authDatabase.dart'; |
|||
import 'editUser.dart'; |
|||
|
|||
class ListUserPage extends StatefulWidget { |
|||
const ListUserPage({super.key}); |
|||
|
|||
@override |
|||
_ListUserPageState createState() => _ListUserPageState(); |
|||
} |
|||
|
|||
class _ListUserPageState extends State<ListUserPage> { |
|||
List<Users> userList = []; |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
getUsersFromDatabase(); |
|||
} |
|||
|
|||
Future<void> getUsersFromDatabase() async { |
|||
try { |
|||
List<Users> users = await AuthDatabase.instance.getAllUsers(); |
|||
setState(() { |
|||
userList = users; |
|||
}); |
|||
} catch (e) { |
|||
print(e); |
|||
} |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: const CustomAppBar(title: 'Liste des utilisateurs'), |
|||
body: ListView.builder( |
|||
itemCount: userList.length, |
|||
itemBuilder: (context, index) { |
|||
Users user = userList[index]; |
|||
return Card( |
|||
elevation: 3, |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(20), |
|||
), |
|||
shadowColor: Colors.deepOrange, |
|||
borderOnForeground: true, |
|||
child: ListTile( |
|||
title: Text( |
|||
"${user.name} ${user.lastName}", |
|||
style: const TextStyle( |
|||
fontWeight: FontWeight.bold, |
|||
), |
|||
), |
|||
subtitle: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
const SizedBox(height: 4), |
|||
Text("Username: ${user.username}"), |
|||
const SizedBox(height: 4), |
|||
Text("Privilège: ${user.role}"), |
|||
], |
|||
), |
|||
trailing: Row( |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: [ |
|||
IconButton( |
|||
icon: const Icon(Icons.delete), |
|||
color: Colors.red, |
|||
onPressed: () { |
|||
// Action de suppression |
|||
// Vous pouvez appeler une méthode de suppression appropriée ici |
|||
// confirmation de suppression |
|||
showDialog( |
|||
context: context, |
|||
builder: (context) { |
|||
return AlertDialog( |
|||
title: const Text("Supprimer"), |
|||
content: const Text( |
|||
"Êtes-vous sûr de vouloir supprimer cet utilisateur?"), |
|||
actions: [ |
|||
TextButton( |
|||
onPressed: () { |
|||
Navigator.of(context).pop(); |
|||
}, |
|||
child: const Text("Annuler"), |
|||
), |
|||
TextButton( |
|||
onPressed: () async { |
|||
await AuthDatabase.instance |
|||
.deleteUser(user.id); |
|||
Navigator.of(context).pop(); |
|||
setState(() { |
|||
userList.removeAt(index); |
|||
}); |
|||
}, |
|||
child: const Text("Supprimer"), |
|||
), |
|||
], |
|||
); |
|||
}, |
|||
); |
|||
}, |
|||
), |
|||
IconButton( |
|||
icon: const Icon(Icons.edit), |
|||
color: Colors.blue, |
|||
onPressed: () { |
|||
// Action de modification |
|||
// Vous pouvez naviguer vers la page de modification avec les détails de l'utilisateur |
|||
// en utilisant Navigator.push ou showDialog, selon votre besoin |
|||
Get.to(() => EditUserPage(user: user)); |
|||
}, |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
}, |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,183 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:shared_preferences/shared_preferences.dart'; |
|||
import 'package:youmazgestion/Views/particles.dart' show ParticleBackground; |
|||
import 'package:youmazgestion/accueil.dart'; |
|||
import 'package:youmazgestion/Services/authDatabase.dart'; |
|||
|
|||
import '../Models/users.dart'; |
|||
import '../controller/userController.dart'; |
|||
|
|||
class LoginPage extends StatefulWidget { |
|||
const LoginPage({super.key}); |
|||
|
|||
@override |
|||
_LoginPageState createState() => _LoginPageState(); |
|||
} |
|||
|
|||
class _LoginPageState extends State<LoginPage> { |
|||
late TextEditingController _usernameController; |
|||
late TextEditingController _passwordController; |
|||
final UserController userController = Get.put(UserController()); |
|||
bool _isErrorVisible = false; |
|||
|
|||
@override |
|||
void initState() { |
|||
super.initState(); |
|||
_usernameController = TextEditingController(); |
|||
_passwordController = TextEditingController(); |
|||
checkUserCount(); |
|||
} |
|||
|
|||
void checkUserCount() async { |
|||
final userCount = await AuthDatabase.instance.getUserCount(); |
|||
if (userCount == 0) { |
|||
// No user found, redirect to home page |
|||
Navigator.pushReplacement( |
|||
context, |
|||
MaterialPageRoute(builder: (context) => const AccueilPage()), |
|||
); |
|||
} |
|||
} |
|||
|
|||
@override |
|||
void dispose() { |
|||
_usernameController.dispose(); |
|||
_passwordController.dispose(); |
|||
super.dispose(); |
|||
} |
|||
Future<void> saveUser(String? username,String? role)async{ |
|||
final prefs = await SharedPreferences.getInstance(); |
|||
await prefs.setString('username', username!); |
|||
await prefs.setString('role', role!); |
|||
} |
|||
void _login() async { |
|||
final String username = _usernameController.text; |
|||
final String password = _passwordController.text; |
|||
print(username); |
|||
print(password); |
|||
|
|||
try { |
|||
bool isValidUser = |
|||
await AuthDatabase.instance.verifyUser(username, password); |
|||
Users user = await AuthDatabase.instance.getUser(username); |
|||
|
|||
Map<String, String>? getUserCredentials = await AuthDatabase.instance.getUserCredentials(username,password); |
|||
print(isValidUser); |
|||
if (isValidUser) { |
|||
print('User is valid'); |
|||
print(user); |
|||
userController.setUser(user); |
|||
|
|||
setState(() { |
|||
_isErrorVisible = false; |
|||
}); |
|||
Navigator.pushReplacement( |
|||
context, |
|||
MaterialPageRoute(builder: (context) => const AccueilPage()), |
|||
); |
|||
saveUser(getUserCredentials?['username'], getUserCredentials?['role']); |
|||
} else { |
|||
setState(() { |
|||
_isErrorVisible = true; |
|||
}); |
|||
} |
|||
} catch (error) { |
|||
print(error); |
|||
setState(() { |
|||
_isErrorVisible = true; |
|||
}); |
|||
} |
|||
} |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: const Text( |
|||
'Login', |
|||
style: TextStyle(color:Colors.white), |
|||
), |
|||
backgroundColor: const Color.fromARGB(255, 4, 54, 95), |
|||
centerTitle: true, |
|||
), |
|||
body: ParticleBackground( |
|||
child: Center( |
|||
child: Container( |
|||
width: MediaQuery.of(context).size.width * 0.5, |
|||
height: MediaQuery.of(context).size.height * 0.8, |
|||
padding: const EdgeInsets.all(16.0), |
|||
decoration: BoxDecoration( |
|||
color: Colors.white, |
|||
shape: BoxShape.rectangle, |
|||
borderRadius: BorderRadius.circular(30.0), |
|||
), |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
children: [ |
|||
Container( |
|||
padding: const EdgeInsets.symmetric(vertical: 16.0), |
|||
child: const Icon( |
|||
Icons.lock_outline, |
|||
size: 100.0, |
|||
color: Color.fromARGB(255, 4, 54, 95), |
|||
), |
|||
), |
|||
TextField( |
|||
controller: _usernameController, |
|||
decoration: InputDecoration( |
|||
labelText: 'Username', |
|||
prefixIcon: |
|||
const Icon(Icons.person, color: Colors.blueAccent), |
|||
border: OutlineInputBorder( |
|||
borderRadius: BorderRadius.circular(30.0), |
|||
), |
|||
), |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
TextField( |
|||
controller: _passwordController, |
|||
decoration: InputDecoration( |
|||
labelText: 'Password', |
|||
prefixIcon: const Icon(Icons.lock, color: Colors.redAccent), |
|||
border: OutlineInputBorder( |
|||
borderRadius: BorderRadius.circular(30.0), |
|||
), |
|||
), |
|||
obscureText: true, |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
Visibility( |
|||
visible: _isErrorVisible, |
|||
child: const Text( |
|||
'Invalid username or password', |
|||
style: TextStyle( |
|||
color: Colors.red, |
|||
), |
|||
), |
|||
), |
|||
const SizedBox(height: 16.0), |
|||
ElevatedButton( |
|||
onPressed: _login, |
|||
style: ElevatedButton.styleFrom( |
|||
backgroundColor: const Color(0xFF0015B7), // Nouvelle couleur |
|||
elevation: 5.0, |
|||
shape: RoundedRectangleBorder( |
|||
borderRadius: BorderRadius.circular(30.0), |
|||
), |
|||
), |
|||
child: const Text( |
|||
'Login', |
|||
style: TextStyle( |
|||
color: Colors.white, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||