@ -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, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||