Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca5d2a58e7 | ||
|
|
5d9197c986 | ||
|
|
9a61cbecc4 | ||
|
|
cf8f0b373d | ||
|
|
4fee7c4bb7 |
@@ -1,28 +1,20 @@
|
|||||||
# 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
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
|
||||||
# included above or to enable additional rules. A list of all available lints
|
|
||||||
# and their documentation is published at https://dart.dev/lints.
|
|
||||||
#
|
|
||||||
# Instead of disabling a lint rule for the entire project in the
|
|
||||||
# section below, it can also be suppressed for a single line of code
|
|
||||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
|
||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
|
||||||
# producing the lint.
|
|
||||||
rules:
|
rules:
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
sort_pub_dependencies: false
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
prefer_relative_imports: true
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
analyzer:
|
||||||
# https://dart.dev/guides/language/analysis-options
|
errors:
|
||||||
|
missing_required_param: error
|
||||||
|
missing_return: error
|
||||||
|
must_be_immutable: error
|
||||||
|
sort_unnamed_constructors_first: ignore
|
||||||
|
invalid_annotation_target: ignore
|
||||||
|
use_build_context_synchronously: ignore
|
||||||
|
deprecated_member_use: ignore
|
||||||
|
exclude:
|
||||||
|
- test/generated/**
|
||||||
|
- "**/**.g.dart"
|
||||||
|
- "**/**.freezed.dart"
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ plugins {
|
|||||||
id("kotlin-android")
|
id("kotlin-android")
|
||||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
|
id("com.google.gms.google-services")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.apskel_pos_flutter_v2"
|
namespace = "com.apskel.pos"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId = "com.example.apskel_pos_flutter_v2"
|
applicationId = "com.apskel.pos"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
@@ -42,3 +43,10 @@ android {
|
|||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Import the Firebase BoM
|
||||||
|
implementation(platform("com.google.firebase:firebase-bom:34.4.0"))
|
||||||
|
|
||||||
|
implementation("com.google.firebase:firebase-analytics")
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "765730035527",
|
||||||
|
"project_id": "apskel-pos-v2",
|
||||||
|
"storage_bucket": "apskel-pos-v2.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:765730035527:android:498defd7071336dd241e62",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.apskel.pos"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyAOZwVSQwUeeM9BjcyTOK9GUh8AmTWucuc"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
@@ -1,8 +1,19 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
|
||||||
|
<!-- Izin khusus untuk akses foto (media images) di Android 33 ke atas -->
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||||
<application
|
<application
|
||||||
android:label="apskel_pos_flutter_v2"
|
android:label="Apskel POS"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/launcher_icon">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.example.apskel_pos_flutter_v2
|
package com.apskel.pos
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 19 KiB |
@@ -20,6 +20,7 @@ plugins {
|
|||||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
id("com.android.application") version "8.7.3" apply false
|
id("com.android.application") version "8.7.3" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
|
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
|
||||||
|
id("com.google.gms.google-services") version "4.4.4" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
include(":app")
|
include(":app")
|
||||||
|
|||||||
|
After Width: | Height: | Size: 79 KiB |
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||||
#include "Generated.xcconfig"
|
#include "Generated.xcconfig"
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
# platform :ios, '13.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!
|
||||||
|
|
||||||
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
target 'RunnerTests' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
post_install do |installer|
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
flutter_additional_ios_build_settings(target)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -427,7 +427,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
@@ -484,7 +484,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
|||||||
@@ -1,122 +1 @@
|
|||||||
{
|
{"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":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"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":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@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"}}
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 678 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
# Generate: dart run flutter_launcher_icons -f launcher_icon.yaml
|
||||||
|
|
||||||
|
flutter_launcher_icons:
|
||||||
|
android: "launcher_icon"
|
||||||
|
ios: true
|
||||||
|
image_path: "assets/images/logo.png"
|
||||||
|
remove_alpha_ios: true
|
||||||
|
min_sdk_android: 21 # android min sdk min:16, default 21
|
||||||
|
web:
|
||||||
|
generate: true
|
||||||
|
image_path: "assets/images/logo.png"
|
||||||
|
windows:
|
||||||
|
generate: true
|
||||||
|
image_path: "assets/images/logo.png"
|
||||||
|
icon_size: 48
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../../domain/auth/auth.dart';
|
||||||
|
|
||||||
|
part 'login_form_event.dart';
|
||||||
|
part 'login_form_state.dart';
|
||||||
|
part 'login_form_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
|
||||||
|
final IAuthRepository _authRepository;
|
||||||
|
LoginFormBloc(this._authRepository) : super(LoginFormState.initial()) {
|
||||||
|
on<LoginFormEvent>(_onLoginFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onLoginFormEvent(
|
||||||
|
LoginFormEvent event,
|
||||||
|
Emitter<LoginFormState> emit,
|
||||||
|
) {
|
||||||
|
return event.map(
|
||||||
|
emailChanged: (e) async {
|
||||||
|
emit(state.copyWith(email: e.email, failureOrLoginOption: none()));
|
||||||
|
},
|
||||||
|
passwordChanged: (e) async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(password: e.password, failureOrLoginOption: none()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
submitted: (e) async {
|
||||||
|
Either<AuthFailure, Login>? failureOrLogin;
|
||||||
|
emit(state.copyWith(isSubmitting: true, failureOrLoginOption: none()));
|
||||||
|
|
||||||
|
final emailValid = state.email.isNotEmpty;
|
||||||
|
final passwordValid = state.password.isNotEmpty;
|
||||||
|
|
||||||
|
log(
|
||||||
|
'emailValid: $emailValid, passwordValid: $passwordValid, email: ${state.email}, password: ${state.password}',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (emailValid && passwordValid) {
|
||||||
|
failureOrLogin = await _authRepository.login(
|
||||||
|
email: state.email,
|
||||||
|
password: state.password,
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
failureOrLoginOption: optionOf(failureOrLogin),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
emit(state.copyWith(showErrorMessages: true, isSubmitting: false));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,734 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'login_form_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoginFormEvent {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
required TResult Function() submitted,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(String email)? emailChanged,
|
||||||
|
TResult? Function(String password)? passwordChanged,
|
||||||
|
TResult? Function()? submitted,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
TResult Function()? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(_PasswordChanged value) passwordChanged,
|
||||||
|
required TResult Function(_Submitted value) submitted,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult? Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult? Function(_Submitted value)? submitted,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult Function(_Submitted value)? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LoginFormEventCopyWith<$Res> {
|
||||||
|
factory $LoginFormEventCopyWith(
|
||||||
|
LoginFormEvent value,
|
||||||
|
$Res Function(LoginFormEvent) then,
|
||||||
|
) = _$LoginFormEventCopyWithImpl<$Res, LoginFormEvent>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LoginFormEventCopyWithImpl<$Res, $Val extends LoginFormEvent>
|
||||||
|
implements $LoginFormEventCopyWith<$Res> {
|
||||||
|
_$LoginFormEventCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$EmailChangedImplCopyWith<$Res> {
|
||||||
|
factory _$$EmailChangedImplCopyWith(
|
||||||
|
_$EmailChangedImpl value,
|
||||||
|
$Res Function(_$EmailChangedImpl) then,
|
||||||
|
) = __$$EmailChangedImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String email});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$EmailChangedImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoginFormEventCopyWithImpl<$Res, _$EmailChangedImpl>
|
||||||
|
implements _$$EmailChangedImplCopyWith<$Res> {
|
||||||
|
__$$EmailChangedImplCopyWithImpl(
|
||||||
|
_$EmailChangedImpl _value,
|
||||||
|
$Res Function(_$EmailChangedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? email = null}) {
|
||||||
|
return _then(
|
||||||
|
_$EmailChangedImpl(
|
||||||
|
null == email
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$EmailChangedImpl implements _EmailChanged {
|
||||||
|
const _$EmailChangedImpl(this.email);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String email;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent.emailChanged(email: $email)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$EmailChangedImpl &&
|
||||||
|
(identical(other.email, email) || other.email == email));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, email);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$EmailChangedImplCopyWith<_$EmailChangedImpl> get copyWith =>
|
||||||
|
__$$EmailChangedImplCopyWithImpl<_$EmailChangedImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
required TResult Function() submitted,
|
||||||
|
}) {
|
||||||
|
return emailChanged(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(String email)? emailChanged,
|
||||||
|
TResult? Function(String password)? passwordChanged,
|
||||||
|
TResult? Function()? submitted,
|
||||||
|
}) {
|
||||||
|
return emailChanged?.call(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
TResult Function()? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (emailChanged != null) {
|
||||||
|
return emailChanged(email);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(_PasswordChanged value) passwordChanged,
|
||||||
|
required TResult Function(_Submitted value) submitted,
|
||||||
|
}) {
|
||||||
|
return emailChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult? Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult? Function(_Submitted value)? submitted,
|
||||||
|
}) {
|
||||||
|
return emailChanged?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult Function(_Submitted value)? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (emailChanged != null) {
|
||||||
|
return emailChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _EmailChanged implements LoginFormEvent {
|
||||||
|
const factory _EmailChanged(final String email) = _$EmailChangedImpl;
|
||||||
|
|
||||||
|
String get email;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$EmailChangedImplCopyWith<_$EmailChangedImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$PasswordChangedImplCopyWith<$Res> {
|
||||||
|
factory _$$PasswordChangedImplCopyWith(
|
||||||
|
_$PasswordChangedImpl value,
|
||||||
|
$Res Function(_$PasswordChangedImpl) then,
|
||||||
|
) = __$$PasswordChangedImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String password});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$PasswordChangedImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoginFormEventCopyWithImpl<$Res, _$PasswordChangedImpl>
|
||||||
|
implements _$$PasswordChangedImplCopyWith<$Res> {
|
||||||
|
__$$PasswordChangedImplCopyWithImpl(
|
||||||
|
_$PasswordChangedImpl _value,
|
||||||
|
$Res Function(_$PasswordChangedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? password = null}) {
|
||||||
|
return _then(
|
||||||
|
_$PasswordChangedImpl(
|
||||||
|
null == password
|
||||||
|
? _value.password
|
||||||
|
: password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$PasswordChangedImpl implements _PasswordChanged {
|
||||||
|
const _$PasswordChangedImpl(this.password);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String password;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent.passwordChanged(password: $password)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$PasswordChangedImpl &&
|
||||||
|
(identical(other.password, password) ||
|
||||||
|
other.password == password));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, password);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$PasswordChangedImplCopyWith<_$PasswordChangedImpl> get copyWith =>
|
||||||
|
__$$PasswordChangedImplCopyWithImpl<_$PasswordChangedImpl>(
|
||||||
|
this,
|
||||||
|
_$identity,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
required TResult Function() submitted,
|
||||||
|
}) {
|
||||||
|
return passwordChanged(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(String email)? emailChanged,
|
||||||
|
TResult? Function(String password)? passwordChanged,
|
||||||
|
TResult? Function()? submitted,
|
||||||
|
}) {
|
||||||
|
return passwordChanged?.call(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
TResult Function()? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (passwordChanged != null) {
|
||||||
|
return passwordChanged(password);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(_PasswordChanged value) passwordChanged,
|
||||||
|
required TResult Function(_Submitted value) submitted,
|
||||||
|
}) {
|
||||||
|
return passwordChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult? Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult? Function(_Submitted value)? submitted,
|
||||||
|
}) {
|
||||||
|
return passwordChanged?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult Function(_Submitted value)? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (passwordChanged != null) {
|
||||||
|
return passwordChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _PasswordChanged implements LoginFormEvent {
|
||||||
|
const factory _PasswordChanged(final String password) = _$PasswordChangedImpl;
|
||||||
|
|
||||||
|
String get password;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$PasswordChangedImplCopyWith<_$PasswordChangedImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$SubmittedImplCopyWith<$Res> {
|
||||||
|
factory _$$SubmittedImplCopyWith(
|
||||||
|
_$SubmittedImpl value,
|
||||||
|
$Res Function(_$SubmittedImpl) then,
|
||||||
|
) = __$$SubmittedImplCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$SubmittedImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoginFormEventCopyWithImpl<$Res, _$SubmittedImpl>
|
||||||
|
implements _$$SubmittedImplCopyWith<$Res> {
|
||||||
|
__$$SubmittedImplCopyWithImpl(
|
||||||
|
_$SubmittedImpl _value,
|
||||||
|
$Res Function(_$SubmittedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$SubmittedImpl implements _Submitted {
|
||||||
|
const _$SubmittedImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent.submitted()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType && other is _$SubmittedImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(String email) emailChanged,
|
||||||
|
required TResult Function(String password) passwordChanged,
|
||||||
|
required TResult Function() submitted,
|
||||||
|
}) {
|
||||||
|
return submitted();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(String email)? emailChanged,
|
||||||
|
TResult? Function(String password)? passwordChanged,
|
||||||
|
TResult? Function()? submitted,
|
||||||
|
}) {
|
||||||
|
return submitted?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(String email)? emailChanged,
|
||||||
|
TResult Function(String password)? passwordChanged,
|
||||||
|
TResult Function()? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (submitted != null) {
|
||||||
|
return submitted();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_EmailChanged value) emailChanged,
|
||||||
|
required TResult Function(_PasswordChanged value) passwordChanged,
|
||||||
|
required TResult Function(_Submitted value) submitted,
|
||||||
|
}) {
|
||||||
|
return submitted(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult? Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult? Function(_Submitted value)? submitted,
|
||||||
|
}) {
|
||||||
|
return submitted?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_EmailChanged value)? emailChanged,
|
||||||
|
TResult Function(_PasswordChanged value)? passwordChanged,
|
||||||
|
TResult Function(_Submitted value)? submitted,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (submitted != null) {
|
||||||
|
return submitted(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _Submitted implements LoginFormEvent {
|
||||||
|
const factory _Submitted() = _$SubmittedImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoginFormState {
|
||||||
|
String get email => throw _privateConstructorUsedError;
|
||||||
|
String get password => throw _privateConstructorUsedError;
|
||||||
|
Option<Either<AuthFailure, Login>> get failureOrLoginOption =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
bool get isSubmitting => throw _privateConstructorUsedError;
|
||||||
|
bool get showErrorMessages => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$LoginFormStateCopyWith<LoginFormState> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LoginFormStateCopyWith<$Res> {
|
||||||
|
factory $LoginFormStateCopyWith(
|
||||||
|
LoginFormState value,
|
||||||
|
$Res Function(LoginFormState) then,
|
||||||
|
) = _$LoginFormStateCopyWithImpl<$Res, LoginFormState>;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String email,
|
||||||
|
String password,
|
||||||
|
Option<Either<AuthFailure, Login>> failureOrLoginOption,
|
||||||
|
bool isSubmitting,
|
||||||
|
bool showErrorMessages,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LoginFormStateCopyWithImpl<$Res, $Val extends LoginFormState>
|
||||||
|
implements $LoginFormStateCopyWith<$Res> {
|
||||||
|
_$LoginFormStateCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? email = null,
|
||||||
|
Object? password = null,
|
||||||
|
Object? failureOrLoginOption = null,
|
||||||
|
Object? isSubmitting = null,
|
||||||
|
Object? showErrorMessages = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
email: null == email
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
password: null == password
|
||||||
|
? _value.password
|
||||||
|
: password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
failureOrLoginOption: null == failureOrLoginOption
|
||||||
|
? _value.failureOrLoginOption
|
||||||
|
: failureOrLoginOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Login>>,
|
||||||
|
isSubmitting: null == isSubmitting
|
||||||
|
? _value.isSubmitting
|
||||||
|
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
showErrorMessages: null == showErrorMessages
|
||||||
|
? _value.showErrorMessages
|
||||||
|
: showErrorMessages // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LoginFormStateImplCopyWith<$Res>
|
||||||
|
implements $LoginFormStateCopyWith<$Res> {
|
||||||
|
factory _$$LoginFormStateImplCopyWith(
|
||||||
|
_$LoginFormStateImpl value,
|
||||||
|
$Res Function(_$LoginFormStateImpl) then,
|
||||||
|
) = __$$LoginFormStateImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String email,
|
||||||
|
String password,
|
||||||
|
Option<Either<AuthFailure, Login>> failureOrLoginOption,
|
||||||
|
bool isSubmitting,
|
||||||
|
bool showErrorMessages,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LoginFormStateImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoginFormStateCopyWithImpl<$Res, _$LoginFormStateImpl>
|
||||||
|
implements _$$LoginFormStateImplCopyWith<$Res> {
|
||||||
|
__$$LoginFormStateImplCopyWithImpl(
|
||||||
|
_$LoginFormStateImpl _value,
|
||||||
|
$Res Function(_$LoginFormStateImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? email = null,
|
||||||
|
Object? password = null,
|
||||||
|
Object? failureOrLoginOption = null,
|
||||||
|
Object? isSubmitting = null,
|
||||||
|
Object? showErrorMessages = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$LoginFormStateImpl(
|
||||||
|
email: null == email
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
password: null == password
|
||||||
|
? _value.password
|
||||||
|
: password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
failureOrLoginOption: null == failureOrLoginOption
|
||||||
|
? _value.failureOrLoginOption
|
||||||
|
: failureOrLoginOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Login>>,
|
||||||
|
isSubmitting: null == isSubmitting
|
||||||
|
? _value.isSubmitting
|
||||||
|
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
showErrorMessages: null == showErrorMessages
|
||||||
|
? _value.showErrorMessages
|
||||||
|
: showErrorMessages // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$LoginFormStateImpl implements _LoginFormState {
|
||||||
|
const _$LoginFormStateImpl({
|
||||||
|
required this.email,
|
||||||
|
required this.password,
|
||||||
|
required this.failureOrLoginOption,
|
||||||
|
this.isSubmitting = false,
|
||||||
|
this.showErrorMessages = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String email;
|
||||||
|
@override
|
||||||
|
final String password;
|
||||||
|
@override
|
||||||
|
final Option<Either<AuthFailure, Login>> failureOrLoginOption;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final bool isSubmitting;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final bool showErrorMessages;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormState(email: $email, password: $password, failureOrLoginOption: $failureOrLoginOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LoginFormStateImpl &&
|
||||||
|
(identical(other.email, email) || other.email == email) &&
|
||||||
|
(identical(other.password, password) ||
|
||||||
|
other.password == password) &&
|
||||||
|
(identical(other.failureOrLoginOption, failureOrLoginOption) ||
|
||||||
|
other.failureOrLoginOption == failureOrLoginOption) &&
|
||||||
|
(identical(other.isSubmitting, isSubmitting) ||
|
||||||
|
other.isSubmitting == isSubmitting) &&
|
||||||
|
(identical(other.showErrorMessages, showErrorMessages) ||
|
||||||
|
other.showErrorMessages == showErrorMessages));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
failureOrLoginOption,
|
||||||
|
isSubmitting,
|
||||||
|
showErrorMessages,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LoginFormStateImplCopyWith<_$LoginFormStateImpl> get copyWith =>
|
||||||
|
__$$LoginFormStateImplCopyWithImpl<_$LoginFormStateImpl>(
|
||||||
|
this,
|
||||||
|
_$identity,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _LoginFormState implements LoginFormState {
|
||||||
|
const factory _LoginFormState({
|
||||||
|
required final String email,
|
||||||
|
required final String password,
|
||||||
|
required final Option<Either<AuthFailure, Login>> failureOrLoginOption,
|
||||||
|
final bool isSubmitting,
|
||||||
|
final bool showErrorMessages,
|
||||||
|
}) = _$LoginFormStateImpl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get email;
|
||||||
|
@override
|
||||||
|
String get password;
|
||||||
|
@override
|
||||||
|
Option<Either<AuthFailure, Login>> get failureOrLoginOption;
|
||||||
|
@override
|
||||||
|
bool get isSubmitting;
|
||||||
|
@override
|
||||||
|
bool get showErrorMessages;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$LoginFormStateImplCopyWith<_$LoginFormStateImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
part of 'login_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LoginFormEvent with _$LoginFormEvent {
|
||||||
|
const factory LoginFormEvent.emailChanged(String email) = _EmailChanged;
|
||||||
|
const factory LoginFormEvent.passwordChanged(String password) =
|
||||||
|
_PasswordChanged;
|
||||||
|
const factory LoginFormEvent.submitted() = _Submitted;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
part of 'login_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LoginFormState with _$LoginFormState {
|
||||||
|
const factory LoginFormState({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
required Option<Either<AuthFailure, Login>> failureOrLoginOption,
|
||||||
|
@Default(false) bool isSubmitting,
|
||||||
|
@Default(false) bool showErrorMessages,
|
||||||
|
}) = _LoginFormState;
|
||||||
|
|
||||||
|
factory LoginFormState.initial() =>
|
||||||
|
LoginFormState(email: '', password: '', failureOrLoginOption: none());
|
||||||
|
}
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
// ignore: depend_on_referenced_packages
|
||||||
|
import 'package:awesome_dio_interceptor/awesome_dio_interceptor.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../env.dart';
|
||||||
|
import 'api_failure.dart';
|
||||||
|
import 'errors/bad_network_error.dart';
|
||||||
|
import 'errors/bad_request_error.dart';
|
||||||
|
import 'errors/connection_timeout_error.dart';
|
||||||
|
import 'errors/internal_server_error.dart';
|
||||||
|
import 'errors/not_found_error.dart';
|
||||||
|
import 'errors/unauthorized_error.dart';
|
||||||
|
import 'interceptors/bad_network_interceptor.dart';
|
||||||
|
import 'interceptors/bad_request_interceptor.dart';
|
||||||
|
import 'interceptors/connection_timeout_interceptor.dart';
|
||||||
|
import 'interceptors/crashlytic_interceptor.dart';
|
||||||
|
import 'interceptors/internal_server_interceptor.dart';
|
||||||
|
import 'interceptors/not_found_interceptor.dart';
|
||||||
|
import 'interceptors/unauthorized_interceptor.dart';
|
||||||
|
|
||||||
|
@lazySingleton
|
||||||
|
class ApiClient {
|
||||||
|
final Dio _dio;
|
||||||
|
final Env _env;
|
||||||
|
|
||||||
|
ApiClient(this._dio, this._env) {
|
||||||
|
_dio.options.baseUrl = _env.baseUrl;
|
||||||
|
_dio.options.connectTimeout = const Duration(seconds: 20);
|
||||||
|
_dio.options.validateStatus = (status) =>
|
||||||
|
status != null && status >= 200 && status < 500;
|
||||||
|
_dio.interceptors.add(BadNetworkErrorInterceptor());
|
||||||
|
_dio.interceptors.add(BadRequestErrorInterceptor());
|
||||||
|
_dio.interceptors.add(InternalServerErrorInterceptor());
|
||||||
|
_dio.interceptors.add(NotFoundErrorInterceptor());
|
||||||
|
_dio.interceptors.add(UnauthorizedInterceptor());
|
||||||
|
_dio.interceptors.add(ConnectionTimeoutErrorInterceptor());
|
||||||
|
_dio.interceptors.add(CrashlyticsInterceptor());
|
||||||
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
_dio.interceptors.add(
|
||||||
|
AwesomeDioInterceptor(
|
||||||
|
logResponseHeaders: false,
|
||||||
|
logRequestTimeout: false,
|
||||||
|
logRequestHeaders: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> post(
|
||||||
|
String path, {
|
||||||
|
dynamic data,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? params,
|
||||||
|
bool followRedirects = true,
|
||||||
|
bool Function(int?)? validateStatus,
|
||||||
|
String? contentType,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _dio.post(
|
||||||
|
path,
|
||||||
|
data: data,
|
||||||
|
options: Options(
|
||||||
|
headers: headers,
|
||||||
|
followRedirects: followRedirects,
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
contentType: contentType,
|
||||||
|
),
|
||||||
|
queryParameters: params,
|
||||||
|
);
|
||||||
|
} on UnauthorizedError catch (e) {
|
||||||
|
throw ApiFailure.unauthorized(e.messageError);
|
||||||
|
} on InternalServerError {
|
||||||
|
throw const ApiFailure.internalServerError();
|
||||||
|
} on BadNetworkError {
|
||||||
|
throw const ApiFailure.connectionError();
|
||||||
|
} on BadRequestError catch (e) {
|
||||||
|
throw ApiFailure.badRequest(e.messageError);
|
||||||
|
} on NotFoundError catch (e) {
|
||||||
|
throw ApiFailure.notFound(e.messageError);
|
||||||
|
} on ConnectionTimeoutError {
|
||||||
|
throw const ApiFailure.connectionTimeout();
|
||||||
|
} on DioException catch (e) {
|
||||||
|
var errorMessage =
|
||||||
|
e.response?.data['message'] ?? e.response?.statusMessage ?? e.error;
|
||||||
|
|
||||||
|
if (errorMessage.toString().contains('Connection reset')) {
|
||||||
|
errorMessage = 'Connection reset';
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ApiFailure.serverError(
|
||||||
|
statusCode: e.response?.statusCode ?? 0,
|
||||||
|
errorMessage: errorMessage.toString(),
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
throw ApiFailure.unexpectedError(errorMessage: e, stackTrace: s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> get(
|
||||||
|
String path, {
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? params,
|
||||||
|
bool followRedirects = true,
|
||||||
|
bool Function(int?)? validateStatus,
|
||||||
|
String? contentType,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _dio.get(
|
||||||
|
path,
|
||||||
|
options: Options(
|
||||||
|
headers: headers,
|
||||||
|
followRedirects: followRedirects,
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
contentType: contentType,
|
||||||
|
),
|
||||||
|
queryParameters: params,
|
||||||
|
);
|
||||||
|
} on UnauthorizedError catch (e) {
|
||||||
|
throw ApiFailure.unauthorized(e.messageError);
|
||||||
|
} on InternalServerError {
|
||||||
|
throw const ApiFailure.internalServerError();
|
||||||
|
} on BadNetworkError {
|
||||||
|
throw const ApiFailure.connectionError();
|
||||||
|
} on BadRequestError catch (e) {
|
||||||
|
throw ApiFailure.badRequest(e.messageError);
|
||||||
|
} on NotFoundError catch (e) {
|
||||||
|
throw ApiFailure.notFound(e.messageError);
|
||||||
|
} on ConnectionTimeoutError {
|
||||||
|
throw const ApiFailure.connectionTimeout();
|
||||||
|
} on DioException catch (e) {
|
||||||
|
var errorMessage =
|
||||||
|
e.response?.data['message'] ?? e.response?.statusMessage ?? e.error;
|
||||||
|
|
||||||
|
if (errorMessage.toString().contains('Connection reset')) {
|
||||||
|
errorMessage = 'Connection reset';
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ApiFailure.serverError(
|
||||||
|
statusCode: e.response?.statusCode ?? 0,
|
||||||
|
errorMessage: errorMessage.toString(),
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
throw ApiFailure.unexpectedError(errorMessage: e, stackTrace: s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> put(
|
||||||
|
String path, {
|
||||||
|
dynamic data,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? params,
|
||||||
|
bool followRedirects = true,
|
||||||
|
bool Function(int?)? validateStatus,
|
||||||
|
String? contentType,
|
||||||
|
void Function(int count, int total)? onSendProgress,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _dio.put(
|
||||||
|
path,
|
||||||
|
data: data,
|
||||||
|
options: Options(
|
||||||
|
headers: headers,
|
||||||
|
followRedirects: followRedirects,
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
contentType: contentType,
|
||||||
|
),
|
||||||
|
queryParameters: params,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
);
|
||||||
|
} on UnauthorizedError catch (e) {
|
||||||
|
throw ApiFailure.unauthorized(e.messageError);
|
||||||
|
} on InternalServerError {
|
||||||
|
throw const ApiFailure.internalServerError();
|
||||||
|
} on BadNetworkError {
|
||||||
|
throw const ApiFailure.connectionError();
|
||||||
|
} on BadRequestError catch (e) {
|
||||||
|
throw ApiFailure.badRequest(e.messageError);
|
||||||
|
} on NotFoundError catch (e) {
|
||||||
|
throw ApiFailure.notFound(e.messageError);
|
||||||
|
} on ConnectionTimeoutError {
|
||||||
|
throw const ApiFailure.connectionTimeout();
|
||||||
|
} on DioException catch (e) {
|
||||||
|
var errorMessage =
|
||||||
|
e.response?.data['message'] ?? e.response?.statusMessage ?? e.error;
|
||||||
|
|
||||||
|
if (errorMessage.toString().contains('Connection reset')) {
|
||||||
|
errorMessage = 'Connection reset';
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ApiFailure.serverError(
|
||||||
|
statusCode: e.response?.statusCode ?? 0,
|
||||||
|
errorMessage: errorMessage.toString(),
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
throw ApiFailure.unexpectedError(errorMessage: e, stackTrace: s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> delete(
|
||||||
|
String path, {
|
||||||
|
dynamic data,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? params,
|
||||||
|
bool followRedirects = true,
|
||||||
|
bool Function(int?)? validateStatus,
|
||||||
|
String? contentType,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _dio.delete(
|
||||||
|
path,
|
||||||
|
data: data,
|
||||||
|
options: Options(
|
||||||
|
headers: headers,
|
||||||
|
followRedirects: followRedirects,
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
contentType: contentType,
|
||||||
|
),
|
||||||
|
queryParameters: params,
|
||||||
|
);
|
||||||
|
} on UnauthorizedError catch (e) {
|
||||||
|
throw ApiFailure.unauthorized(e.messageError);
|
||||||
|
} on InternalServerError {
|
||||||
|
throw const ApiFailure.internalServerError();
|
||||||
|
} on BadNetworkError {
|
||||||
|
throw const ApiFailure.connectionError();
|
||||||
|
} on BadRequestError catch (e) {
|
||||||
|
throw ApiFailure.badRequest(e.messageError);
|
||||||
|
} on NotFoundError catch (e) {
|
||||||
|
throw ApiFailure.notFound(e.messageError);
|
||||||
|
} on DioException catch (e) {
|
||||||
|
throw ApiFailure.serverError(
|
||||||
|
statusCode: e.response?.statusCode ?? 0,
|
||||||
|
errorMessage:
|
||||||
|
e.response?.data['message'] ?? e.response?.statusMessage ?? e.error,
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
throw ApiFailure.unexpectedError(errorMessage: e, stackTrace: s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'api_failure.freezed.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class ApiFailure with _$ApiFailure {
|
||||||
|
const ApiFailure._();
|
||||||
|
|
||||||
|
const factory ApiFailure.serverError({
|
||||||
|
required int statusCode,
|
||||||
|
required Object errorMessage,
|
||||||
|
}) = _ServerError;
|
||||||
|
|
||||||
|
const factory ApiFailure.unexpectedError({
|
||||||
|
required Object errorMessage,
|
||||||
|
required StackTrace stackTrace,
|
||||||
|
}) = _UnexpectedError;
|
||||||
|
|
||||||
|
const factory ApiFailure.connectionError() = _ConnectionError;
|
||||||
|
|
||||||
|
const factory ApiFailure.internalServerError() = _InternalServerError;
|
||||||
|
|
||||||
|
const factory ApiFailure.unauthorized(String? message) = _Unauthorized;
|
||||||
|
|
||||||
|
const factory ApiFailure.badRequest(String? message) = _BadRequest;
|
||||||
|
|
||||||
|
const factory ApiFailure.notFound(String? message) = _NotFound;
|
||||||
|
|
||||||
|
const factory ApiFailure.connectionTimeout() = _ConnectionTimeout;
|
||||||
|
|
||||||
|
String toStringFormatted(
|
||||||
|
BuildContext context, {
|
||||||
|
String? unauthorizedMessage,
|
||||||
|
}) {
|
||||||
|
return switch (this) {
|
||||||
|
_ServerError(:final statusCode, :final errorMessage) =>
|
||||||
|
'There is a problem with the server. Status code: $statusCode Error: $errorMessage',
|
||||||
|
|
||||||
|
_UnexpectedError() => 'An error occurred. Please try again later.',
|
||||||
|
|
||||||
|
_ConnectionError() => 'No Internet',
|
||||||
|
|
||||||
|
_InternalServerError() =>
|
||||||
|
'The server is experiencing problems. Please try again later.',
|
||||||
|
|
||||||
|
_Unauthorized(:final message) =>
|
||||||
|
message ?? unauthorizedMessage ?? 'Session has expired.',
|
||||||
|
|
||||||
|
_BadRequest(:final message) =>
|
||||||
|
message ?? 'There is an incorrect entry. Please check again',
|
||||||
|
|
||||||
|
_NotFound(:final message) => message ?? 'Not Found',
|
||||||
|
|
||||||
|
_ConnectionTimeout() => 'Connection Timeout',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
class BadNetworkError extends DioException {
|
||||||
|
final DioException dioError;
|
||||||
|
|
||||||
|
BadNetworkError(this.dioError)
|
||||||
|
: super(
|
||||||
|
requestOptions: dioError.requestOptions,
|
||||||
|
error: dioError.error,
|
||||||
|
response: dioError.response,
|
||||||
|
type: dioError.type,
|
||||||
|
message: dioError.message,
|
||||||
|
stackTrace: dioError.stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
class BadRequestError extends DioException {
|
||||||
|
final DioException dioError;
|
||||||
|
final String? messageError;
|
||||||
|
|
||||||
|
BadRequestError(this.dioError, this.messageError)
|
||||||
|
: super(
|
||||||
|
error: dioError.error,
|
||||||
|
requestOptions: dioError.requestOptions,
|
||||||
|
response: dioError.response,
|
||||||
|
type: dioError.type,
|
||||||
|
message: dioError.message,
|
||||||
|
stackTrace: dioError.stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
class ConnectionTimeoutError extends DioException {
|
||||||
|
final DioException dioError;
|
||||||
|
|
||||||
|
ConnectionTimeoutError(this.dioError)
|
||||||
|
: super(
|
||||||
|
error: dioError.error,
|
||||||
|
requestOptions: dioError.requestOptions,
|
||||||
|
response: dioError.response,
|
||||||
|
type: dioError.type,
|
||||||
|
message: dioError.message,
|
||||||
|
stackTrace: dioError.stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
class InternalServerError extends DioException {
|
||||||
|
final DioException dioError;
|
||||||
|
|
||||||
|
InternalServerError(this.dioError)
|
||||||
|
: super(
|
||||||
|
requestOptions: dioError.requestOptions,
|
||||||
|
error: dioError.error,
|
||||||
|
response: dioError.response,
|
||||||
|
type: dioError.type,
|
||||||
|
message: dioError.message,
|
||||||
|
stackTrace: dioError.stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
class NotFoundError extends DioException {
|
||||||
|
final DioException dioError;
|
||||||
|
final String? messageError;
|
||||||
|
|
||||||
|
NotFoundError(this.dioError, this.messageError)
|
||||||
|
: super(
|
||||||
|
error: dioError.error,
|
||||||
|
requestOptions: dioError.requestOptions,
|
||||||
|
response: dioError.response,
|
||||||
|
type: dioError.type,
|
||||||
|
message: dioError.message,
|
||||||
|
stackTrace: dioError.stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
class UnauthorizedError extends DioException {
|
||||||
|
final DioException dioError;
|
||||||
|
final String? messageError;
|
||||||
|
|
||||||
|
UnauthorizedError(this.dioError, this.messageError)
|
||||||
|
: super(
|
||||||
|
requestOptions: dioError.requestOptions,
|
||||||
|
error: dioError.error,
|
||||||
|
response: dioError.response,
|
||||||
|
type: dioError.type,
|
||||||
|
message: dioError.message,
|
||||||
|
stackTrace: dioError.stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../../../injection.dart';
|
||||||
|
import '../../network/network_client.dart';
|
||||||
|
import '../errors/bad_network_error.dart';
|
||||||
|
|
||||||
|
class BadNetworkErrorInterceptor extends Interceptor {
|
||||||
|
final _networkClient = getIt<NetworkClient>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
||||||
|
final isConnected = await _networkClient.isConnected;
|
||||||
|
|
||||||
|
if (err.type == DioExceptionType.connectionTimeout ||
|
||||||
|
!isConnected ||
|
||||||
|
err.type == DioExceptionType.receiveTimeout ||
|
||||||
|
err.type == DioExceptionType.connectionError) {
|
||||||
|
return super.onError(BadNetworkError(err), handler);
|
||||||
|
}
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../errors/bad_request_error.dart';
|
||||||
|
|
||||||
|
class BadRequestErrorInterceptor extends Interceptor {
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||||
|
if (err.response?.statusCode == 422 ||
|
||||||
|
err.response?.statusCode == 400 ||
|
||||||
|
err.response?.statusCode == 405) {
|
||||||
|
return super.onError(BadRequestError(err, null), handler);
|
||||||
|
}
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../errors/connection_timeout_error.dart';
|
||||||
|
|
||||||
|
class ConnectionTimeoutErrorInterceptor extends Interceptor {
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||||
|
if (err.type == DioExceptionType.connectionTimeout) {
|
||||||
|
return super.onError(ConnectionTimeoutError(err), handler);
|
||||||
|
}
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||||
|
|
||||||
|
class CrashlyticsInterceptor extends Interceptor {
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||||
|
// Log semua error ke Crashlytics
|
||||||
|
FirebaseCrashlytics.instance.recordError(
|
||||||
|
err,
|
||||||
|
err.stackTrace,
|
||||||
|
reason: _getErrorReason(err),
|
||||||
|
information: _getErrorInformation(err),
|
||||||
|
fatal: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getErrorReason(DioException err) {
|
||||||
|
final statusCode = err.response?.statusCode;
|
||||||
|
|
||||||
|
if (statusCode != null) {
|
||||||
|
return 'HTTP $statusCode Error: ${err.requestOptions.uri.path}';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (err.type) {
|
||||||
|
case DioExceptionType.connectionTimeout:
|
||||||
|
return 'Connection Timeout';
|
||||||
|
case DioExceptionType.sendTimeout:
|
||||||
|
return 'Send Timeout';
|
||||||
|
case DioExceptionType.receiveTimeout:
|
||||||
|
return 'Receive Timeout';
|
||||||
|
case DioExceptionType.connectionError:
|
||||||
|
return 'Connection Error';
|
||||||
|
case DioExceptionType.cancel:
|
||||||
|
return 'Request Cancelled';
|
||||||
|
default:
|
||||||
|
return 'Network Error: ${err.type.name}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> _getErrorInformation(DioException err) {
|
||||||
|
return [
|
||||||
|
'URL: ${err.requestOptions.uri}',
|
||||||
|
'Method: ${err.requestOptions.method}',
|
||||||
|
'Status Code: ${err.response?.statusCode ?? 'N/A'}',
|
||||||
|
'Error Type: ${err.type.name}',
|
||||||
|
'Message: ${err.message ?? 'No message'}',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../errors/internal_server_error.dart';
|
||||||
|
|
||||||
|
class InternalServerErrorInterceptor extends Interceptor {
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||||
|
if (err.response != null) {
|
||||||
|
if (err.response?.statusCode != null &&
|
||||||
|
err.response!.statusCode! >= 500 &&
|
||||||
|
err.response!.statusCode! < 600) {
|
||||||
|
return super.onError(InternalServerError(err), handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../errors/not_found_error.dart';
|
||||||
|
|
||||||
|
class NotFoundErrorInterceptor extends Interceptor {
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||||
|
if (err.response?.statusCode == 404) {
|
||||||
|
return super.onError(NotFoundError(err, null), handler);
|
||||||
|
}
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import '../errors/unauthorized_error.dart';
|
||||||
|
|
||||||
|
class UnauthorizedInterceptor extends Interceptor {
|
||||||
|
@override
|
||||||
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||||
|
if (err.response?.statusCode == 401 ||
|
||||||
|
err.response?.statusCode == 403 ||
|
||||||
|
err.response?.statusCode == 419) {
|
||||||
|
return super.onError(UnauthorizedError(err, null), handler);
|
||||||
|
}
|
||||||
|
super.onError(err, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// TODO: define your code
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class AppConstant {
|
||||||
|
static const String appName = "Apskel POS";
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class LocalStorageKey {
|
||||||
|
static const String token = 'token';
|
||||||
|
static const String user = 'user';
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../presentation/router/app_router.dart';
|
||||||
|
|
||||||
|
@module
|
||||||
|
abstract class AutoRouteDi {
|
||||||
|
@lazySingleton
|
||||||
|
AppRouter get appRouter => AppRouter();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
@module
|
||||||
|
abstract class ConnectivityDi {
|
||||||
|
@lazySingleton
|
||||||
|
Connectivity get connectivity => Connectivity();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
@module
|
||||||
|
abstract class DioDi {
|
||||||
|
@lazySingleton
|
||||||
|
Dio get dio => Dio();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
@module
|
||||||
|
abstract class SharedPreferencesDi {
|
||||||
|
@preResolve
|
||||||
|
Future<SharedPreferences> get prefs => SharedPreferences.getInstance();
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// TODO: define your code
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
void dismissKeyboard(BuildContext context) {
|
||||||
|
final currentFocus = FocusScope.of(context);
|
||||||
|
if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
@lazySingleton
|
||||||
|
class NetworkClient extends NetworkInfoBase {
|
||||||
|
final Connectivity connectivity;
|
||||||
|
|
||||||
|
NetworkClient(this.connectivity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> get isConnected async {
|
||||||
|
final result = await connectivity.checkConnectivity();
|
||||||
|
return result.first != ConnectivityResult.none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class NetworkInfoBase {
|
||||||
|
Future<bool> get isConnected;
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
part of 'theme.dart';
|
||||||
|
|
||||||
|
class AppColor {
|
||||||
|
// Primary Colors
|
||||||
|
static const Color primary = Color(0xFF36175e);
|
||||||
|
static const Color primaryLight = Color(0xFF5a2d85);
|
||||||
|
static const Color primaryDark = Color(0xFF1e0d35);
|
||||||
|
|
||||||
|
// Secondary Colors
|
||||||
|
static const Color secondary = Color(0xFF4CAF50);
|
||||||
|
static const Color secondaryLight = Color(0xFF81C784);
|
||||||
|
static const Color secondaryDark = Color(0xFF388E3C);
|
||||||
|
|
||||||
|
// Background Colors
|
||||||
|
static const Color background = Color(0xFFF8F9FA);
|
||||||
|
static const Color backgroundLight = Color(0xFFFFFFFF);
|
||||||
|
static const Color backgroundDark = Color(0xFF1A1A1A);
|
||||||
|
static const Color surface = Color(0xFFFFFFFF);
|
||||||
|
static const Color surfaceDark = Color(0xFF2D2D2D);
|
||||||
|
|
||||||
|
// Text Colors
|
||||||
|
static const Color textPrimary = Color(0xFF212121);
|
||||||
|
static const Color textSecondary = Color(0xFF757575);
|
||||||
|
static const Color textLight = Color(0xFFBDBDBD);
|
||||||
|
static const Color textWhite = Color(0xFFFFFFFF);
|
||||||
|
|
||||||
|
// Status Colors
|
||||||
|
static const Color success = Color(0xFF4CAF50);
|
||||||
|
static const Color error = Color(0xFFE53E3E);
|
||||||
|
static const Color warning = Color(0xFFFF9800);
|
||||||
|
static const Color info = Color(0xFF2196F3);
|
||||||
|
|
||||||
|
// Border Colors
|
||||||
|
static const Color border = Color(0xFFE0E0E0);
|
||||||
|
static const Color borderLight = Color(0xFFF0F0F0);
|
||||||
|
static const Color borderDark = Color(0xFFBDBDBD);
|
||||||
|
|
||||||
|
// Basic Color
|
||||||
|
static const Color white = Color(0xFFFFFFFF);
|
||||||
|
static const Color black = Color(0xFF000000);
|
||||||
|
|
||||||
|
// Gradient Colors
|
||||||
|
static const List<Color> primaryGradient = [
|
||||||
|
Color(0xFF36175e),
|
||||||
|
Color(0xFF5a2d85),
|
||||||
|
];
|
||||||
|
|
||||||
|
static const List<Color> successGradient = [
|
||||||
|
Color(0xFF4CAF50),
|
||||||
|
Color(0xFF81C784),
|
||||||
|
];
|
||||||
|
|
||||||
|
static const List<Color> backgroundGradient = [
|
||||||
|
Color(0xFFF5F5F5),
|
||||||
|
Color(0xFFE8E8E8),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Opacity Variations
|
||||||
|
static Color primaryWithOpacity(double opacity) =>
|
||||||
|
primary.withOpacity(opacity);
|
||||||
|
static Color successWithOpacity(double opacity) =>
|
||||||
|
success.withOpacity(opacity);
|
||||||
|
static Color errorWithOpacity(double opacity) => error.withOpacity(opacity);
|
||||||
|
static Color warningWithOpacity(double opacity) =>
|
||||||
|
warning.withOpacity(opacity);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
part of 'theme.dart';
|
||||||
|
|
||||||
|
class AppStyle {
|
||||||
|
static TextStyle xs = TextStyle(color: AppColor.black, fontSize: 11);
|
||||||
|
|
||||||
|
static TextStyle sm = TextStyle(color: AppColor.black, fontSize: 12);
|
||||||
|
|
||||||
|
static TextStyle md = TextStyle(color: AppColor.black, fontSize: 14);
|
||||||
|
|
||||||
|
static TextStyle lg = TextStyle(color: AppColor.black, fontSize: 16);
|
||||||
|
|
||||||
|
static TextStyle xl = TextStyle(color: AppColor.black, fontSize: 18);
|
||||||
|
|
||||||
|
static TextStyle xxl = TextStyle(color: AppColor.black, fontSize: 20);
|
||||||
|
|
||||||
|
static TextStyle h6 = TextStyle(color: AppColor.black, fontSize: 22);
|
||||||
|
|
||||||
|
static TextStyle h5 = TextStyle(color: AppColor.black, fontSize: 24);
|
||||||
|
|
||||||
|
static TextStyle h4 = TextStyle(color: AppColor.black, fontSize: 26);
|
||||||
|
|
||||||
|
static TextStyle h3 = TextStyle(color: AppColor.black, fontSize: 28);
|
||||||
|
|
||||||
|
static TextStyle h2 = TextStyle(color: AppColor.black, fontSize: 30);
|
||||||
|
|
||||||
|
static TextStyle h1 = TextStyle(color: AppColor.black, fontSize: 32);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
part of 'theme.dart';
|
||||||
|
|
||||||
|
class AppValue {
|
||||||
|
// TODO: define value
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../presentation/components/assets/fonts.gen.dart';
|
||||||
|
|
||||||
|
part 'app_color.dart';
|
||||||
|
part 'app_style.dart';
|
||||||
|
part 'app_value.dart';
|
||||||
|
|
||||||
|
class ThemeApp {
|
||||||
|
static ThemeData get theme => ThemeData(
|
||||||
|
useMaterial3: true,
|
||||||
|
primaryColor: AppColor.primary,
|
||||||
|
scaffoldBackgroundColor: AppColor.white,
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
color: AppColor.white,
|
||||||
|
elevation: 0,
|
||||||
|
titleTextStyle: TextStyle(
|
||||||
|
color: AppColor.primary,
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
iconTheme: const IconThemeData(color: AppColor.primary),
|
||||||
|
),
|
||||||
|
fontFamily: FontFamily.quicksand,
|
||||||
|
colorScheme: ColorScheme.fromSeed(seedColor: AppColor.primary),
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
hintStyle: const TextStyle(color: AppColor.textSecondary),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(color: AppColor.borderDark),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(color: AppColor.primary),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(color: AppColor.borderDark),
|
||||||
|
),
|
||||||
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
borderSide: BorderSide(color: AppColor.error),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class ApiPath {
|
||||||
|
static const String login = '/api/v1/auth/login';
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
class AppValidator {
|
||||||
|
static String? validateEmail(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Email wajib diisi';
|
||||||
|
}
|
||||||
|
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
|
||||||
|
if (!emailRegex.hasMatch(value)) {
|
||||||
|
return 'Format email tidak valid';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String? validatePassword(String? value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Password wajib diisi';
|
||||||
|
}
|
||||||
|
if (value.length < 8) {
|
||||||
|
return 'Password minimal 8 karakter';
|
||||||
|
}
|
||||||
|
// if (!RegExp(r'[A-Z]').hasMatch(value)) {
|
||||||
|
// return 'Password harus mengandung huruf besar';
|
||||||
|
// }
|
||||||
|
// if (!RegExp(r'[0-9]').hasMatch(value)) {
|
||||||
|
// return 'Password harus mengandung angka';
|
||||||
|
// }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
import '../../common/api/api_failure.dart';
|
||||||
|
|
||||||
|
part 'auth.freezed.dart';
|
||||||
|
|
||||||
|
part 'entities/login_entity.dart';
|
||||||
|
part 'entities/user_entity.dart';
|
||||||
|
part 'failures/auth_failure.dart';
|
||||||
|
part 'repositories/i_auth_repository.dart';
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
part of '../auth.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class Login with _$Login {
|
||||||
|
const factory Login({
|
||||||
|
required String token,
|
||||||
|
required String refreshToken,
|
||||||
|
required String expiresAt,
|
||||||
|
required String refreshExpiresAt,
|
||||||
|
required User user,
|
||||||
|
}) = _Login;
|
||||||
|
|
||||||
|
factory Login.empty() => Login(
|
||||||
|
token: '',
|
||||||
|
refreshToken: '',
|
||||||
|
expiresAt: '',
|
||||||
|
refreshExpiresAt: '',
|
||||||
|
user: User.empty(),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
part of '../auth.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class User with _$User {
|
||||||
|
const factory User({
|
||||||
|
required String id,
|
||||||
|
required String organizationId,
|
||||||
|
required String outletId,
|
||||||
|
required String name,
|
||||||
|
required String email,
|
||||||
|
required String role,
|
||||||
|
required Map<String, dynamic> permissions,
|
||||||
|
required bool isActive,
|
||||||
|
required String createdAt,
|
||||||
|
required String updatedAt,
|
||||||
|
}) = _User;
|
||||||
|
|
||||||
|
factory User.empty() => const User(
|
||||||
|
id: '',
|
||||||
|
organizationId: '',
|
||||||
|
outletId: '',
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
role: '',
|
||||||
|
permissions: {},
|
||||||
|
isActive: false,
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
part of '../auth.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class AuthFailure with _$AuthFailure {
|
||||||
|
const factory AuthFailure.serverError(ApiFailure failure) = _ServerError;
|
||||||
|
const factory AuthFailure.unexpectedError() = _UnexpectedError;
|
||||||
|
const factory AuthFailure.dynamicErrorMessage(String erroMessage) =
|
||||||
|
_DynamicErrorMessage;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
part of '../auth.dart';
|
||||||
|
|
||||||
|
abstract class IAuthRepository {
|
||||||
|
Future<Either<AuthFailure, Login>> login({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
abstract class Env {
|
||||||
|
String get baseUrl;
|
||||||
|
// add getter here...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable(as: Env)
|
||||||
|
@dev
|
||||||
|
class DevEnv implements Env {
|
||||||
|
@override
|
||||||
|
String get baseUrl => 'https://api-pos.apskel.id'; // example value
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable(as: Env)
|
||||||
|
@prod
|
||||||
|
class ProdEnv implements Env {
|
||||||
|
@override
|
||||||
|
String get baseUrl => 'https://api-pos.apskel.id';
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
import '../../domain/auth/auth.dart';
|
||||||
|
|
||||||
|
part 'auth_dtos.freezed.dart';
|
||||||
|
part 'auth_dtos.g.dart';
|
||||||
|
|
||||||
|
part 'dto/login_dto.dart';
|
||||||
|
part 'dto/user_dto.dart';
|
||||||
@@ -0,0 +1,700 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'auth_dtos.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||||
|
);
|
||||||
|
|
||||||
|
LoginDto _$LoginDtoFromJson(Map<String, dynamic> json) {
|
||||||
|
return _LoginDto.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoginDto {
|
||||||
|
@JsonKey(name: "token")
|
||||||
|
String? get token => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "refresh_token")
|
||||||
|
String? get refreshToken => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "expires_at")
|
||||||
|
String? get expiresAt => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "refresh_expires_at")
|
||||||
|
String? get refreshExpiresAt => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "user")
|
||||||
|
UserDto? get user => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this LoginDto to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of LoginDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$LoginDtoCopyWith<LoginDto> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LoginDtoCopyWith<$Res> {
|
||||||
|
factory $LoginDtoCopyWith(LoginDto value, $Res Function(LoginDto) then) =
|
||||||
|
_$LoginDtoCopyWithImpl<$Res, LoginDto>;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
@JsonKey(name: "token") String? token,
|
||||||
|
@JsonKey(name: "refresh_token") String? refreshToken,
|
||||||
|
@JsonKey(name: "expires_at") String? expiresAt,
|
||||||
|
@JsonKey(name: "refresh_expires_at") String? refreshExpiresAt,
|
||||||
|
@JsonKey(name: "user") UserDto? user,
|
||||||
|
});
|
||||||
|
|
||||||
|
$UserDtoCopyWith<$Res>? get user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LoginDtoCopyWithImpl<$Res, $Val extends LoginDto>
|
||||||
|
implements $LoginDtoCopyWith<$Res> {
|
||||||
|
_$LoginDtoCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? token = freezed,
|
||||||
|
Object? refreshToken = freezed,
|
||||||
|
Object? expiresAt = freezed,
|
||||||
|
Object? refreshExpiresAt = freezed,
|
||||||
|
Object? user = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
token: freezed == token
|
||||||
|
? _value.token
|
||||||
|
: token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
refreshToken: freezed == refreshToken
|
||||||
|
? _value.refreshToken
|
||||||
|
: refreshToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
expiresAt: freezed == expiresAt
|
||||||
|
? _value.expiresAt
|
||||||
|
: expiresAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
refreshExpiresAt: freezed == refreshExpiresAt
|
||||||
|
? _value.refreshExpiresAt
|
||||||
|
: refreshExpiresAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
user: freezed == user
|
||||||
|
? _value.user
|
||||||
|
: user // ignore: cast_nullable_to_non_nullable
|
||||||
|
as UserDto?,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of LoginDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$UserDtoCopyWith<$Res>? get user {
|
||||||
|
if (_value.user == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $UserDtoCopyWith<$Res>(_value.user!, (value) {
|
||||||
|
return _then(_value.copyWith(user: value) as $Val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LoginDtoImplCopyWith<$Res>
|
||||||
|
implements $LoginDtoCopyWith<$Res> {
|
||||||
|
factory _$$LoginDtoImplCopyWith(
|
||||||
|
_$LoginDtoImpl value,
|
||||||
|
$Res Function(_$LoginDtoImpl) then,
|
||||||
|
) = __$$LoginDtoImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
@JsonKey(name: "token") String? token,
|
||||||
|
@JsonKey(name: "refresh_token") String? refreshToken,
|
||||||
|
@JsonKey(name: "expires_at") String? expiresAt,
|
||||||
|
@JsonKey(name: "refresh_expires_at") String? refreshExpiresAt,
|
||||||
|
@JsonKey(name: "user") UserDto? user,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$UserDtoCopyWith<$Res>? get user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LoginDtoImplCopyWithImpl<$Res>
|
||||||
|
extends _$LoginDtoCopyWithImpl<$Res, _$LoginDtoImpl>
|
||||||
|
implements _$$LoginDtoImplCopyWith<$Res> {
|
||||||
|
__$$LoginDtoImplCopyWithImpl(
|
||||||
|
_$LoginDtoImpl _value,
|
||||||
|
$Res Function(_$LoginDtoImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LoginDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? token = freezed,
|
||||||
|
Object? refreshToken = freezed,
|
||||||
|
Object? expiresAt = freezed,
|
||||||
|
Object? refreshExpiresAt = freezed,
|
||||||
|
Object? user = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$LoginDtoImpl(
|
||||||
|
token: freezed == token
|
||||||
|
? _value.token
|
||||||
|
: token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
refreshToken: freezed == refreshToken
|
||||||
|
? _value.refreshToken
|
||||||
|
: refreshToken // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
expiresAt: freezed == expiresAt
|
||||||
|
? _value.expiresAt
|
||||||
|
: expiresAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
refreshExpiresAt: freezed == refreshExpiresAt
|
||||||
|
? _value.refreshExpiresAt
|
||||||
|
: refreshExpiresAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
user: freezed == user
|
||||||
|
? _value.user
|
||||||
|
: user // ignore: cast_nullable_to_non_nullable
|
||||||
|
as UserDto?,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$LoginDtoImpl extends _LoginDto {
|
||||||
|
const _$LoginDtoImpl({
|
||||||
|
@JsonKey(name: "token") this.token,
|
||||||
|
@JsonKey(name: "refresh_token") this.refreshToken,
|
||||||
|
@JsonKey(name: "expires_at") this.expiresAt,
|
||||||
|
@JsonKey(name: "refresh_expires_at") this.refreshExpiresAt,
|
||||||
|
@JsonKey(name: "user") this.user,
|
||||||
|
}) : super._();
|
||||||
|
|
||||||
|
factory _$LoginDtoImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$LoginDtoImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "token")
|
||||||
|
final String? token;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "refresh_token")
|
||||||
|
final String? refreshToken;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "expires_at")
|
||||||
|
final String? expiresAt;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "refresh_expires_at")
|
||||||
|
final String? refreshExpiresAt;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "user")
|
||||||
|
final UserDto? user;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginDto(token: $token, refreshToken: $refreshToken, expiresAt: $expiresAt, refreshExpiresAt: $refreshExpiresAt, user: $user)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LoginDtoImpl &&
|
||||||
|
(identical(other.token, token) || other.token == token) &&
|
||||||
|
(identical(other.refreshToken, refreshToken) ||
|
||||||
|
other.refreshToken == refreshToken) &&
|
||||||
|
(identical(other.expiresAt, expiresAt) ||
|
||||||
|
other.expiresAt == expiresAt) &&
|
||||||
|
(identical(other.refreshExpiresAt, refreshExpiresAt) ||
|
||||||
|
other.refreshExpiresAt == refreshExpiresAt) &&
|
||||||
|
(identical(other.user, user) || other.user == user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
token,
|
||||||
|
refreshToken,
|
||||||
|
expiresAt,
|
||||||
|
refreshExpiresAt,
|
||||||
|
user,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Create a copy of LoginDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LoginDtoImplCopyWith<_$LoginDtoImpl> get copyWith =>
|
||||||
|
__$$LoginDtoImplCopyWithImpl<_$LoginDtoImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$LoginDtoImplToJson(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _LoginDto extends LoginDto {
|
||||||
|
const factory _LoginDto({
|
||||||
|
@JsonKey(name: "token") final String? token,
|
||||||
|
@JsonKey(name: "refresh_token") final String? refreshToken,
|
||||||
|
@JsonKey(name: "expires_at") final String? expiresAt,
|
||||||
|
@JsonKey(name: "refresh_expires_at") final String? refreshExpiresAt,
|
||||||
|
@JsonKey(name: "user") final UserDto? user,
|
||||||
|
}) = _$LoginDtoImpl;
|
||||||
|
const _LoginDto._() : super._();
|
||||||
|
|
||||||
|
factory _LoginDto.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$LoginDtoImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "token")
|
||||||
|
String? get token;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "refresh_token")
|
||||||
|
String? get refreshToken;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "expires_at")
|
||||||
|
String? get expiresAt;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "refresh_expires_at")
|
||||||
|
String? get refreshExpiresAt;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "user")
|
||||||
|
UserDto? get user;
|
||||||
|
|
||||||
|
/// Create a copy of LoginDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$LoginDtoImplCopyWith<_$LoginDtoImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDto _$UserDtoFromJson(Map<String, dynamic> json) {
|
||||||
|
return _UserDto.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$UserDto {
|
||||||
|
@JsonKey(name: "id")
|
||||||
|
String? get id => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "organization_id")
|
||||||
|
String? get organizationId => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "outlet_id")
|
||||||
|
String? get outletId => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "name")
|
||||||
|
String? get name => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "email")
|
||||||
|
String? get email => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "role")
|
||||||
|
String? get role => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "permissions")
|
||||||
|
Map<String, dynamic>? get permissions => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "is_active")
|
||||||
|
bool? get isActive => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "created_at")
|
||||||
|
String? get createdAt => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(name: "updated_at")
|
||||||
|
String? get updatedAt => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this UserDto to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of UserDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$UserDtoCopyWith<UserDto> get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $UserDtoCopyWith<$Res> {
|
||||||
|
factory $UserDtoCopyWith(UserDto value, $Res Function(UserDto) then) =
|
||||||
|
_$UserDtoCopyWithImpl<$Res, UserDto>;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
@JsonKey(name: "id") String? id,
|
||||||
|
@JsonKey(name: "organization_id") String? organizationId,
|
||||||
|
@JsonKey(name: "outlet_id") String? outletId,
|
||||||
|
@JsonKey(name: "name") String? name,
|
||||||
|
@JsonKey(name: "email") String? email,
|
||||||
|
@JsonKey(name: "role") String? role,
|
||||||
|
@JsonKey(name: "permissions") Map<String, dynamic>? permissions,
|
||||||
|
@JsonKey(name: "is_active") bool? isActive,
|
||||||
|
@JsonKey(name: "created_at") String? createdAt,
|
||||||
|
@JsonKey(name: "updated_at") String? updatedAt,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$UserDtoCopyWithImpl<$Res, $Val extends UserDto>
|
||||||
|
implements $UserDtoCopyWith<$Res> {
|
||||||
|
_$UserDtoCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of UserDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? id = freezed,
|
||||||
|
Object? organizationId = freezed,
|
||||||
|
Object? outletId = freezed,
|
||||||
|
Object? name = freezed,
|
||||||
|
Object? email = freezed,
|
||||||
|
Object? role = freezed,
|
||||||
|
Object? permissions = freezed,
|
||||||
|
Object? isActive = freezed,
|
||||||
|
Object? createdAt = freezed,
|
||||||
|
Object? updatedAt = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
id: freezed == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
organizationId: freezed == organizationId
|
||||||
|
? _value.organizationId
|
||||||
|
: organizationId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
outletId: freezed == outletId
|
||||||
|
? _value.outletId
|
||||||
|
: outletId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
name: freezed == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
email: freezed == email
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
role: freezed == role
|
||||||
|
? _value.role
|
||||||
|
: role // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
permissions: freezed == permissions
|
||||||
|
? _value.permissions
|
||||||
|
: permissions // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>?,
|
||||||
|
isActive: freezed == isActive
|
||||||
|
? _value.isActive
|
||||||
|
: isActive // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool?,
|
||||||
|
createdAt: freezed == createdAt
|
||||||
|
? _value.createdAt
|
||||||
|
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
updatedAt: freezed == updatedAt
|
||||||
|
? _value.updatedAt
|
||||||
|
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$UserDtoImplCopyWith<$Res> implements $UserDtoCopyWith<$Res> {
|
||||||
|
factory _$$UserDtoImplCopyWith(
|
||||||
|
_$UserDtoImpl value,
|
||||||
|
$Res Function(_$UserDtoImpl) then,
|
||||||
|
) = __$$UserDtoImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
@JsonKey(name: "id") String? id,
|
||||||
|
@JsonKey(name: "organization_id") String? organizationId,
|
||||||
|
@JsonKey(name: "outlet_id") String? outletId,
|
||||||
|
@JsonKey(name: "name") String? name,
|
||||||
|
@JsonKey(name: "email") String? email,
|
||||||
|
@JsonKey(name: "role") String? role,
|
||||||
|
@JsonKey(name: "permissions") Map<String, dynamic>? permissions,
|
||||||
|
@JsonKey(name: "is_active") bool? isActive,
|
||||||
|
@JsonKey(name: "created_at") String? createdAt,
|
||||||
|
@JsonKey(name: "updated_at") String? updatedAt,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$UserDtoImplCopyWithImpl<$Res>
|
||||||
|
extends _$UserDtoCopyWithImpl<$Res, _$UserDtoImpl>
|
||||||
|
implements _$$UserDtoImplCopyWith<$Res> {
|
||||||
|
__$$UserDtoImplCopyWithImpl(
|
||||||
|
_$UserDtoImpl _value,
|
||||||
|
$Res Function(_$UserDtoImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of UserDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? id = freezed,
|
||||||
|
Object? organizationId = freezed,
|
||||||
|
Object? outletId = freezed,
|
||||||
|
Object? name = freezed,
|
||||||
|
Object? email = freezed,
|
||||||
|
Object? role = freezed,
|
||||||
|
Object? permissions = freezed,
|
||||||
|
Object? isActive = freezed,
|
||||||
|
Object? createdAt = freezed,
|
||||||
|
Object? updatedAt = freezed,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$UserDtoImpl(
|
||||||
|
id: freezed == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
organizationId: freezed == organizationId
|
||||||
|
? _value.organizationId
|
||||||
|
: organizationId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
outletId: freezed == outletId
|
||||||
|
? _value.outletId
|
||||||
|
: outletId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
name: freezed == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
email: freezed == email
|
||||||
|
? _value.email
|
||||||
|
: email // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
role: freezed == role
|
||||||
|
? _value.role
|
||||||
|
: role // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
permissions: freezed == permissions
|
||||||
|
? _value._permissions
|
||||||
|
: permissions // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>?,
|
||||||
|
isActive: freezed == isActive
|
||||||
|
? _value.isActive
|
||||||
|
: isActive // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool?,
|
||||||
|
createdAt: freezed == createdAt
|
||||||
|
? _value.createdAt
|
||||||
|
: createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
updatedAt: freezed == updatedAt
|
||||||
|
? _value.updatedAt
|
||||||
|
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$UserDtoImpl extends _UserDto {
|
||||||
|
const _$UserDtoImpl({
|
||||||
|
@JsonKey(name: "id") this.id,
|
||||||
|
@JsonKey(name: "organization_id") this.organizationId,
|
||||||
|
@JsonKey(name: "outlet_id") this.outletId,
|
||||||
|
@JsonKey(name: "name") this.name,
|
||||||
|
@JsonKey(name: "email") this.email,
|
||||||
|
@JsonKey(name: "role") this.role,
|
||||||
|
@JsonKey(name: "permissions") final Map<String, dynamic>? permissions,
|
||||||
|
@JsonKey(name: "is_active") this.isActive,
|
||||||
|
@JsonKey(name: "created_at") this.createdAt,
|
||||||
|
@JsonKey(name: "updated_at") this.updatedAt,
|
||||||
|
}) : _permissions = permissions,
|
||||||
|
super._();
|
||||||
|
|
||||||
|
factory _$UserDtoImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$UserDtoImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "id")
|
||||||
|
final String? id;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "organization_id")
|
||||||
|
final String? organizationId;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "outlet_id")
|
||||||
|
final String? outletId;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "name")
|
||||||
|
final String? name;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "email")
|
||||||
|
final String? email;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "role")
|
||||||
|
final String? role;
|
||||||
|
final Map<String, dynamic>? _permissions;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "permissions")
|
||||||
|
Map<String, dynamic>? get permissions {
|
||||||
|
final value = _permissions;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_permissions is EqualUnmodifiableMapView) return _permissions;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "is_active")
|
||||||
|
final bool? isActive;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "created_at")
|
||||||
|
final String? createdAt;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "updated_at")
|
||||||
|
final String? updatedAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'UserDto(id: $id, organizationId: $organizationId, outletId: $outletId, name: $name, email: $email, role: $role, permissions: $permissions, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$UserDtoImpl &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.organizationId, organizationId) ||
|
||||||
|
other.organizationId == organizationId) &&
|
||||||
|
(identical(other.outletId, outletId) ||
|
||||||
|
other.outletId == outletId) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.email, email) || other.email == email) &&
|
||||||
|
(identical(other.role, role) || other.role == role) &&
|
||||||
|
const DeepCollectionEquality().equals(
|
||||||
|
other._permissions,
|
||||||
|
_permissions,
|
||||||
|
) &&
|
||||||
|
(identical(other.isActive, isActive) ||
|
||||||
|
other.isActive == isActive) &&
|
||||||
|
(identical(other.createdAt, createdAt) ||
|
||||||
|
other.createdAt == createdAt) &&
|
||||||
|
(identical(other.updatedAt, updatedAt) ||
|
||||||
|
other.updatedAt == updatedAt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
id,
|
||||||
|
organizationId,
|
||||||
|
outletId,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
role,
|
||||||
|
const DeepCollectionEquality().hash(_permissions),
|
||||||
|
isActive,
|
||||||
|
createdAt,
|
||||||
|
updatedAt,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Create a copy of UserDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$UserDtoImplCopyWith<_$UserDtoImpl> get copyWith =>
|
||||||
|
__$$UserDtoImplCopyWithImpl<_$UserDtoImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$UserDtoImplToJson(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _UserDto extends UserDto {
|
||||||
|
const factory _UserDto({
|
||||||
|
@JsonKey(name: "id") final String? id,
|
||||||
|
@JsonKey(name: "organization_id") final String? organizationId,
|
||||||
|
@JsonKey(name: "outlet_id") final String? outletId,
|
||||||
|
@JsonKey(name: "name") final String? name,
|
||||||
|
@JsonKey(name: "email") final String? email,
|
||||||
|
@JsonKey(name: "role") final String? role,
|
||||||
|
@JsonKey(name: "permissions") final Map<String, dynamic>? permissions,
|
||||||
|
@JsonKey(name: "is_active") final bool? isActive,
|
||||||
|
@JsonKey(name: "created_at") final String? createdAt,
|
||||||
|
@JsonKey(name: "updated_at") final String? updatedAt,
|
||||||
|
}) = _$UserDtoImpl;
|
||||||
|
const _UserDto._() : super._();
|
||||||
|
|
||||||
|
factory _UserDto.fromJson(Map<String, dynamic> json) = _$UserDtoImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "id")
|
||||||
|
String? get id;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "organization_id")
|
||||||
|
String? get organizationId;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "outlet_id")
|
||||||
|
String? get outletId;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "name")
|
||||||
|
String? get name;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "email")
|
||||||
|
String? get email;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "role")
|
||||||
|
String? get role;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "permissions")
|
||||||
|
Map<String, dynamic>? get permissions;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "is_active")
|
||||||
|
bool? get isActive;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "created_at")
|
||||||
|
String? get createdAt;
|
||||||
|
@override
|
||||||
|
@JsonKey(name: "updated_at")
|
||||||
|
String? get updatedAt;
|
||||||
|
|
||||||
|
/// Create a copy of UserDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$UserDtoImplCopyWith<_$UserDtoImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'auth_dtos.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$LoginDtoImpl _$$LoginDtoImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$LoginDtoImpl(
|
||||||
|
token: json['token'] as String?,
|
||||||
|
refreshToken: json['refresh_token'] as String?,
|
||||||
|
expiresAt: json['expires_at'] as String?,
|
||||||
|
refreshExpiresAt: json['refresh_expires_at'] as String?,
|
||||||
|
user: json['user'] == null
|
||||||
|
? null
|
||||||
|
: UserDto.fromJson(json['user'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$LoginDtoImplToJson(_$LoginDtoImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'token': instance.token,
|
||||||
|
'refresh_token': instance.refreshToken,
|
||||||
|
'expires_at': instance.expiresAt,
|
||||||
|
'refresh_expires_at': instance.refreshExpiresAt,
|
||||||
|
'user': instance.user,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$UserDtoImpl _$$UserDtoImplFromJson(Map<String, dynamic> json) =>
|
||||||
|
_$UserDtoImpl(
|
||||||
|
id: json['id'] as String?,
|
||||||
|
organizationId: json['organization_id'] as String?,
|
||||||
|
outletId: json['outlet_id'] as String?,
|
||||||
|
name: json['name'] as String?,
|
||||||
|
email: json['email'] as String?,
|
||||||
|
role: json['role'] as String?,
|
||||||
|
permissions: json['permissions'] as Map<String, dynamic>?,
|
||||||
|
isActive: json['is_active'] as bool?,
|
||||||
|
createdAt: json['created_at'] as String?,
|
||||||
|
updatedAt: json['updated_at'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$UserDtoImplToJson(_$UserDtoImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'organization_id': instance.organizationId,
|
||||||
|
'outlet_id': instance.outletId,
|
||||||
|
'name': instance.name,
|
||||||
|
'email': instance.email,
|
||||||
|
'role': instance.role,
|
||||||
|
'permissions': instance.permissions,
|
||||||
|
'is_active': instance.isActive,
|
||||||
|
'created_at': instance.createdAt,
|
||||||
|
'updated_at': instance.updatedAt,
|
||||||
|
};
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../../common/constant/local_storage_key.dart';
|
||||||
|
import '../../../domain/auth/auth.dart';
|
||||||
|
import '../auth_dtos.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class AuthLocalDataProvider {
|
||||||
|
final SharedPreferences _sharedPreferences;
|
||||||
|
final String _logName = 'AuthLocalDataProvider';
|
||||||
|
|
||||||
|
AuthLocalDataProvider(this._sharedPreferences);
|
||||||
|
|
||||||
|
Future<void> saveToken(String token) async {
|
||||||
|
await _sharedPreferences.setString(LocalStorageKey.token, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getToken() async {
|
||||||
|
return _sharedPreferences.getString(LocalStorageKey.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteToken() async {
|
||||||
|
await _sharedPreferences.remove(LocalStorageKey.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> hasToken() async {
|
||||||
|
return _sharedPreferences.containsKey(LocalStorageKey.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveCurrentUser(UserDto user) async {
|
||||||
|
final userJsonString = jsonEncode(user.toJson());
|
||||||
|
await _sharedPreferences.setString(LocalStorageKey.user, userJsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<User> currentUser() async {
|
||||||
|
final userString = _sharedPreferences.getString(LocalStorageKey.user);
|
||||||
|
if (userString == null) return User.empty();
|
||||||
|
|
||||||
|
final Map<String, dynamic> userMap = jsonDecode(userString);
|
||||||
|
final userDto = UserDto.fromJson(userMap);
|
||||||
|
return userDto.toDomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteCurrentUser() async {
|
||||||
|
await _sharedPreferences.remove(LocalStorageKey.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteAllAuth() async {
|
||||||
|
try {
|
||||||
|
await _sharedPreferences.remove(LocalStorageKey.token);
|
||||||
|
await _sharedPreferences.remove(LocalStorageKey.user);
|
||||||
|
} catch (e) {
|
||||||
|
log('deleteAllAuthError', name: _logName, error: e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:data_channel/data_channel.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../../common/api/api_client.dart';
|
||||||
|
import '../../../common/api/api_failure.dart';
|
||||||
|
import '../../../common/url/api_path.dart';
|
||||||
|
import '../../../domain/auth/auth.dart';
|
||||||
|
import '../auth_dtos.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class AuthRemoteDataProvider {
|
||||||
|
final ApiClient _apiClient;
|
||||||
|
final String _logName = 'AuthRemoteDataProvider';
|
||||||
|
|
||||||
|
AuthRemoteDataProvider(this._apiClient);
|
||||||
|
|
||||||
|
Future<DC<AuthFailure, LoginDto>> login({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final response = await _apiClient.post(
|
||||||
|
ApiPath.login,
|
||||||
|
data: {'email': email, 'password': password},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.data['code'] == 401) {
|
||||||
|
return DC.error(
|
||||||
|
AuthFailure.serverError(
|
||||||
|
ApiFailure.unauthorized('Incorrect email or password'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final dto = LoginDto.fromJson(response.data['data']);
|
||||||
|
return DC.data(dto);
|
||||||
|
} on ApiFailure catch (e, s) {
|
||||||
|
log('login', name: _logName, error: e, stackTrace: s);
|
||||||
|
return DC.error(AuthFailure.serverError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
part of '../auth_dtos.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LoginDto with _$LoginDto {
|
||||||
|
const LoginDto._();
|
||||||
|
|
||||||
|
const factory LoginDto({
|
||||||
|
@JsonKey(name: "token") String? token,
|
||||||
|
@JsonKey(name: "refresh_token") String? refreshToken,
|
||||||
|
@JsonKey(name: "expires_at") String? expiresAt,
|
||||||
|
@JsonKey(name: "refresh_expires_at") String? refreshExpiresAt,
|
||||||
|
@JsonKey(name: "user") UserDto? user,
|
||||||
|
}) = _LoginDto;
|
||||||
|
|
||||||
|
factory LoginDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$LoginDtoFromJson(json);
|
||||||
|
|
||||||
|
/// mapping ke domain
|
||||||
|
Login toDomain() => Login(
|
||||||
|
token: token ?? '',
|
||||||
|
refreshToken: refreshToken ?? '',
|
||||||
|
expiresAt: expiresAt ?? '',
|
||||||
|
refreshExpiresAt: refreshExpiresAt ?? '',
|
||||||
|
user:
|
||||||
|
user?.toDomain() ??
|
||||||
|
User(
|
||||||
|
id: '',
|
||||||
|
organizationId: '',
|
||||||
|
outletId: '',
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
role: '',
|
||||||
|
permissions: {},
|
||||||
|
isActive: false,
|
||||||
|
createdAt: '',
|
||||||
|
updatedAt: '',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
part of '../auth_dtos.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class UserDto with _$UserDto {
|
||||||
|
const UserDto._();
|
||||||
|
|
||||||
|
const factory UserDto({
|
||||||
|
@JsonKey(name: "id") String? id,
|
||||||
|
@JsonKey(name: "organization_id") String? organizationId,
|
||||||
|
@JsonKey(name: "outlet_id") String? outletId,
|
||||||
|
@JsonKey(name: "name") String? name,
|
||||||
|
@JsonKey(name: "email") String? email,
|
||||||
|
@JsonKey(name: "role") String? role,
|
||||||
|
@JsonKey(name: "permissions") Map<String, dynamic>? permissions,
|
||||||
|
@JsonKey(name: "is_active") bool? isActive,
|
||||||
|
@JsonKey(name: "created_at") String? createdAt,
|
||||||
|
@JsonKey(name: "updated_at") String? updatedAt,
|
||||||
|
}) = _UserDto;
|
||||||
|
|
||||||
|
factory UserDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$UserDtoFromJson(json);
|
||||||
|
|
||||||
|
User toDomain() => User(
|
||||||
|
id: id ?? '',
|
||||||
|
organizationId: organizationId ?? '',
|
||||||
|
outletId: outletId ?? '',
|
||||||
|
name: name ?? '',
|
||||||
|
email: email ?? '',
|
||||||
|
role: role ?? '',
|
||||||
|
permissions: permissions ?? {},
|
||||||
|
isActive: isActive ?? false,
|
||||||
|
createdAt: createdAt ?? '',
|
||||||
|
updatedAt: updatedAt ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../../domain/auth/auth.dart';
|
||||||
|
import '../datasources/local_data_provider.dart';
|
||||||
|
import '../datasources/remote_data_provider.dart';
|
||||||
|
|
||||||
|
@Injectable(as: IAuthRepository)
|
||||||
|
class AuthRepository implements IAuthRepository {
|
||||||
|
final AuthRemoteDataProvider _dataProvider;
|
||||||
|
final AuthLocalDataProvider _localDataProvider;
|
||||||
|
final String _logName = 'AuthRepository';
|
||||||
|
|
||||||
|
AuthRepository(this._dataProvider, this._localDataProvider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Either<AuthFailure, Login>> login({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final result = await _dataProvider.login(
|
||||||
|
email: email,
|
||||||
|
password: password,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.hasError) {
|
||||||
|
return left(result.error!);
|
||||||
|
}
|
||||||
|
|
||||||
|
final auth = result.data!.toDomain();
|
||||||
|
|
||||||
|
await _localDataProvider.saveToken(auth.token);
|
||||||
|
await _localDataProvider.saveCurrentUser(result.data!.user!);
|
||||||
|
|
||||||
|
return right(auth);
|
||||||
|
} catch (e, s) {
|
||||||
|
log('loginError', name: _logName, error: e, stackTrace: s);
|
||||||
|
return left(const AuthFailure.unexpectedError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// InjectableConfigGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// coverage:ignore-file
|
||||||
|
|
||||||
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
|
import 'package:apskel_pos_flutter_v2/application/auth/bloc/login_form_bloc.dart'
|
||||||
|
as _i185;
|
||||||
|
import 'package:apskel_pos_flutter_v2/common/api/api_client.dart' as _i457;
|
||||||
|
import 'package:apskel_pos_flutter_v2/common/di/di_auto_route.dart' as _i729;
|
||||||
|
import 'package:apskel_pos_flutter_v2/common/di/di_connectivity.dart' as _i807;
|
||||||
|
import 'package:apskel_pos_flutter_v2/common/di/di_dio.dart' as _i86;
|
||||||
|
import 'package:apskel_pos_flutter_v2/common/di/di_shared_preferences.dart'
|
||||||
|
as _i135;
|
||||||
|
import 'package:apskel_pos_flutter_v2/common/network/network_client.dart'
|
||||||
|
as _i171;
|
||||||
|
import 'package:apskel_pos_flutter_v2/domain/auth/auth.dart' as _i776;
|
||||||
|
import 'package:apskel_pos_flutter_v2/env.dart' as _i923;
|
||||||
|
import 'package:apskel_pos_flutter_v2/infrastructure/auth/datasources/local_data_provider.dart'
|
||||||
|
as _i204;
|
||||||
|
import 'package:apskel_pos_flutter_v2/infrastructure/auth/datasources/remote_data_provider.dart'
|
||||||
|
as _i370;
|
||||||
|
import 'package:apskel_pos_flutter_v2/infrastructure/auth/repositories/auth_repository.dart'
|
||||||
|
as _i941;
|
||||||
|
import 'package:apskel_pos_flutter_v2/presentation/router/app_router.dart'
|
||||||
|
as _i800;
|
||||||
|
import 'package:connectivity_plus/connectivity_plus.dart' as _i895;
|
||||||
|
import 'package:dio/dio.dart' as _i361;
|
||||||
|
import 'package:get_it/get_it.dart' as _i174;
|
||||||
|
import 'package:injectable/injectable.dart' as _i526;
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart' as _i460;
|
||||||
|
|
||||||
|
const String _dev = 'dev';
|
||||||
|
const String _prod = 'prod';
|
||||||
|
|
||||||
|
extension GetItInjectableX on _i174.GetIt {
|
||||||
|
// initializes the registration of main-scope dependencies inside of GetIt
|
||||||
|
Future<_i174.GetIt> init({
|
||||||
|
String? environment,
|
||||||
|
_i526.EnvironmentFilter? environmentFilter,
|
||||||
|
}) async {
|
||||||
|
final gh = _i526.GetItHelper(this, environment, environmentFilter);
|
||||||
|
final sharedPreferencesDi = _$SharedPreferencesDi();
|
||||||
|
final dioDi = _$DioDi();
|
||||||
|
final autoRouteDi = _$AutoRouteDi();
|
||||||
|
final connectivityDi = _$ConnectivityDi();
|
||||||
|
await gh.factoryAsync<_i460.SharedPreferences>(
|
||||||
|
() => sharedPreferencesDi.prefs,
|
||||||
|
preResolve: true,
|
||||||
|
);
|
||||||
|
gh.lazySingleton<_i361.Dio>(() => dioDi.dio);
|
||||||
|
gh.lazySingleton<_i800.AppRouter>(() => autoRouteDi.appRouter);
|
||||||
|
gh.lazySingleton<_i895.Connectivity>(() => connectivityDi.connectivity);
|
||||||
|
gh.lazySingleton<_i171.NetworkClient>(
|
||||||
|
() => _i171.NetworkClient(gh<_i895.Connectivity>()),
|
||||||
|
);
|
||||||
|
gh.factory<_i923.Env>(() => _i923.DevEnv(), registerFor: {_dev});
|
||||||
|
gh.factory<_i204.AuthLocalDataProvider>(
|
||||||
|
() => _i204.AuthLocalDataProvider(gh<_i460.SharedPreferences>()),
|
||||||
|
);
|
||||||
|
gh.lazySingleton<_i457.ApiClient>(
|
||||||
|
() => _i457.ApiClient(gh<_i361.Dio>(), gh<_i923.Env>()),
|
||||||
|
);
|
||||||
|
gh.factory<_i923.Env>(() => _i923.ProdEnv(), registerFor: {_prod});
|
||||||
|
gh.factory<_i370.AuthRemoteDataProvider>(
|
||||||
|
() => _i370.AuthRemoteDataProvider(gh<_i457.ApiClient>()),
|
||||||
|
);
|
||||||
|
gh.factory<_i776.IAuthRepository>(
|
||||||
|
() => _i941.AuthRepository(
|
||||||
|
gh<_i370.AuthRemoteDataProvider>(),
|
||||||
|
gh<_i204.AuthLocalDataProvider>(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
gh.factory<_i185.LoginFormBloc>(
|
||||||
|
() => _i185.LoginFormBloc(gh<_i776.IAuthRepository>()),
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$SharedPreferencesDi extends _i135.SharedPreferencesDi {}
|
||||||
|
|
||||||
|
class _$DioDi extends _i86.DioDi {}
|
||||||
|
|
||||||
|
class _$AutoRouteDi extends _i729.AutoRouteDi {}
|
||||||
|
|
||||||
|
class _$ConnectivityDi extends _i807.ConnectivityDi {}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import 'injection.config.dart';
|
||||||
|
|
||||||
|
final getIt = GetIt.instance;
|
||||||
|
|
||||||
|
@InjectableInit()
|
||||||
|
Future<void> configureDependencies(String env) => getIt.init(environment: env);
|
||||||
@@ -1,122 +1,57 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
void main() {
|
import 'injection.dart';
|
||||||
runApp(const MyApp());
|
import 'presentation/app_widget.dart';
|
||||||
}
|
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
void main() async {
|
||||||
const MyApp({super.key});
|
runZonedGuarded(
|
||||||
|
() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
// This widget is the root of your application.
|
await Firebase.initializeApp();
|
||||||
@override
|
await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return MaterialApp(
|
|
||||||
title: 'Flutter Demo',
|
|
||||||
theme: ThemeData(
|
|
||||||
// This is the theme of your application.
|
|
||||||
//
|
|
||||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
|
||||||
// the application has a purple toolbar. Then, without quitting the app,
|
|
||||||
// try changing the seedColor in the colorScheme below to Colors.green
|
|
||||||
// and then invoke "hot reload" (save your changes or press the "hot
|
|
||||||
// reload" button in a Flutter-supported IDE, or press "r" if you used
|
|
||||||
// the command line to start the app).
|
|
||||||
//
|
|
||||||
// Notice that the counter didn't reset back to zero; the application
|
|
||||||
// state is not lost during the reload. To reset the state, use hot
|
|
||||||
// restart instead.
|
|
||||||
//
|
|
||||||
// This works for code too, not just values: Most code changes can be
|
|
||||||
// tested with just a hot reload.
|
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
|
||||||
),
|
|
||||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
FlutterError.onError = (errorDetails) {
|
||||||
const MyHomePage({super.key, required this.title});
|
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
|
||||||
|
};
|
||||||
|
|
||||||
// This widget is the home page of your application. It is stateful, meaning
|
PlatformDispatcher.instance.onError = (error, stack) {
|
||||||
// that it has a State object (defined below) that contains fields that affect
|
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
||||||
// how it looks.
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// This class is the configuration for the state. It holds the values (in this
|
SystemChrome.setSystemUIOverlayStyle(
|
||||||
// case the title) provided by the parent (in this case the App widget) and
|
const SystemUiOverlayStyle(
|
||||||
// used by the build method of the State. Fields in a Widget subclass are
|
statusBarColor: Colors.transparent,
|
||||||
// always marked "final".
|
statusBarIconBrightness: Brightness.dark,
|
||||||
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<MyHomePage> createState() => _MyHomePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
|
||||||
int _counter = 0;
|
|
||||||
|
|
||||||
void _incrementCounter() {
|
|
||||||
setState(() {
|
|
||||||
// This call to setState tells the Flutter framework that something has
|
|
||||||
// changed in this State, which causes it to rerun the build method below
|
|
||||||
// so that the display can reflect the updated values. If we changed
|
|
||||||
// _counter without calling setState(), then the build method would not be
|
|
||||||
// called again, and so nothing would appear to happen.
|
|
||||||
_counter++;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// This method is rerun every time setState is called, for instance as done
|
|
||||||
// by the _incrementCounter method above.
|
|
||||||
//
|
|
||||||
// The Flutter framework has been optimized to make rerunning build methods
|
|
||||||
// fast, so that you can just rebuild anything that needs updating rather
|
|
||||||
// than having to individually change instances of widgets.
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
// TRY THIS: Try changing the color here to a specific color (to
|
|
||||||
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
|
|
||||||
// change color while the other colors stay the same.
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
|
||||||
// Here we take the value from the MyHomePage object that was created by
|
|
||||||
// the App.build method, and use it to set our appbar title.
|
|
||||||
title: Text(widget.title),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
// Center is a layout widget. It takes a single child and positions it
|
|
||||||
// in the middle of the parent.
|
|
||||||
child: Column(
|
|
||||||
// Column is also a layout widget. It takes a list of children and
|
|
||||||
// arranges them vertically. By default, it sizes itself to fit its
|
|
||||||
// children horizontally, and tries to be as tall as its parent.
|
|
||||||
//
|
|
||||||
// Column has various properties to control how it sizes itself and
|
|
||||||
// how it positions its children. Here we use mainAxisAlignment to
|
|
||||||
// center the children vertically; the main axis here is the vertical
|
|
||||||
// axis because Columns are vertical (the cross axis would be
|
|
||||||
// horizontal).
|
|
||||||
//
|
|
||||||
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
|
|
||||||
// action in the IDE, or press "p" in the console), to see the
|
|
||||||
// wireframe for each widget.
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
const Text('You have pushed the button this many times:'),
|
|
||||||
Text(
|
|
||||||
'$_counter',
|
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: _incrementCounter,
|
await SystemChrome.setPreferredOrientations([
|
||||||
tooltip: 'Increment',
|
DeviceOrientation.landscapeLeft,
|
||||||
child: const Icon(Icons.add),
|
DeviceOrientation.landscapeRight,
|
||||||
), // This trailing comma makes auto-formatting nicer for build methods.
|
]);
|
||||||
);
|
|
||||||
}
|
if (kReleaseMode) {
|
||||||
|
debugPrint = (message, {wrapWidth}) => '';
|
||||||
|
}
|
||||||
|
|
||||||
|
await configureDependencies(
|
||||||
|
kReleaseMode ? Environment.prod : Environment.dev,
|
||||||
|
);
|
||||||
|
|
||||||
|
runApp(const AppWidget());
|
||||||
|
},
|
||||||
|
(error, stack) {
|
||||||
|
// âś… Ini udah bener
|
||||||
|
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../common/theme/theme.dart';
|
||||||
|
import '../common/constant/app_constant.dart';
|
||||||
|
import '../injection.dart';
|
||||||
|
import 'router/app_router.dart';
|
||||||
|
import 'router/app_router_observer.dart';
|
||||||
|
|
||||||
|
class AppWidget extends StatefulWidget {
|
||||||
|
const AppWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AppWidget> createState() => _AppWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppWidgetState extends State<AppWidget> {
|
||||||
|
final _appRouter = getIt<AppRouter>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp.router(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
title: AppConstant.appName,
|
||||||
|
theme: ThemeApp.theme,
|
||||||
|
routerConfig: _appRouter.config(
|
||||||
|
navigatorObservers: () => <NavigatorObserver>[AppRouteObserver()],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
// dart format width=80
|
||||||
|
|
||||||
|
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
/// *****************************************************
|
||||||
|
/// FlutterGen
|
||||||
|
/// *****************************************************
|
||||||
|
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: deprecated_member_use,directives_ordering,implicit_dynamic_list_literal,unnecessary_import
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class $AssetsImagesGen {
|
||||||
|
const $AssetsImagesGen();
|
||||||
|
|
||||||
|
/// File path: assets/images/logo.png
|
||||||
|
AssetGenImage get logo => const AssetGenImage('assets/images/logo.png');
|
||||||
|
|
||||||
|
/// List of all assets
|
||||||
|
List<AssetGenImage> get values => [logo];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Assets {
|
||||||
|
const Assets._();
|
||||||
|
|
||||||
|
static const $AssetsImagesGen images = $AssetsImagesGen();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AssetGenImage {
|
||||||
|
const AssetGenImage(
|
||||||
|
this._assetName, {
|
||||||
|
this.size,
|
||||||
|
this.flavors = const {},
|
||||||
|
this.animation,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String _assetName;
|
||||||
|
|
||||||
|
final Size? size;
|
||||||
|
final Set<String> flavors;
|
||||||
|
final AssetGenImageAnimation? animation;
|
||||||
|
|
||||||
|
Image image({
|
||||||
|
Key? key,
|
||||||
|
AssetBundle? bundle,
|
||||||
|
ImageFrameBuilder? frameBuilder,
|
||||||
|
ImageErrorWidgetBuilder? errorBuilder,
|
||||||
|
String? semanticLabel,
|
||||||
|
bool excludeFromSemantics = false,
|
||||||
|
double? scale,
|
||||||
|
double? width,
|
||||||
|
double? height,
|
||||||
|
Color? color,
|
||||||
|
Animation<double>? opacity,
|
||||||
|
BlendMode? colorBlendMode,
|
||||||
|
BoxFit? fit,
|
||||||
|
AlignmentGeometry alignment = Alignment.center,
|
||||||
|
ImageRepeat repeat = ImageRepeat.noRepeat,
|
||||||
|
Rect? centerSlice,
|
||||||
|
bool matchTextDirection = false,
|
||||||
|
bool gaplessPlayback = true,
|
||||||
|
bool isAntiAlias = false,
|
||||||
|
String? package,
|
||||||
|
FilterQuality filterQuality = FilterQuality.medium,
|
||||||
|
int? cacheWidth,
|
||||||
|
int? cacheHeight,
|
||||||
|
}) {
|
||||||
|
return Image.asset(
|
||||||
|
_assetName,
|
||||||
|
key: key,
|
||||||
|
bundle: bundle,
|
||||||
|
frameBuilder: frameBuilder,
|
||||||
|
errorBuilder: errorBuilder,
|
||||||
|
semanticLabel: semanticLabel,
|
||||||
|
excludeFromSemantics: excludeFromSemantics,
|
||||||
|
scale: scale,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
color: color,
|
||||||
|
opacity: opacity,
|
||||||
|
colorBlendMode: colorBlendMode,
|
||||||
|
fit: fit,
|
||||||
|
alignment: alignment,
|
||||||
|
repeat: repeat,
|
||||||
|
centerSlice: centerSlice,
|
||||||
|
matchTextDirection: matchTextDirection,
|
||||||
|
gaplessPlayback: gaplessPlayback,
|
||||||
|
isAntiAlias: isAntiAlias,
|
||||||
|
package: package,
|
||||||
|
filterQuality: filterQuality,
|
||||||
|
cacheWidth: cacheWidth,
|
||||||
|
cacheHeight: cacheHeight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageProvider provider({AssetBundle? bundle, String? package}) {
|
||||||
|
return AssetImage(_assetName, bundle: bundle, package: package);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get path => _assetName;
|
||||||
|
|
||||||
|
String get keyName => _assetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AssetGenImageAnimation {
|
||||||
|
const AssetGenImageAnimation({
|
||||||
|
required this.isAnimation,
|
||||||
|
required this.duration,
|
||||||
|
required this.frames,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool isAnimation;
|
||||||
|
final Duration duration;
|
||||||
|
final int frames;
|
||||||
|
}
|
||||||