Compare commits

...

No commits in common. 'main' and 'aamir_dev' have entirely different histories.

47
.gitignore vendored

@ -0,0 +1,47 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# 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
/pubspec.lock

@ -0,0 +1,10 @@
# 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: 18116933e77adc82f80866c928266a5b4f1ed645
channel: stable
project_type: app

@ -1,93 +1,16 @@
# car_provider_app
A new Flutter project.
## Getting Started
## Getting started
This project is a starting point for a Flutter application.
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
A few resources to get you started if this is your first Flutter project:
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/mirza.shafique/car_provider_app.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://gitlab.com/mirza.shafique/car_provider_app/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://gitlab.com/-/experiment/new_project_readme_content:9529efb8c774508b24431e4d43ca8b4e?https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

13
android/.gitignore vendored

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

@ -0,0 +1,71 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 34
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.cloud.solutions.mowater.ksa.provider"
minSdkVersion 23
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
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.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation platform('com.google.firebase:firebase-bom:33.1.2')
// implementation 'com.google.firebase:firebase-analytics'
}

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "294636898500",
"project_id": "mowater-2c81a",
"storage_bucket": "mowater-2c81a.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:294636898500:android:e93b7e5d1cc15ae6b0e191",
"android_client_info": {
"package_name": "com.cloud.solutions.mowater.ksa.provider"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyD1WNNGrbBiCNvCrI31d3DV5AOgToq-Lus"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cloud.solutions.mowater.ksa.provider">
<!-- Flutter 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,68 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cloud.solutions.mowater.ksa.provider">
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<!-- Devices running Android 13 (API level 33) or higher -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- To handle the reselection within the app on devices running Android 14
or higher if your app targets Android 14 (API level 34) or higher. -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<application
android:icon="@mipmap/ic_launcher"
android:extractNativeLibs="true"
android:label="Provider">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
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" />
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8" />
<!-- 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>
</manifest>

@ -0,0 +1,7 @@
package com.cloud.solutions.mowater.ksa.provider
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
}

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

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
Flutter 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
Flutter 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"
package="com.cloud.solutions.mowater.ksa.provider">
<!-- Flutter 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,31 @@
buildscript {
ext.kotlin_version = '1.8.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.4.2'
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

@ -0,0 +1,16 @@
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Wed Dec 13 16:00:22 AST 2023
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
android.useAndroidX=true
android.enableJetifier=true

34
ios/.gitignore vendored

@ -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,54 @@
# Uncomment this line to define a global platform for your project
platform :ios, '14.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!
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)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_CAMERA=1',
'PERMISSION_PHOTOS=1',
'PERMISSION_LOCATION=1',
'PERMISSION_LOCATION_WHENINUSE=0',
'PERMISSION_NOTIFICATIONS=1',
]
end
end
end

@ -0,0 +1,575 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
290601662C7B4B300089E959 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 290601652C7B4B300089E959 /* GoogleService-Info.plist */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
5E9559759AEA0E089FDD9FD7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFCFDCCDB03A7D75BCB22117 /* Pods_Runner.framework */; };
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 */; };
/* 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>"; };
290601652C7B4B300089E959 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../../GoogleService-Info.plist"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
589B0447F002C308698802BD /* 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>"; };
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>"; };
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>"; };
B5D2F47A7F9A7D8C8678860A /* 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>"; };
BFCFDCCDB03A7D75BCB22117 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F095357B123772C701252686 /* 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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5E9559759AEA0E089FDD9FD7 /* 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 */,
CF641C50961DBDC07AA7AD64 /* Pods */,
C0F0C01C1B0541A9B1F8E6D5 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
290601652C7B4B300089E959 /* GoogleService-Info.plist */,
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>";
};
C0F0C01C1B0541A9B1F8E6D5 /* Frameworks */ = {
isa = PBXGroup;
children = (
BFCFDCCDB03A7D75BCB22117 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
CF641C50961DBDC07AA7AD64 /* Pods */ = {
isa = PBXGroup;
children = (
589B0447F002C308698802BD /* Pods-Runner.debug.xcconfig */,
F095357B123772C701252686 /* Pods-Runner.release.xcconfig */,
B5D2F47A7F9A7D8C8678860A /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
719FDEEFEE98A49E1AC9E990 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
C9CF36692C973DF3840AB8D9 /* [CP] Embed Pods Frameworks */,
4B705D790544D366DF3E5A40 /* [CP] Copy Pods Resources */,
);
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 */,
290601662C7B4B300089E959 /* GoogleService-Info.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";
};
4B705D790544D366DF3E5A40 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
719FDEEFEE98A49E1AC9E990 /* [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;
};
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";
};
C9CF36692C973DF3840AB8D9 /* [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;
};
/* 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 = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.cloud.solutions.mowater.ksa.provider.ios;
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_OPTIMIZATION_LEVEL = "-Owholemodule";
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 = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.cloud.solutions.mowater.ksa.provider.ios;
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 = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.cloud.solutions.mowater.ksa.provider.ios;
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,94 @@
<?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"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "IDEPreferLogStreaming"
value = "YES"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</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,28 @@
import UIKit
import Flutter
import GoogleMaps
import Firebase
import flutter_local_notifications
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
// This is required to make any communication available in the action isolate.
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
GMSServices.provideAPIKey("AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8")
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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

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,30 @@
<?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>API_KEY</key>
<string>AIzaSyAQoUIOm-5FtUqUngK0zvkkF2fafRxsm_I</string>
<key>GCM_SENDER_ID</key>
<string>294636898500</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.cloud.solutions.mowater.ksa.provider.ios</string>
<key>PROJECT_ID</key>
<string>mowater-2c81a</string>
<key>STORAGE_BUCKET</key>
<string>mowater-2c81a.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:294636898500:ios:1e92b79681dff7f1b0e191</string>
</dict>
</plist>

@ -0,0 +1,63 @@
<?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>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</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>car_provider_app</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>NSAppleMusicUsageDescription</key>
<string>Access to pick a photo</string>
<key>NSCameraUsageDescription</key>
<string>Access to take a photo by camera</string>
<key>NSFaceIDUsageDescription</key>
<string>This app requires Face ID to allow biometric authentication for app login.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This App requires access to your location to pick the location.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This App requires access to your location to pick the location.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This App requires access to your location to pick the location.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Access to pick a photo</string>
<key>UIApplicationSupportsIndirectInputEvents</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/>
</dict>
</plist>

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

@ -0,0 +1,13 @@
import 'package:mc_common_app/repositories/items_repo.dart';
import 'package:mc_common_app/repositories/schedule_repo.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/repositories/subscription_repo.dart';
class ProviderAppDependencies {
static void addDependencies() {
AppDependencies.addDependencies();
injector.registerSingleton<ItemsRepo>(() => ItemsRepoImp());
injector.registerSingleton<SubscriptionRepo>(() => SubscriptionRepoImp());
injector.registerSingleton<ScheduleRepo>(() => ScheduleRepoImp());
}
}

@ -0,0 +1,103 @@
import 'package:car_provider_app/views/appoinments/add_new_service_appointment_page.dart';
import 'package:car_provider_app/views/appoinments/appoinment_detail_list_page.dart';
import 'package:car_provider_app/views/appoinments/appointment_page.dart';
import 'package:car_provider_app/views/appoinments/merge_appointment_page.dart';
import 'package:car_provider_app/views/appoinments/update_appointment_page.dart';
import 'package:car_provider_app/views/dashboard/dashboard_view.dart';
import 'package:car_provider_app/views/branch_management/branch/branch_detail_page.dart';
import 'package:car_provider_app/views/branch_management/branch/dealer/dealer_user_page.dart';
import 'package:car_provider_app/views/branch_management/branch/define_branch_view.dart';
import 'package:car_provider_app/views/branch_management/schedule/add_schedules_page.dart';
import 'package:car_provider_app/views/branch_management/schedule/schedules_list_page.dart';
import 'package:car_provider_app/views/branch_management/services/create_item_page.dart';
import 'package:car_provider_app/views/branch_management/branch/dealer/dealership_view.dart';
import 'package:car_provider_app/views/branch_management/services/create_services_page3.dart';
import 'package:car_provider_app/views/branch_management/services/duplication/matched_services_page.dart';
import 'package:car_provider_app/views/branch_management/services/duplication/sheet/approved_branches_list_sheet.dart';
import 'package:car_provider_app/views/branch_management/services/items_list_page.dart';
import 'package:car_provider_app/views/branch_management/services/services_list_page.dart';
import 'package:car_provider_app/views/subscriptions/my_subscritions_page.dart';
import 'package:car_provider_app/views/subscriptions/all_subscriptions_page.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
class ProviderAppRoutes {
//settings
static const defineLicense = "/defineLicese";
static const String dealershipSetting = "/dealershipSetting";
static const String branchList = "/branchList";
static const String branchDetail = "/branchDetail";
static const String defineBranch = "/defineBranch";
//Appointments
static const String appointment = "/appointment";
static const String appointmentDetailList = "/appointmentDetailList";
static const String updateAppointmentPage = "/updateAppointmentPage";
static const String addServiceInAppointment = "/addServiceInAppointment";
static const String mergeAppointments = "/mergeAppointments";
//Requests
static const String requestsDetailPage = "/requestsDetailPage";
static const String sendOfferPage = "/sendOfferPage";
//Services
static const String dealerUser = "/dealerUser";
static const String servicesList = "/servicesList";
static const String itemsList = "/itemsList";
static const String createItem = "/createItem";
static const String createServices = "/createServices";
static const String createServices2 = "/createServices2";
static const String createServices3 = "/createServices3";
//Schedules
static const String schedulesList = "/schedulesList";
static const String addSchedule = "/addSchedule";
// Subscriptions
static const String mySubscriptionsPage = "/mySubscriptionsPage";
static const String subscriptionsPage = "/subscriptionsPage";
//Bracnh Duplication
static const String matchServices = "/matchServices";
static const String userSettings = "/userSettings";
static final Map<String, WidgetBuilder> routes = {
//Home page
AppRoutes.dashboard: (context) => const DashboardView(),
// defineLicense: (context) => DefineLicensePage(),
dealershipSetting: (context) => const DealershipView(),
// branchList: (context) => BranchListPage(),
defineBranch: (context) => DefineBranchView((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as BranchDetailModel)),
branchDetail: (context) => BranchDetailPage(ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
//Appointments
appointment: (context) => AppointmentPage(branch: ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
appointmentDetailList: (context) => const AppointmentDetailListPage(),
updateAppointmentPage: (context) => UpdateAppointmentPage(),
addServiceInAppointment: (context) => AddNewServiceAppointmentPage(ModalRoute.of(context)!.settings.arguments as AppointmentListModel),
mergeAppointments: (context) => const MergeAppointmentListPage(),
//Subscriptions
mySubscriptionsPage: (context) => const MySubscriptionsPage(),
subscriptionsPage: (context) => const SubscriptionsPage(),
//Services
dealerUser: (context) => DealerUserPage(ModalRoute.of(context)!.settings.arguments as String),
servicesList: (context) => const ServicesListPage(),
itemsList: (context) => ItemsListPage(),
createItem: (context) => const CreateItemPage(),
//createServices: (context) => CreateServicesPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as ServiceProviderBranch)),
//createServices2: (context) => CreateServicesPage2((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as ServiceProviderBranch)),
createServices3: (context) => CreateServicesPage3((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as CreateBranchModel)),
//Schedules
schedulesList: (context) => SchedulesListPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as String)),
addSchedule: (context) => const AddSchedulesPage(),
//Branch Duplication
matchServices: (context) => MatchedServicesPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as MatchServicesArguments)),
};
}

@ -0,0 +1,406 @@
// // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart
//
// // ignore_for_file: prefer_single_quotes
//
// import 'dart:ui';
//
// import 'package:easy_localization/easy_localization.dart' show AssetLoader;
//
// class CodegenLoader extends AssetLoader{
// const CodegenLoader();
//
// @override
// Future<Map<String, dynamic>> load(String fullPath, Locale locale ) {
// return Future.value(mapLocales[locale.toString()]);
// }
//
// static const Map<String,dynamic> ar_SA = {
// "firstTimeLogIn": "تسجيل الدخول لأول مره",
// "signUp": "التسجيل",
// "changeMobile": "تغيير رقم الجوال",
// "notifications": "الاشعارات",
// "general": "عام",
// "defineLicences": "تحديد الرخص",
// "dealershipSettings": "اعدادات البيع",
// "changePassword": "تغيير كلمة المرور",
// "retrievePassword": "استرجاع كلمة المرور",
// "changeEmail": "تغيير الايميل",
// "verify": "تحقق",
// "verified": "تم التحقق",
// "signOut": "تسجيل خروج",
// "enterEmail": "ادخل الايميل",
// "enterNewEmail": "ادخل ايميل جديد",
// "enterCurrentPassword": "كلمة المرور الحاليه",
// "enterNewPassword": "كلمة المرور الجديده",
// "enterOldPassword": "كلمة المرور القديمه",
// "confirm": "تأكيد",
// "enterNewPhoneNumber": "رقم جوال جديد",
// "completeProfile": "الملف الشخصي",
// "continu": "استمرار",
// "confirmPassword": "تأكيد كلمة المرور",
// "createPassword": "انشاء كلمة مرور جديده",
// "email": "ايميل",
// "firstName": "الأسم الأول *",
// "surname": "اسم العائله *",
// "confirmPass": "تأكيد كلمة المرور *",
// "createPass": "انشاء كلمة مرور جديده *",
// "newPassword": " كلمة مرور جديده",
// "forgetPassword": "نسيت كلمة المرور",
// "forgetPasswordQ": "نسيت كلمة المرور؟",
// "recover": "استعادة",
// "forgetPasswordRecover": "نسيت كلمة المرور؟ استعادة",
// "editAccount": "تعديل الحساب",
// "change": "تغيير",
// "verifyAccount": "التحقق من الحساب",
// "login": "تسجيل دخول",
// "log_in": "تسجيل الدخول",
// "welcomeMessage": "مرحبا",
// "welcomeDes": "أنت مكان واحد لكل ما تحتاجه سيارتك",
// "forgetPass": "نسيت كلمة المرور ؟",
// "enterPhoneNumber": "رقم جوال ",
// "phoneNumberVerified": "تم التحقق من الجوال",
// "verifyNewPassword": "التحقق من كلمة المرور",
// "EnterPass": "ادخل كلمة المرور",
// "send": "إرسال",
// "retrivePassword": "استرجع كلمة المرور بإحدى الطرق التالية",
// "retriveOnPhone": "سوف نرسل الاختيار إلى رقم هاتفك المحمول المسجل",
// "retriveOnEmail": "سوف نرسل الاختيار إلى عنوان بريدك الإلكتروني المسجل",
// "enterPhoneForVerfication": "الرجاء إدخال رقم هاتفك وسنرسل لك رمز التحقق",
// "selectYourCountry": "اختر بلدك",
// "welcomeBack": "مرحبًا بعودتك!!!",
// "alreadySigned": " تم تسجيل الدخول",
// "emailChangedSuccessfully": "تم تغيير الايميل بنجاح",
// "passwordIsUpdated": "تم تحجيث كلمة المرور",
// "passwordShouldContains": "كلمة المرور يجب ان تحتوي على رمز رقم حرف كبير حرف صغير",
// " successfullyRegistered": "تم التسجيل بنجاح",
// "pleaseEnterSamePassword": "ادخل كلمة مرور مطابقه",
// "firstNameMandatory": "ادخل الأسم الأول ",
// "surnameNameMandatory": "ادخل اسم العائله",
// "passwordNameMandatory": "ادخل كلمة المرور",
// "enterValidEmail": "ادخل ايميل صحيح",
// "pleaseAcceptTerms": "يجب الموافقه على الشروط",
// "emailVerified": "تم التحقق من الايميل بنجاح",
// "selectMethod": "اختر",
// "emailAddress": "ايميل",
// "loginSelection": "اختر",
// "selectCountryCode": "اختر رمز الدوله",
// "selectProviderRole": "اختر نوع الخدمه",
// "addPhoneNo": "اضف الهاتف",
// "onlyProviderApp": "نأسف هذا التطبيق فقط لمقدمي الخدمات",
// "imageUploaded": "تم تحميل الصوره",
// "fileLarger": "1KB حجم الملف اكبر من",
// "account": "الحساب",
// "edit": "تعديل",
// "imageDeleted": "تم حذف الصوره",
// "dashboard": "الصفحه الرئيسيه",
// "pickAddress": "اختر العنوان",
// "pickLocation": "اختر الموقع",
// "save": "حفظ",
// "defineServices": "تحديد الخدمات",
// "selectBranch ": "اختر الفرع",
// "selectServiceCategory": "اختر فئة الخدمة",
// "defineBranches": "تحديد الفروع",
// "defineProviders": "تحديد الموفرين",
// "closeAccount": "اغلاق الحساب",
// "createBranch": "انشاء فرع",
// "updateBranch": "فرع التحديث",
// "address": "العنوان",
// "branchDescription": "وصف الفرع",
// "branchName": "اسم الفرع",
// "chooseCity": "اختر المدينه",
// "chooseCountry": "اختر الدوله",
// "selectAttachment": "اختيار مرفق",
// "somethingWrong": "هناك خطأ ما",
// "documentsUploaded": "تم ارفاق الملف بنجاح",
// "update": "تحديث",
// "termsOfService": "من خلال إنشاء حساب فإنك توافق على",
// "terms": "بنود الخدمة وخصوصية السياسة",
// "profileMsg": "أدخل التفاصيل أدناه وأكمل معلومات الملف الشخصي",
// "branchInfo": "معلومات الفرع و الخدمات",
// "profileCompleted": "الملف الشخصي مكتمل",
// "selectLocationMap": "اختر الموقع",
// "licensesAndCertifications": "الرخص و الشهادات",
// "completeProfile1": "اكمل الملف الشخصي 1/3",
// "completeProfile2": "اكمل الملف الشخصي 2/3",
// "completeProfile3": "اكمل الملف الشخصي 3/3",
// "userInformation": "معلومات المتسخدم",
// "faceRecognition": "تحقق مع بصمة الوجه",
// "fingerPrint": "تحقق مع بصمة الاصبع",
// "whatsapp": "تحقق مع Whatsapp",
// "SMS": "رسائل قصيره",
// "selectRole": "حدد الدور",
// "userRoleOrTitle": "عنوان المستخدم",
// "codeSentToEmail": "تم ارسال الرمز للايميل",
// "number": "موبايل",
// "phoneNumber": "رقم الهاتف",
// "english": "English",
// "provider": "Provider",
// "title": "Hello",
// "msg": "Hello {} in the {} world ",
// "msg_named": "{} are written in the {lang} language",
// "clickMe": "Click me",
// "profile": {
// "reset_password": {
// "label": "Reset Password",
// "username": "Username",
// "password": "password"
// }
// },
// "clicked": {
// "zero": "You clicked {} times!",
// "one": "You clicked {} time!",
// "two": "You clicked {} times!",
// "few": "You clicked {} times!",
// "many": "You clicked {} times!",
// "other": "You clicked {} times!"
// },
// "amount": {
// "zero": "Your amount : {} ",
// "one": "Your amount : {} ",
// "two": "Your amount : {} ",
// "few": "Your amount : {} ",
// "many": "Your amount : {} ",
// "other": "Your amount : {} "
// },
// "gender": {
// "male": "Hi man ;) ",
// "female": "Hello girl :)",
// "with_arg": {
// "male": "Hi man ;) {}",
// "female": "Hello girl :) {}"
// }
// },
// "reset_locale": "Reset Language",
// "insert_otp_code": "ادخل الرمز",
// "type_code": "الرجاء كتابة الرمز الذي أرسلناه إلى",
// "resend_code": "أعد إرسال الرمز",
// "check_code": "التحقق من الشفرة",
// "time_will_expire": "إعادة إرسال الرمز بتنسيق",
// "sec": "ثانية",
// "no_city_available": "لا توجد مدينة متاحة لهذا البلد",
// "branch_created": "تم إنشاء الفرع بنجاح",
// "branch_updated": "تم تحديث الفرع بنجاح",
// "branch_deleted": "تم حذف الفرع بنجاح",
// "dashboard_main": "لوحة القيادة / الصفحة الرئيسية",
// "logo_brand": "الشعار / العلامة التجارية",
// "remove": "إزالة",
// "no_branch": "لم يتم إضافة فرع حتى الآن",
// "login_once": "الرجاء تسجيل الدخول مرة واحدة",
// "defineLicenese": "تحميل التراخيص والشهادات",
// "description": "وصف",
// "attachFile": "أرفق ملف",
// "branchLocation": "معلومات الفرع والموقع",
// "tapToEdit": "انقر للتعديل",
// "myServiceBranches": "فروع خدمتي",
// "enter_licence_detail": "الرجاء إدخال تفاصيل السجلات التجارية وإرفاق صور الترخيص",
// "country": "بلد",
// "city": "مدينة",
// "editServices": "تحرير الخدمات",
// "providers": "الموفرون",
// "appointments": "تعيينات",
// "home": "بيت",
// "ads": "إعلانات",
// "settings": "إعدادات",
// "view_all": "مشاهدة الكل",
// "my_active_Ads": "إعلاناتي النشطة",
// "recommended_ads": "الإعلانات الموصى بها",
// "upcoming_appointment": "الموعد القادم",
// "my_service_providers": "مزودي الخدمة الجدد",
// "appointment_details": "تفاصيل الموعد"
// };
// static const Map<String,dynamic> en_US = {
// "firstTimeLogIn": "First Time Log In",
// "signUp": "Register",
// "changeMobile": "Change Mobile",
// "notifications": "Notifications",
// "general": "General",
// "defineLicences": "Register Licences",
// "dealershipSettings": "Dealership Settings",
// "changePassword": "Change Password",
// "retrievePassword": "Retrieve Password",
// "changeEmail": "Change Email",
// "verify": "Verify",
// "verified": "Verified",
// "signOut": "Sign Out",
// "enterEmail": "Enter Email and Password",
// "enterNewEmail": "Enter New Email",
// "enterNewPassword": "Enter New Password",
// "enterCurrentPassword": "Enter Current Password",
// "enterOldPassword": "Enter Old Password",
// "confirm": "Confirm",
// "completeProfile": "Complete Profile",
// "enterNewPhoneNumber": "Enter New Phone Number",
// "enterPhoneNumber": "Enter the login credentials",
// "continu": "Continue",
// "confirmPassword": "Confirm Password",
// "createPassword": "Create Password",
// "email": "Email",
// "firstName": "First Name *",
// "surname": "Surname *",
// "confirmPass": "Confirm Password *",
// "createPass": "Create Password *",
// "newPassword": "New Password",
// "forgetPassword": "Forget Password",
// "forgetPasswordQ": "Forget Password?",
// "recover": "Recover",
// "forgetPasswordRecover": "Forget Password? Recover",
// "editAccount": "Edit Account",
// "change": "Change",
// "verifyAccount": "Verify Account",
// "login": "Login",
// "log_in": "Log In",
// "welcomeMessage": "Welcome To Mowater",
// "welcomeDes": "You one stop place all your car needs",
// "forgetPass": "Forget Password ?",
// "phoneNumberVerified": "Phone Number Verified",
// "verifyNewPassword": "Verify New Password",
// "send": "Send",
// "EnterPass": "Enter Password ?",
// "retrivePassword": "Retrive password by one of following method",
// "retriveOnPhone": "We will send the opt to your registered mobile number",
// "retriveOnEmail": "We will send the opt to your registered email address",
// "enterPhoneForVerfication": "Please enter your phone number We will send you the verification code",
// "selectYourCountry": "Select Your Country",
// "welcomeBack": "Welcome Back!!!",
// "alreadySigned": " Already Signed Up and Logged In",
// "emailChangedSuccessfully": "Email is Changed Successfully",
// "passwordIsUpdated": "Password is Updated",
// "passwordShouldContains": "Password Should contains Character, Number, Capital and small letters,",
// " successfullyRegistered": " Successfully Registered, Please login once,",
// "pleaseEnterSamePassword": "Please enter same password",
// "firstNameMandatory": "First name is mandatory",
// "surnameNameMandatory": "Surname is mandatory",
// "passwordNameMandatory": "Password is mandatory",
// "enterValidEmail": "Enter Valid Email",
// "pleaseAcceptTerms": "Please accept terms",
// "emailVerified": "Email is verified successfully",
// "selectMethod": "Select Method",
// "emailAddress": "Email Address",
// "loginSelection": "Login Selection",
// "selectCountryCode": "Please select Country Code",
// "selectProviderRole": "Please select Provider Role",
// "addPhoneNo": "Please add Phone No",
// "onlyCustomerApp": "Sorry, Only Customer's can log in this app",
// "imageUploaded": "Image is uploaded",
// "fileLarger": "File is larger then 1KB",
// "account": "Account",
// "edit": "EDIT",
// "imageDeleted": "Image is Deleted",
// "dashboard": "Dashboard/Main Page",
// "pickAddress": "Pick Address",
// "pickLocation": "Pick Location",
// "save": "Save",
// "defineServices": "Define Services",
// "selectBranch ": "Select Branch ",
// "selectServiceCategory": "Select Service Category",
// "defineBranches": "Define Branches",
// "defineProviders": "Define Providers",
// "closeAccount": "Close Account",
// "createBranch": "Create Branch",
// "updateBranch": "Update Branch",
// "address": "Address",
// "branchDescription": "Branch Description",
// "branchName": "Branch Name",
// "chooseCity": "Select City",
// "chooseCountry": "Choose Country",
// "selectAttachment": "Select Attachment",
// "somethingWrong": "Something went wrong",
// "documentsUploaded": "Documents uploaded successfully",
// "update": "Update",
// "termsOfService": "By creating an account you agree to our",
// "terms": "Terms of Service and Privacy Policy",
// "profileMsg": "Enter the details below and complete the profile info",
// "branchInfo": "Branch Info and Services",
// "profileCompleted": "Profile is Completed",
// "selectLocationMap": "Select Location Map",
// "licensesAndCertifications": "licenses & certifications",
// "completeProfile1": "Complete Profile 1/3",
// "completeProfile2": "Complete Profile 2/3",
// "completeProfile3": "Complete Profile 3/3",
// "userInformation": "User Information",
// "provider": "Provider",
// "faceRecognition": "Face Recognition",
// "fingerPrint": "Finger Print",
// "whatsapp": "With Whatsapp",
// "SMS": "With SMS",
// "selectRole": "Choose Role",
// "userRoleOrTitle": "User role or title",
// "codeSentToEmail": "Code is sent to email",
// "number": "Number",
// "phoneNumber": "Phone Number",
// "english": "عربي",
// "title": "Hello",
// "msg": "Hello {} in the {} world ",
// "msg_named": "{} are written in the {lang} language",
// "clickMe": "Click me",
// "profile": {
// "reset_password": {
// "label": "Reset Password",
// "username": "Username",
// "password": "password"
// }
// },
// "clicked": {
// "zero": "You clicked {} times!",
// "one": "You clicked {} time!",
// "two": "You clicked {} times!",
// "few": "You clicked {} times!",
// "many": "You clicked {} times!",
// "other": "You clicked {} times!"
// },
// "amount": {
// "zero": "Your amount : {} ",
// "one": "Your amount : {} ",
// "two": "Your amount : {} ",
// "few": "Your amount : {} ",
// "many": "Your amount : {} ",
// "other": "Your amount : {} "
// },
// "gender": {
// "male": "Hi man ;) ",
// "female": "Hello girl :)",
// "with_arg": {
// "male": "Hi man ;) {}",
// "female": "Hello girl :) {}"
// }
// },
// "reset_locale": "Reset Language",
// "insert_otp_code": "Enter the code",
// "type_code": "Please type the code we sent to",
// "resend_code": "Resend Code",
// "check_code": "Check Code",
// "time_will_expire": "Resend code in",
// "sec": "sec",
// "no_city_available": "No City Available for this country",
// "branch_created": "Branch is successfully created",
// "branch_updated": "Branch is successfully Updated",
// "branch_deleted": "Branch is successfully Deleted",
// "dashboard_main": "Dashboard/Main Page",
// "logo_brand": "Logo/Brand",
// "remove": "Remove",
// "no_branch": "No Branch Added Yet",
// "login_once": "Please login once",
// "defineLicenese": "Upload Licenses and Certificates",
// "description": "Description",
// "attachFile": "Attach File",
// "branchLocation": "Branch info and Location",
// "tapToEdit": "Tap to edit",
// "myServiceBranches": "My Service Branches",
// "enter_licence_detail": "Please enter the detail for commercial records and attach the license images",
// "country": "country",
// "city": "city",
// "editServices": "Edit Services",
// "providers": "Providers",
// "appointments": "Appointments",
// "home": "Home",
// "ads": "Ads",
// "settings": "Settings",
// "view_all": "view all",
// "my_active_Ads": "My Active Ads",
// "recommended_ads": "Recommended Ads",
// "upcoming_appointment": "Upcoming Appointment",
// "my_service_providers": "My Recent Service Providers",
// "appointment_details": "Appointment Details"
// };
// static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
// }

@ -0,0 +1,175 @@
// // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart
//
// abstract class LocaleKeys {
// static const firstTimeLogIn = 'firstTimeLogIn';
// static const signUp = 'signUp';
// static const changeMobile = 'changeMobile';
// static const notifications = 'notifications';
// static const general = 'general';
// static const defineLicences = 'defineLicences';
// static const dealershipSettings = 'dealershipSettings';
// static const changePassword = 'changePassword';
// static const retrievePassword = 'retrievePassword';
// static const changeEmail = 'changeEmail';
// static const verify = 'verify';
// static const verified = 'verified';
// static const signOut = 'signOut';
// static const enterEmail = 'enterEmail';
// static const enterNewEmail = 'enterNewEmail';
// static const enterCurrentPassword = 'enterCurrentPassword';
// static const enterNewPassword = 'enterNewPassword';
// static const enterOldPassword = 'enterOldPassword';
// static const confirm = 'confirm';
// static const enterNewPhoneNumber = 'enterNewPhoneNumber';
// static const completeProfile = 'completeProfile';
// static const continu = 'continu';
// static const confirmPassword = 'confirmPassword';
// static const createPassword = 'createPassword';
// static const email = 'email';
// static const firstName = 'firstName';
// static const surname = 'surname';
// static const confirmPass = 'confirmPass';
// static const createPass = 'createPass';
// static const newPassword = 'newPassword';
// static const forgetPassword = 'forgetPassword';
// static const forgetPasswordQ = 'forgetPasswordQ';
// static const recover = 'recover';
// static const forgetPasswordRecover = 'forgetPasswordRecover';
// static const editAccount = 'editAccount';
// static const change = 'change';
// static const verifyAccount = 'verifyAccount';
// static const login = 'login';
// static const log_in = 'log_in';
// static const welcomeMessage = 'welcomeMessage';
// static const welcomeDes = 'welcomeDes';
// static const forgetPass = 'forgetPass';
// static const enterPhoneNumber = 'enterPhoneNumber';
// static const phoneNumberVerified = 'phoneNumberVerified';
// static const verifyNewPassword = 'verifyNewPassword';
// static const EnterPass = 'EnterPass';
// static const send = 'send';
// static const retrivePassword = 'retrivePassword';
// static const retriveOnPhone = 'retriveOnPhone';
// static const retriveOnEmail = 'retriveOnEmail';
// static const enterPhoneForVerfication = 'enterPhoneForVerfication';
// static const selectYourCountry = 'selectYourCountry';
// static const welcomeBack = 'welcomeBack';
// static const alreadySigned = 'alreadySigned';
// static const emailChangedSuccessfully = 'emailChangedSuccessfully';
// static const passwordIsUpdated = 'passwordIsUpdated';
// static const passwordShouldContains = 'passwordShouldContains';
// static const successfullyRegistered = ' successfullyRegistered';
// static const pleaseEnterSamePassword = 'pleaseEnterSamePassword';
// static const firstNameMandatory = 'firstNameMandatory';
// static const surnameNameMandatory = 'surnameNameMandatory';
// static const passwordNameMandatory = 'passwordNameMandatory';
// static const enterValidEmail = 'enterValidEmail';
// static const pleaseAcceptTerms = 'pleaseAcceptTerms';
// static const emailVerified = 'emailVerified';
// static const selectMethod = 'selectMethod';
// static const emailAddress = 'emailAddress';
// static const loginSelection = 'loginSelection';
// static const selectCountryCode = 'selectCountryCode';
// static const selectProviderRole = 'selectProviderRole';
// static const addPhoneNo = 'addPhoneNo';
// static const onlyProviderApp = 'onlyProviderApp';
// static const imageUploaded = 'imageUploaded';
// static const fileLarger = 'fileLarger';
// static const account = 'account';
// static const edit = 'edit';
// static const imageDeleted = 'imageDeleted';
// static const dashboard = 'dashboard';
// static const pickAddress = 'pickAddress';
// static const pickLocation = 'pickLocation';
// static const save = 'save';
// static const defineServices = 'defineServices';
// static const selectBranch = 'selectBranch ';
// static const selectServiceCategory = 'selectServiceCategory';
// static const defineBranches = 'defineBranches';
// static const defineProviders = 'defineProviders';
// static const closeAccount = 'closeAccount';
// static const createBranch = 'createBranch';
// static const updateBranch = 'updateBranch';
// static const address = 'address';
// static const branchDescription = 'branchDescription';
// static const branchName = 'branchName';
// static const chooseCity = 'chooseCity';
// static const chooseCountry = 'chooseCountry';
// static const selectAttachment = 'selectAttachment';
// static const somethingWrong = 'somethingWrong';
// static const documentsUploaded = 'documentsUploaded';
// static const update = 'update';
// static const termsOfService = 'termsOfService';
// static const terms = 'terms';
// static const profileMsg = 'profileMsg';
// static const branchInfo = 'branchInfo';
// static const profileCompleted = 'profileCompleted';
// static const selectLocationMap = 'selectLocationMap';
// static const licensesAndCertifications = 'licensesAndCertifications';
// static const completeProfile1 = 'completeProfile1';
// static const completeProfile2 = 'completeProfile2';
// static const completeProfile3 = 'completeProfile3';
// static const userInformation = 'userInformation';
// static const faceRecognition = 'faceRecognition';
// static const fingerPrint = 'fingerPrint';
// static const whatsapp = 'whatsapp';
// static const SMS = 'SMS';
// static const selectRole = 'selectRole';
// static const userRoleOrTitle = 'userRoleOrTitle';
// static const codeSentToEmail = 'codeSentToEmail';
// static const number = 'number';
// static const phoneNumber = 'phoneNumber';
// static const english = 'english';
// static const provider = 'provider';
// static const title = 'title';
// static const msg = 'msg';
// static const msg_named = 'msg_named';
// static const clickMe = 'clickMe';
// static const profile_reset_password_label = 'profile.reset_password.label';
// static const profile_reset_password_username = 'profile.reset_password.username';
// static const profile_reset_password_password = 'profile.reset_password.password';
// static const profile_reset_password = 'profile.reset_password';
// static const profile = 'profile';
// static const clicked = 'clicked';
// static const amount = 'amount';
// static const gender_with_arg = 'gender.with_arg';
// static const gender = 'gender';
// static const reset_locale = 'reset_locale';
// static const insert_otp_code = 'insert_otp_code';
// static const type_code = 'type_code';
// static const resend_code = 'resend_code';
// static const check_code = 'check_code';
// static const time_will_expire = 'time_will_expire';
// static const sec = 'sec';
// static const no_city_available = 'no_city_available';
// static const branch_created = 'branch_created';
// static const branch_updated = 'branch_updated';
// static const branch_deleted = 'branch_deleted';
// static const dashboard_main = 'dashboard_main';
// static const logo_brand = 'logo_brand';
// static const remove = 'remove';
// static const no_branch = 'no_branch';
// static const login_once = 'login_once';
// static const defineLicenese = 'defineLicenese';
// static const description = 'description';
// static const attachFile = 'attachFile';
// static const branchLocation = 'branchLocation';
// static const tapToEdit = 'tapToEdit';
// static const myServiceBranches = 'myServiceBranches';
// static const enter_licence_detail = 'enter_licence_detail';
// static const country = 'country';
// static const city = 'city';
// static const editServices = 'editServices';
// static const providers = 'providers';
// static const appointments = 'appointments';
// static const home = 'home';
// static const ads = 'ads';
// static const settings = 'settings';
// static const view_all = 'view_all';
// static const my_active_Ads = 'my_active_Ads';
// static const recommended_ads = 'recommended_ads';
// static const upcoming_appointment = 'upcoming_appointment';
// static const my_service_providers = 'my_service_providers';
// static const appointment_details = 'appointment_details';
//
// }

@ -0,0 +1,186 @@
import 'dart:io';
import 'package:car_provider_app/config/provider_dependencies.dart';
import 'package:mc_common_app/repositories/items_repo.dart';
import 'package:mc_common_app/repositories/schedule_repo.dart';
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:mc_common_app/repositories/setting_options_repo.dart';
import 'package:mc_common_app/repositories/shipping_repo.dart';
import 'package:mc_common_app/services/firebase_service.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/models/general_models/post_params_model.dart';
import 'package:mc_common_app/repositories/ads_repo.dart';
import 'package:mc_common_app/repositories/appointment_repo.dart';
import 'package:mc_common_app/repositories/branch_repo.dart';
import 'package:mc_common_app/repositories/chat_repo.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/repositories/payments_repo.dart';
import 'package:mc_common_app/repositories/request_repo.dart';
import 'package:mc_common_app/repositories/subscription_repo.dart';
import 'package:mc_common_app/repositories/user_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/services/payments_service.dart';
import 'package:mc_common_app/theme/app_theme.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/view_models/setting_options_view_model.dart';
import 'package:mc_common_app/view_models/shipping_management_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
import 'package:firebase_core/firebase_core.dart';
import 'config/provider_routes.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
if (Platform.isAndroid) {
await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey: 'AIzaSyD1WNNGrbBiCNvCrI31d3DV5AOgToq-Lus',
appId: '1:294636898500:android:e93b7e5d1cc15ae6b0e191',
messagingSenderId: '294636898500',
projectId: 'mowater-2c81a',
),
);
} else {
await Firebase.initializeApp();
}
ProviderAppDependencies.addDependencies();
injector.get<FirebaseMessagingService>().initializeNotifications();
ProviderAppRoutes.routes.addAll(AppRoutes.routes);
runApp(MultiProvider(
providers: [
ChangeNotifierProvider<BaseVM>(
create: (_) => BaseVM(),
),
ChangeNotifierProvider<DashboardVM>(
create: (_) => DashboardVM(
userRepo: injector.get<UserRepo>(),
commonServices: injector.get<CommonAppServices>(),
),
),
ChangeNotifierProvider<UserVM>(
create: (_) => UserVM(
userRepo: injector.get<UserRepo>(),
commanServices: injector.get<CommonAppServices>(),
),
),
ChangeNotifierProvider<ServiceVM>(
create: (_) => ServiceVM(
branchRepo: injector.get<BranchRepo>(),
commonServices: injector.get<CommonAppServices>(),
commonRepo: injector.get<CommonRepo>(),
),
),
ChangeNotifierProvider<SubscriptionsVM>(
create: (_) => SubscriptionsVM(subscriptionRepo: injector.get<SubscriptionRepo>()),
),
ChangeNotifierProvider<ItemsVM>(
create: (_) => ItemsVM(
itemsRepo: injector.get<ItemsRepo>(),
commonServices: injector.get<CommonAppServices>(),
),
),
ChangeNotifierProvider<ScheduleVM>(
create: (_) => ScheduleVM(
scheduleRepo: injector.get<ScheduleRepo>(),
),
),
ChangeNotifierProvider<AdVM>(
create: (_) => AdVM(
commonServices: injector.get<CommonAppServices>(),
adsRepo: injector.get<AdsRepo>(),
commonRepo: injector.get<CommonRepo>(),
),
),
ChangeNotifierProvider<RequestsVM>(
create: (_) => RequestsVM(
commonServices: injector.get<CommonAppServices>(),
commonRepo: injector.get<CommonRepo>(),
requestRepo: injector.get<RequestRepo>(),
),
),
ChangeNotifierProvider<AppointmentsVM>(
create: (_) => AppointmentsVM(
appointmentRepo: injector.get<AppointmentRepo>(),
commonServices: injector.get<CommonAppServices>(),
commonRepo: injector.get<CommonRepo>(),
branchRepo: injector.get<BranchRepo>(),
),
),
ChangeNotifierProvider<ChatVM>(
create: (_) => ChatVM(
chatRepo: injector.get<ChatRepo>(),
requestRepo: injector.get<RequestRepo>(),
commonServices: injector.get<CommonAppServices>(),
),
),
ChangeNotifierProvider<PaymentVM>(
create: (_) => PaymentVM(
paymentService: injector.get<PaymentService>(),
paymentRepo: injector.get<PaymentsRepo>(),
),
),
ChangeNotifierProvider<ShippingManagementVM>(
create: (_) => ShippingManagementVM(
shippingRepo: injector.get<ShippingRepo>(),
commonRepo: injector.get<CommonRepo>(),
)),
ChangeNotifierProvider<SettingOptionsVM>(
create: (_) => SettingOptionsVM(
settingOptionsRepo: injector.get<SettingOptionsRepo>(),
)),
],
child: const MyApp(),
).setupLocale());
}
// todo terminal command to genertate translation files
// flutter pub run easy_localization:generate --source-dir ./assets/langs
// todo terminal command to genertate translation keys
// flutter pub run easy_localization:generate --source-dir ./assets/langs -f keys -o locale_keys.g.dart
// command to generate languages data from json
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Sizer(
builder: (context, orientation, deviceType) {
injector.get<AppState>().setAppType(AppType.provider);
AppState().setPostParamsModel(
PostParamsModel(
languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2,
),
);
// ThemeData data = AppTheme.getTheme(isArabic: EasyLocalization.of(context)?.locale.languageCode == "ar");
return MaterialApp(
theme: AppTheme.getTheme(isArabic: EasyLocalization.of(context)?.locale.languageCode == "ar"),
debugShowCheckedModeBanner: false,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
initialRoute: AppRoutes.initialRoute,
routes: ProviderAppRoutes.routes,
);
},
);
}
}

@ -0,0 +1,218 @@
// import 'dart:io';
//
// import 'package:car_provider_app/repositories/branch_repo.dart';
// import 'package:file_picker/file_picker.dart';
// import 'package:mc_common_app/models/m_response.dart';
// import 'package:mc_common_app/models/model/branch2.dart';
// import 'package:mc_common_app/models/profile/branch.dart';
// import 'package:mc_common_app/models/profile/categroy.dart';
// import 'package:mc_common_app/models/profile/document.dart';
// import 'package:mc_common_app/models/profile/services.dart';
// import 'package:mc_common_app/models/user/cities.dart';
// import 'package:mc_common_app/models/user/country.dart';
// import 'package:mc_common_app/repositories/common_repo.dart';
// import 'package:mc_common_app/services/services.dart';
// import 'package:mc_common_app/utils/enums.dart';
// import 'package:mc_common_app/utils/utils.dart';
// import 'package:mc_common_app/view_models/base_view_model.dart';
// import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
// import 'package:permission_handler/permission_handler.dart';
//
// class BranchVM extends BaseVM {
// final BranchRepo branchRepo;
// final CommonServices commonServices;
// final CommonRepo commonRepo;
//
// BranchVM({required this.branchRepo, required this.commonServices, required this.commonRepo});
//
// Document? document;
// Branch2? branchs;
//
// //Create Branch
// String countryCode = "", address = "", branchName = "", branchDescription = "";
// double latitude = 0, longitude = 0;
// int role = -1, countryId = -1, cityId = -1;
// List<DropValue> countryDropList = [];
// List<DropValue> citiesDropList = [];
// DropValue? countryValue;
// DropValue? cityValue;
//
// Country? country;
// Cities? cities;
//
// //Create Service
// String? branchNameForService;
// int categoryId = -1, branchId = -1, serviceId = -1;
// DropValue? branchValue;
//
// List<DropValue> countryDropListForService = [];
// List<DropValue> categoryDropList = [];
// List<DropValue> servicesDropList = [];
//
// Branch? branch;
// Category? category;
// Services? services;
//
// getServiceProviderDocument(int providerId) async {
// setState(ViewState.busy);
// document = await branchRepo.getServiceProviderDocument(providerId);
// setState(ViewState.idle);
// }
//
// selectFile(int index) async {
// File? file = await commonServices.pickFile(fileType: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg']);
//
// if (file != null) {
// int sizeInBytes = file.lengthSync();
// // double sizeInMb = sizeInBytes / (1024 * 1024);
// if (sizeInBytes > 1000) {
// Utils.showToast("File is larger then 1KB");
// } else {
// document!.data![index].document = Utils.convertFileToBase64(file);
// document!.data![index].fileExt = Utils.checkFileExt(file.path);
// document!.data![index].documentUrl = file.path;
// setState(ViewState.idle);
// }
// } else {
// // User canceled the picker
// }
// }
//
// Future<MResponse> updateDocument(List<DocumentData>? data) async {
// return await branchRepo.serviceProviderDocumentsUpdate(data);
// }
//
// //Create new branch
// getBranchAndServices() async {
// setState(ViewState.busy);
// branchs = await branchRepo.getBranchAndServices();
// setState(ViewState.idle);
// }
//
// getAllCountriesList(ServiceProviderBranch? branchData, String countryCode) async {
// setState(ViewState.busy);
// resetValues();
// country = await commonRepo.getAllCountries();
// country!.data?.forEach((element) {
// if (branchData != null) if (branchData.id != null) {
// if (element.id == branchData.countryID) {
// countryValue = DropValue(element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? "");
// }
// }
// countryDropList.add(DropValue(element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? ""));
// });
// if (branchData != null) if (branchData.id != null) getAllCities(branchData, countryCode);
// setState(ViewState.idle);
// }
//
// getAllCities(ServiceProviderBranch? branchData, String countryCode) async {
// setState(ViewState.busy);
// citiesDropList.clear();
// cities = null;
// cityId = -1;
// cities = await commonRepo.getAllCites(countryId.toString());
// cities!.data?.forEach((element) {
// if (branchData != null && branchData.id != null) {
// if (element.id == branchData.cityId) {
// address = branchData.address!;
// branchName = branchData.branchName!;
// branchDescription = branchData.branchDescription!;
// latitude = double.parse(branchData.latitude ?? "");
// longitude = double.parse(branchData.longitude ?? "");
// countryId = branchData.countryID!;
// cityId = branchData.cityId!;
// cityValue = DropValue(element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? "");
// }
// }
// citiesDropList.add(DropValue(element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), element.id.toString() ?? ""));
// });
// setState(ViewState.idle);
// }
//
// resetValues() {
// countryCode = "";
// address = "";
// branchName = "";
// branchDescription = "";
// latitude = 0;
// longitude = 0;
// role = -1;
// countryId = -1;
// cityId = -1;
// countryDropList.clear();
// countryId = -1;
// cityId = -1;
// cities = null;
// branchNameForService = null;
// categoryId = -1;
// branchId = -1;
// branchValue = null;
// serviceId = -1;
//
// countryDropListForService = [];
// categoryDropList = [];
// servicesDropList = [];
//
// branch = null;
// category = null;
// services = null;
// }
//
// Future<MResponse> createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async {
// return await branchRepo.createBranch(branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString());
// }
//
// Future<MResponse> updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}) async {
// return await branchRepo.updateBranch(id ?? 0, branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString());
// }
//
// //Create Service
// fetchBranches() async {
// resetValues();
// setState(ViewState.busy);
// branch = await branchRepo.fetchAllBranches();
// branch!.data?.forEach((element) {
// countryDropListForService.add(DropValue(element.id ?? 0, ((element.branchName!.isEmpty ? "N/A" : element.branchName) ?? "N/A"), ""));
// });
// setState(ViewState.idle);
// }
//
// fetchBranchCategory(String countryCode) async {
// category = null;
// services = null;
// categoryId = -1;
// categoryDropList.clear();
// setState(ViewState.busy);
// category = await branchRepo.fetchBranchCategory();
// category!.data?.forEach((element) {
// categoryDropList.add(DropValue(
// element.id ?? 0,
// ((element.categoryName!.isEmpty
// ? "N/A"
// : countryCode == "SA"
// ? element.categoryNameN
// : element.categoryName) ??
// "N/A"),
// ""));
// });
// setState(ViewState.idle);
// }
//
// fetchServicesByCategoryId() async {
// setState(ViewState.busy);
// services = await branchRepo.fetchServicesByCategoryId(categoryId.toString());
// servicesDropList = [];
// for (var element in services!.data!) {
// servicesDropList.add(DropValue(element.id ?? 0, element.description ?? "N/aA", ""));
// }
// setState(ViewState.idle);
// }
//
// Future<MResponse> createService(List<Map<String, dynamic>> map) async {
// return await branchRepo.createService(map);
// }
//
// Future<MResponse> updateServices(List<Map<String, dynamic>> map) async {
// return await branchRepo.updateService(map);
// }
// }

@ -0,0 +1,151 @@
import 'dart:io';
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/branch_management/branch/dealer/widget/add_phone_num_wiget.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/user_models/image_response.dart';
import 'package:mc_common_app/repositories/user_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/shipping_management_view_model.dart';
import 'package:provider/provider.dart';
import 'package:mc_common_app/utils/location/Location.dart';
import 'package:mc_common_app/utils/shared_prefrence.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
class DashboardVM extends BaseVM {
final CommonAppServices commonServices;
final UserRepo userRepo;
DashboardVM({required this.commonServices, required this.userRepo});
String pickedImage = "";
int selectedNavbarBarIndex = 2;
void onNavbarTapped(int index) async {
logger.i(AppState().getDeviceToken);
selectedNavbarBarIndex = index;
notifyListeners();
}
void pickImageFromPhone(BuildContext context, int sourceFlag) async {
final File? pickedImageFile = await commonServices.pickImageFromPhone(sourceFlag);
if (pickedImageFile == null) {
return;
}
int sizeInBytes = pickedImageFile.lengthSync();
if (sizeInBytes > 1000000) {
Utils.showToast(LocaleKeys.fileLarger.tr());
return;
} else {
String image64 = Utils.convertFileToBase64(pickedImageFile);
Utils.showLoading(context);
ImageResponse response = await userRepo.updateUserImage(image64);
Utils.hideLoading(context);
Navigator.pop(context);
if (response.messageStatus == 1) {
Utils.showToast(LocaleKeys.imageUploaded.tr());
AppState().getUser.data!.userInfo!.userImageUrl = response.data;
} else {
Utils.showToast(response.message ?? "");
}
}
}
Future<ImageResponse> updateUserImage(String image) async {
return await userRepo.updateUserImage(image);
}
fetchUsernameAndLocation() async {
String userName = await SharedPrefManager.getPhoneOrEmail();
Location.getCurrentLocation(
(LatLng? latlng) {
AppState().currentLocation = latlng ?? const LatLng(0, 0);
},
);
notifyListeners();
}
Future<void> onRefresh(BuildContext context) async {
final requestsVM = context.read<RequestsVM>();
final chatVM = context.read<ChatVM>();
final appointmentVM = context.read<AppointmentsVM>();
final shippingManagementVM = context.read<ShippingManagementVM>();
final serviceVM = context.read<ServiceVM>();
final adVm = context.read<AdVM>();
final subscriptionsVM = context.read<SubscriptionsVM>();
requestsVM.populateDataForRequestsFilter();
appointmentVM.populateAppointmentsFilterList();
shippingManagementVM.populateShippingRequestFilterList();
await serviceVM.getBranchAndServices();
await appointmentVM.getMyAppointmentsForProvider({"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0"});
adVm.populateAdsFilterList();
await chatVM.buildHubConnection(context);
await adVm.getMyAds();
await adVm.getExploreAds();
await adVm.getVehicleTypes();
await adVm.getVehicleAdsDuration();
await requestsVM.getRequests();
// await subscriptionsVM.getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
// await subscriptionsVM.getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
}
void checkUserSubscription(SubscriptionActionTypeEnum actionType, BuildContext context, {required Function() callback}) async {
switch (actionType) {
case SubscriptionActionTypeEnum.ads:
performCheckOnAds(context);
break;
case SubscriptionActionTypeEnum.users:
performCheckOnUsers(context, callback);
break;
case SubscriptionActionTypeEnum.branches:
performCheckOnBranches(context);
break;
}
}
void performCheckOnBranches(BuildContext context) async {
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.branchesRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
await navigateWithName(context, ProviderAppRoutes.defineBranch);
} else {
Utils.showToast("Upgrade your subscription to add more Branches.");
}
}
void performCheckOnAds(BuildContext context) async {
//adsRemaining
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.adsRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
await navigateWithName(context, ProviderAppRoutes.defineBranch);
} else {
Utils.showToast("Upgrade your subscription to add more Ads.");
}
}
void performCheckOnUsers(BuildContext context, Function() callBack) async {
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.subUsersRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
showMyBottomSheet(context, isDismissible: false, child: const AddPhoneNumWidget(), callBackFunc: callBack);
} else {
Utils.showToast("Upgrade your subscription to add more Sub Users.");
}
}
}

@ -0,0 +1,80 @@
import 'dart:io';
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/repositories/items_repo.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:file_picker/file_picker.dart';
import 'package:easy_localization/easy_localization.dart';
class ItemsVM extends BaseVM {
final ItemsRepo itemsRepo;
final CommonAppServices commonServices;
ItemsVM({required this.itemsRepo, required this.commonServices});
//Items
ItemModel? serviceItems;
Future<String?> selectFile(BuildContext context) async {
File? file = await commonServices.pickFile(context, fileType: FileType.image);
if (file != null) {
int sizeInBytes = file.lengthSync();
// double sizeInMb = sizeInBytes / (1024 * 1024);
if (sizeInBytes > 1000) {
Utils.showToast(LocaleKeys.fileLarger.tr());
} else {
return Utils.convertFileToBase64(file);
}
} else {
// User canceled the picker
}
return null;
}
Future<GenericRespModel> createServiceItem(Map map) async {
GenericRespModel response = await itemsRepo.createServiceItems(map);
return response;
}
Future<ItemModel?> getServiceItems(int serviceId, {List<PickerItem>? list}) async {
serviceItems = null;
setOnlyState(ViewState.busy);
serviceItems = await itemsRepo.getServiceItems(serviceId);
if (list != null) {
for (var element in list) {
for (var innerElement in serviceItems!.data!) {
if (element.id == innerElement.id) {
innerElement.isUpdateOrSelected = true;
}
}
// serviceItems!.data!.where(
// (innerElement) => element.id == innerElement.id
// ? innerElement.isUpdateOrSelected = true
// : innerElement.isUpdateOrSelected = true,
// );
}
}
setState(ViewState.idle);
return serviceItems;
}
Future<GenericRespModel> updateServiceItem(Map map) async {
GenericRespModel response = await itemsRepo.updateServiceItem(map);
return response;
}
Future<File?> pickSingleFile(BuildContext context) async {
File? file = await commonServices.pickFile(context, fileType: FileType.custom, allowedExtensions: ['jpg', 'png', 'jpeg']);
if (file == null) return null;
return file;
}
}

@ -0,0 +1,126 @@
import 'package:mc_common_app/models/appointments_models/schedule_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
import 'package:mc_common_app/repositories/schedule_repo.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
List<PickerItem> initDaysList = [
PickerItem(id: 1, title: "Monday", isSelected: false),
PickerItem(id: 2, title: "Tuesday", isSelected: false),
PickerItem(id: 3, title: "Wednesday", isSelected: false),
PickerItem(id: 4, title: "Thursday", isSelected: false),
PickerItem(id: 5, title: "Friday", isSelected: false),
PickerItem(id: 6, title: "Saturday", isSelected: false),
PickerItem(id: 7, title: "Sunday", isSelected: false),
];
class ScheduleVM extends BaseVM {
ScheduleRepo scheduleRepo;
ScheduleVM({required this.scheduleRepo});
List<PickerItem> selectedServicesItems = [];
List<ServicesData>? servicesList;
List<PickerItem> selectedDaysItems = [];
Schedule? schedule;
refresh() {
setState(ViewState.idle);
}
Future<GenericRespModel> setScheduleInactive(int scheduleId, int branchId) async {
GenericRespModel val = await scheduleRepo.setScheduleInActive(scheduleId, branchId);
if (val.messageStatus == 1) {
if (schedule!.data != null) {
schedule!.data!.removeWhere((element) => element.serviceProviderBranchId == branchId && element.id == scheduleId);
} else {
Utils.showToast(val.message ?? "");
}
}
return val;
}
getAllServices(String branchId, ScheduleData selectedSchedule) async {
// if (servicesList == null) {
servicesList = null;
Services services = await scheduleRepo.getAllServices(branchId);
if (services.messageStatus == 1) {
servicesList = services.data;
if (selectedSchedule.id != null) {
for (var element in servicesList!) {
for (var innerElement in selectedSchedule.scheduleServices!) {
if (element.id == innerElement.providerServiceId) {
element.isSelected = true;
}
}
}
}
}
setState(ViewState.idle);
// }
}
filterSelectedServices() {
if (servicesList != null) {
selectedServicesItems = [];
for (var element in servicesList!) {
if (element.isSelected ?? false) {
selectedServicesItems.add(PickerItem(id: element.id ?? 0, title: element.description ?? ""));
}
}
setState(ViewState.idle);
}
}
//Days
List<PickerItem> intiDays() {
for (var element in initDaysList) {
element.isSelected = false;
for (var innerElement in selectedDaysItems) {
if (element.id == innerElement.id) {
element.isSelected = true;
}
}
}
return initDaysList;
}
filterDays(List<PickerItem> picked) {
selectedDaysItems = [];
for (var element in picked) {
if (element.isSelected ?? false) {
selectedDaysItems.add(element);
}
}
setState(ViewState.idle);
}
Future<GenericRespModel> createSchedule(Map map) async {
GenericRespModel response = await scheduleRepo.createSchedule(map);
return response;
}
Future<GenericRespModel> addServicesInSchedule(Map map) async {
GenericRespModel response = await scheduleRepo.addServicesInSchedule(map);
return response;
}
getSchedules(String branchId) async {
schedule = null;
schedule = await scheduleRepo.getSchedules(branchId);
setState(ViewState.idle);
}
Future<GenericRespModel> updateSchedule(Map map) async {
GenericRespModel response = await scheduleRepo.updateSchedule(map);
return response;
}
Future<GenericRespModel> updateServicesInSchedule(Map map) async {
GenericRespModel response = await scheduleRepo.updateServicesInSchedule(map);
return response;
}
}

@ -0,0 +1,289 @@
import 'dart:async';
import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/appoinments/widget/select_items_sheet.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class AddNewServiceAppointmentPage extends StatefulWidget {
final AppointmentListModel appointmentListModel;
const AddNewServiceAppointmentPage(this.appointmentListModel, {Key? key}) : super(key: key);
@override
State<AddNewServiceAppointmentPage> createState() => _AddNewServiceAppointmentPageState();
}
class _AddNewServiceAppointmentPageState extends State<AddNewServiceAppointmentPage> {
DropValue? category;
DropValue? service;
List<ItemData> selectedList = [];
List<PickerItem>? pickedItems;
ServiceVM? serviceVM;
@override
void initState() {
// TODO: implement initState
super.initState();
scheduleMicrotask(() {
serviceVM = context.read<ServiceVM>();
serviceVM!.fetchBranchCategory(EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.white,
appBar: CustomAppBar(
title: LocaleKeys.addService.tr(),
),
body: Padding(
padding: const EdgeInsets.all(21.0),
child: Stack(
fit: StackFit.expand,
children: [
SingleChildScrollView(
child: Column(
children: [
GeneralAppointmentWidget(
appointmentListModel: widget.appointmentListModel,
isNeedTotalPayment: true,
isNeedToShowItems: true,
isNeedToShowToMoreText: false,
onTap: () {},
),
12.height,
Consumer<ServiceVM>(
builder: (context, model, _) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.selectServicestoAdd.tr().toText(
fontSize: 18,
isBold: true,
),
12.height,
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
model.categoryDropList.isNotEmpty
? DropdownField(
(DropValue value) async {
category = value;
service = null;
model.fetchProviderServices(widget.appointmentListModel.branchId.toString(), value.id.toString());
},
dropdownValue: category,
list: model.categoryDropList,
hint: LocaleKeys.selectServiceCategory.tr(),
)
: const Center(
child: CircularProgressIndicator(),
),
12.height,
model.servicesDropList.isNotEmpty
? DropdownField(
(DropValue value) {
service = value;
pickedItems = null;
model.setState(ViewState.idle);
showMyBottomSheet(
context,
child: SelectItemsSheet(
serviceId: service?.id ?? 0,
onSelectItems: (List<ItemData> selectedList) {
this.selectedList.clear();
this.selectedList = selectedList;
pickedItems = [];
for (var element in selectedList) {
pickedItems!.add(
PickerItem(id: element.id ?? 0, title: element.name ?? ""),
);
}
model.notifyListeners();
},
),
);
},
dropdownValue: service,
list: model.servicesDropList,
hint: LocaleKeys.defineServices.tr(),
)
: category == null
? Container()
: model.services != null && model.servicesDropList.isEmpty
? Text(LocaleKeys.noServiceFound.tr())
: const CircularProgressIndicator(),
12.height,
(service != null && pickedItems != null && pickedItems!.isNotEmpty)
? ChipsPickerItem(
hint: LocaleKeys.selectItems.tr(),
itemsList: [...pickedItems ?? []],
onClick: () {
showMyBottomSheet(
context,
child: SelectItemsSheet(
serviceId: service?.id ?? 0,
list: pickedItems,
onSelectItems: (List<ItemData> selectedList) {
pickedItems = [];
for (var element in selectedList) {
pickedItems!.add(
PickerItem(id: element.id ?? 0, title: element.name ?? ""),
);
}
model.notifyListeners();
},
),
);
},
)
: service != null
? Text(LocaleKeys.noItemSelectedYet.tr())
: const SizedBox(),
if ((service != null && pickedItems != null && pickedItems!.isNotEmpty))
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
16.height,
LocaleKeys.totalAdditionalAmount.tr().toText(
fontSize: 14,
isBold: true,
color: MyColors.lightTextColor,
),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
calculatePrice().toString().toText(
fontSize: 29,
isBold: true,
),
2.width,
LocaleKeys.sar
.tr()
.toText(
fontSize: 16,
isBold: true,
color: MyColors.lightTextColor,
)
.paddingOnly(bottom: 5),
],
),
],
),
],
),
],
).toWhiteContainer(width: double.infinity, allPading: 12),
],
);
},
),
],
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Row(
children: [
Expanded(
child: ShowFillButton(
title: LocaleKeys.cancel.tr(),
maxWidth: double.infinity,
isFilled: false,
txtColor: MyColors.redColor,
borderColor: MyColors.redColor,
onPressed: () {
if (pickedItems != null && pickedItems!.isNotEmpty) {
pickedItems!.clear();
}
pop(context);
},
),
),
12.width,
Expanded(
child: ShowFillButton(
title: LocaleKeys.add.tr(),
maxWidth: double.infinity,
onPressed: () async {
if (pickedItems != null && pickedItems!.isNotEmpty) {
List<int> items = [];
pickedItems?.forEach((element) {
items.add(element.id);
});
Utils.showLoading(context);
var postParams = {"providerBranchID": widget.appointmentListModel.branchId, "appointmentID": widget.appointmentListModel.id, "serviceItemID": items};
GenericRespModel res = await serviceVM!.addNewServiceInAppointment(postParams);
_updateAppointment(context, widget.appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
if (res.messageStatus == 1) {
Utils.showToast(LocaleKeys.itemsAddedSuccessfully.tr());
pop(context);
pop(context);
} else {
Utils.showToast(res.message.toString());
}
} else {
Utils.showToast(LocaleKeys.pleaseSelectItems.tr());
}
},
),
),
],
).toWhiteContainer(width: double.infinity),
),
],
),
),
);
}
Future<void> _updateAppointment(BuildContext context, int branchId) async {
await context.read<AppointmentsVM>().getMyAppointmentsForProvider(
{
"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0",
"ProviderBranchID": branchId.toString(),
},
);
}
double calculatePrice() {
double total = 0;
for (var element in selectedList) {
total = total + double.parse(element.price ?? "0");
}
return total;
}
}

@ -0,0 +1,70 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class AppointmentDetailListPage extends StatelessWidget {
const AppointmentDetailListPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.appointment_details.tr(),
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Expanded(
child: Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
if (appointmentsVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
return ListView.separated(
itemBuilder: (context, index) {
return GeneralAppointmentWidget(
appointmentListModel: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index],
isNeedTotalPayment: true,
isNeedToShowAppointmentStatus: true,
isNeedToShowMergeStatus: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].isMerged ?? false,
onTap: () {
appointmentsVM.selectedAppointmentId = appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index].id ?? 0;
appointmentsVM.selectedAppointmentSubIndex = index;
navigateWithName(context, ProviderAppRoutes.updateAppointmentPage, arguments: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index]);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!.length,
padding: const EdgeInsets.all(21),
);
}
}),
),
context.read<AppointmentsVM>().isShowMergeButton()
? ShowFillButton(
title: LocaleKeys.mergeAppointments.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(21),
onPressed: () {
navigateWithName(context, ProviderAppRoutes.mergeAppointments);
},
)
: const SizedBox(),
],
)),
);
}
}

@ -0,0 +1,268 @@
import 'dart:async';
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/categories_list.dart';
import 'package:mc_common_app/widgets/empty_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class AppointmentPage extends StatefulWidget {
BranchDetailModel branch;
AppointmentPage({
required this.branch,
Key? key,
}) : super(key: key);
@override
State<AppointmentPage> createState() => _AppointmentPageState();
}
class _AppointmentPageState extends State<AppointmentPage> {
String date = "";
GlobalKey<RefreshIndicatorState> refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
Future<void> _pullRefresh(BuildContext context) async {
await context.read<AppointmentsVM>().getAppointmentSlotsInfo(
context: context,
map: {"ProviderBranchID": widget.branch.id.toString(), "FromDate": date, "ToDate": date},
isNeedToRebuild: true,
);
await context.read<AppointmentsVM>().getMyAppointmentsForProvider({
"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0",
"ProviderBranchID": widget.branch.id.toString(),
"FromDate": date,
"DateTo": date,
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
scheduleMicrotask(() {
date = DateHelper.formatAsYearMonthDay(DateTime.now());
context.read<AppointmentsVM>().populateAppointmentsFilterList();
_pullRefresh(context);
context.read<AppointmentsVM>().selectedBranch = widget.branch.id ?? 0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
//profileImageUrl: MyAssets.carBanner,
title: widget.branch.branchName,
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
if (appointmentsVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
return RefreshIndicator(
onRefresh: () => _pullRefresh(context),
key: refreshIndicatorKey,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
progressWidget(context, appointmentsVM),
FiltersList(
filterList: appointmentsVM.appointmentsFilterOptions,
padding: const EdgeInsets.symmetric(horizontal: 18),
onFilterTapped: (index, selectedFilterId) {
appointmentsVM.applyFilterOnAppointmentsVM(
appointmentStatusEnum: selectedFilterId.toAppointmentStatusEnum(),
isNeedCustomerFilter: true,
);
},
),
if (appointmentsVM.myFilteredAppointments2.isEmpty)
EmptyWidget(
spacerWidget: const SizedBox(height: 25),
text: LocaleKeys.noAppointmentFound.tr(),
),
ListView.separated(
itemBuilder: (context, index) {
return GeneralAppointmentWidget(
appointmentListModel: appointmentsVM.myFilteredAppointments2[index],
isNeedTotalPayment: false,
onTap: () {
context.read<AppointmentsVM>().selectedAppointmentIndex = index;
navigateWithName(
context,
ProviderAppRoutes.appointmentDetailList,
// arguments: appointmentsVM
// .myFilteredAppointments2[index]
// .customerAppointmentList,
);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM.myFilteredAppointments2.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.all(21),
),
],
),
),
);
}
}),
),
);
}
Widget progressWidget(BuildContext context, AppointmentsVM appointmentsVM) {
double percent = 0.0;
if (appointmentsVM.appointmentSlots != null) {
percent = appointmentsVM.appointmentSlots!.occupiedSlots / appointmentsVM.appointmentSlots!.totalSlots;
}
return Column(
children: [
Row(
children: [
Expanded(
child: LocaleKeys.slotsOverview.tr().toText(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Row(
children: [
date.toText(
fontWeight: FontWeight.bold,
),
const Icon(
Icons.keyboard_arrow_down_outlined,
size: 16,
),
],
)
.toContainer(
backgroundColor: MyColors.lightGreyEAColor,
borderRadius: 100,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
)
.onPress(() async {
date = await Utils.pickDateFromDatePicker(
context,
firstDate: null,
);
_pullRefresh(context);
// context.read<AppointmentsVM>().notifyListeners();
}),
],
),
24.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 14,
height: 14,
color: MyColors.lightGreyEAColor,
),
4.width,
(LocaleKeys.empty.tr() + ":").toText(
fontSize: 8,
color: Colors.white,
),
(appointmentsVM.appointmentSlots?.emptySlots ?? 0).toString().toText(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Colors.white,
),
],
).toContainer(
backgroundColor: MyColors.darkIconColor,
),
8.height,
Row(
children: [
Container(
width: 14,
height: 14,
color: MyColors.darkPrimaryColor,
),
4.width,
(LocaleKeys.occupied.tr() + ":").toText(
fontSize: 8,
color: Colors.white,
),
(appointmentsVM.appointmentSlots?.occupiedSlots ?? 0).toString().toText(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Colors.white,
),
],
).toContainer(
backgroundColor: MyColors.darkIconColor,
),
],
),
CircularPercentIndicator(
radius: 60.0,
lineWidth: 12.0,
percent: percent,
circularStrokeCap: CircularStrokeCap.round,
center: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LocaleKeys.totalSlots.tr().toText(
fontSize: 13,
fontWeight: FontWeight.bold,
),
(appointmentsVM.appointmentSlots?.totalSlots ?? 0).toString().toText(
fontSize: 24,
fontWeight: FontWeight.bold,
),
],
),
backgroundColor: MyColors.lightGreyEAColor,
progressColor: MyColors.darkPrimaryColor,
),
],
)
],
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
margin: const EdgeInsets.all(21),
);
}
}

@ -0,0 +1,119 @@
import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class MergeAppointmentListPage extends StatelessWidget {
const MergeAppointmentListPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.selectAppointments.tr(),
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Consumer(
builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
return Column(
children: [
Expanded(
child: Column(
children: [
Expanded(
child: (appointmentsVM.state == ViewState.busy)
? const Center(child: CircularProgressIndicator())
: ListView.separated(
itemBuilder: (context, index) {
return GeneralAppointmentWidget(
appointmentListModel: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![index],
isNeedTotalPayment: true,
isSelectable: true,
isNeedToShowAppointmentStatus: true,
isNeedToShowMergeStatus: true,
onTap: () {
appointmentsVM.updateCheckBoxInMergeRequest(index);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!.length,
padding: const EdgeInsets.all(21),
),
),
],
),
),
ShowFillButton(
title: LocaleKeys.mergeAppointments.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(21),
txtColor: appointmentsVM.inNeedToEnableMergeButton ? MyColors.white : MyColors.black,
backgroundColor: appointmentsVM.inNeedToEnableMergeButton ? MyColors.primaryColor : MyColors.greyButtonColor,
onPressed: () async {
Utils.showLoading(context);
List<int> appointmentIDs = [];
for (var element in appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList!) {
if (element.isSelected ?? false) {
appointmentIDs.add(element.id ?? 0);
}
}
Map<String, dynamic> map = {
"serviceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0",
"serviceProviderBranchID": appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].branchId,
"serviceAppointmentIDs": appointmentIDs
};
try {
GenericRespModel response = await appointmentsVM.createMergeAppointment(map);
Utils.hideLoading(context);
if (response.messageStatus == 1) {
Utils.showToast(LocaleKeys.appointmentMergeSuccessfully.tr());
_updateAppointment(context, appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].branchId ?? 0);
pop(context);
pop(context);
} else {
Utils.showToast(response.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
Utils.hideLoading(context);
}
},
),
],
);
},
),
),
);
}
Future<void> _updateAppointment(BuildContext context, int branchId) async {
await context.read<AppointmentsVM>().getMyAppointmentsForProvider({
"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0",
"ProviderBranchID": branchId.toString(),
});
}
}

@ -0,0 +1,287 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/appoinments/widget/sheets.dart';
import 'package:car_provider_app/views/dashboard/widget/general_appointment_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class UpdateAppointmentPage extends StatelessWidget {
late AppointmentListModel appointmentListModel;
UpdateAppointmentPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.updateAppointment.tr()),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
appointmentListModel = appointmentsVM.myFilteredAppointments2[appointmentsVM.selectedAppointmentIndex].customerAppointmentList![appointmentsVM.selectedAppointmentSubIndex];
if (appointmentsVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
return Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.all(21),
children: [
GeneralAppointmentWidget(
appointmentListModel: appointmentListModel,
isNeedTotalPayment: true,
isNeedToShowItems: true,
isNeedToShowToMoreText: false,
onTap: () {},
),
21.height,
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.confirmed ||
appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.arrived ||
appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.workStarted) ...[
ShowFillButton(
title: ("+ ${LocaleKeys.addNewService.tr()}"),
txtColor: MyColors.darkPrimaryColor,
isFilled: false,
onPressed: () {
navigateWithName(
context,
ProviderAppRoutes.addServiceInAppointment,
arguments: appointmentListModel,
);
},
),
],
],
),
),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.cancelled) ...[
Utils.buildStatusContainer("Appointment Cancelled").paddingAll(10),
],
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: showPayNowButton(context, appointmentsVM)),
12.width,
Expanded(child: showCancelButton(context, appointmentsVM)),
],
).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.confirmed &&
(appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.payPartial || appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.defaultStatus))
Column(
children: [
showArrivedButton(context, appointmentsVM),
],
).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.arrived &&
(appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.payPartial || appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.defaultStatus))
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: showPayNowButton(context, appointmentsVM)),
12.width,
Expanded(child: showPayLaterButton(context, appointmentsVM)),
],
).paddingAll(21),
if ((appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.arrived || appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.workStarted) &&
appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.payNow)
Utils.buildStatusContainer(LocaleKeys.waitingPaymentfromtheCustomer.tr()).paddingAll(10),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.arrived &&
(appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.paid || appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.payLater))
Column(
children: [
showWorkStartButton(context, appointmentsVM),
],
).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.workStarted && appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.payPartial)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: showPayNowButton(context, appointmentsVM)),
12.width,
Expanded(child: showPayLaterButton(context, appointmentsVM)),
],
).paddingAll(21),
// "Show Pay Now".toText(),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.workStarted && appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.paid)
Column(
children: [
showCompleteButton(context, appointmentsVM),
],
).paddingAll(21),
// "Show Complete Button".toText(),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.workStarted && appointmentListModel.appointmentPaymentStatusEnum == AppointmentPaymentStatusEnum.payLater)
showPayNowButton(context, appointmentsVM).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.visitCompleted) ...[
Utils.buildStatusContainer(LocaleKeys.appointmentisCompleted.tr()).paddingAll(10),
],
//TODO: THIS NEEDS TO BE CHECKED. IMPORTANT
// Padding(
// padding: const EdgeInsets.all(21.0),
// child: Column(
// children: [
// ShowFillButton(
// title: "Confirm Arrive",
// maxWidth: double.infinity,
// onPressed: () {
// showMyBottomSheet(
// context,
// child: ShowCollectPaymentSheet(
// onClickYes: () {},
// onClickNo: () {},
// ),
// );
// },
// ),
// 12.height,
// ShowFillButton(
// title: "Cancel Appointment",
// maxWidth: double.infinity,
// isFilled: false,
// txtColor: MyColors.redColor,
// borderColor: MyColors.redColor,
// onPressed: () {
// showMyBottomSheet(context,
// child: CancelAppointmentReasonSheet(
// onCancelClick: (String reason) {},
// ));
// },
// ),
// ],
// ),
// ),
],
);
}
})),
);
}
Widget showWorkStartButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: LocaleKeys.workStart.tr(),
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentStatus(appointmentId: appointmentListModel.id!, appointmentStatusEnum: AppointmentStatusEnum.workStarted);
Utils.hideLoading(context);
pop(context);
// showMyBottomSheet(
// context,
// child: ShowCollectPaymentSheet(
// onClickYes: () {},
// onClickNo: () {},
// ),
// );
},
);
}
Widget showPayNowButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: LocaleKeys.payNow.tr(),
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentPaymentStatus({"appointmentID": appointmentListModel.id.toString(), "appointmentServicePaymentStatusID": 2});
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
pop(context);
},
);
}
Widget showArrivedButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: LocaleKeys.arrived.tr(),
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentStatus(appointmentId: appointmentListModel.id!, appointmentStatusEnum: AppointmentStatusEnum.arrived);
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
pop(context);
},
);
}
Widget showPayLaterButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: LocaleKeys.payLater.tr(),
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentPaymentStatus({"appointmentID": appointmentListModel.id.toString(), "appointmentServicePaymentStatusID": 4});
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
pop(context);
},
);
}
Widget showCompleteButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: LocaleKeys.complete.tr(),
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentStatus(appointmentId: appointmentListModel.id!, appointmentStatusEnum: AppointmentStatusEnum.visitCompleted);
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
pop(context);
},
);
}
Widget showCancelButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: LocaleKeys.cancel.tr(),
maxWidth: double.infinity,
isFilled: false,
txtColor: MyColors.redColor,
borderColor: MyColors.redColor,
onPressed: () {
showMyBottomSheet(
context,
child: ShowCollectPaymentSheet(
onClickYes: () {},
onClickNo: () {},
),
);
},
);
}
Future<void> _updateAppointment(BuildContext context, int branchId) async {
await context.read<AppointmentsVM>().getMyAppointmentsForProvider({
"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0",
"ProviderBranchID": branchId.toString(),
});
}
}

@ -0,0 +1,109 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:sizer/sizer.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:easy_localization/easy_localization.dart';
class AppointmentDetailListWidget extends StatelessWidget {
bool isNeedClick;
AppointmentDetailListWidget({Key? key, this.isNeedClick = true}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"Olaya Brach".toText(
fontSize: 12,
color: MyColors.darkTextColor,
isBold: true,
),
"Abdullah Alhbas".toText(
fontSize: 14,
isBold: true,
),
Row(
children: [
"Appt. On:".toText(
color: MyColors.lightTextColor,
),
2.width,
"19-Mar-2023 11:48 AM".toText(),
],
),
],
),
),
SvgPicture.asset(
MyAssets.icEdit,
color: Colors.black,
width: 20,
height: 20,
)
],
),
8.height,
showServices("Maintenance"),
2.height,
showServices("Accessories and Modification"),
24.height,
LocaleKeys.totalAmount.tr().toText(
fontSize: 12,
color: MyColors.lightTextColor,
isBold: true,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"30,000".toText(fontSize: 16, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(
color: MyColors.lightTextColor,
),
],
),
],
).toWhiteContainer(
width: double.infinity,
allPading: 12,
onTap: () {
if (isNeedClick) navigateWithName(context, ProviderAppRoutes.updateAppointmentPage);
},
);
}
Widget showServices(String title) {
return Row(
children: [
const Icon(
Icons.ac_unit,
color: MyColors.primaryColor,
size: 18,
),
8.width,
title.toText(
fontSize: 14,
isBold: true,
),
],
);
}
}

@ -0,0 +1,117 @@
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/empty_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class SelectItemsSheet extends StatelessWidget {
int serviceId;
Function(List<ItemData>) onSelectItems;
List<PickerItem>? list;
SelectItemsSheet({Key? key, required this.serviceId, required this.onSelectItems, this.list}) : super(key: key);
@override
Widget build(BuildContext context) {
context.read<ItemsVM>().getServiceItems(serviceId, list: list);
return SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.4,
child: Column(
children: [
Expanded(
child: Consumer<ItemsVM>(
builder: (_, itemsVM, child) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 6),
child: Column(
children: [
Row(
children: [
Expanded(
child: LocaleKeys.selectItems.tr().toText(fontSize: 24, isBold: true),
),
Center(
child: (itemsVM.serviceItems == null ? "0" : itemsVM.serviceItems!.data!.where((element) => element.isUpdateOrSelected == true).toList().length.toString()).toText(
fontSize: 10,
isBold: true,
color: Colors.white,
),
).toContainer(
borderRadius: 100,
width: 24,
height: 24,
paddingAll: 0,
backgroundColor: MyColors.darkPrimaryColor,
),
],
),
// 12.height,
// TxtField(
// hint: LocaleKeys.searchItems.tr(),
// onChanged: (v) {},
// ),
12.height,
Expanded(
child: itemsVM.serviceItems?.data == null
? const Center(child: CircularProgressIndicator())
: itemsVM.serviceItems?.data!.length == 0
? Center(child: EmptyWidget(text: LocaleKeys.noItemstoShow.tr()))
: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
contentPadding: EdgeInsets.zero,
controlAffinity: ListTileControlAffinity.leading,
title: itemsVM.serviceItems!.data![index].name!.toText(fontSize: 16),
subtitle: itemsVM.serviceItems!.data![index].price.toString().toText(fontSize: 14, color: MyColors.lightTextColor),
value: itemsVM.serviceItems!.data![index].isUpdateOrSelected,
onChanged: (bool? v) {
itemsVM.serviceItems!.data![index].isUpdateOrSelected = v;
itemsVM.notifyListeners();
},
);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider(height: 1);
},
itemCount: itemsVM.serviceItems?.data?.length ?? 0,
),
),
],
),
);
},
),
),
ShowFillButton(
title: LocaleKeys.addSelectedItems.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
if (context.read<ItemsVM>().serviceItems != null) {
List<ItemData> list = [];
for (var element in context.read<ItemsVM>().serviceItems!.data!) {
if (element.isUpdateOrSelected ?? false) {
list.add(element);
}
}
onSelectItems(list);
}
Navigator.pop(context);
},
)
],
),
);
}
}

@ -0,0 +1,188 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:easy_localization/easy_localization.dart';
class ShowCollectPaymentSheet extends StatelessWidget {
Function() onClickYes;
Function() onClickNo;
ShowCollectPaymentSheet(
{required this.onClickYes, required this.onClickNo, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 12),
child: Column(
children: [
LocaleKeys.collectMoneyBefore.tr().toText(
fontSize: 24,
isBold: true,
),
21.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: LocaleKeys.yes.tr(),
onPressed: onClickYes,
),
),
12.width,
Expanded(
child: ShowFillButton(
title: LocaleKeys.no.tr(),
isFilled: false,
txtColor: MyColors.darkPrimaryColor,
onPressed: onClickNo,
),
),
],
),
],
),
);
}
}
class Reason {
String title;
bool isSelected;
Reason(this.title, this.isSelected);
}
class CancelAppointmentReasonSheet extends StatefulWidget {
Function(String) onCancelClick;
CancelAppointmentReasonSheet({required this.onCancelClick, Key? key})
: super(key: key);
@override
State<CancelAppointmentReasonSheet> createState() =>
_CancelAppointmentReasonSheetState();
}
class _CancelAppointmentReasonSheetState
extends State<CancelAppointmentReasonSheet> {
String reason = "";
List<Reason> reasonList = [
Reason("Operational Issue", true),
Reason("Material Issue", false),
Reason("The customer no longer responding", false),
Reason("Other", false),
];
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 21, right: 21, top: 12, bottom: 21),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.reason.tr().toText(fontSize: 24, isBold: true),
ListView.separated(
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 12, bottom: 12),
child: Row(
children: [
Container(
width: 14,
height: 14,
decoration: BoxDecoration(
color: reasonList[index].isSelected
? MyColors.darkPrimaryColor
: Colors.transparent,
borderRadius: BorderRadius.circular(122),
border: Border.all(
color: reasonList[index].isSelected
? MyColors.darkPrimaryColor
: borderColor,
width: 1),
),
child: const Icon(
Icons.done,
size: 12,
color: Colors.white,
),
),
12.width,
reasonList[index].title.toText(isBold: true)
],
),
).onPress(() {
for (var element in reasonList) {
element.isSelected = false;
}
setState(() {
reason = reasonList[index].title;
reasonList[index].isSelected = true;
});
});
},
separatorBuilder: (context, index) {
return Container(
width: double.infinity,
height: 1,
color: MyColors.borderColor,
);
},
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: reasonList.length,
),
if (reason == "Other")
TxtField(
hint: LocaleKeys.typeHere.tr(),
maxLines: 5,
onChanged: (v) {
reason = v;
},
),
12.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: LocaleKeys.no.tr(),
isFilled: false,
txtColor: MyColors.darkPrimaryColor,
onPressed: () {
pop(context);
},
),
),
12.width,
Expanded(
child: ShowFillButton(
title: LocaleKeys.yes.tr(),
onPressed: () {
if (reason.isEmpty || reason == "Other") {
Utils.showToast(LocaleKeys.pleaseSelectReason.tr());
} else {
widget.onCancelClick(reason);
pop(context);
}
},
),
),
],
)
],
),
);
}
}

@ -0,0 +1,370 @@
import 'dart:async';
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/branch_management/branch/dealer/widget/assign_dealer_user_sheet.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/branch_management/services/services_list_page.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/row_with_arrow.dart';
import 'package:provider/provider.dart';
class BranchDetailPage extends StatelessWidget {
final BranchDetailModel branchData;
const BranchDetailPage(this.branchData, {super.key});
getBranchUsers(BuildContext context) {
scheduleMicrotask(() {
if (context.read<ServiceVM>().allProviderDealersList.isNotEmpty) {
context.read<ServiceVM>().getAllProviderDealers(
{"ServiceProviderBranchID": branchData.id.toString(), "ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""},
);
}
context.read<ServiceVM>().filterUserBranchCategories();
});
}
bool validation(BuildContext context) {
bool isValid = false;
for (var element in context.read<ServiceVM>().allProviderDealersList) {
if (element.isBranchUser ?? false) {
isValid = true;
}
}
return isValid;
}
Widget showData(String title, String value) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title.toText(
fontSize: 12,
color: MyColors.darkTextColor,
),
if (title.isNotEmpty) 8.width,
Flexible(
child: value.toText(
fontSize: 12,
color: MyColors.textColor,
),
)
],
);
}
Widget pendingApprovalAction({required String pendingText}) {
return Center(
child: pendingText.toText(color: MyColors.lightTextColor, fontSize: 15),
).toContainer(
paddingAll: 15,
borderRadius: 8,
width: double.infinity,
backgroundColor: MyColors.grey98Color.withOpacity(0.1),
);
}
Widget buildFooterActionWidget(BuildContext context) {
Widget actionWidget = const SizedBox();
if (AppState().userType == UserType.providerDealer && branchData.branchStatus == BranchStatusEnum.approvedOrActive) {
actionWidget = ShowFillButton(
title: LocaleKeys.assignDealerUser.tr(),
maxWidth: double.infinity,
backgroundColor: Colors.transparent,
borderColor: MyColors.darkPrimaryColor,
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
isFilled: false,
onPressed: () async {
showMyBottomSheet(
context,
child: AssignDealerUserSheet(
branchId: branchData.id.toString(),
callBackFunc: () {
getBranchUsers(context);
},
),
);
},
);
} else if (branchData.branchStatus == BranchStatusEnum.pending) {
actionWidget = pendingApprovalAction(pendingText: "Approval Pending");
} else if (branchData.branchStatus == BranchStatusEnum.deactivated) {
actionWidget = pendingApprovalAction(pendingText: "Activate Now");
} else if (branchData.branchStatus == BranchStatusEnum.rejected) {
actionWidget = Column(
children: [
Row(
children: [
('${LocaleKeys.rejectionComments.tr()}:').toText(fontSize: 16, color: MyColors.darkTextColor, textAlign: TextAlign.right),
],
),
Row(
children: [
if (branchData.branchAuditTrial != null && branchData.branchAuditTrial!.isNotEmpty) ...[
Flexible(
child: ("${branchData.branchAuditTrial!.first.comment}").toText(
fontSize: 14,
color: MyColors.primaryColor,
isItalic: true,
),
),
]
],
),
12.height,
ShowFillButton(
title: LocaleKeys.rejectedFormAdmin.tr(),
maxWidth: double.infinity,
backgroundColor: MyColors.darkWhiteColor,
borderColor: MyColors.darkPrimaryColor,
txtColor: MyColors.lightTextColor,
isFilled: true,
onPressed: () {},
),
],
);
}
return actionWidget.paddingAll(21);
}
Widget buildServiceTileWidget(int pIndex, ServiceVM serviceVM) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(top: 5),
child: SvgPicture.asset(
MyAssets.maintenanceIcon,
width: 14,
height: 14,
),
),
8.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
serviceVM.categories[pIndex].categoryName.toString().toText(fontSize: 16),
],
),
8.height,
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
return Container(
child: (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA"
? serviceVM.categories[pIndex].services![index].serviceDescriptionN.toString()
: serviceVM.categories[pIndex].services![index].serviceDescription.toString())
.toText(
fontSize: 12,
color: MyColors.lightTextColor,
),
);
},
itemCount: serviceVM.categories[pIndex].services?.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.zero,
),
),
],
).withArrow(isArrowEnabled: true)
],
)),
],
).toWhiteContainer(width: double.infinity, allPading: 12);
}
@override
Widget build(BuildContext context) {
getBranchUsers(context);
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.branchDetail.tr()),
body: Consumer<ServiceVM>(builder: (context, serviceVM, _) {
return SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
10.height,
Column(
children: [
Row(
children: [
Expanded(
child: Row(
children: [
branchData.branchProfileImage.buildNetworkImage(height: 66, width: 53, fit: BoxFit.cover),
11.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(branchData.branchName!).toText(fontSize: 16, color: MyColors.darkTextColor),
showData("", branchData.branchDescription.toString()),
],
),
),
],
),
),
if (branchData.branchStatus != BranchStatusEnum.pending) ...[
SvgPicture.asset(MyAssets.icEdit).onPress(() {
navigateWithName(context, ProviderAppRoutes.defineBranch, arguments: branchData);
}),
],
],
),
Column(
children: [
showData("${LocaleKeys.location.tr()}:", "${branchData.cityName.toString()}, ${branchData.countryName.toString()}"),
showData("${LocaleKeys.provider.tr()}:", branchData.serviceProviderName.toString()),
showData("${LocaleKeys.time.tr()}:", "${branchData.openTime.toString()} - ${branchData.closeTime.toString()}"),
showData("${LocaleKeys.address.tr()}:", branchData.address.toString()),
],
).paddingOnly(left: 65),
],
).horPaddingMain(),
10.height,
Container(
width: double.infinity,
color: MyColors.darkIconColor,
padding: const EdgeInsets.symmetric(horizontal: 21, vertical: 10),
child: Row(
children: [
const Icon(
Icons.calendar_month,
color: Colors.white,
),
8.width,
Expanded(
child: LocaleKeys.setorEditBranchSchedule.tr().toText(
isUnderLine: true,
fontSize: 12,
color: Colors.white,
decorationColor: MyColors.white,
),
),
],
)
.withArrow(
isArrowEnabled: true,
color: Colors.white,
arrowWidth: 16.16,
arrowHeight: 11.75,
)
.margin(right: 5),
).onPress(() {
if (branchData.branchStatus == BranchStatusEnum.pending || branchData.branchStatus == BranchStatusEnum.rejected) {
Utils.showToast("Please wait for the branch verification.");
return;
}
navigateWithName(context, ProviderAppRoutes.schedulesList, arguments: branchData.id.toString());
}),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.add,
color: Colors.white,
size: 18,
).toContainer(
borderRadius: 100,
paddingAll: 2,
backgroundColor: MyColors.darkIconColor,
),
8.width,
LocaleKeys.addNewService.tr().toText(fontSize: 15, color: MyColors.lightTextColor, letterSpacing: -0.52),
],
)
.toContainer(
borderRadius: 0,
backgroundColor: MyColors.darkWhiteColor,
width: double.infinity,
paddingAll: 25,
margin: const EdgeInsets.only(
left: 20,
right: 20,
top: 20,
))
.onPress(() {
if (branchData.branchStatus == BranchStatusEnum.pending || branchData.branchStatus == BranchStatusEnum.rejected) {
Utils.showToast("Please wait for the branch verification.");
return;
}
navigateWithName(
context,
ProviderAppRoutes.createServices3,
arguments: CreateBranchModel(
branchId: branchData.id.toString(),
branchName: branchData.branchName.toString(),
isForEdit: false,
),
);
}),
ListView.separated(
itemBuilder: (context, pIndex) {
return buildServiceTileWidget(pIndex, serviceVM).onPress(() {
serviceVM.categories[pIndex].branchId = branchData.id.toString();
serviceVM.categories[pIndex].branchName = branchData.branchName.toString();
navigateWithName(context, ProviderAppRoutes.servicesList, arguments: serviceVM.categories[pIndex]);
});
},
itemCount: serviceVM.categories.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.all(20),
separatorBuilder: (BuildContext context, int index) {
return 12.height;
},
),
12.height,
],
),
),
),
Container(
width: double.infinity,
height: 1,
color: Colors.grey[100],
),
buildFooterActionWidget(context),
],
),
);
}),
);
}
}

@ -0,0 +1,213 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:flutter/gestures.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/tab/role_type_tab.dart';
import 'package:mc_common_app/widgets/row_with_arrow.dart';
import 'package:provider/provider.dart';
class BranchListPage extends StatelessWidget {
const BranchListPage({Key? key}) : super(key: key);
void deleteBranchBottomSheet(BuildContext context, int branchID) {
return actionConfirmationBottomSheet(
context: context,
title: LocaleKeys.deleteBranchConfirmation.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: LocaleKeys.deleteBranchConfirmationMessage.tr(),
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.yes.tr(),
fontSize: 15,
onPressed: () async {
Navigator.pop(context);
await context.read<ServiceVM>().onDeleteBranchPressed(context: context, branchID: branchID ?? -1);
},
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: LocaleKeys.no.tr(),
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.myBranches.tr(),
isRemoveBackButton: true,
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 21, right: 21, top: 21),
child: RoleTypeTab(
context.watch<ServiceVM>().selectedBranchStatus == 3 ? 0 : context.watch<ServiceVM>().selectedBranchStatus,
[
DropValue(3, "Active", ""),
DropValue(1, "Requested", ""),
],
onSelect: (DropValue value) {
context.read<ServiceVM>().updateSelectedBranchType(value.id);
},
),
),
Expanded(
child: Consumer<ServiceVM>(
builder: (context, serviceVM, _) {
if (serviceVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
List<BranchDetailModel> branches = [];
if (serviceVM.branches!.data != null) {
if (serviceVM.selectedBranchStatus == 3) {
// 3 means active branch
branches = serviceVM.branches!.data!.serviceProviderBranch!.where((element) => element.statusId == 3).toList();
} else {
branches = serviceVM.branches!.data!.serviceProviderBranch!.where((element) {
return element.statusId != 3; // means rest of the branches
}).toList();
}
}
return RefreshIndicator(
onRefresh: () async => await context.read<ServiceVM>().getBranchAndServices(),
child: branches.isEmpty
? Center(child: LocaleKeys.no_branch.tr().toText(fontSize: 16, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium))
: ListView.separated(
itemBuilder: (context, index) {
BranchDetailModel branchModel = branches[index];
return Dismissible(
key: Key(index.toString()),
background: const SizedBox(),
secondaryBackground: Container(
color: const Color(0xFFDD0505),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [
LocaleKeys.delete.tr().toText(fontSize: 15, fontWeight: MyFonts.Medium, height: 23 / 25, color: MyColors.white).margin(right: 23),
],
),
),
dragStartBehavior: DragStartBehavior.start,
direction: DismissDirection.endToStart,
confirmDismiss: (DismissDirection direction) async {
deleteBranchBottomSheet(context, branchModel.id!);
},
child: Row(
children: [
branchModel.branchProfileImage.buildNetworkImage(width: 66, height: 53, fit: BoxFit.cover),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Utils.statusContainerChip(
text: branchModel.branchStatusLabel ?? "",
chipColor: Utils.getChipColorByBranchStatus(branchModel.branchStatus!),
),
],
),
2.height,
// branchModel.distanceKm == null
// ? const SizedBox()
// : Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// const Icon(
// Icons.location_on,
// color: MyColors.darkPrimaryColor,
// size: 15,
// ),
// 2.width,
// ("${branchModel.distanceKm} KM").toText(
// color: MyColors.darkPrimaryColor,
// fontSize: 10,
// )
// ],
// ),
// 5.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
(branchModel.branchName ?? "").toText(fontSize: 16, height: 18 / 16),
],
).withArrow(isArrowEnabled: true).margin(right: 10),
(branchModel.branchDescription ?? "").toText(
fontSize: 10,
overflow: TextOverflow.ellipsis,
color: MyColors.grey70Color,
maxLines: 2,
)
],
),
),
],
).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12)).onPress(() async {
branchModel.countryID = serviceVM.branches!.data!.countryID;
branchModel.countryName = serviceVM.branches!.data!.countryName;
navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: branchModel);
}),
);
},
separatorBuilder: (context, index) => 12.height,
itemCount: branches.length,
).paddingAll(21),
);
}
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: MyColors.darkPrimaryColor,
child: const Icon(
Icons.add,
color: Colors.white,
),
onPressed: () {
context.read<DashboardVM>().checkUserSubscription(SubscriptionActionTypeEnum.branches, context, callback: () { });
},
),
);
}
}

@ -0,0 +1,159 @@
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/branch_management/branch/dealer/widget/assign_dealer_user_sheet.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class DealerUserPage extends StatefulWidget {
String branchId;
DealerUserPage(this.branchId, {Key? key}) : super(key: key);
@override
State<DealerUserPage> createState() => _DealerUserPageState();
}
class _DealerUserPageState extends State<DealerUserPage> {
late ServiceVM provider;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
provider = Provider.of<ServiceVM>(context, listen: false);
getBranchUsers();
});
}
getBranchUsers() {
provider.getBranchUsers({
// "id": services!.data![i].id,
"ServiceProviderBranchID": widget.branchId,
"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.dealerUser.tr(),
),
body: Column(
children: [
Expanded(
child: Consumer<ServiceVM>(builder: (context, model, _) {
if (model.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
if (model.branchUserList.isEmpty) {
return Center(child: Text(LocaleKeys.noUserAddedYet.tr()));
} else {
return ListView.separated(
itemBuilder: (context, index) {
return dealerUsersWidget(model, index);
},
separatorBuilder: (context, index) {
return 12.height;
},
padding: const EdgeInsets.all(12),
itemCount: model.branchUserList.length,
);
}
}
}),
),
Container(
width: double.infinity,
height: 1,
color: Colors.grey[100],
),
ShowFillButton(
title: LocaleKeys.assignDealerUser.tr(),
maxWidth: double.infinity,
onPressed: () {
showMyBottomSheet(
context,
child: AssignDealerUserSheet(
branchId: widget.branchId,
callBackFunc: () {
getBranchUsers();
},
),
);
},
).paddingAll(12),
],
),
);
}
Widget dealerUsersWidget(ServiceVM model, int index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
("${model.branchUserList[index].firstName} ${model.branchUserList[index].lastName}").toText(fontSize: 16, isBold: true),
8.height,
itemWidget("Role", "Dealer User"),
itemWidget("Email", model.branchUserList[index].email??""),
itemWidget("Phone", model.branchUserList[index].mobileNo??"")
],
),
),
4.width,
IconButton(
onPressed: () async {
var map = {
"id": model.branchUserList[index].id,
"dealershipUserID": model.branchUserList[index].dealershipUserID,
"serviceProviderBranchID": widget.branchId,
"isActive": false,
};
Utils.showLoading(context);
GenericRespModel response = await provider.removeDealerFromBranch(map);
Utils.hideLoading(context);
if (response.messageStatus == 1) {
getBranchUsers();
} else {
Utils.showToast(response.message.toString());
}
},
icon: const Icon(Icons.delete_outline),
),
],
).toWhiteContainer(
width: double.infinity,
borderRadius: 12,
pading: const EdgeInsets.only(left: 14, right: 2, top: 12, bottom: 12),
);
}
Widget itemWidget(String title, String value) {
return Row(
children: [
(title + ": ").toText(isBold: true, color: MyColors.lightTextColor),
value.toText(isBold: true),
],
);
}
}

@ -0,0 +1,73 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
class DealershipView extends StatelessWidget {
const DealershipView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.dealershipSettings.tr()),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
ListTile(
leading: SvgPicture.asset(
MyAssets.icSettings,
color: MyColors.darkPrimaryColor,
),
title: LocaleKeys.general.tr().toText(fontSize: 12),
),
ListTile(
leading: SvgPicture.asset(
MyAssets.requestsIcon,
color: MyColors.darkPrimaryColor,
),
title: LocaleKeys.defineBranches.tr().toText(fontSize: 12),
onTap: () {
navigateWithName(context, ProviderAppRoutes.branchList);
},
),
ListTile(
leading: SvgPicture.asset(
MyAssets.icServices,
color: MyColors.darkPrimaryColor,
),
title: LocaleKeys.defineServices.tr().toText(fontSize: 12),
onTap: () {
navigateWithName(context, ProviderAppRoutes.createServices2);
},
),
ListTile(
leading: SvgPicture.asset(
MyAssets.icProvider,
color: MyColors.darkPrimaryColor,
),
title: LocaleKeys.defineProviders.tr().toText(fontSize: 12),
onTap: () async {
// Branch2 mResponse = await BranchApiClent().getBranchAndServices();
},
),
ListTile(
leading: SvgPicture.asset(
MyAssets.icCloseAccount,
color: MyColors.darkPrimaryColor,
),
title: LocaleKeys.closeAccount.tr().toText(fontSize: 12),
),
],
),
),
);
}
}

@ -0,0 +1,140 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:car_provider_app/generated/locale_keys.g.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
class AddPhoneNumWidget extends StatefulWidget {
const AddPhoneNumWidget({Key? key}) : super(key: key);
@override
State<AddPhoneNumWidget> createState() => _AddPhoneNumWidgetState();
}
class _AddPhoneNumWidgetState extends State<AddPhoneNumWidget> {
String phoneNum = "", countryCode = "";
late UserVM userVM;
Country? _country;
@override
void initState() {
super.initState();
scheduleMicrotask(() {
userVM = Provider.of(context, listen: false);
getCountryList();
});
}
getCountryList() async {
_country = await userVM.getAllCountries();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
width: double.infinity,
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
"Enter Phone Number".toText(fontSize: 16, isBold: true),
8.height,
getCountry(context),
8.height,
TxtField(
keyboardType: TextInputType.phone,
hint: "546758594",
value: phoneNum,
isSidePaddingZero: true,
onChanged: (v) {
phoneNum = v;
},
),
16.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: "Cancel",
backgroundColor: MyColors.greyButtonColor,
txtColor: Colors.black,
onPressed: () {
pop(context);
},
),
),
12.width,
Expanded(
child: ShowFillButton(
title: LocaleKeys.sendOTP.tr(),
onPressed: () {
//User Role: Dealer|Manager for a branch
FocusScope.of(context).unfocus();
if (validation()) {
userVM.performBasicOtpRegisterPage(context, countryCode: countryCode, phoneNum: phoneNum, role: 7, isNeedToPassToken: true, reloadPage: () {
pop(context);
});
}
},
),
),
],
)
],
),
),
);
}
Widget getCountry(BuildContext context) {
if (_country != null) {
List<DropValue> dropList = [];
_country!.data?.forEach((element) {
dropList.add(DropValue(element.id ?? 0, "${element.countryName ?? ""} ${element.countryCode ?? ""}", element.countryCode ?? ""));
});
return DropdownField(
(DropValue value) {
countryCode = value.subValue;
},
list: dropList,
hint: countryCode.isNotEmpty ? countryCode.toString() : LocaleKeys.selectCountryCode.tr(),
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
}
bool validation() {
bool isValid = true;
if (countryCode.isEmpty) {
Utils.showToast(LocaleKeys.selectCountryCode.tr());
//("Please select Country Code");
isValid = false;
} else if (phoneNum.isEmpty) {
Utils.showToast(LocaleKeys.addPhoneNo.tr());
//("Please add Phone No");
isValid = false;
}
return isValid;
}
}

@ -0,0 +1,193 @@
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
// ignore: must_be_immutable
class AssignDealerUserSheet extends StatefulWidget {
String branchId;
VoidCallback callBackFunc;
bool? isFromBranch;
AssignDealerUserSheet({required this.branchId, required this.callBackFunc, this.isFromBranch, Key? key}) : super(key: key);
@override
State<AssignDealerUserSheet> createState() => _AssignDealerUserSheetState();
}
class _AssignDealerUserSheetState extends State<AssignDealerUserSheet> {
late ServiceVM provider;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
provider = Provider.of<ServiceVM>(context, listen: false);
getBranchUsers();
});
}
getBranchUsers() {
provider.getAllProviderDealers({"ServiceProviderBranchID": widget.branchId, "ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""});
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.2,
padding: const EdgeInsets.all(21),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: Consumer<ServiceVM>(builder: (context, model, _) {
if (model.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
if (model.allProviderDealersList.isEmpty) {
return Center(child: Text(LocaleKeys.noUserAddedYet.tr()));
} else {
return ListView.separated(
itemBuilder: (context, index) {
return dealerUsersWidget(model, index);
},
separatorBuilder: (context, index) => 12.height,
itemCount: model.allProviderDealersList.length,
);
}
}
}),
),
Container(
width: double.infinity,
height: 1,
color: Colors.grey[100],
),
Column(
children: [
ShowFillButton(
title: LocaleKeys.assignDealerUser.tr(),
maxWidth: double.infinity,
maxHeight: 55,
fontSize: 15,
onPressed: () async {
if (validation()) {
Utils.showLoading(context);
List<int> userIds = [];
for (var element in provider.allProviderDealersList) {
if (element.isBranchUser ?? false) {
userIds.add(element.id);
}
}
var map = {
"dealershipUserIDs": userIds,
"serviceProviderBranchID": widget.branchId,
};
GenericRespModel response = await provider.assignDealerToBranch(map);
Utils.hideLoading(context);
if (response.messageStatus == 1) {
Utils.showToast(response.message.toString());
pop(context);
widget.callBackFunc();
} else {
Utils.showToast(response.message.toString());
}
}
},
),
12.height,
ShowFillButton(
title: ("+ ${LocaleKeys.createNewUser.tr()}"),
maxWidth: double.infinity,
maxHeight: 55,
fontSize: 15,
backgroundColor: Colors.transparent,
borderColor: MyColors.darkPrimaryColor,
txtColor: MyColors.darkPrimaryColor,
isFilled: false,
onPressed: () {
context.read<DashboardVM>().checkUserSubscription(SubscriptionActionTypeEnum.users, context, callback: () {
getBranchUsers();
});
},
)
],
)
],
),
);
}
Widget dealerUsersWidget(ServiceVM model, int index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Checkbox(
value: model.allProviderDealersList[index].isBranchUser,
onChanged: (v) {
model.allProviderDealersList[index].isBranchUser = v ?? false;
model.notifyListeners();
},
visualDensity: VisualDensity.comfortable,
),
4.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
("${model.allProviderDealersList[index].firstName} ${model.allProviderDealersList[index].lastName}").toText(fontSize: 16),
8.height,
itemWidget("Role", "Dealer User"),
itemWidget("Email", model.allProviderDealersList[index].email ?? ""),
itemWidget("Phone", model.allProviderDealersList[index].mobileNo ?? "")
],
),
),
],
).toWhiteContainer(
width: double.infinity,
borderRadius: 0,
pading: const EdgeInsets.symmetric(horizontal: 6, vertical: 12),
);
}
Widget itemWidget(String title, String value) {
return Row(
children: [
("$title: ").toText(isBold: true, color: MyColors.lightTextColor),
Flexible(
child: value.toText(isBold: true, overflow: TextOverflow.ellipsis),
),
],
);
}
bool validation() {
bool isValid = false;
for (var element in provider.allProviderDealersList) {
if (element.isBranchUser ?? false) {
isValid = true;
}
}
return isValid;
}
}

@ -0,0 +1,265 @@
import 'dart:async';
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/views/location_views/pick_location_page.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:provider/provider.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
class DefineBranchView extends StatefulWidget {
final BranchDetailModel? branchData;
const DefineBranchView(this.branchData, {super.key});
@override
State<DefineBranchView> createState() => _DefineBranchViewState();
}
class _DefineBranchViewState extends State<DefineBranchView> {
late ServiceVM serviceVM;
@override
void initState() {
super.initState();
scheduleMicrotask(() {
serviceVM = context.read<ServiceVM>();
serviceVM.getAllCountriesList(widget.branchData, EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.defineBranches.tr()),
body: Consumer<ServiceVM>(builder: (context, serviceVM, _) {
return SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
12.height,
serviceVM.country != null
? DropdownField(
(DropValue value) {
serviceVM.countryValue = DropValue(value.id, value.value, "");
serviceVM.countryCode = value.subValue;
serviceVM.countryId = value.id;
serviceVM.getAllCities(widget.branchData, EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
},
isSelectAble: widget.branchData == null,
list: serviceVM.countryDropList,
dropdownValue: serviceVM.countryValue,
hint: "${LocaleKeys.chooseCountry.tr()}*",
)
: const CircularProgressIndicator(),
12.height,
if (serviceVM.countryId != -1)
serviceVM.cities != null
? serviceVM.citiesDropList.isEmpty
? Text(LocaleKeys.no_city_available.tr())
: DropdownField(
(DropValue value) {
serviceVM.cityValue = DropValue(value.id, value.value, "");
serviceVM.setOnlyState(ViewState.busy);
serviceVM.cityId = value.id;
serviceVM.setState(ViewState.idle);
},
list: serviceVM.citiesDropList,
dropdownValue: serviceVM.cityValue,
hint: "${LocaleKeys.chooseCity.tr()}*",
)
: const CircularProgressIndicator(),
12.height,
if (serviceVM.cityId != -1)
Column(
children: [
TxtField(
hint: "${LocaleKeys.branchName.tr()}*",
value: serviceVM.branchName,
onChanged: (v) {
serviceVM.branchName = v;
},
),
12.height,
TxtField(
maxLines: 3,
hint: "${LocaleKeys.branchDescription.tr()}*",
value: serviceVM.branchDescription,
onChanged: (v) {
serviceVM.branchDescription = v;
},
),
12.height,
Row(
children: [
Expanded(
child: TxtField(
errorValue: '',
hint: 'Opening Time*',
value: serviceVM.openTime,
isNeedClickAll: true,
postfixData: Icons.access_time,
postFixDataColor: MyColors.lightTextColor,
onTap: () async {
TimeOfDay startTime = TimeOfDay.now();
String endTime = await Utils.pickTime(context, initialTime: startTime);
FocusManager.instance.primaryFocus?.unfocus();
serviceVM.updateSelectionOpenTime(endTime);
},
),
),
12.width,
Expanded(
child: TxtField(
errorValue: '',
hint: 'Closing Time*',
value: serviceVM.closedTime,
isNeedClickAll: true,
postfixData: Icons.access_time,
postFixDataColor: MyColors.lightTextColor,
onTap: () async {
TimeOfDay startTime = TimeOfDay.now();
String endTime = await Utils.pickTime(context, initialTime: startTime);
FocusManager.instance.primaryFocus?.unfocus();
serviceVM.updateSelectionCloseTime(endTime);
},
),
),
],
),
12.height,
TxtField(
hint: LocaleKeys.address.tr(),
isNeedClickAll: false,
value: serviceVM.address,
postfixWidget: IconButton(
icon: const Icon(
size: 28,
Icons.add_location_outlined,
),
onPressed: () {
navigateTo(
context,
PickLocationPage(
onPickAddress: (double latitude, double longitude, String address) {
serviceVM.latitude = latitude;
serviceVM.longitude = longitude;
serviceVM.address = address;
serviceVM.setState(ViewState.idle);
},
),
);
}),
onChanged: (v) {
serviceVM.address = v;
},
),
12.height,
DottedRectContainer(
onTap: () => serviceVM.pickMultipleImages(),
text: LocaleKeys.attachImage.tr(),
icon: MyAssets.attachmentIcon.buildSvg(),
),
if (serviceVM.branchImageError != "") ...[
10.height,
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
serviceVM.branchImageError.toText(fontSize: 14, color: Colors.red),
],
).paddingOnly(right: 10)
],
if (serviceVM.pickedBranchImages.isNotEmpty) ...[
16.height,
PickedFilesContainer(
pickedFiles: serviceVM.pickedBranchImages,
onCrossPressedPrimary: serviceVM.removeImageFromList,
onAddFilePressed: () {
serviceVM.pickMultipleImages();
},
),
],
],
),
],
).horPaddingMain(),
),
),
if (serviceVM.branchErrorScreen.isNotEmpty) ...[
serviceVM.branchErrorScreen.toText(fontSize: 14, color: Colors.red).paddingAll(21),
],
if (widget.branchData == null || widget.branchData!.id == null) ...[
SizedBox(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10),
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.createBranch.tr(),
onPressed: () async {
await serviceVM.onCreateBranchPressed(
context: context,
branchName: serviceVM.branchName,
branchDesc: serviceVM.branchDescription,
openTime: serviceVM.openTime,
closeTime: serviceVM.closedTime,
cityID: serviceVM.cityId,
address: serviceVM.address,
latitude: serviceVM.latitude,
longitude: serviceVM.longitude,
);
},
),
),
),
] else ...[
SizedBox(
width: double.infinity,
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.updateBranch.tr(),
onPressed: () async {
await serviceVM.onUpdateBranchPressed(
context: context,
branchID: widget.branchData!.id ?? 0,
branchName: serviceVM.branchName,
branchDesc: serviceVM.branchDescription,
openTime: serviceVM.openTime,
closedTime: serviceVM.closedTime,
cityID: serviceVM.cityId,
address: serviceVM.address,
latitude: widget.branchData!.latitude ?? "0",
longitude: widget.branchData!.longitude ?? "0",
);
},
).horPaddingMain(),
),
12.height,
],
],
),
);
}),
);
}
}

@ -0,0 +1,400 @@
import 'dart:async';
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/select_days_sheet.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/select_services_sheet.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/appointments_models/schedule_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:easy_localization/easy_localization.dart';
class AddSchedulesPage extends StatefulWidget {
const AddSchedulesPage({Key? key}) : super(key: key);
@override
State<AddSchedulesPage> createState() => _AddSchedulesPageState();
}
class _AddSchedulesPageState extends State<AddSchedulesPage> {
late ScheduleVM mModel;
String name = "", startDate = "", endDate = "", startTime = "", endTime = "", slotsTime = "", appointmentPerSlot = "", servicesGroupID = "";
late ScheduleData scheduleData;
setEditData() {
name = scheduleData.scheduleName ?? "";
startDate = DateHelper.formatAsYearMonthDay(scheduleData.fromDate ?? DateTime.now());
endDate = DateHelper.formatAsYearMonthDay(scheduleData.toDate ?? DateTime.now());
startTime = scheduleData.startTime ?? "";
endTime = scheduleData.endTime ?? "";
slotsTime = scheduleData.slotDurationMinute.toString();
appointmentPerSlot = scheduleData.perSlotAppointment.toString();
// mModel.selectedServicesItems.clear();
scheduleData.scheduleServices?.forEach((element) {
print("Services Elements");
print(element);
mModel.selectedServicesItems.add(PickerItem(id: element.serviceProviderServiceId ?? 0, title: element.serviceDescription ?? ""));
});
logger.d(mModel.selectedServicesItems.first.id);
mModel.selectedDaysItems.clear();
scheduleData.weeklyOffDays?.forEach((element) {
for (var daysElement in initDaysList) {
if (element.dayNumber == daysElement.id) {
daysElement.isSelected = true;
mModel.selectedDaysItems.add(daysElement);
}
}
});
}
@override
void initState() {
super.initState();
scheduleMicrotask(() {
mModel = context.read<ScheduleVM>();
scheduleData = ModalRoute.of(context)!.settings.arguments as ScheduleData;
mModel.getAllServices(scheduleData.branchId, scheduleData);
mModel.selectedServicesItems = [];
mModel.selectedDaysItems = [];
if (scheduleData.id != null) {
setEditData();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CustomAppBar(
title: "Create Schedules",
),
body: SizedBox(
width: double.infinity,
child: Consumer<ScheduleVM>(
builder: (_, ScheduleVM model, child) {
return Column(
children: [
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
children: [
TxtField(
hint: LocaleKeys.nameofSchedule.tr(),
value: name,
onChanged: (v) {
name = v;
},
),
8.height,
ChipsPickerItem(
hint: LocaleKeys.select_Services.tr(),
itemsList: [...model.selectedServicesItems],
onClick: () {
showMyBottomSheet(
context,
child: SelectServicesSheet(
onSelectServices: () {
model.filterSelectedServices();
FocusManager.instance.primaryFocus?.unfocus();
},
),
);
},
),
8.height,
TxtField(
hint: LocaleKeys.startingDate.tr(),
value: startDate,
postfixWidget: const Icon(
Icons.calendar_month,
size: 16,
),
isNeedClickAll: true,
onTap: () async {
startDate = await Utils.pickDateFromDatePicker(
context,
firstDate: DateTime.now(),
);
FocusManager.instance.primaryFocus?.unfocus();
model.refresh();
},
),
8.height,
TxtField(
hint: LocaleKeys.endDate.tr(),
postfixWidget: const Icon(
Icons.calendar_month,
size: 16,
),
value: endDate,
isNeedClickAll: true,
onTap: () async {
endDate = await Utils.pickDateFromDatePicker(
context,
firstDate: DateTime.now(),
);
FocusManager.instance.primaryFocus?.unfocus();
model.refresh();
},
),
8.height,
ChipsPickerItem(
hint: LocaleKeys.offDays.tr(),
itemsList: [...model.selectedDaysItems],
onClick: () {
showMyBottomSheet(
context,
child: SelectDaysSheet(
onSelected: (List<PickerItem> picked) {
model.filterDays(picked);
FocusManager.instance.primaryFocus?.unfocus();
},
),
);
},
),
8.height,
Row(
children: [
Expanded(
child: TxtField(
hint: LocaleKeys.shiftStartTime.tr(),
postfixWidget: const Icon(
Icons.access_time_filled_outlined,
size: 16,
),
value: startTime,
isNeedClickAll: true,
onTap: () async {
startTime = await Utils.pickTime(context);
FocusManager.instance.primaryFocus?.unfocus();
model.refresh();
},
),
),
8.width,
Expanded(
child: TxtField(
hint: LocaleKeys.shiftEndTime.tr(),
postfixWidget: const Icon(
Icons.access_time_filled_outlined,
size: 16,
),
value: endTime,
isNeedClickAll: true,
onTap: () async {
TimeOfDay _startTime = TimeOfDay.now();
if (startTime.isNotEmpty) _startTime = TimeOfDay(hour: int.parse(startTime.split(":")[0]), minute: int.parse(startTime.split(":")[1]));
endTime = await Utils.pickTime(
context,
initialTime: _startTime,
);
FocusManager.instance.primaryFocus?.unfocus();
model.refresh();
},
),
),
],
),
8.height,
TxtField(
hint: LocaleKeys.slotsTime.tr(),
postfixWidget: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
"Min".toText(color: MyColors.lightTextColor),
],
),
keyboardType: TextInputType.number,
value: slotsTime,
onChanged: (v) {
slotsTime = v;
},
),
8.height,
TxtField(
hint: LocaleKeys.appointmentPerSlot.tr(),
value: appointmentPerSlot,
keyboardType: TextInputType.number,
onChanged: (v) {
appointmentPerSlot = v;
},
),
],
),
),
),
ShowFillButton(
title: LocaleKeys.create.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
if (validation(model)) {
if (scheduleData.id != null) {
updateSchedule(context, model);
} else {
createSchedule(context, model);
}
}
},
),
],
);
},
),
),
);
}
bool validation(ScheduleVM model) {
bool valid = true;
if (name.length < 3) {
Utils.showToast(LocaleKeys.pleaseEnterValidScheduleName.tr());
valid = false;
} else if (model.selectedServicesItems.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectServices.tr());
valid = false;
} else if (startDate.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectStartDate.tr());
valid = false;
} else if (endDate.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectEndDate.tr());
valid = false;
} else if (model.selectedDaysItems.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectOffDays.tr());
valid = false;
} else if (startTime.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectStartTime.tr());
valid = false;
} else if (endTime.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectEndTime.tr());
valid = false;
} else if (slotsTime.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectSlotTime.tr());
valid = false;
} else if (appointmentPerSlot.isEmpty) {
Utils.showToast(LocaleKeys.pleaseSelectAppointmentPerSlot.tr());
valid = false;
}
return valid;
}
createSchedule(BuildContext context, ScheduleVM model) async {
List<int> days = [];
for (var element in model.selectedDaysItems) {
days.add(element.id);
}
//TODO: needs to verify with Zahoor about appointment type while creating Schedule
var map = {
"scheduleName": name,
"serviceProviderBranchID": scheduleData.branchId,
"fromDate": startDate,
"toDate": endDate,
"startTime": startTime,
"endTime": endTime,
"slotDurationMinute": slotsTime,
"perSlotAppointment": appointmentPerSlot,
"deliveryServiceType": 1,
"appointmentType": 1,
"weeklyOffDays": days
};
Utils.showLoading(context);
GenericRespModel scheduleResponse = await model.createSchedule(map);
if (scheduleResponse.messageStatus == 1) {
List<int> services = [];
for (var element in model.selectedServicesItems) {
services.add(element.id);
}
var map1 = {
"branchAppointmentScheduleID": scheduleResponse.data,
"serviceProviderServiceID": services,
"serviceGroupDescription": "string",
};
GenericRespModel servicesResponse = await model.addServicesInSchedule(map1);
Utils.hideLoading(context);
if (servicesResponse.messageStatus == 1) {
Utils.showToast("Successfully schedule created");
context.read<ScheduleVM>().getSchedules(scheduleData.branchId ?? "");
pop(context);
} else {
Utils.showToast(servicesResponse.message ?? "");
// context.read<ScheduleVM>().getSchedules(scheduleData.branchId ?? "");
// pop(context);
}
} else {
Utils.hideLoading(context);
Utils.showToast(scheduleResponse.message ?? "");
}
}
updateSchedule(BuildContext context, ScheduleVM model) async {
List<int> days = [];
for (var element in model.selectedDaysItems) {
days.add(element.id);
}
var map = {
"id": scheduleData.id,
"scheduleName": name,
"serviceProviderBranchID": scheduleData.branchId,
"fromDate": startDate,
"toDate": endDate,
"startTime": startTime,
"endTime": endTime,
"slotDurationMinute": slotsTime,
"perSlotAppointment": appointmentPerSlot,
"deliveryServiceType": 1,
"weeklyOffDays": days,
"appointmentType": scheduleData.appointmentType
};
Utils.showLoading(context);
GenericRespModel scheduleResponse = await model.updateSchedule(map);
if (scheduleResponse.messageStatus == 1) {
List<int> services = [];
for (var element in model.selectedServicesItems) {
services.add(element.id);
}
var map1 = {
"branchAppointmentScheduleID": scheduleData.id,
"serviceProviderServiceID": services,
"serviceGroupDescription": "string",
};
GenericRespModel servicesResponse = await model.updateServicesInSchedule(map1);
Utils.hideLoading(context);
if (servicesResponse.messageStatus == 1) {
Utils.showToast(servicesResponse.message ?? "Schedule Successfully Updated");
context.read<ScheduleVM>().getSchedules(scheduleData.branchId ?? "");
pop(context);
} else {
Utils.showToast(servicesResponse.message ?? LocaleKeys.somethingWrong.tr());
}
} else {
Utils.hideLoading(context);
Utils.showToast(scheduleResponse.message ?? LocaleKeys.somethingWrong.tr());
}
}
}

@ -0,0 +1,192 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/appointments_models/schedule_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/empty_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:easy_localization/easy_localization.dart';
class SchedulesListPage extends StatefulWidget {
final String? branchId;
const SchedulesListPage(this.branchId, {Key? key}) : super(key: key);
@override
State<SchedulesListPage> createState() => _SchedulesListPageState();
}
class _SchedulesListPageState extends State<SchedulesListPage> {
@override
void initState() {
super.initState();
context.read<ScheduleVM>().getSchedules(widget.branchId ?? "");
}
void deleteScheduleConfirmationSheet(int index, ScheduleVM serviceVM, BuildContext context) {
return actionConfirmationBottomSheet(
context: context,
title: LocaleKeys.deleteScheduleConfirmation.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: LocaleKeys.deleteScheduleAdConfirmationMessage.tr(),
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.yes.tr(),
fontSize: 15,
onPressed: () async {
Navigator.pop(context);
Utils.showLoading(context);
GenericRespModel res = await serviceVM.setScheduleInactive(serviceVM.schedule!.data![index].id!, serviceVM.schedule!.data![index].serviceProviderBranchId!);
Utils.hideLoading(context);
if (res.messageStatus == 1) {
Utils.showToast(LocaleKeys.branch_deleted.tr());
} else {
Utils.showToast(res.message ?? "");
}
},
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: LocaleKeys.no.tr(),
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.branchSchedules.tr()),
body: SizedBox(
width: double.infinity,
child: Column(
children: [
Expanded(
child: Consumer<ScheduleVM>(
builder: (BuildContext context, scheduleVM, Widget? child) {
return scheduleVM.schedule == null
? const Center(
child: CircularProgressIndicator(),
)
: scheduleVM.schedule!.data!.isEmpty
? EmptyWidget(
text: LocaleKeys.noSchedulesFound.tr(),
)
: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: scheduleVM.schedule!.data![index].scheduleName.toString().toText(fontSize: 16)),
IconButton(
onPressed: () async {
return deleteScheduleConfirmationSheet(index, scheduleVM, context);
},
icon: const Icon(Icons.delete_outline),
color: Colors.red,
),
Padding(
padding: const EdgeInsets.all(4.0),
child: SvgPicture.asset(
MyAssets.icEdit,
width: 16,
height: 16,
),
).onPress(() {
scheduleVM.schedule!.data![index].branchId = widget.branchId ?? "";
navigateWithName(context, ProviderAppRoutes.addSchedule, arguments: scheduleVM.schedule!.data![index]);
}),
],
),
8.height,
showItem("${LocaleKeys.startDate.tr()}:", DateHelper.formatAsDayMonthYear(scheduleVM.schedule!.data![index].fromDate)),
showItem("${LocaleKeys.endDate.tr()}:", DateHelper.formatAsDayMonthYear(scheduleVM.schedule!.data![index].toDate)),
showItem("${LocaleKeys.shiftStartTime.tr()}:", scheduleVM.schedule!.data![index].startTime ?? ""),
showItem("${LocaleKeys.shiftEndTime.tr()}:", scheduleVM.schedule!.data![index].endTime ?? ""),
showItem("${LocaleKeys.slotsTime.tr()}:", "${scheduleVM.schedule!.data![index].slotDurationMinute} Mins"),
showItem("${LocaleKeys.appointmentPerSlot.tr()}:", scheduleVM.schedule!.data![index].perSlotAppointment.toString()),
showItem("${LocaleKeys.offDays.tr()}:", offDays(scheduleVM.schedule!.data![index])),
12.height,
"${LocaleKeys.services.tr()}:".toText(fontSize: 12, color: MyColors.lightTextColor),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: scheduleVM.schedule!.data![index].scheduleServices!
.map(
(element) => Container(
child: element.serviceDescription.toString().toText(fontSize: 12),
),
)
.toList(),
)
],
).toWhiteContainer(width: double.infinity, allPading: 12);
},
separatorBuilder: (BuildContext context, int index) {
return 12.height;
},
padding: const EdgeInsets.all(20),
itemCount: scheduleVM.schedule!.data!.length,
);
},
),
),
ShowFillButton(
title: LocaleKeys.createSchedule.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
navigateWithName(context, ProviderAppRoutes.addSchedule, arguments: ScheduleData(branchId: widget.branchId ?? ""));
},
),
],
),
),
);
}
String offDays(ScheduleData scheduleData) {
String offDays = "";
for (int i = 0; i < scheduleData.weeklyOffDays!.length; i++) {
offDays = offDays + initDaysList[scheduleData.weeklyOffDays![i].dayNumber! - 1].title;
if (i != scheduleData.weeklyOffDays!.length - 1) {
offDays = "$offDays , ";
}
}
return offDays;
}
Widget showItem(String title, String value) {
return Row(
children: [
title.toText(fontSize: 12, color: MyColors.lightTextColor),
4.width,
value.toText(fontSize: 12),
],
);
}
}

@ -0,0 +1,88 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:sizer/sizer.dart';
class PickerItem {
int id;
String title;
bool? isSelected;
PickerItem({required this.id, required this.title, this.isSelected});
}
class ChipsPickerItem extends StatelessWidget {
final String hint;
final List<PickerItem> itemsList;
final Function onClick;
const ChipsPickerItem({Key? key, required this.hint, required this.itemsList, required this.onClick}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
if (itemsList.isEmpty) Expanded(child: hint.toText(fontSize: 15, fontWeight: MyFonts.Medium, color: borderColor)),
if (itemsList.isNotEmpty)
Expanded(
child: ListView(
scrollDirection: Axis.horizontal,
children: [
showItem(itemsList[0].title),
6.width,
if (itemsList.length > 1) showItem(itemsList[1].title),
6.width,
if (itemsList.length > 2) showItem("${itemsList.length - 2}+ more", isNeedToShowIcon: false),
6.width,
],
),
),
const Icon(
Icons.arrow_forward_ios_rounded,
size: 16,
color: MyColors.lightIconColor,
),
],
)
.toContainer(
width: double.infinity,
height: 45,
isEnabledBorder: true,
borderWidget: 2,
borderRadius: 0,
borderColor: MyColors.darkPrimaryColor,
)
.onPress(() {
onClick();
});
}
Widget showItem(String title, {bool isNeedToShowIcon = true}) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 6),
height: double.infinity,
color: MyColors.chipColor,
child: Row(
children: [
title.toText(fontSize: 14, fontWeight: MyFonts.Medium),
if (isNeedToShowIcon) 4.width,
if (isNeedToShowIcon)
const Icon(
Icons.close,
size: 8,
color: Colors.white,
).toContainer(
borderRadius: 100,
width: 12,
height: 12,
paddingAll: 0,
backgroundColor: MyColors.grey70Color,
),
],
),
);
}
}

@ -0,0 +1,94 @@
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:car_provider_app/views/branch_management/schedule/widgets/chips_picker_item.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class SelectDaysSheet extends StatefulWidget {
final Function(List<PickerItem>) onSelected;
const SelectDaysSheet({Key? key, required this.onSelected}) : super(key: key);
@override
State<SelectDaysSheet> createState() => _SelectDaysSheetState();
}
class _SelectDaysSheetState extends State<SelectDaysSheet> {
List<PickerItem> list = [];
@override
void initState() {
super.initState();
list = context.read<ScheduleVM>().intiDays();
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.4,
padding: const EdgeInsets.only(left: 20, right: 20, top: 6, bottom: 20),
child: Column(
children: [
Row(
children: [
Expanded(
child: LocaleKeys.selectDays.tr().toText(fontSize: 24, isBold: true),
),
Center(
child: list.where((element) => element.isSelected == true).toList().length.toString().toText(
fontSize: 10,
isBold: true,
color: Colors.white,
),
).toContainer(
borderRadius: 100,
width: 24,
height: 24,
paddingAll: 0,
backgroundColor: MyColors.darkPrimaryColor,
),
],
),
12.height,
Expanded(
child: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
contentPadding: EdgeInsets.zero,
controlAffinity: ListTileControlAffinity.leading,
title: list[index].title.toText(fontSize: 16),
value: list[index].isSelected,
onChanged: (bool? v) {
list[index].isSelected = v;
setState(() {});
},
);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1,
);
},
itemCount: list.length,
),
),
ShowFillButton(
title: LocaleKeys.addSelectedDays.tr(),
maxWidth: double.infinity,
onPressed: () {
widget.onSelected(list);
Navigator.pop(context);
},
)
],
),
);
}
}

@ -0,0 +1,102 @@
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class SelectServicesSheet extends StatelessWidget {
Function onSelectServices;
SelectServicesSheet({Key? key, required this.onSelectServices}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.4,
child: Column(
children: [
Expanded(
child: Consumer<ScheduleVM>(
builder: (_, model, child) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 6),
child: Column(
children: [
Row(
children: [
Expanded(
child: LocaleKeys.select_Services.tr().toText(fontSize: 24, isBold: true),
),
Center(
child: (model.servicesList == null ? "0" : model.servicesList!.where((element) => element.isSelected == true).toList().length.toString()).toText(
fontSize: 10,
isBold: true,
color: Colors.white,
),
).toContainer(
borderRadius: 100,
width: 24,
height: 24,
paddingAll: 0,
backgroundColor: MyColors.darkPrimaryColor,
),
],
),
12.height,
TxtField(
hint: LocaleKeys.searchService.tr(),
onChanged: (v) {},
),
12.height,
Expanded(
child: model.servicesList == null
? const Center(child: CircularProgressIndicator())
: ListView.separated(
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
contentPadding: EdgeInsets.zero,
controlAffinity: ListTileControlAffinity.leading,
title: model.servicesList![index].description!.toText(fontSize: 16),
value: model.servicesList![index].isSelected,
onChanged: (bool? v) {
model.servicesList![index].isSelected = v;
model.notifyListeners();
},
);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1,
);
},
itemCount: model.servicesList!.length,
),
),
],
),
);
},
),
),
ShowFillButton(
title: LocaleKeys.addSelectedServices.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
onSelectServices();
Navigator.pop(context);
},
)
],
),
);
}
}

@ -0,0 +1,285 @@
import 'dart:convert';
import 'dart:io';
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class CreateItemPage extends StatefulWidget {
const CreateItemPage({Key? key}) : super(key: key);
@override
State<CreateItemPage> createState() => _CreateItemPageState();
}
class _CreateItemPageState extends State<CreateItemPage> {
String? name, description, price, year, itemImage;
bool isAppointmentAvailable = false;
bool isWorkshopAppointmentAvailable = false;
bool isHomeAppointmentAvailable = false;
bool isDefaultValudDone = false;
File? file;
ItemsVM? itemsVM;
ItemData? itemData;
setDefaultData() {
name = itemData!.name;
description = itemData!.description;
price = itemData!.price;
if (itemData!.pictureUrl != null && itemData!.pictureUrl!.isNotEmpty) {
pickedImage.clear();
pickedImage.add(ImageModel(isFromNetwork: true, id: 1, filePath: itemData!.pictureUrl!));
}
//TODO: need to discuss with zahoor year and picture
if (itemData!.manufactureDate != null) year = DateHelper.formatAsYearMonthDay(DateHelper.parseStringToDate(itemData!.manufactureDate ?? DateTime.now().toString()));
isAppointmentAvailable = itemData!.isAllowAppointment ?? false;
isWorkshopAppointmentAvailable = itemData!.isAppointmentCompanyLoc ?? false;
isHomeAppointmentAvailable = itemData!.isAppointmentCustomerLoc ?? false;
isDefaultValudDone = true;
}
@override
Widget build(BuildContext context) {
itemsVM ??= context.read<ItemsVM>();
itemData ??= ModalRoute.of(context)!.settings.arguments as ItemData;
if (!isDefaultValudDone) setDefaultData();
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.addItems.tr(),
),
body: Container(
width: double.infinity,
height: double.infinity,
padding: const EdgeInsets.all(20),
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
TxtField(
hint: LocaleKeys.itemName.tr(),
value: name,
onChanged: (v) {
name = v;
},
),
12.height,
TxtField(
hint: LocaleKeys.itemDescription.tr(),
value: description,
onChanged: (v) {
description = v;
},
),
12.height,
TxtField(
hint: LocaleKeys.itemPrice.tr(),
value: price,
keyboardType: TextInputType.number,
onChanged: (v) {
price = v;
},
),
12.height,
TxtField(
hint: LocaleKeys.manufacturedOn.tr(),
value: year,
keyboardType: TextInputType.number,
isNeedClickAll: true,
postfixWidget: const IconButton(
onPressed: null,
icon: Icon(Icons.date_range),
),
onTap: () async {
year = await Utils.pickDateFromDatePicker(context, firstDate: DateTime(1990), lastDate: DateTime.now());
setState(() {});
},
onChanged: (v) {
year = v;
},
),
12.height,
if (pickedImage.isNotEmpty) ...[
PickedFilesContainer(
pickedFiles: pickedImage,
onCrossPressedPrimary: onCrossPress,
isPdf: false,
isReview: false,
isFromNetwork: false,
allowAdButton: false,
onAddFilePressed: () async {
file = await itemsVM!.pickSingleFile(context);
if (file != null) {
pickedImage.add(ImageModel(isFromNetwork: false, id: 1, filePath: file!.path));
}
setState(() {});
},
),
] else ...[
10.height,
DottedRectContainer(
onTap: () async {
file = await itemsVM!.pickSingleFile(context);
if (file != null) {
pickedImage.add(ImageModel(isFromNetwork: false, id: 1, filePath: file!.path));
}
setState(() {});
},
text: LocaleKeys.attachImage.tr(),
icon: MyAssets.attachmentIcon.buildSvg(),
)
],
20.height,
CheckBoxWithTitleDescription(
isSelected: isAppointmentAvailable,
title: LocaleKeys.availableforAppointment.tr(),
description: LocaleKeys.bookAppointmentForServices.tr(),
onSelection: (bool v) {
setState(() {
isAppointmentAvailable = v;
// isWorkshopAppointmentAvailable = v;
});
},
),
12.height,
if (isAppointmentAvailable)
CheckBoxWithTitleDescription(
isSelected: isWorkshopAppointmentAvailable,
title: LocaleKeys.allowingWorkshopService.tr(),
description: LocaleKeys.showServiceAvailability.tr(),
onSelection: (bool v) {
setState(() {
isWorkshopAppointmentAvailable = v;
});
},
),
12.height,
if (isAppointmentAvailable)
CheckBoxWithTitleDescription(
isSelected: isHomeAppointmentAvailable,
title: LocaleKeys.allowingHomeService.tr(),
description: LocaleKeys.bookAppointmentAtLocation.tr(),
onSelection: (bool v) {
setState(() {
isHomeAppointmentAvailable = v;
});
},
),
12.height,
],
),
),
),
ShowFillButton(
title: (itemData!.isUpdateOrSelected ?? false) ? "Update Item" : "Create Item",
maxWidth: double.infinity,
onPressed: () async {
if (validation()) {
var attachedFile = Utils.convertFileToBase64(file!);
if (!(itemData?.isUpdateOrSelected ?? false)) {
Map map = {
"name": name,
"price": price,
"description": description,
"itemImage": attachedFile ?? "",
"companyID": 1,
"manufactureDate": year,
"serviceProviderServiceID": itemData!.serviceProviderServiceId,
"isActive": true,
"isAllowAppointment": isAppointmentAvailable,
"isAppointmentCompanyLoc": isWorkshopAppointmentAvailable,
"isAppointmentCustomerLoc": isHomeAppointmentAvailable
};
Utils.showLoading(context);
GenericRespModel mResponse = await itemsVM!.createServiceItem(map);
Utils.hideLoading(context);
if (mResponse.messageStatus == 1) {
itemsVM!.getServiceItems(itemData!.serviceProviderServiceId ?? 0);
pop(context);
}
Utils.showToast(mResponse.message ?? "");
} else {
Map map = {
"id": itemData!.id,
"name": name,
"price": price,
"description": description,
"itemImage": attachedFile ?? "",
"companyID": 1,
"manufactureDate": year,
"serviceProviderServiceID": itemData!.serviceProviderServiceId,
"isActive": true,
"isAllowAppointment": isAppointmentAvailable,
"isAppointmentCompanyLoc": isWorkshopAppointmentAvailable,
"isAppointmentCustomerLoc": isHomeAppointmentAvailable
};
Utils.showLoading(context);
GenericRespModel mResponse = await itemsVM!.updateServiceItem(map);
Utils.hideLoading(context);
if (mResponse.messageStatus == 1) {
itemsVM!.getServiceItems(itemData!.serviceProviderServiceId ?? 0);
pop(context);
}
Utils.showToast(mResponse.message ?? "");
pop(context);
}
}
},
),
],
),
),
);
}
bool validation() {
bool valid = true;
if (file == null) {
Utils.showToast("Please add al least one item image.");
valid = false;
}
if (name == null || name!.length < 3) {
Utils.showToast("Please add valid item name");
valid = false;
} else if (description == null || description!.length < 3) {
Utils.showToast("Please add valid item description");
valid = false;
} else if (price == null) {
Utils.showToast("Please add valid item price");
valid = false;
} else if (year == null) {
Utils.showToast("Please add valid year");
valid = false;
}
return valid;
}
void onCrossPress(String item) {
file = null;
pickedImage.clear();
setState(() {});
}
List<ImageModel> pickedImage = [];
}

@ -0,0 +1,292 @@
import 'dart:async';
import 'dart:developer';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/branch_management/services/services_list_page.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
// [log] 1035 -> branch ID
// [log] HMG Branch QA II -> branchName
// [log] 8 -> category ID
// [log] Sell Car -> categegory name
// [log] New Car -> service name
class CreateServicesPage3 extends StatefulWidget {
final CreateBranchModel? branchModel;
const CreateServicesPage3(this.branchModel, {Key? key}) : super(key: key);
@override
State<CreateServicesPage3> createState() => _CreateServicesPage3State();
}
class _CreateServicesPage3State extends State<CreateServicesPage3> {
bool isAppointmentAvailable = false;
bool isHomeAppointmentAvailable = false;
int serviceRage = 0;
String chargersPerKm = "";
int? categoryId;
int? serviceId = -1;
DropValue? category;
DropValue? service;
@override
void initState() {
super.initState();
scheduleMicrotask(() async {
ServiceVM serviceVM = context.read<ServiceVM>();
log("widget.branchModel!.categoryId: ${widget.branchModel!.categoryId}");
if (widget.branchModel!.categoryId != null) {
await serviceVM.fetchServicesByCategoryId(int.parse(widget.branchModel!.categoryId ?? "0"));
category = DropValue(int.parse(widget.branchModel!.categoryId ?? "0"), widget.branchModel!.categoryName ?? "", "");
service = serviceVM.servicesDropList.firstWhere((element) => element.id == widget.branchModel!.serviceProviderService!.serviceId);
isAppointmentAvailable = widget.branchModel?.serviceProviderService?.isAllowAppointment ?? false;
serviceRage = widget.branchModel?.serviceProviderService?.customerLocationRange ?? 0;
if (serviceRage > 0) {
isHomeAppointmentAvailable = true;
}
chargersPerKm = widget.branchModel?.serviceProviderService?.rangePricePerKm ?? "";
serviceId = widget.branchModel?.serviceProviderService?.serviceProviderServiceId ?? -1;
setState(() {});
} else {
serviceVM.fetchBranchCategory(EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.editServices.tr()),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Consumer<ServiceVM>(
builder: (context, model, _) {
return Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
(model.state == ViewState.idle)
? DropdownField(
isSelectAble: !widget.branchModel!.isForEdit,
(DropValue value) async {
categoryId = value.id;
category = value;
service = null;
serviceId = -1;
isAppointmentAvailable = false;
isHomeAppointmentAvailable = false;
model.fetchServicesByCategoryId(value.id);
},
dropdownValue: category,
list: model.categoryDropList,
hint: category != null ? category!.value : LocaleKeys.selectServiceCategory.tr(),
)
: const CircularProgressIndicator(),
12.height,
model.servicesDropList.isNotEmpty
? DropdownField(
(DropValue value) {
service = value;
serviceId = value.id;
isAppointmentAvailable = false;
isHomeAppointmentAvailable = false;
model.setState(ViewState.idle);
},
dropdownValue: service,
list: model.servicesDropList,
hint: LocaleKeys.defineServices.tr(),
)
: Container(),
12.height,
if (serviceId != -1) ...[
Column(
children: [
20.height,
CheckBoxWithTitleDescription(
isSelected: isAppointmentAvailable,
title: LocaleKeys.availableforAppointment.tr(),
description: LocaleKeys.bookAppointmentForServices.tr(),
onSelection: (bool v) {
isAppointmentAvailable = v;
model.setState(ViewState.idle);
},
),
20.height,
CheckBoxWithTitleDescription(
isSelected: isHomeAppointmentAvailable,
title: LocaleKeys.allowingHomeService.tr(),
description: LocaleKeys.bookAppointmentAtLocation.tr(),
onSelection: (bool v) {
isHomeAppointmentAvailable = v;
model.setState(ViewState.idle);
},
),
20.height,
if (isHomeAppointmentAvailable)
Column(
children: [
TxtField(
hint: LocaleKeys.homeServiceRange.tr(),
keyboardType: TextInputType.number,
value: serviceRage == 0 ? null : serviceRage.toString(),
postfixWidget: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
"KM".toText(color: MyColors.lightTextColor),
],
),
onChanged: (v) {
if (v.isNotEmpty) {
serviceRage = int.parse(v);
} else {
serviceRage = 0;
}
},
),
12.height,
TxtField(
hint: LocaleKeys.chargesPerKM.tr(),
keyboardType: TextInputType.number,
value: chargersPerKm == "" ? null : chargersPerKm,
onChanged: (v) {
if (v.isNotEmpty) {
chargersPerKm = v;
} else {
chargersPerKm = "";
}
},
postfixWidget: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor),
],
),
),
],
),
],
),
]
],
),
),
),
),
if (serviceId != -1)
ShowFillButton(
title: LocaleKeys.save.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
if (widget.branchModel!.serviceProviderService != null) {
updateService(context, model);
} else {
if (model.services != null) {
createService(context, model);
}
}
},
),
],
);
},
),
),
);
}
createService(BuildContext context, ServiceVM model) async {
List<Map<String, dynamic>> map = [];
model.services!.data?.forEach((element) {
if (serviceId == element.id) {
element.isSelected = true;
} else {
element.isSelected = false;
}
});
for (int i = 0; i < model.services!.data!.length; i++) {
if (model.services!.data![i].isSelected ?? false) {
var postParams = {
// "id": services!.data![i].id,
"providerBranchID": widget.branchModel!.branchId,
"serviceID": model.services!.data![i].id,
"isAllowAppointment": isAppointmentAvailable,
"isActive": true,
"customerLocationRange": serviceRage,
"rangePricePerKm": chargersPerKm.isEmpty ? "0.0" : chargersPerKm,
};
map.add(postParams);
}
}
// print(map);
Utils.showLoading(context);
GenericRespModel mResponse = await model.createService(map);
await model.getBranchAndServices();
Utils.hideLoading(context);
Utils.showToast(mResponse.message ?? "");
if (mResponse.messageStatus == 1) {
context.read<ServiceVM>().filterUserBranchCategories();
pop(context);
}
}
updateService(BuildContext context, ServiceVM model) async {
List<Map<String, dynamic>> map = [];
if (isHomeAppointmentAvailable) {
map = [
{
"id": widget.branchModel!.serviceProviderService!.serviceProviderServiceId.toString(),
"isAllowAppointment": isAppointmentAvailable,
"isActive": true,
"customerLocationRange": serviceRage,
"rangePricePerKm": chargersPerKm.isEmpty ? "0.0" : chargersPerKm,
}
];
} else {
map = [
{
"id": widget.branchModel!.serviceProviderService!.serviceProviderServiceId.toString(),
"isAllowAppointment": isAppointmentAvailable,
"isActive": true,
}
];
}
// print(map);
Utils.showLoading(context);
GenericRespModel mResponse = await model.updateServices(map);
model.getBranchAndServices();
model.filterUserBranchCategories();
Utils.hideLoading(context);
Utils.showToast(mResponse.message ?? "");
if (mResponse.messageStatus == 1) {
context.read<ServiceVM>().filterUserBranchCategories();
pop(context);
}
}
}

@ -0,0 +1,211 @@
// import 'package:mc_common_app/view_models/service_view_model.dart';
// import 'package:easy_localization/easy_localization.dart';
//
// import 'package:flutter/material.dart';
//
// import 'package:car_provider_app/generated/locale_keys.g.dart';
//
// import 'package:car_provider_app/view_models/branch_view_model.dart';
// import 'package:mc_common_app/extensions/int_extensions.dart';
// import 'package:mc_common_app/extensions/string_extensions.dart';
// import 'package:mc_common_app/models/m_response.dart';
// import 'package:mc_common_app/models/model/branch2.dart';
// import 'package:mc_common_app/theme/colors.dart';
// import 'package:mc_common_app/utils/enums.dart';
// import 'package:mc_common_app/utils/navigator.dart';
// import 'package:mc_common_app/utils/utils.dart';
// import 'package:mc_common_app/widgets/button/show_fill_button.dart';
// import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
// import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
// import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
//
// import 'package:provider/provider.dart';
//
// class CreateServicesPage extends StatelessWidget {
// ServiceProviderBranch? serviceProviderBranch;
//
// CreateServicesPage(this.serviceProviderBranch, {Key? key}) : super(key: key);
//
// @override
// Widget build(BuildContext context) {
// ServiceVM branchVM = context.read<ServiceVM>();
// branchVM.getBranchAndServices();
// branchVM.fetchBranches();
// if (serviceProviderBranch != null) {
// // branchVM.branchId = serviceProviderBranch!.id ?? -1;
// // branchVM.branchValue = DropValue(branchVM.branchId, serviceProviderBranch!.branchName ?? "", "");
// // print("llll1 ${branchVM.branchId} ${serviceProviderBranch!.branchName} ${branchVM.branchValue!.value}");
// if (branchVM.branchId != 1) branchVM.fetchBranchCategory(EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
// }
//
// return Scaffold(
// appBar: CustomAppBar(title: LocaleKeys.defineServices.tr()),
// body: SizedBox(
// width: double.infinity,
// height: double.infinity,
// child: Consumer<ServiceVM>(builder: (context, model, _) {
// return Column(
// children: [
// Expanded(
// child: SingleChildScrollView(
// child: Padding(
// padding: const EdgeInsets.all(12.0),
// child: Column(
// children: [
// model.branch != null
// ? (model.branchValue != null && model.branchId != -1)
// ? Text(
// model.branchValue!.value ?? "",
// style: const TextStyle(
// fontSize: 12,
// fontWeight: FontWeight.bold,
// ),
// ).toContainer(
// padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12, top: 12),
// backgroundColor: MyColors.textFieldColor,
// borderRadius: 0,
// width: double.infinity,
// )
// : DropdownField(
// (DropValue value) {
// // countryCode = value.subValue;
// // countryId = value.id;
// // fetchCites();
// model.branchId = value.id;
// model.fetchBranchCategory(EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
// model.setState(ViewState.idle);
// },
// list: model.countryDropListForService,
// hint: LocaleKeys.selectBranch.tr(),
// dropdownValue: model.branchValue,
// )
// : const CircularProgressIndicator(),
// 12.height,
// (model.category != null)
// ? DropdownField((DropValue value) {
// // countryCode = value.subValue;
// // countryId = value.id;
// // fetchCites();
// model.categoryId = value.id;
// model.fetchServicesByCategoryId();
// model.setState(ViewState.idle);
// }, list: model.categoryDropList, hint: LocaleKeys.selectServiceCategory.tr())
// : model.branchId == -1
// ? Container()
// : const CircularProgressIndicator(),
// 12.height,
// if ((model.categoryId != -1))
// model.services == null
// ? const CircularProgressIndicator()
// : ListView.separated(
// itemBuilder: (context, index) {
// return Padding(
// padding: const EdgeInsets.all(8.0),
// child: Row(
// children: [
// Checkbox(
// value: model.services!.data![index].isSelected,
// onChanged: (v) {
// model.services!.data![index].isSelected = v;
// model.setState(ViewState.idle);
// },
// ),
// 12.width,
// ((EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" ? model.services!.data![index].descriptionN : model.services!.data![index].description) ??
// "")
// .toText(fontSize: 12)
// ],
// ),
// );
// },
// separatorBuilder: (context, index) {
// return 1.height;
// },
// itemCount: model.services!.data!.length,
// physics: NeverScrollableScrollPhysics(),
// shrinkWrap: true,
// )
// ],
// ),
// ),
// ),
// ),
// if (checkServicesSelection(model))
// Padding(
// padding: const EdgeInsets.all(12.0),
// child: ShowFillButton(
// title: LocaleKeys.save.tr(),
// maxWidth: double.infinity,
// onPressed: () {
// createService(context, model);
// },
// ),
// ),
// ],
// );
// }),
// ),
// );
// }
//
// bool checkServicesSelection(BranchVM model) {
// bool isServiceSelected = false;
// try {
// for (var element in model.services!.data!) {
// if (element.isSelected ?? false) isServiceSelected = true;
// }
// } catch (e) {
// isServiceSelected = false;
// }
//
// return isServiceSelected;
// }
//
// createService(BuildContext context, BranchVM model) async {
// List<Map<String, dynamic>> map = [];
// if (serviceProviderBranch != null && model.branchId != -1) {
// for (int i = 0; i < model.services!.data!.length; i++) {
// if (model.services!.data![i].isSelected ?? false) {
// var postParams = {
// // "id": services!.data![i].id,
// "providerBranchID": model.branchId,
// "serviceID": model.services!.data![i].id,
// "isAllowAppointment": true,
// "isActive": true
// };
// map.add(postParams);
// }
// }
// Utils.showLoading(context);
// MResponse mResponse = await model.createService(map);
// Utils.hideLoading(context);
//
// if (serviceProviderBranch != null) {
// Utils.showToast(mResponse.message ?? "");
// if (mResponse.messageStatus != 2) {
// pop(context);
// pop(context);
// model.getBranchAndServices();
// }
// }
// } else {
// for (int i = 0; i < model.services!.data!.length; i++) {
// if (model.services!.data![i].isSelected ?? false) {
// var postParams = {
// // "id": services!.data![i].id,
// "providerBranchID": model.branchId,
// "serviceID": model.services!.data![i].id,
// "isAllowAppointment": true,
// "isActive": true
// };
// map.add(postParams);
// }
// }
// Utils.showLoading(context);
// MResponse mResponse = await model.createService(map);
// model.getBranchAndServices();
// Utils.hideLoading(context);
// Utils.showToast(mResponse.message ?? "");
// }
// }
// }

@ -0,0 +1,171 @@
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/branch_management/services/duplication/sheet/approved_branches_list_sheet.dart';
import 'package:car_provider_app/views/branch_management/services/duplication/sheet/items_selection_sheet.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/dropdown/dropdown_text.dart';
import 'package:mc_common_app/widgets/empty_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class MatchedServicesPage extends StatefulWidget {
final MatchServicesArguments? matchServicesArguments;
const MatchedServicesPage(this.matchServicesArguments, {Key? key}) : super(key: key);
@override
State<MatchedServicesPage> createState() => _MatchedServicesPageState();
}
class _MatchedServicesPageState extends State<MatchedServicesPage> {
late ServiceVM serviceVM;
@override
void initState() {
super.initState();
serviceVM = Provider.of<ServiceVM>(context, listen: false);
getMatchedServices();
}
getMatchedServices() {
serviceVM.getAllMatchedServices(widget.matchServicesArguments!.oldBranch, widget.matchServicesArguments!.newBranch, widget.matchServicesArguments!.categoryId);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.selectServices.tr(),
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
DropDownText(widget.matchServicesArguments!.oldBranchName).toContainer(
padding: const EdgeInsets.only(
left: 14,
right: 14,
top: 21,
),
),
12.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Checkbox(
value: context.watch<ServiceVM>().isAllSelected,
onChanged: (v) {
serviceVM.selectAllServices(v ?? false);
},
),
LocaleKeys.selectAll.tr().toText(isBold: true)
],
),
Container(
alignment: Alignment.centerRight,
margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 7),
child: LocaleKeys.unselectAll.tr().toText(
color: MyColors.primaryColor,
isUnderLine: true,
isBold: true,
),
).onPress(() {
serviceVM.selectAllServices(false);
}),
],
),
12.height,
Expanded(
child: Consumer<ServiceVM>(builder: (context, model, _) {
if (model.matchedServices == null) {
return const Center(child: CircularProgressIndicator());
} else if (model.matchedServices!.isEmpty) {
return EmptyWidget(text: LocaleKeys.noServicesAvailable.tr(), isWrappedColumn: false);
}
return ListView.separated(
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Checkbox(
value: model.matchedServices![index].isExpandedOrSelected,
onChanged: (v) {
if (model.matchedServices![index].serviceItems!.isEmpty) {
Utils.showToast(LocaleKeys.noItemstoShow.tr());
} else {
model.matchedServices![index].isExpandedOrSelected = v ?? false;
model.updateServiceItem(index, model.matchedServices![index].isExpandedOrSelected);
}
},
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
model.matchedServices![index].serviceDescription.toString().toText(fontSize: 16, isBold: true),
"${model.matchedServices![index].serviceItems!.where((c) => c.isUpdateOrSelected == true).length} items selected out of ${model.matchedServices![index].serviceItems!.length}".toText(color: MyColors.lightTextColor)
],
),
),
SvgPicture.asset(
MyAssets.icEdit,
width: 16,
height: 16,
),
],
).toWhiteContainer(width: double.infinity, allPading: 8).onPress(
() {
showMyBottomSheet(
context,
child: ItemsSelectionSheet(
model.matchedServices![index].serviceItems ?? [],
onItemCopied: (List<ItemData> selected) {
model.copyItems(index, selected);
},
),
);
},
);
},
separatorBuilder: (context, index) {
return 8.height;
},
padding: const EdgeInsets.symmetric(horizontal: 14),
itemCount: model.matchedServices!.length,
);
}),
),
12.height,
ShowFillButton(
title: LocaleKeys.copySelectedServices.tr(),
maxWidth: double.infinity,
margin: const EdgeInsets.all(14),
onPressed: () async {
await serviceVM.duplicateItems(
providerBranchID: widget.matchServicesArguments!.newBranch.toString(),
context: context,
);
},
),
],
),
),
);
}
}

@ -0,0 +1,141 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_svg/svg.dart';
import 'package:geolocator/geolocator.dart';
class MatchServicesArguments {
int oldBranch, newBranch, categoryId;
String oldBranchName;
MatchServicesArguments({required this.oldBranch, required this.oldBranchName, required this.newBranch, required this.categoryId});
}
class ApprovedBranchesListSheet extends StatelessWidget {
int newBranch, categoryId;
ApprovedBranchesListSheet({required this.newBranch, required this.categoryId, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
height: MediaQuery.of(context).size.height / 1.2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Select Branch".toText(fontSize: 20, isBold: true),
"Select the branch to copy their items to this branch. You can modify the selection at any time.".toText(
fontSize: 12,
),
12.height,
Expanded(
child: Consumer<ServiceVM>(
builder: (context, model, _) {
if (model.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
List<BranchDetailModel> branches = [];
if (model.branches!.data != null) {
branches = model.branches!.data!.serviceProviderBranch!.where((element) => model.selectedBranchStatus == element.statusId).toList();
}
return branches.isEmpty
? Center(child: Text(LocaleKeys.no_branch.tr()))
: ListView.separated(
itemBuilder: (context, index) {
return Row(
children: [
Container(
width: 74,
height: 50,
decoration: const BoxDecoration(
color: MyColors.darkPrimaryColor,
borderRadius: BorderRadius.all(Radius.circular(8)),
),
padding: const EdgeInsets.all(6),
child: SvgPicture.asset(
MyAssets.icBranches,
color: Colors.white,
),
),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
const Icon(
Icons.place,
size: 12,
color: MyColors.darkPrimaryColor,
),
Geolocator.distanceBetween(AppState().currentLocation.latitude, AppState().currentLocation.latitude, double.parse(branches[index].latitude ?? "0"),
double.parse(branches[index].longitude ?? "0"))
.toStringAsFixed(2)
.toText(
fontSize: 12,
color: MyColors.darkPrimaryColor,
)
],
),
Text(
branches[index].branchName ?? "",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
"Tap to select".toText(fontSize: 10, color: MyColors.grey70Color),
],
),
),
12.width,
const Icon(
Icons.arrow_forward_rounded,
size: 16,
),
],
).toContainer(isShadowEnabled: true).onPress(() async {
// branches[index].countryID = model.branchs!.data!.countryID;
// branches[index].countryName = model.branchs!.data!.countryName;
navigateWithName(
context,
ProviderAppRoutes.matchServices,
arguments: MatchServicesArguments(
oldBranch: branches[index].id ?? 0,
oldBranchName: branches[index].branchName ?? "",
newBranch: newBranch,
categoryId: categoryId,
),
);
});
},
separatorBuilder: (context, index) {
return 12.height;
},
itemCount: branches.length,
);
}
},
),
),
],
),
);
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save