Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57fb56303a | ||
|
|
8f0a5d3fb5 | ||
|
|
5a8b020256 | ||
|
|
e273785268 | ||
|
|
5ba60747a8 | ||
|
|
c35d0eedbe | ||
|
|
bc751246d8 | ||
|
|
f5e3075205 | ||
|
|
5954510b93 | ||
|
|
7887704a5c | ||
|
|
4c12244d3c | ||
|
|
f4f775b9ed | ||
|
|
44d48d41d4 | ||
|
|
82e1f93cce | ||
|
|
1ce980a87b | ||
|
|
909c312af0 | ||
|
|
73918430b2 | ||
|
|
a5d66c63b7 | ||
|
|
3c596461c6 | ||
|
|
006486bc2a | ||
|
|
2e00207343 | ||
|
|
8e35582f93 | ||
|
|
0ea1a6fa56 | ||
|
|
cee78e179b | ||
|
|
1ca1a45126 | ||
|
|
214dfe3262 | ||
|
|
3b26b19b25 | ||
|
|
b20854f329 | ||
|
|
1a0c0cf49b | ||
|
|
c40f96fc88 | ||
|
|
13c55afe3c | ||
|
|
99bf4d5c7f | ||
|
|
207dda29df | ||
|
|
c3263edb89 | ||
|
|
c072e4c168 | ||
|
|
e4af5f10d7 | ||
|
|
37b22fe662 | ||
|
|
c12e9bd188 | ||
|
|
dc4fdf5fbf | ||
|
|
0d1e516686 | ||
|
|
4d994e303b | ||
|
|
b0cf40136b | ||
|
|
89c94c796a | ||
|
|
06cc7e3781 | ||
|
|
88c3cebd31 | ||
|
|
c13e3c598e | ||
|
|
936875c30a | ||
|
|
0afb683045 | ||
|
|
c790d00341 | ||
|
|
00c9d8435a | ||
|
|
079813e95b | ||
|
|
30a2bece41 | ||
|
|
2d596a25b9 | ||
|
|
dcf76b5fed | ||
|
|
4dc56662c8 | ||
|
|
74d706b32a | ||
|
|
5f0284a9e5 | ||
|
|
f70b43c6ab | ||
|
|
c36a4059e1 | ||
|
|
8951ca44eb | ||
|
|
ec1beeeb1b | ||
|
|
2870f39bcb | ||
|
|
fb7c9a19a9 | ||
|
|
d86c38e77c | ||
|
|
627de219cb | ||
|
|
c3eb62077f | ||
|
|
d3120c1bf2 | ||
|
|
09d8f6af69 | ||
|
|
8412220a06 | ||
|
|
8312429be3 | ||
|
|
2d29a2f38a | ||
|
|
472e9f5f69 | ||
|
|
59e61fe6c8 | ||
|
|
16bafb7e17 | ||
|
|
3c24fff82e | ||
|
|
30007415c7 | ||
|
|
13d07caa74 |
@@ -0,0 +1,150 @@
|
|||||||
|
name: Build & Deploy iOS to TestFlight
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: macos-26
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: "stable"
|
||||||
|
# Dipin biar CI nggak ikut naik versi diam-diam.
|
||||||
|
# Flutter 3.47 mensyaratkan iOS deployment target minimal 15.0.
|
||||||
|
flutter-version: "3.47.0"
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: flutter pub get
|
||||||
|
|
||||||
|
# ── Code Signing Setup ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Install Apple Certificate
|
||||||
|
env:
|
||||||
|
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
|
||||||
|
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
|
||||||
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||||
|
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
|
||||||
|
|
||||||
|
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||||
|
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||||
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
|
||||||
|
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A \
|
||||||
|
-t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||||
|
security set-key-partition-list -S apple-tool:,apple: \
|
||||||
|
-s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||||
|
|
||||||
|
- name: Install Provisioning Profile
|
||||||
|
env:
|
||||||
|
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
|
||||||
|
run: |
|
||||||
|
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
|
||||||
|
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
|
||||||
|
|
||||||
|
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||||
|
|
||||||
|
# Xcode requires the filename to be the profile's UUID
|
||||||
|
UUID=$(security cms -D -i $PP_PATH | plutil -extract UUID raw -)
|
||||||
|
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/$UUID.mobileprovision
|
||||||
|
echo "Installed provisioning profile UUID: $UUID"
|
||||||
|
|
||||||
|
# ── Disable SPM ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Disable Swift Package Manager
|
||||||
|
run: flutter config --no-enable-swift-package-manager
|
||||||
|
|
||||||
|
# ── CocoaPods ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Install CocoaPods Dependencies
|
||||||
|
run: |
|
||||||
|
cd ios
|
||||||
|
rm -rf Pods Podfile.lock
|
||||||
|
pod install --repo-update
|
||||||
|
|
||||||
|
# ── Build & Archive ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Build iOS (no codesign)
|
||||||
|
run: flutter build ios --release --no-codesign
|
||||||
|
|
||||||
|
- name: Re-run pod install to apply Podfile signing settings
|
||||||
|
run: |
|
||||||
|
cd ios
|
||||||
|
pod install
|
||||||
|
|
||||||
|
- name: Archive with Xcode
|
||||||
|
env:
|
||||||
|
TEAM_ID: ${{ secrets.TEAM_ID }}
|
||||||
|
run: |
|
||||||
|
cat > $RUNNER_TEMP/signing.xcconfig << 'XCCONFIG'
|
||||||
|
CODE_SIGN_STYLE = Manual
|
||||||
|
CODE_SIGN_IDENTITY = iPhone Distribution
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = Enaklo Customer
|
||||||
|
CODE_SIGNING_REQUIRED = YES
|
||||||
|
XCCONFIG
|
||||||
|
|
||||||
|
xcodebuild archive \
|
||||||
|
-workspace ios/Runner.xcworkspace \
|
||||||
|
-scheme Runner \
|
||||||
|
-configuration Release \
|
||||||
|
-archivePath $RUNNER_TEMP/Runner.xcarchive \
|
||||||
|
-destination "generic/platform=iOS" \
|
||||||
|
-xcconfig $RUNNER_TEMP/signing.xcconfig \
|
||||||
|
DEVELOPMENT_TEAM="$TEAM_ID"
|
||||||
|
|
||||||
|
- name: Export IPA
|
||||||
|
run: |
|
||||||
|
xcodebuild -exportArchive \
|
||||||
|
-archivePath $RUNNER_TEMP/Runner.xcarchive \
|
||||||
|
-exportPath $RUNNER_TEMP/export \
|
||||||
|
-exportOptionsPlist ios/ExportOptions.plist
|
||||||
|
|
||||||
|
mkdir -p build/ios/ipa
|
||||||
|
cp $RUNNER_TEMP/export/*.ipa build/ios/ipa/
|
||||||
|
|
||||||
|
# ── Upload to TestFlight ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Upload to TestFlight via Transporter
|
||||||
|
env:
|
||||||
|
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||||
|
APP_SPECIFIC_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
IPA_PATH=$(find build/ios/ipa -name "*.ipa" | head -1)
|
||||||
|
echo "Uploading: $IPA_PATH"
|
||||||
|
xcrun altool --upload-app \
|
||||||
|
--type ios \
|
||||||
|
--file "$IPA_PATH" \
|
||||||
|
--username "$APPLE_ID" \
|
||||||
|
--password "$APP_SPECIFIC_PASSWORD" \
|
||||||
|
--verbose
|
||||||
|
|
||||||
|
# ── Cleanup ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Clean Up Keychain and Provisioning Profile
|
||||||
|
if: ${{ always() }}
|
||||||
|
run: |
|
||||||
|
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true
|
||||||
|
rm -rf ~/Library/MobileDevice/Provisioning\ Profiles/*.mobileprovision || true
|
||||||
|
|
||||||
|
# ── Artifact ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
- name: Upload IPA as Artifact
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ios-ipa
|
||||||
|
path: build/ios/ipa/*.ipa
|
||||||
|
retention-days: 7
|
||||||
@@ -1,28 +1,27 @@
|
|||||||
# 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"
|
||||||
|
- build/**
|
||||||
|
- android/**
|
||||||
|
- ios/**
|
||||||
|
- web/**
|
||||||
|
- windows/**
|
||||||
|
- macos/**
|
||||||
|
- linux/**
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.enaklo"
|
namespace = "com.apskel.enaklocustomer"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = "27.0.12077973"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
@@ -21,7 +21,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.enaklo"
|
applicationId = "com.apskel.enaklocustomer"
|
||||||
// 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
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
<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.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="enaklo"
|
android:label="Enaklo"
|
||||||
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"
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.apskel.enaklocustomer
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import io.flutter.plugins.webviewflutter.WebViewFlutterAndroidExternalApi
|
||||||
|
|
||||||
|
class MainActivity : FlutterActivity() {
|
||||||
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
|
super.configureFlutterEngine(flutterEngine)
|
||||||
|
|
||||||
|
// Pengaturan WebView yang tidak disediakan plugin webview_flutter.
|
||||||
|
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, WEBVIEW_CHANNEL)
|
||||||
|
.setMethodCallHandler { call, result ->
|
||||||
|
when (call.method) {
|
||||||
|
"enableOffscreenPreRaster" -> {
|
||||||
|
val id = call.argument<Number>("webViewId")?.toLong()
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
val webView = id?.let {
|
||||||
|
WebViewFlutterAndroidExternalApi.getWebView(flutterEngine, it)
|
||||||
|
}
|
||||||
|
if (webView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
webView.settings.offscreenPreRaster = true
|
||||||
|
}
|
||||||
|
result.success(webView != null)
|
||||||
|
}
|
||||||
|
else -> result.notImplemented()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val WEBVIEW_CHANNEL = "com.apskel.enaklocustomer/webview"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package com.example.enaklo
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
|
||||||
|
|
||||||
class MainActivity : FlutterActivity()
|
|
||||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 115 KiB |
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground>
|
||||||
|
<inset
|
||||||
|
android:drawable="@drawable/ic_launcher_foreground"
|
||||||
|
android:inset="16%" />
|
||||||
|
</foreground>
|
||||||
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#ffffff</color>
|
||||||
|
</resources>
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
# This builtInKotlin flag was added automatically by Flutter migrator
|
||||||
|
android.builtInKotlin=false
|
||||||
|
# This newDsl flag was added automatically by Flutter migrator
|
||||||
|
android.newDsl=false
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
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.11.1" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
|
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
include(":app")
|
include(":app")
|
||||||
|
|||||||
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 174 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 790 KiB |
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 367 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 851 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 722 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 47 KiB |
@@ -0,0 +1,617 @@
|
|||||||
|
# Prompt: fitur EnakPoint & EnakCoin di Mobile App Customer
|
||||||
|
|
||||||
|
Kamu mengerjakan aplikasi mobile untuk **customer** (bukan kasir, bukan backoffice).
|
||||||
|
Tugasmu: membangun fitur loyalitas EnakPoint & EnakCoin di aplikasi, memakai API backend
|
||||||
|
yang sudah jadi dan dijelaskan di dokumen ini. Jangan mengarang endpoint, field, atau
|
||||||
|
aturan yang tidak tertulis di sini; kalau ada yang kurang jelas, tanyakan dulu.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Konteks bisnis
|
||||||
|
|
||||||
|
| | EnakPoint (`POINT`) | EnakCoin (`COIN`) |
|
||||||
|
| ----------------------------- | ---------------------------------------------------- | ----------------------------------- |
|
||||||
|
| Didapat dari | Belanja (order lunas), koreksi admin, tukar EnakCoin | Belanja, koreksi admin |
|
||||||
|
| Dipakai untuk | **Membayar order** | **Main game**, ditukar ke EnakPoint |
|
||||||
|
| Bisa dikirim ke customer lain | Ya | Ya |
|
||||||
|
| Bisa kedaluwarsa | Ya, bila owner mengaktifkan | Ya, bila owner mengaktifkan |
|
||||||
|
|
||||||
|
Tidak ada lagi "token". Semua yang dulu token sekarang EnakCoin, dan endpoint serta
|
||||||
|
field bernama token sudah dihapus dari API.
|
||||||
|
|
||||||
|
### Aturan yang wajib dipatuhi di UI
|
||||||
|
|
||||||
|
1. **Semua jumlah bilangan bulat.** Tidak ada desimal pada EnakPoint atau EnakCoin.
|
||||||
|
2. **Saldo bukan uang.** Nilai rupiah EnakPoint selalu ditulis **"setara potongan
|
||||||
|
Rp …"**, tidak pernah "saldo Rp …" atau "uang". Tidak ada fitur tarik tunai.
|
||||||
|
3. **PIN 6 digit wajib** untuk: membuat kode bayar, tukar
|
||||||
|
EnakCoin, dan transfer. **Main game tidak butuh PIN.** Melihat saldo dan riwayat
|
||||||
|
tidak butuh PIN.
|
||||||
|
4. **PIN terpisah dari password login** dan selalu dikirim sebagai **string** (supaya
|
||||||
|
nol di depan tidak hilang). Jangan pernah menyimpan PIN di perangkat, log, atau
|
||||||
|
analytics.
|
||||||
|
5. **Satu akun customer = satu organisasi.** Saldo berlaku di semua outlet organisasi itu.
|
||||||
|
6. **Waktu memakai WIB.** Tanggal kedaluwarsa berarti saldo masih bisa dipakai sampai
|
||||||
|
23:59:59 WIB di tanggal itu.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Koneksi ke API
|
||||||
|
|
||||||
|
- Base URL: `/api/v1`
|
||||||
|
- Semua endpoint customer: header `Authorization: Bearer <token login customer>`
|
||||||
|
- Semua jumlah di request dan response berupa integer.
|
||||||
|
|
||||||
|
### Registrasi customer
|
||||||
|
|
||||||
|
`POST /api/v1/customer-auth/register/start` menerima `organization_id` (opsional):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "phone_number": "0812…", "name": "Budi", "birth_date": "2000-01-31", "organization_id": "648b96a0-1d1d-414e-baee-37e9d6317b4e" }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Customer terdaftar di satu organisasi, dan saldonya berlaku di semua outlet organisasi itu.
|
||||||
|
- Bila `organization_id` tidak dikirim dan backend hanya punya satu organisasi, customer
|
||||||
|
otomatis masuk ke organisasi itu. Bila ada lebih dari satu, registrasi ditolak
|
||||||
|
("organization_id is required"), jadi sebaiknya app selalu mengirimnya dari config per
|
||||||
|
environment/brand.
|
||||||
|
- `organization_id` yang dikirim harus ada; bila tidak, registrasi ditolak sebelum OTP dikirim.
|
||||||
|
- Wallet customer baru belum punya baris sampai saldo pertama kali bergerak;
|
||||||
|
`GET /customer/wallet` tetap menjawab saldo 0.
|
||||||
|
|
||||||
|
### Format response
|
||||||
|
|
||||||
|
Sukses:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "success": true, "data": { … }, "errors": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
Gagal:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "success": false, "data": null, "errors": [{ "code": "304", "entity": "wallet_service", "cause": "wallet move refused: not enough EnakCoin" }] }
|
||||||
|
```
|
||||||
|
|
||||||
|
| `errors[0].code` | HTTP | Arti | Yang dilakukan app |
|
||||||
|
| ------------------ | ---- | ------------------------------------ | ------------------------------------------------------------------------------------------------- |
|
||||||
|
| `303`, `310` | 400 | Request tidak lengkap / salah format | Bug di app; tampilkan pesan umum |
|
||||||
|
| `304` | 400 | Ditolak aturan bisnis | Tampilkan pesan yang ramah (lihat tiap fitur); `cause` berbahasa Inggris, jangan tampilkan mentah |
|
||||||
|
| `404` | 404 | Tidak ditemukan | Tampilkan "tidak ditemukan" |
|
||||||
|
| `429` | 429 | Minta OTP terlalu cepat | Tampilkan hitung mundur sebelum boleh minta lagi |
|
||||||
|
| `PIN_NOT_SET` | 403 | Belum punya PIN | Buka alur buat PIN (§6.2) |
|
||||||
|
| `PIN_INVALID` | 400 | PIN salah | §6.5 |
|
||||||
|
| `PIN_LOCKED` | 423 | PIN terkunci | §6.5 |
|
||||||
|
| `TRANSFER_BLOCKED` | 403 | Transfer ditahan setelah reset PIN | §6.5 |
|
||||||
|
| `900` | 500 | Error server | "Terjadi kesalahan, coba lagi" |
|
||||||
|
|
||||||
|
### Idempotency-Key
|
||||||
|
|
||||||
|
Endpoint **tukar** dan **transfer** wajib header `Idempotency-Key` (string unik, maks.
|
||||||
|
50 karakter, mis. UUID v4).
|
||||||
|
|
||||||
|
- Buat **satu key baru saat customer menekan tombol konfirmasi**.
|
||||||
|
- Bila request gagal karena jaringan/timeout, **kirim ulang dengan key yang sama**.
|
||||||
|
Server mengembalikan hasil pertama dengan `"replayed": true` dan tidak memotong saldo
|
||||||
|
dua kali.
|
||||||
|
- Jangan pakai ulang key untuk transaksi yang berbeda; server menolaknya (`304`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Layar yang perlu dibuat
|
||||||
|
|
||||||
|
| Layar | Endpoint utama | Butuh PIN |
|
||||||
|
| -------------------------------- | ------------------------------------------------------------ | --------- |
|
||||||
|
| Beranda wallet | `GET /customer/wallet` | – |
|
||||||
|
| Riwayat mutasi | `GET /customer/wallet/transactions` | – |
|
||||||
|
| Saldo akan kedaluwarsa | `GET /customer/wallet/expiring` | – |
|
||||||
|
| Daftar outlet | `GET /customer/outlets` | – |
|
||||||
|
| Riwayat order + detail | `GET /customer/orders`, `GET /customer/orders/:id` | – |
|
||||||
|
| Kode bayar (angka + QR) | `POST /customer/wallet/payment-code` | Ya |
|
||||||
|
| Tukar EnakCoin | `GET …/exchange/preview`, `POST /customer/wallet/exchange` | Ya |
|
||||||
|
| Transfer | `GET …/transfer/recipient`, `POST /customer/wallet/transfer` | Ya |
|
||||||
|
| PIN (buat, ganti, lupa) | `/customer/pin/*` | – |
|
||||||
|
| Game | `POST /customer/spin` | – |
|
||||||
|
| (latar belakang) registrasi push | `PUT` / `DELETE /customer/devices` | – |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Beranda wallet, riwayat, kedaluwarsa
|
||||||
|
|
||||||
|
### 4.1 Beranda — `GET /customer/wallet`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"point_balance": 12500,
|
||||||
|
"coin_balance": 8,
|
||||||
|
"point_value": 1,
|
||||||
|
"point_discount_value": 12500,
|
||||||
|
"nearest_expiring": {
|
||||||
|
"point": { "amount": 150, "date": "2026-12-31" },
|
||||||
|
"coin": null
|
||||||
|
},
|
||||||
|
"recent_transactions": [
|
||||||
|
/* sama dengan item riwayat §4.2, maksimal 5 */
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Tampilkan:
|
||||||
|
|
||||||
|
- Saldo EnakPoint (`point_balance`) dengan keterangan "setara potongan Rp
|
||||||
|
{point_discount_value}" (format ribuan Indonesia: `Rp 12.500`).
|
||||||
|
- Saldo EnakCoin (`coin_balance`).
|
||||||
|
- Bila `nearest_expiring.point` / `.coin` tidak `null`: banner "{amount} EnakPoint akan
|
||||||
|
kedaluwarsa pada {date}" yang membuka layar §4.3.
|
||||||
|
- 5 mutasi terakhir dari `recent_transactions`, dengan tautan "Lihat semua" ke §4.2.
|
||||||
|
- Tombol aksi: Bayar di kasir (§7.1), Tukar EnakCoin (§8.1), Transfer (§8.2), Main game (§9).
|
||||||
|
|
||||||
|
Muat ulang beranda setelah setiap transaksi dan saat menerima push (§5).
|
||||||
|
|
||||||
|
Field `total_points`, `points_history`, `last_updated` di response ini **deprecated**;
|
||||||
|
jangan dipakai.
|
||||||
|
|
||||||
|
### 4.2 Riwayat — `GET /customer/wallet/transactions`
|
||||||
|
|
||||||
|
Query (semua opsional):
|
||||||
|
|
||||||
|
| Query | Contoh | Keterangan |
|
||||||
|
| ------------ | -------------- | --------------------------------------------------- |
|
||||||
|
| `page` | `1` | Mulai dari 1 |
|
||||||
|
| `limit` | `20` | 1–100, default 20 |
|
||||||
|
| `currency` | `POINT` | `POINT` atau `COIN`; untuk tab EnakPoint / EnakCoin |
|
||||||
|
| `type` | `EARN,PAYMENT` | Satu atau beberapa tipe dipisah koma, untuk filter |
|
||||||
|
| `from`, `to` | `2026-09-01` | Tanggal WIB, inklusif |
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": "…",
|
||||||
|
"currency": "POINT",
|
||||||
|
"type": "EARN",
|
||||||
|
"amount": 875,
|
||||||
|
"balance_after": 12500,
|
||||||
|
"description": "Belanja #ORD-0123 di Outlet Kemang",
|
||||||
|
"source": { "type": "ORDER", "id": "…" },
|
||||||
|
"outlet_id": "…",
|
||||||
|
"group_id": null,
|
||||||
|
"expires_at": "2026-12-31T23:59:59+07:00",
|
||||||
|
"lots": [{ "amount": 875, "remaining": 875, "expires_at": "2026-12-31T23:59:59+07:00" }],
|
||||||
|
"created_at": "2026-09-30T12:01:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": { "page": 1, "limit": 20, "total_count": 42, "total_pages": 3 }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Aturan tampilan:
|
||||||
|
|
||||||
|
- `amount` bertanda: positif tampil hijau dengan `+`, negatif merah dengan `−`.
|
||||||
|
- `description` sudah siap tampil (nama lawan transfer sudah disamarkan). Tampilkan apa
|
||||||
|
adanya.
|
||||||
|
- Mutasi masuk yang punya `expires_at` menampilkan "Berlaku sampai {tanggal}".
|
||||||
|
- Infinite scroll memakai `pagination.total_pages`.
|
||||||
|
- Riwayat tidak pernah berubah atau hilang; koreksi muncul sebagai baris baru.
|
||||||
|
|
||||||
|
Label tipe:
|
||||||
|
|
||||||
|
| `type` | Label | Arah |
|
||||||
|
| ---------------- | --------------------------------- | ----- |
|
||||||
|
| `EARN` | Dari belanja | + |
|
||||||
|
| `EARN_REVERSAL` | Dibatalkan (order di-void/refund) | − |
|
||||||
|
| `PAYMENT` | Bayar pesanan | − |
|
||||||
|
| `PAYMENT_REFUND` | Pengembalian pembayaran | + |
|
||||||
|
| `EXCHANGE_OUT` | Ditukar ke EnakPoint | − |
|
||||||
|
| `EXCHANGE_IN` | Hasil tukar EnakCoin | + |
|
||||||
|
| `TRANSFER_OUT` | Transfer keluar | − |
|
||||||
|
| `TRANSFER_IN` | Transfer masuk | + |
|
||||||
|
| `GAME_SPEND` | Main game | − |
|
||||||
|
| `EXPIRE` | Kedaluwarsa | − |
|
||||||
|
| `ADJUSTMENT` | Koreksi | + / − |
|
||||||
|
| `MIGRATION` | Saldo awal | + |
|
||||||
|
|
||||||
|
### 4.3 Akan kedaluwarsa — `GET /customer/wallet/expiring`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"point": [
|
||||||
|
{ "amount": 150, "date": "2026-10-31" },
|
||||||
|
{ "amount": 200, "date": "2026-12-31" }
|
||||||
|
],
|
||||||
|
"coin": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Daftar per tanggal, paling dekat di atas. Daftar kosong: tampilkan "Tidak ada saldo
|
||||||
|
yang akan kedaluwarsa". Saldo yang kedaluwarsa hangus tanpa kompensasi.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.4 Daftar outlet — `GET /customer/outlets`
|
||||||
|
|
||||||
|
Outlet aktif di organisasi customer, tempat saldo EnakPoint & EnakCoin berlaku. Urut
|
||||||
|
berdasarkan nama.
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "…",
|
||||||
|
"name": "Gokuna Kemang",
|
||||||
|
"address": "Jl. Kemang Raya 10",
|
||||||
|
"accepts_point_payment": true,
|
||||||
|
"earns_points": true,
|
||||||
|
"earns_coins": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
- `address` bisa `null`.
|
||||||
|
- `accepts_point_payment`: kasir di outlet ini menerima pembayaran EnakPoint. Pakai
|
||||||
|
untuk label "Bisa bayar pakai EnakPoint".
|
||||||
|
- `earns_points` / `earns_coins`: belanja di outlet ini memberi EnakPoint / EnakCoin.
|
||||||
|
- Belum ada telepon, koordinat, atau jam buka; data itu belum disimpan di backend.
|
||||||
|
|
||||||
|
### 4.5 Riwayat order — `GET /customer/orders` dan `GET /customer/orders/:id`
|
||||||
|
|
||||||
|
Order milik customer yang login di semua outlet organisasinya, terbaru di atas. Order
|
||||||
|
hanya masuk ke sini bila kasir mengaitkannya ke customer.
|
||||||
|
|
||||||
|
`GET /api/v1/customer/orders?page=1&limit=20` (`limit` 1–100, default 20):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": "…",
|
||||||
|
"order_number": "ORD-0123",
|
||||||
|
"outlet_id": "…",
|
||||||
|
"outlet_name": "Gokuna 1",
|
||||||
|
"order_type": "dine_in",
|
||||||
|
"status": "completed",
|
||||||
|
"payment_status": "completed",
|
||||||
|
"total_amount": 99000,
|
||||||
|
"item_count": 2,
|
||||||
|
"is_void": false,
|
||||||
|
"is_refund": false,
|
||||||
|
"points_earned": 865,
|
||||||
|
"coins_earned": 3,
|
||||||
|
"created_at": "2026-09-30T12:01:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": { "page": 1, "limit": 20, "total_count": 42, "total_pages": 3 }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`GET /api/v1/customer/orders/{id}` mengembalikan field yang sama, ditambah:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"table_number": "A3",
|
||||||
|
"subtotal": 90000,
|
||||||
|
"discount_amount": 0,
|
||||||
|
"tax_amount": 9000,
|
||||||
|
"refund_amount": 0,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "…",
|
||||||
|
"product_id": "…",
|
||||||
|
"product_name": "Kopi Susu",
|
||||||
|
"variant_name": "Large",
|
||||||
|
"quantity": 2,
|
||||||
|
"unit_price": 25000,
|
||||||
|
"total_price": 50000,
|
||||||
|
"refund_quantity": 0,
|
||||||
|
"modifiers": [],
|
||||||
|
"status": "completed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "…",
|
||||||
|
"product_id": "…",
|
||||||
|
"product_name": "Ikan Tude",
|
||||||
|
"variant_name": null,
|
||||||
|
"quantity": 1,
|
||||||
|
"weight": 4.2,
|
||||||
|
"unit_name": "ons",
|
||||||
|
"unit_price": 4500,
|
||||||
|
"total_price": 18900,
|
||||||
|
"refund_quantity": 0,
|
||||||
|
"modifiers": [],
|
||||||
|
"status": "completed"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payments": [
|
||||||
|
{ "id": "…", "method_name": "EnakPoint", "method_type": "point", "amount": 12500, "status": "completed", "refund_amount": 0, "points_used": 12500, "point_value": 1, "created_at": "…" },
|
||||||
|
{ "id": "…", "method_name": "Cash", "method_type": "cash", "amount": 86500, "status": "completed", "refund_amount": 0, "created_at": "…" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Order customer lain atau yang tidak ada → `404`.
|
||||||
|
- `points_earned` / `coins_earned`: yang didapat dari order ini; 0 bila tidak ada.
|
||||||
|
- Item timbangan membawa `weight` dan `unit_name`; tampilkan "1 × 4,2 ons".
|
||||||
|
- Pembayaran EnakPoint membawa `points_used`; tampilkan "EnakPoint 12.500 (Rp 12.500)".
|
||||||
|
- Order yang `is_void` atau `is_refund` tetap tampil, beri label "Dibatalkan" /
|
||||||
|
"Direfund".
|
||||||
|
|
||||||
|
## 5. Notifikasi push (FCM)
|
||||||
|
|
||||||
|
### 5.1 Registrasi device
|
||||||
|
|
||||||
|
Setelah login berhasil **dan** setiap kali FCM memberi token baru (`onTokenRefresh`):
|
||||||
|
|
||||||
|
`PUT /api/v1/customer/devices`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "device_id": "<id unik & stabil per instalasi>", "fcm_token": "<token FCM>", "platform": "android", "app_version": "2.4.0" }
|
||||||
|
```
|
||||||
|
|
||||||
|
- `device_id` wajib, stabil untuk satu instalasi (simpan di secure storage).
|
||||||
|
- `platform`: `android`, `ios`, atau `web`.
|
||||||
|
- Saat **logout**, panggil `DELETE /api/v1/customer/devices/{device_id}` sebelum
|
||||||
|
menghapus token login, supaya HP itu tidak lagi menerima notifikasi akun ini.
|
||||||
|
|
||||||
|
Tanpa registrasi ini, customer tidak menerima push apa pun.
|
||||||
|
|
||||||
|
### 5.2 Tipe push
|
||||||
|
|
||||||
|
Semua nilai di `data` berupa string.
|
||||||
|
|
||||||
|
| `data.type` | Kapan | Isi `data` lain | Aksi saat di-tap |
|
||||||
|
| -------------------- | ---------------------------------- | -------------------------------------------------- | --------------------------------- |
|
||||||
|
| `WALLET_TRANSFER_IN` | Menerima transfer | `transaction_id`, `group_id`, `currency`, `amount` | Buka riwayat, sorot transaksi itu |
|
||||||
|
| `WALLET_EXPIRING` | Beberapa hari sebelum saldo hangus | `currency`, `amount`, `expiry_date` | Buka layar kedaluwarsa (§4.3) |
|
||||||
|
| `WALLET_EXPIRED` | Saldo baru saja hangus | `currency`, `amount` | Buka riwayat |
|
||||||
|
| `PIN_LOCKED` | PIN terkunci setelah 5 kali salah | `locked_until` (RFC3339 UTC) | Buka layar lupa PIN (§6.4) |
|
||||||
|
|
||||||
|
Saat app terbuka dan menerima push wallet, muat ulang beranda.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. PIN
|
||||||
|
|
||||||
|
### 6.1 Kapan diminta
|
||||||
|
|
||||||
|
Jangan minta PIN saat registrasi. Minta saat customer **pertama kali** melakukan aksi
|
||||||
|
yang butuh PIN. Cek dengan:
|
||||||
|
|
||||||
|
`GET /api/v1/customer/pin/status` → `{ "has_pin": false, "locked_until": null, "transfer_blocked_until": null }`
|
||||||
|
|
||||||
|
Bila `has_pin: false`, arahkan ke alur buat PIN, lalu kembali ke aksi semula.
|
||||||
|
|
||||||
|
### 6.2 Buat PIN
|
||||||
|
|
||||||
|
1. `POST /api/v1/customer/pin/otp` dengan `{ "purpose": "pin_setup" }`.
|
||||||
|
Response: `{ "purpose": "pin_setup", "otp_token": "…", "expires_at": "…" }`.
|
||||||
|
OTP dikirim ke WhatsApp customer.
|
||||||
|
2. Customer memasukkan kode OTP, lalu PIN dua kali.
|
||||||
|
3. `POST /api/v1/customer/pin` dengan
|
||||||
|
`{ "otp_token": "…", "otp_code": "123456", "pin": "482913", "confirm_pin": "482913" }`.
|
||||||
|
Response: status PIN.
|
||||||
|
|
||||||
|
Validasi di app sebelum kirim (server juga memeriksa, jawab `304`):
|
||||||
|
|
||||||
|
- Tepat 6 digit angka, dan konfirmasi sama.
|
||||||
|
- Bukan satu digit berulang (`111111`).
|
||||||
|
- Bukan berurutan naik/turun (`123456`, `654321`).
|
||||||
|
- Bukan tanggal lahir customer (`DDMMYY` atau `YYMMDD`).
|
||||||
|
|
||||||
|
Minta OTP lagi terlalu cepat → `429`: tampilkan hitung mundur.
|
||||||
|
|
||||||
|
### 6.3 Ganti PIN
|
||||||
|
|
||||||
|
`PUT /api/v1/customer/pin` dengan `{ "old_pin": "…", "pin": "…", "confirm_pin": "…" }`.
|
||||||
|
|
||||||
|
### 6.4 Lupa PIN
|
||||||
|
|
||||||
|
1. `POST /customer/pin/otp` dengan `{ "purpose": "pin_reset" }`.
|
||||||
|
2. `POST /customer/pin/reset` dengan `{ "otp_token", "otp_code", "pin", "confirm_pin" }`.
|
||||||
|
|
||||||
|
Reset juga membuka PIN yang terkunci. Setelah reset, **transfer keluar ditahan 24 jam**;
|
||||||
|
bayar dan tukar tetap bisa. Beri tahu customer hal ini di layar sukses.
|
||||||
|
|
||||||
|
### 6.5 Menangani error PIN
|
||||||
|
|
||||||
|
Semua endpoint yang menerima `pin` bisa menjawab error PIN. Pada error ini **`data`
|
||||||
|
tidak `null`**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "success": false, "data": { "code": "PIN_INVALID", "remaining_attempts": 3 }, "errors": [ … ] }
|
||||||
|
```
|
||||||
|
|
||||||
|
| `data.code` | Field tambahan | Tampilan |
|
||||||
|
| ------------------ | ------------------------ | ---------------------------------------------------- |
|
||||||
|
| `PIN_NOT_SET` | – | Buka alur buat PIN (§6.2) |
|
||||||
|
| `PIN_INVALID` | `remaining_attempts` | "PIN salah, sisa {n} percobaan." Kosongkan input PIN |
|
||||||
|
| `PIN_LOCKED` | `locked_until` | "PIN terkunci sampai {jam}." Tombol "Lupa PIN" |
|
||||||
|
| `TRANSFER_BLOCKED` | `transfer_blocked_until` | "Transfer bisa dilakukan lagi pada {waktu}." |
|
||||||
|
|
||||||
|
5 kali salah berturut-turut mengunci PIN 30 menit; selama terkunci PIN yang benar pun
|
||||||
|
ditolak. Penghitung ada di server, jadi jangan membuat penghitung sendiri di app.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Membayar dengan EnakPoint
|
||||||
|
|
||||||
|
App customer tidak membuat atau membayar order; order hanya bisa dilihat (§4.5).
|
||||||
|
EnakPoint hanya dipakai membayar di kasir, lewat kode bayar dari app. Jangan membangun
|
||||||
|
layar checkout atau memanggil `POST /customer/orders/:id/pay-with-points`.
|
||||||
|
|
||||||
|
### 7.1 Di kasir — kode bayar
|
||||||
|
|
||||||
|
Customer tidak pernah mengetik PIN di mesin kasir. Alurnya:
|
||||||
|
|
||||||
|
1. Customer membuka "Bayar di kasir" dan memasukkan PIN.
|
||||||
|
2. `POST /api/v1/customer/wallet/payment-code` dengan `{ "pin": "482913" }`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": "482913", "qr_payload": "enakpoint:482913", "expires_at": "2026-09-30T05:02:00Z" }
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Tampilkan `code` besar (angka) **dan** QR dari `qr_payload` (string apa adanya).
|
||||||
|
4. Tampilkan hitung mundur ke `expires_at` (2 menit). Setelah habis, sembunyikan kode
|
||||||
|
dan tampilkan tombol "Buat kode baru".
|
||||||
|
5. Kasir memindai/mengetik kode dan memilih jumlah EnakPoint. App tidak menerima
|
||||||
|
callback; setelah customer kembali ke beranda, muat ulang saldo.
|
||||||
|
|
||||||
|
Kode sekali pakai. Membuat kode baru membatalkan kode lama.
|
||||||
|
|
||||||
|
### 7.2 Refund
|
||||||
|
|
||||||
|
Bila order yang dibayar EnakPoint dibatalkan atau direfund, EnakPoint kembali sebagai
|
||||||
|
EnakPoint (tidak pernah tunai) dan muncul di riwayat sebagai `PAYMENT_REFUND`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Tukar dan transfer
|
||||||
|
|
||||||
|
### 8.1 Tukar EnakCoin → EnakPoint
|
||||||
|
|
||||||
|
1. Customer mengetik jumlah EnakCoin. Panggil preview (debounce saat mengetik):
|
||||||
|
|
||||||
|
`GET /api/v1/customer/wallet/exchange/preview?coins=30`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "coin_amount": 10, "point_amount": 3, "coin_balance": 35, "coins": 30, "points": 9, "valid": true }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Kurs: `coin_amount` EnakCoin = `point_amount` EnakPoint. Tampilkan "10 EnakCoin =
|
||||||
|
3 EnakPoint".
|
||||||
|
- Bila `valid: false`, tampilkan `reason` sebagai alasan dan nonaktifkan tombol. Jumlah
|
||||||
|
harus kelipatan `coin_amount`.
|
||||||
|
- Tampilkan "Kamu akan mendapat {points} EnakPoint".
|
||||||
|
|
||||||
|
2. Konfirmasi (tukar tidak bisa dibatalkan) → minta PIN →
|
||||||
|
|
||||||
|
`POST /api/v1/customer/wallet/exchange` + header `Idempotency-Key`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "coins": 30, "pin": "482913" }
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"group_id": "…",
|
||||||
|
"coins": 30,
|
||||||
|
"points": 9,
|
||||||
|
"coin_amount": 10,
|
||||||
|
"point_amount": 3,
|
||||||
|
"lots": [{ "amount": 9, "expires_at": "2026-12-31T23:59:59+07:00" }],
|
||||||
|
"coin_balance": 5,
|
||||||
|
"point_balance": 9,
|
||||||
|
"replayed": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Layar sukses: saldo baru, dan bila `lots[].expires_at` ada, "EnakPoint ini berlaku
|
||||||
|
sampai {tanggal}".
|
||||||
|
|
||||||
|
### 8.2 Transfer
|
||||||
|
|
||||||
|
1. Pilih mata uang (EnakPoint / EnakCoin), isi nomor HP penerima dan jumlah.
|
||||||
|
2. Cek penerima:
|
||||||
|
|
||||||
|
`GET /api/v1/customer/wallet/transfer/recipient?phone=081234561234`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "name": "Bu*** Sa***", "phone_number": "08**-****-1234" }
|
||||||
|
```
|
||||||
|
|
||||||
|
| Hasil | Tampilan |
|
||||||
|
| ------ | ---------------------------------------------------------------- |
|
||||||
|
| Sukses | "Kirim ke Bu*** Sa*** (08**-\*\***-1234)?" |
|
||||||
|
| `404` | "Nomor ini tidak terdaftar" |
|
||||||
|
| `304` | "Tidak bisa mengirim ke nomor ini" (diri sendiri, akun nonaktif) |
|
||||||
|
|
||||||
|
3. Konfirmasi (transfer final, tidak bisa dibatalkan) → minta PIN →
|
||||||
|
|
||||||
|
`POST /api/v1/customer/wallet/transfer` + header `Idempotency-Key`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "currency": "POINT", "amount": 120, "recipient_phone": "081234561234", "pin": "482913" }
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"group_id": "…",
|
||||||
|
"currency": "POINT",
|
||||||
|
"amount": 120,
|
||||||
|
"recipient": { "name": "Bu*** Sa***", "phone_number": "08**-****-1234" },
|
||||||
|
"lots": [
|
||||||
|
{ "amount": 100, "expires_at": "2026-12-31T23:59:59+07:00" },
|
||||||
|
{ "amount": 20, "expires_at": null }
|
||||||
|
],
|
||||||
|
"balance": 30,
|
||||||
|
"replayed": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Layar sukses: saldo tersisa (`balance`). Bila ada `lots[].expires_at`, tampilkan
|
||||||
|
"Saldo yang dikirim berlaku sampai {tanggal}" (tanggal kedaluwarsa ikut terbawa ke
|
||||||
|
penerima).
|
||||||
|
|
||||||
|
Penolakan `304` yang mungkin: transfer dimatikan owner, di bawah minimal, di atas
|
||||||
|
maksimal per transaksi, melewati batas harian (reset tengah malam WIB), saldo tidak
|
||||||
|
cukup. Tampilkan pesan umum "Transfer tidak bisa diproses" plus alasan yang sesuai
|
||||||
|
bila bisa dikenali. Bila kena `TRANSFER_BLOCKED`, ikuti §6.5.
|
||||||
|
|
||||||
|
Penerima mendapat push `WALLET_TRANSFER_IN`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Game (memakai EnakCoin)
|
||||||
|
|
||||||
|
`POST /api/v1/customer/spin` dengan `{ "spin_id": "<id game>" }`. Tanpa PIN.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"game_play": { "id": "…", "game_id": "…", "coins_used": 1, "created_at": "…" },
|
||||||
|
"prize_won": { "id": "…", "name": "Voucher 10rb" },
|
||||||
|
"coins_remaining": 7
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Setiap game punya biaya sendiri: `metadata.coin_cost` pada data game dari
|
||||||
|
`GET /api/v1/customer/games` (atau `GET /customer/ferris-wheel`), default 1 bila kosong.
|
||||||
|
Tampilkan biaya sebelum main, dan nonaktifkan tombol bila `coin_balance` kurang.
|
||||||
|
- `304`: EnakCoin kurang, game nonaktif, atau hadiah baru saja habis. Tidak ada
|
||||||
|
EnakCoin yang terpotong; tampilkan pesan dan biarkan customer mencoba lagi.
|
||||||
|
- Setelah main, perbarui saldo EnakCoin dari `coins_remaining`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Yang sudah dihapus / deprecated
|
||||||
|
|
||||||
|
Sudah **dihapus** dari API (jangan dipanggil, akan error / tidak ada):
|
||||||
|
|
||||||
|
| Lama | Pengganti |
|
||||||
|
| ------------------------------------------------- | ----------------------------------------------------------------- |
|
||||||
|
| `GET /customer/tokens` | `GET /customer/wallet` → `coin_balance` |
|
||||||
|
| `total_tokens`, `tokens_history` | `coin_balance`, `GET /customer/wallet/transactions?currency=COIN` |
|
||||||
|
| `token_used`, `tokens_remaining` di response game | `coins_used`, `coins_remaining` |
|
||||||
|
|
||||||
|
Masih ada tapi **deprecated** (akan dihapus, jangan dipakai di kode baru):
|
||||||
|
|
||||||
|
| Lama | Pengganti |
|
||||||
|
| ---------------------------------------------------------------------- | ---------------------------------------- |
|
||||||
|
| `GET /customer/points` | `GET /customer/wallet` → `point_balance` |
|
||||||
|
| `total_points`, `points_history`, `last_updated` di `/customer/wallet` | `point_balance`, `recent_transactions` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Checklist selesai
|
||||||
|
|
||||||
|
- [ ] Beranda menampilkan saldo EnakPoint ("setara potongan Rp …"), EnakCoin, dan banner kedaluwarsa terdekat.
|
||||||
|
- [ ] Riwayat dengan tab per mata uang, filter tipe/tanggal, infinite scroll, label tipe sesuai §4.2.
|
||||||
|
- [ ] Layar saldo akan kedaluwarsa.
|
||||||
|
- [ ] Registrasi device FCM setelah login dan saat token berganti; unregister saat logout.
|
||||||
|
- [ ] Penanganan tap untuk keempat tipe push.
|
||||||
|
- [ ] PIN diminta hanya saat aksi yang membutuhkan; alur buat, ganti, dan lupa PIN lewat OTP.
|
||||||
|
- [ ] Keempat error PIN ditangani di semua layar yang meminta PIN.
|
||||||
|
- [ ] Kode bayar: angka + QR, hitung mundur 2 menit, tombol buat ulang.
|
||||||
|
- [ ] Tukar dengan preview, kelipatan kurs, konfirmasi, `Idempotency-Key`, retry dengan key sama.
|
||||||
|
- [ ] Transfer dengan cek penerima tersamar, konfirmasi, `Idempotency-Key`, retry dengan key sama.
|
||||||
|
- [ ] Game memakai `coins_used` / `coins_remaining` dan menampilkan biaya per game.
|
||||||
|
- [ ] Riwayat order dengan pagination dan layar detail (item, pembayaran, EnakPoint/EnakCoin yang didapat).
|
||||||
|
- [ ] Tidak ada pemakaian endpoint atau field di §10.
|
||||||
|
- [ ] PIN tidak pernah disimpan, di-log, atau dikirim ke analytics.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<!-- Ganti "app-store-connect" jika perlu: ad-hoc, enterprise, development -->
|
||||||
|
<key>method</key>
|
||||||
|
<string>app-store-connect</string>
|
||||||
|
|
||||||
|
<!-- Team ID dari Apple Developer account -->
|
||||||
|
<key>teamID</key>
|
||||||
|
<string>5TRC3M8UZG</string>
|
||||||
|
|
||||||
|
<!-- Signing style: manual (pakai provisioning profile eksplisit) -->
|
||||||
|
<key>signingStyle</key>
|
||||||
|
<string>manual</string>
|
||||||
|
|
||||||
|
<!-- Provisioning profiles: key = bundle ID, value = nama profile -->
|
||||||
|
<key>provisioningProfiles</key>
|
||||||
|
<dict>
|
||||||
|
<key>com.apskel.enaklocustomer</key>
|
||||||
|
<string>Enaklo Customer</string>
|
||||||
|
</dict>
|
||||||
|
|
||||||
|
<key>stripSwiftSymbols</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>uploadBitcode</key>
|
||||||
|
<false/>
|
||||||
|
|
||||||
|
<key>uploadSymbols</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>compileBitcode</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>15.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -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,50 @@
|
|||||||
|
# Uncomment this line to define a global platform for your project
|
||||||
|
platform :ios, '15.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)
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
|
||||||
|
# Disable code signing for all Pod targets — only Runner needs signing
|
||||||
|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
||||||
|
config.build_settings['CODE_SIGNING_REQUIRED'] = 'NO'
|
||||||
|
config.build_settings['CODE_SIGN_IDENTITY'] = ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -346,7 +346,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -368,7 +368,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.enaklo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklocustomer;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -384,7 +384,7 @@
|
|||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.enaklo.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklocustomer.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@@ -401,7 +401,7 @@
|
|||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.enaklo.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklocustomer.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
@@ -416,7 +416,7 @@
|
|||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.enaklo.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklocustomer.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||||
@@ -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++";
|
||||||
@@ -472,7 +472,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -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++";
|
||||||
@@ -523,7 +523,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.enaklo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklocustomer;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@@ -569,7 +569,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.enaklo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklocustomer;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|||||||
@@ -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: 795 KiB |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 804 B |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,17 @@
|
|||||||
|
# Generate: dart run flutter_launcher_icons -f launcher_icon.yaml
|
||||||
|
|
||||||
|
flutter_launcher_icons:
|
||||||
|
android: "launcher_icon"
|
||||||
|
ios: true
|
||||||
|
image_path: "assets/images/launcher.png"
|
||||||
|
remove_alpha_ios: true
|
||||||
|
min_sdk_android: 21 # android min sdk min:16, default 21
|
||||||
|
adaptive_icon_background: "#ffffff"
|
||||||
|
adaptive_icon_foreground: "assets/images/launcher.png"
|
||||||
|
web:
|
||||||
|
generate: true
|
||||||
|
image_path: "assets/images/launcher.png"
|
||||||
|
windows:
|
||||||
|
generate: true
|
||||||
|
image_path: "assets/images/launcher.png"
|
||||||
|
icon_size: 48
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../domain/auth/auth.dart';
|
||||||
|
|
||||||
|
part 'auth_event.dart';
|
||||||
|
part 'auth_state.dart';
|
||||||
|
part 'auth_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||||
|
final IAuthRepository _repository;
|
||||||
|
AuthBloc(this._repository) : super(AuthState.initial()) {
|
||||||
|
on<AuthEvent>(_onAuthEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onAuthEvent(AuthEvent event, Emitter<AuthState> emit) {
|
||||||
|
return event.map(
|
||||||
|
fetchCurrentUser: (e) async {
|
||||||
|
emit(state.copyWith(failureOption: none()));
|
||||||
|
|
||||||
|
final token = await _repository.hasToken();
|
||||||
|
|
||||||
|
final failureOrAuth = await _repository.currentUser();
|
||||||
|
|
||||||
|
failureOrAuth.fold(
|
||||||
|
(f) => emit(
|
||||||
|
state.copyWith(
|
||||||
|
failureOption: optionOf(f),
|
||||||
|
status: token
|
||||||
|
? AuthStatus.authenticated()
|
||||||
|
: AuthStatus.unauthenticated(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(user) => emit(
|
||||||
|
state.copyWith(
|
||||||
|
user: user,
|
||||||
|
status: token
|
||||||
|
? AuthStatus.authenticated()
|
||||||
|
: AuthStatus.unauthenticated(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,778 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint, type=warning, deprecated_member_use, deprecated_member_use_from_same_package
|
||||||
|
// 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_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$AuthEvent {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AuthEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthEvent()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class $AuthEventCopyWith<$Res> {
|
||||||
|
$AuthEventCopyWith(AuthEvent _, $Res Function(AuthEvent) __);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [AuthEvent].
|
||||||
|
extension AuthEventPatterns on AuthEvent {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _FetchCurrentUser value)? fetchCurrentUser,required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _FetchCurrentUser() when fetchCurrentUser != null:
|
||||||
|
return fetchCurrentUser(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _FetchCurrentUser value) fetchCurrentUser,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _FetchCurrentUser():
|
||||||
|
return fetchCurrentUser(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _FetchCurrentUser value)? fetchCurrentUser,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _FetchCurrentUser() when fetchCurrentUser != null:
|
||||||
|
return fetchCurrentUser(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? fetchCurrentUser,required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _FetchCurrentUser() when fetchCurrentUser != null:
|
||||||
|
return fetchCurrentUser();case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() fetchCurrentUser,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _FetchCurrentUser():
|
||||||
|
return fetchCurrentUser();case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? fetchCurrentUser,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _FetchCurrentUser() when fetchCurrentUser != null:
|
||||||
|
return fetchCurrentUser();case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _FetchCurrentUser implements AuthEvent {
|
||||||
|
const _FetchCurrentUser();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _FetchCurrentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthEvent.fetchCurrentUser()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$AuthState {
|
||||||
|
|
||||||
|
User get user; AuthStatus get status; Option<AuthFailure> get failureOption; bool get isFetching;
|
||||||
|
/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$AuthStateCopyWith<AuthState> get copyWith => _$AuthStateCopyWithImpl<AuthState>(this as AuthState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
final _this = this as AuthState;
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AuthState&&(identical(other.user, _this.user) || other.user == _this.user)&&(identical(other.status, _this.status) || other.status == _this.status)&&(identical(other.failureOption, _this.failureOption) || other.failureOption == _this.failureOption)&&(identical(other.isFetching, _this.isFetching) || other.isFetching == _this.isFetching));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
final _this = this as AuthState;
|
||||||
|
return Object.hash(runtimeType,_this.user,_this.status,_this.failureOption,_this.isFetching);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
final _this = this as AuthState;
|
||||||
|
return 'AuthState(user: ${_this.user}, status: ${_this.status}, failureOption: ${_this.failureOption}, isFetching: ${_this.isFetching})';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $AuthStateCopyWith<$Res> {
|
||||||
|
factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) _then) = _$AuthStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
User user, AuthStatus status, Option<AuthFailure> failureOption, bool isFetching
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$UserCopyWith<$Res> get user;$AuthStatusCopyWith<$Res> get status;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$AuthStateCopyWithImpl<$Res>
|
||||||
|
implements $AuthStateCopyWith<$Res> {
|
||||||
|
_$AuthStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final AuthState _self;
|
||||||
|
final $Res Function(AuthState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? user = null,Object? status = null,Object? failureOption = null,Object? isFetching = null,}) {
|
||||||
|
return _then(AuthState(
|
||||||
|
user: null == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||||
|
as User,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as AuthStatus,failureOption: null == failureOption ? _self.failureOption : failureOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<AuthFailure>,isFetching: null == isFetching ? _self.isFetching : isFetching // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$UserCopyWith<$Res> get user {
|
||||||
|
|
||||||
|
return $UserCopyWith<$Res>(_self.user, (value) {
|
||||||
|
return _then(_self.copyWith(user: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$AuthStatusCopyWith<$Res> get status {
|
||||||
|
|
||||||
|
return $AuthStatusCopyWith<$Res>(_self.status, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [AuthState].
|
||||||
|
extension AuthStatePatterns on AuthState {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AuthState value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AuthState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AuthState value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AuthState():
|
||||||
|
return $default(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AuthState value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AuthState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( User user, AuthStatus status, Option<AuthFailure> failureOption, bool isFetching)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AuthState() when $default != null:
|
||||||
|
return $default(_that.user,_that.status,_that.failureOption,_that.isFetching);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( User user, AuthStatus status, Option<AuthFailure> failureOption, bool isFetching) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AuthState():
|
||||||
|
return $default(_that.user,_that.status,_that.failureOption,_that.isFetching);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( User user, AuthStatus status, Option<AuthFailure> failureOption, bool isFetching)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AuthState() when $default != null:
|
||||||
|
return $default(_that.user,_that.status,_that.failureOption,_that.isFetching);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _AuthState extends AuthState {
|
||||||
|
const _AuthState({required this.user, this.status = const AuthStatus.initial(), required this.failureOption, this.isFetching = false}): super._();
|
||||||
|
|
||||||
|
|
||||||
|
@override final User user;
|
||||||
|
@override@JsonKey() final AuthStatus status;
|
||||||
|
@override final Option<AuthFailure> failureOption;
|
||||||
|
@override@JsonKey() final bool isFetching;
|
||||||
|
|
||||||
|
/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$AuthStateCopyWith<_AuthState> get copyWith => __$AuthStateCopyWithImpl<_AuthState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AuthState&&(identical(other.user, user) || other.user == user)&&(identical(other.status, status) || other.status == status)&&(identical(other.failureOption, failureOption) || other.failureOption == failureOption)&&(identical(other.isFetching, isFetching) || other.isFetching == isFetching));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return Object.hash(runtimeType,user,status,failureOption,isFetching);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthState(user: $user, status: $status, failureOption: $failureOption, isFetching: $isFetching)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$AuthStateCopyWith<$Res> implements $AuthStateCopyWith<$Res> {
|
||||||
|
factory _$AuthStateCopyWith(_AuthState value, $Res Function(_AuthState) _then) = __$AuthStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
User user, AuthStatus status, Option<AuthFailure> failureOption, bool isFetching
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $UserCopyWith<$Res> get user;@override $AuthStatusCopyWith<$Res> get status;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$AuthStateCopyWithImpl<$Res>
|
||||||
|
implements _$AuthStateCopyWith<$Res> {
|
||||||
|
__$AuthStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _AuthState _self;
|
||||||
|
final $Res Function(_AuthState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? user = null,Object? status = null,Object? failureOption = null,Object? isFetching = null,}) {
|
||||||
|
return _then(_AuthState(
|
||||||
|
user: null == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||||
|
as User,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as AuthStatus,failureOption: null == failureOption ? _self.failureOption : failureOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<AuthFailure>,isFetching: null == isFetching ? _self.isFetching : isFetching // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$UserCopyWith<$Res> get user {
|
||||||
|
|
||||||
|
return $UserCopyWith<$Res>(_self.user, (value) {
|
||||||
|
return _then(_self.copyWith(user: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of AuthState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$AuthStatusCopyWith<$Res> get status {
|
||||||
|
|
||||||
|
return $AuthStatusCopyWith<$Res>(_self.status, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$AuthStatus {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AuthStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthStatus()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class $AuthStatusCopyWith<$Res> {
|
||||||
|
$AuthStatusCopyWith(AuthStatus _, $Res Function(AuthStatus) __);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [AuthStatus].
|
||||||
|
extension AuthStatusPatterns on AuthStatus {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Authenticated value)? authenticated,TResult Function( _Unauthenticated value)? unauthenticated,TResult Function( _Initial value)? initial,required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Authenticated() when authenticated != null:
|
||||||
|
return authenticated(_that);case _Unauthenticated() when unauthenticated != null:
|
||||||
|
return unauthenticated(_that);case _Initial() when initial != null:
|
||||||
|
return initial(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Authenticated value) authenticated,required TResult Function( _Unauthenticated value) unauthenticated,required TResult Function( _Initial value) initial,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Authenticated():
|
||||||
|
return authenticated(_that);case _Unauthenticated():
|
||||||
|
return unauthenticated(_that);case _Initial():
|
||||||
|
return initial(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Authenticated value)? authenticated,TResult? Function( _Unauthenticated value)? unauthenticated,TResult? Function( _Initial value)? initial,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Authenticated() when authenticated != null:
|
||||||
|
return authenticated(_that);case _Unauthenticated() when unauthenticated != null:
|
||||||
|
return unauthenticated(_that);case _Initial() when initial != null:
|
||||||
|
return initial(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? authenticated,TResult Function()? unauthenticated,TResult Function()? initial,required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Authenticated() when authenticated != null:
|
||||||
|
return authenticated();case _Unauthenticated() when unauthenticated != null:
|
||||||
|
return unauthenticated();case _Initial() when initial != null:
|
||||||
|
return initial();case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() authenticated,required TResult Function() unauthenticated,required TResult Function() initial,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Authenticated():
|
||||||
|
return authenticated();case _Unauthenticated():
|
||||||
|
return unauthenticated();case _Initial():
|
||||||
|
return initial();}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? authenticated,TResult? Function()? unauthenticated,TResult? Function()? initial,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Authenticated() when authenticated != null:
|
||||||
|
return authenticated();case _Unauthenticated() when unauthenticated != null:
|
||||||
|
return unauthenticated();case _Initial() when initial != null:
|
||||||
|
return initial();case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _Authenticated implements AuthStatus {
|
||||||
|
const _Authenticated();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Authenticated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthStatus.authenticated()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _Unauthenticated implements AuthStatus {
|
||||||
|
const _Unauthenticated();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Unauthenticated);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthStatus.unauthenticated()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _Initial implements AuthStatus {
|
||||||
|
const _Initial();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Initial);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AuthStatus.initial()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// dart format on
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
part of 'auth_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class AuthEvent with _$AuthEvent {
|
||||||
|
const factory AuthEvent.fetchCurrentUser() = _FetchCurrentUser;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
part of 'auth_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class AuthState with _$AuthState {
|
||||||
|
const AuthState._();
|
||||||
|
|
||||||
|
const factory AuthState({
|
||||||
|
required User user,
|
||||||
|
@Default(AuthStatus.initial()) AuthStatus status,
|
||||||
|
required Option<AuthFailure> failureOption,
|
||||||
|
@Default(false) bool isFetching,
|
||||||
|
}) = _AuthState;
|
||||||
|
|
||||||
|
factory AuthState.initial() =>
|
||||||
|
AuthState(user: User.empty(), failureOption: none());
|
||||||
|
|
||||||
|
bool get isAuthenticated => status == const AuthStatus.authenticated();
|
||||||
|
bool get isInitial => status == const AuthStatus.initial();
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class AuthStatus with _$AuthStatus {
|
||||||
|
const factory AuthStatus.authenticated() = _Authenticated;
|
||||||
|
const factory AuthStatus.unauthenticated() = _Unauthenticated;
|
||||||
|
const factory AuthStatus.initial() = _Initial;
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
|
||||||
|
import '../../../common/function/app_function.dart';
|
||||||
|
import '../../../domain/auth/auth.dart';
|
||||||
|
|
||||||
|
part 'check_phone_form_event.dart';
|
||||||
|
part 'check_phone_form_state.dart';
|
||||||
|
part 'check_phone_form_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class CheckPhoneFormBloc
|
||||||
|
extends Bloc<CheckPhoneFormEvent, CheckPhoneFormState> {
|
||||||
|
final IAuthRepository _repository;
|
||||||
|
CheckPhoneFormBloc(this._repository) : super(CheckPhoneFormState.initial()) {
|
||||||
|
on<CheckPhoneFormEvent>(_onCheckPhoneFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onCheckPhoneFormEvent(
|
||||||
|
CheckPhoneFormEvent event,
|
||||||
|
Emitter<CheckPhoneFormState> emit,
|
||||||
|
) {
|
||||||
|
return event.map(
|
||||||
|
phoneNumberChanged: (e) async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
phoneNumber: e.phoneNumber,
|
||||||
|
failureOrCheckPhoneOption: none(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
submitted: (e) async {
|
||||||
|
Either<AuthFailure, CheckPhone>? failureOrCheckPhone;
|
||||||
|
emit(
|
||||||
|
state.copyWith(isSubmitting: true, failureOrCheckPhoneOption: none()),
|
||||||
|
);
|
||||||
|
|
||||||
|
final phoneNumberValid = state.phoneNumber.isNotEmpty;
|
||||||
|
|
||||||
|
if (phoneNumberValid) {
|
||||||
|
failureOrCheckPhone = await _repository.checkPhone(
|
||||||
|
phoneNumber: getNormalizePhone(state.phoneNumber),
|
||||||
|
);
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
failureOrCheckPhoneOption: optionOf(failureOrCheckPhone),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
emit(state.copyWith(showErrorMessages: true, isSubmitting: false));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,554 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint, type=warning, deprecated_member_use, deprecated_member_use_from_same_package
|
||||||
|
// 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 'check_phone_form_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$CheckPhoneFormEvent {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CheckPhoneFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CheckPhoneFormEvent()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class $CheckPhoneFormEventCopyWith<$Res> {
|
||||||
|
$CheckPhoneFormEventCopyWith(CheckPhoneFormEvent _, $Res Function(CheckPhoneFormEvent) __);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [CheckPhoneFormEvent].
|
||||||
|
extension CheckPhoneFormEventPatterns on CheckPhoneFormEvent {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _PhoneNumberChanged value)? phoneNumberChanged,TResult Function( _Submitted value)? submitted,required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that);case _Submitted() when submitted != null:
|
||||||
|
return submitted(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _PhoneNumberChanged value) phoneNumberChanged,required TResult Function( _Submitted value) submitted,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged():
|
||||||
|
return phoneNumberChanged(_that);case _Submitted():
|
||||||
|
return submitted(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _PhoneNumberChanged value)? phoneNumberChanged,TResult? Function( _Submitted value)? submitted,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that);case _Submitted() when submitted != null:
|
||||||
|
return submitted(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( String phoneNumber)? phoneNumberChanged,TResult Function()? submitted,required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that.phoneNumber);case _Submitted() when submitted != null:
|
||||||
|
return submitted();case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( String phoneNumber) phoneNumberChanged,required TResult Function() submitted,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged():
|
||||||
|
return phoneNumberChanged(_that.phoneNumber);case _Submitted():
|
||||||
|
return submitted();case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( String phoneNumber)? phoneNumberChanged,TResult? Function()? submitted,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that.phoneNumber);case _Submitted() when submitted != null:
|
||||||
|
return submitted();case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _PhoneNumberChanged implements CheckPhoneFormEvent {
|
||||||
|
const _PhoneNumberChanged(this.phoneNumber);
|
||||||
|
|
||||||
|
|
||||||
|
final String phoneNumber;
|
||||||
|
|
||||||
|
/// Create a copy of CheckPhoneFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$PhoneNumberChangedCopyWith<_PhoneNumberChanged> get copyWith => __$PhoneNumberChangedCopyWithImpl<_PhoneNumberChanged>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PhoneNumberChanged&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return Object.hash(runtimeType,phoneNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CheckPhoneFormEvent.phoneNumberChanged(phoneNumber: $phoneNumber)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$PhoneNumberChangedCopyWith<$Res> implements $CheckPhoneFormEventCopyWith<$Res> {
|
||||||
|
factory _$PhoneNumberChangedCopyWith(_PhoneNumberChanged value, $Res Function(_PhoneNumberChanged) _then) = __$PhoneNumberChangedCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$PhoneNumberChangedCopyWithImpl<$Res>
|
||||||
|
implements _$PhoneNumberChangedCopyWith<$Res> {
|
||||||
|
__$PhoneNumberChangedCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _PhoneNumberChanged _self;
|
||||||
|
final $Res Function(_PhoneNumberChanged) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CheckPhoneFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,}) {
|
||||||
|
return _then(_PhoneNumberChanged(
|
||||||
|
null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _Submitted implements CheckPhoneFormEvent {
|
||||||
|
const _Submitted();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Submitted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CheckPhoneFormEvent.submitted()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$CheckPhoneFormState {
|
||||||
|
|
||||||
|
String get phoneNumber; Option<Either<AuthFailure, CheckPhone>> get failureOrCheckPhoneOption; bool get isSubmitting; bool get showErrorMessages;
|
||||||
|
/// Create a copy of CheckPhoneFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CheckPhoneFormStateCopyWith<CheckPhoneFormState> get copyWith => _$CheckPhoneFormStateCopyWithImpl<CheckPhoneFormState>(this as CheckPhoneFormState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
final _this = this as CheckPhoneFormState;
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CheckPhoneFormState&&(identical(other.phoneNumber, _this.phoneNumber) || other.phoneNumber == _this.phoneNumber)&&(identical(other.failureOrCheckPhoneOption, _this.failureOrCheckPhoneOption) || other.failureOrCheckPhoneOption == _this.failureOrCheckPhoneOption)&&(identical(other.isSubmitting, _this.isSubmitting) || other.isSubmitting == _this.isSubmitting)&&(identical(other.showErrorMessages, _this.showErrorMessages) || other.showErrorMessages == _this.showErrorMessages));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
final _this = this as CheckPhoneFormState;
|
||||||
|
return Object.hash(runtimeType,_this.phoneNumber,_this.failureOrCheckPhoneOption,_this.isSubmitting,_this.showErrorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
final _this = this as CheckPhoneFormState;
|
||||||
|
return 'CheckPhoneFormState(phoneNumber: ${_this.phoneNumber}, failureOrCheckPhoneOption: ${_this.failureOrCheckPhoneOption}, isSubmitting: ${_this.isSubmitting}, showErrorMessages: ${_this.showErrorMessages})';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $CheckPhoneFormStateCopyWith<$Res> {
|
||||||
|
factory $CheckPhoneFormStateCopyWith(CheckPhoneFormState value, $Res Function(CheckPhoneFormState) _then) = _$CheckPhoneFormStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber, Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption, bool isSubmitting, bool showErrorMessages
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$CheckPhoneFormStateCopyWithImpl<$Res>
|
||||||
|
implements $CheckPhoneFormStateCopyWith<$Res> {
|
||||||
|
_$CheckPhoneFormStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final CheckPhoneFormState _self;
|
||||||
|
final $Res Function(CheckPhoneFormState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CheckPhoneFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? failureOrCheckPhoneOption = null,Object? isSubmitting = null,Object? showErrorMessages = null,}) {
|
||||||
|
return _then(CheckPhoneFormState(
|
||||||
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,failureOrCheckPhoneOption: null == failureOrCheckPhoneOption ? _self.failureOrCheckPhoneOption : failureOrCheckPhoneOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, CheckPhone>>,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,showErrorMessages: null == showErrorMessages ? _self.showErrorMessages : showErrorMessages // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [CheckPhoneFormState].
|
||||||
|
extension CheckPhoneFormStatePatterns on CheckPhoneFormState {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CheckPhoneFormState value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CheckPhoneFormState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CheckPhoneFormState value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CheckPhoneFormState():
|
||||||
|
return $default(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CheckPhoneFormState value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CheckPhoneFormState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption, bool isSubmitting, bool showErrorMessages)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CheckPhoneFormState() when $default != null:
|
||||||
|
return $default(_that.phoneNumber,_that.failureOrCheckPhoneOption,_that.isSubmitting,_that.showErrorMessages);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption, bool isSubmitting, bool showErrorMessages) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CheckPhoneFormState():
|
||||||
|
return $default(_that.phoneNumber,_that.failureOrCheckPhoneOption,_that.isSubmitting,_that.showErrorMessages);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption, bool isSubmitting, bool showErrorMessages)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CheckPhoneFormState() when $default != null:
|
||||||
|
return $default(_that.phoneNumber,_that.failureOrCheckPhoneOption,_that.isSubmitting,_that.showErrorMessages);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _CheckPhoneFormState implements CheckPhoneFormState {
|
||||||
|
const _CheckPhoneFormState({required this.phoneNumber, required this.failureOrCheckPhoneOption, this.isSubmitting = false, this.showErrorMessages = false});
|
||||||
|
|
||||||
|
|
||||||
|
@override final String phoneNumber;
|
||||||
|
@override final Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption;
|
||||||
|
@override@JsonKey() final bool isSubmitting;
|
||||||
|
@override@JsonKey() final bool showErrorMessages;
|
||||||
|
|
||||||
|
/// Create a copy of CheckPhoneFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$CheckPhoneFormStateCopyWith<_CheckPhoneFormState> get copyWith => __$CheckPhoneFormStateCopyWithImpl<_CheckPhoneFormState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CheckPhoneFormState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.failureOrCheckPhoneOption, failureOrCheckPhoneOption) || other.failureOrCheckPhoneOption == failureOrCheckPhoneOption)&&(identical(other.isSubmitting, isSubmitting) || other.isSubmitting == isSubmitting)&&(identical(other.showErrorMessages, showErrorMessages) || other.showErrorMessages == showErrorMessages));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return Object.hash(runtimeType,phoneNumber,failureOrCheckPhoneOption,isSubmitting,showErrorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CheckPhoneFormState(phoneNumber: $phoneNumber, failureOrCheckPhoneOption: $failureOrCheckPhoneOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$CheckPhoneFormStateCopyWith<$Res> implements $CheckPhoneFormStateCopyWith<$Res> {
|
||||||
|
factory _$CheckPhoneFormStateCopyWith(_CheckPhoneFormState value, $Res Function(_CheckPhoneFormState) _then) = __$CheckPhoneFormStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber, Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption, bool isSubmitting, bool showErrorMessages
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$CheckPhoneFormStateCopyWithImpl<$Res>
|
||||||
|
implements _$CheckPhoneFormStateCopyWith<$Res> {
|
||||||
|
__$CheckPhoneFormStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _CheckPhoneFormState _self;
|
||||||
|
final $Res Function(_CheckPhoneFormState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CheckPhoneFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? failureOrCheckPhoneOption = null,Object? isSubmitting = null,Object? showErrorMessages = null,}) {
|
||||||
|
return _then(_CheckPhoneFormState(
|
||||||
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,failureOrCheckPhoneOption: null == failureOrCheckPhoneOption ? _self.failureOrCheckPhoneOption : failureOrCheckPhoneOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, CheckPhone>>,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,showErrorMessages: null == showErrorMessages ? _self.showErrorMessages : showErrorMessages // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
part of 'check_phone_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class CheckPhoneFormEvent with _$CheckPhoneFormEvent {
|
||||||
|
const factory CheckPhoneFormEvent.phoneNumberChanged(String phoneNumber) =
|
||||||
|
_PhoneNumberChanged;
|
||||||
|
const factory CheckPhoneFormEvent.submitted() = _Submitted;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
part of 'check_phone_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class CheckPhoneFormState with _$CheckPhoneFormState {
|
||||||
|
const factory CheckPhoneFormState({
|
||||||
|
required String phoneNumber,
|
||||||
|
required Option<Either<AuthFailure, CheckPhone>> failureOrCheckPhoneOption,
|
||||||
|
@Default(false) bool isSubmitting,
|
||||||
|
@Default(false) bool showErrorMessages,
|
||||||
|
}) = _CheckPhoneFormState;
|
||||||
|
|
||||||
|
factory CheckPhoneFormState.initial() =>
|
||||||
|
CheckPhoneFormState(phoneNumber: '', failureOrCheckPhoneOption: none());
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
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(
|
||||||
|
phoneNumberChanged: (e) async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
phoneNumber: e.phoneNumber,
|
||||||
|
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 phoneNumberValid = state.phoneNumber.isNotEmpty;
|
||||||
|
final passwordValid = state.password.isNotEmpty;
|
||||||
|
|
||||||
|
log(
|
||||||
|
'phoneNumberValid: $phoneNumberValid, passwordValid: $passwordValid, phoneNumber: ${state.phoneNumber}, password: ${state.password}',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (phoneNumberValid && passwordValid) {
|
||||||
|
failureOrLogin = await _authRepository.login(
|
||||||
|
phoneNumber: state.phoneNumber,
|
||||||
|
password: state.password,
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
failureOrLoginOption: optionOf(failureOrLogin),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
emit(state.copyWith(showErrorMessages: true, isSubmitting: false));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,631 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint, type=warning, deprecated_member_use, deprecated_member_use_from_same_package
|
||||||
|
// 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
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoginFormEvent {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LoginFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class $LoginFormEventCopyWith<$Res> {
|
||||||
|
$LoginFormEventCopyWith(LoginFormEvent _, $Res Function(LoginFormEvent) __);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [LoginFormEvent].
|
||||||
|
extension LoginFormEventPatterns on LoginFormEvent {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _PhoneNumberChanged value)? phoneNumberChanged,TResult Function( _PasswordChanged value)? passwordChanged,TResult Function( _Submitted value)? submitted,required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that);case _PasswordChanged() when passwordChanged != null:
|
||||||
|
return passwordChanged(_that);case _Submitted() when submitted != null:
|
||||||
|
return submitted(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _PhoneNumberChanged value) phoneNumberChanged,required TResult Function( _PasswordChanged value) passwordChanged,required TResult Function( _Submitted value) submitted,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged():
|
||||||
|
return phoneNumberChanged(_that);case _PasswordChanged():
|
||||||
|
return passwordChanged(_that);case _Submitted():
|
||||||
|
return submitted(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _PhoneNumberChanged value)? phoneNumberChanged,TResult? Function( _PasswordChanged value)? passwordChanged,TResult? Function( _Submitted value)? submitted,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that);case _PasswordChanged() when passwordChanged != null:
|
||||||
|
return passwordChanged(_that);case _Submitted() when submitted != null:
|
||||||
|
return submitted(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( String phoneNumber)? phoneNumberChanged,TResult Function( String password)? passwordChanged,TResult Function()? submitted,required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that.phoneNumber);case _PasswordChanged() when passwordChanged != null:
|
||||||
|
return passwordChanged(_that.password);case _Submitted() when submitted != null:
|
||||||
|
return submitted();case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( String phoneNumber) phoneNumberChanged,required TResult Function( String password) passwordChanged,required TResult Function() submitted,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged():
|
||||||
|
return phoneNumberChanged(_that.phoneNumber);case _PasswordChanged():
|
||||||
|
return passwordChanged(_that.password);case _Submitted():
|
||||||
|
return submitted();case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( String phoneNumber)? phoneNumberChanged,TResult? Function( String password)? passwordChanged,TResult? Function()? submitted,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _PhoneNumberChanged() when phoneNumberChanged != null:
|
||||||
|
return phoneNumberChanged(_that.phoneNumber);case _PasswordChanged() when passwordChanged != null:
|
||||||
|
return passwordChanged(_that.password);case _Submitted() when submitted != null:
|
||||||
|
return submitted();case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _PhoneNumberChanged implements LoginFormEvent {
|
||||||
|
const _PhoneNumberChanged(this.phoneNumber);
|
||||||
|
|
||||||
|
|
||||||
|
final String phoneNumber;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$PhoneNumberChangedCopyWith<_PhoneNumberChanged> get copyWith => __$PhoneNumberChangedCopyWithImpl<_PhoneNumberChanged>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PhoneNumberChanged&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return Object.hash(runtimeType,phoneNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent.phoneNumberChanged(phoneNumber: $phoneNumber)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$PhoneNumberChangedCopyWith<$Res> implements $LoginFormEventCopyWith<$Res> {
|
||||||
|
factory _$PhoneNumberChangedCopyWith(_PhoneNumberChanged value, $Res Function(_PhoneNumberChanged) _then) = __$PhoneNumberChangedCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$PhoneNumberChangedCopyWithImpl<$Res>
|
||||||
|
implements _$PhoneNumberChangedCopyWith<$Res> {
|
||||||
|
__$PhoneNumberChangedCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _PhoneNumberChanged _self;
|
||||||
|
final $Res Function(_PhoneNumberChanged) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,}) {
|
||||||
|
return _then(_PhoneNumberChanged(
|
||||||
|
null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _PasswordChanged implements LoginFormEvent {
|
||||||
|
const _PasswordChanged(this.password);
|
||||||
|
|
||||||
|
|
||||||
|
final String password;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$PasswordChangedCopyWith<_PasswordChanged> get copyWith => __$PasswordChangedCopyWithImpl<_PasswordChanged>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PasswordChanged&&(identical(other.password, password) || other.password == password));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return Object.hash(runtimeType,password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent.passwordChanged(password: $password)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$PasswordChangedCopyWith<$Res> implements $LoginFormEventCopyWith<$Res> {
|
||||||
|
factory _$PasswordChangedCopyWith(_PasswordChanged value, $Res Function(_PasswordChanged) _then) = __$PasswordChangedCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String password
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$PasswordChangedCopyWithImpl<$Res>
|
||||||
|
implements _$PasswordChangedCopyWith<$Res> {
|
||||||
|
__$PasswordChangedCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _PasswordChanged _self;
|
||||||
|
final $Res Function(_PasswordChanged) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') $Res call({Object? password = null,}) {
|
||||||
|
return _then(_PasswordChanged(
|
||||||
|
null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _Submitted implements LoginFormEvent {
|
||||||
|
const _Submitted();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Submitted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormEvent.submitted()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LoginFormState {
|
||||||
|
|
||||||
|
String get phoneNumber; String get password; Option<Either<AuthFailure, Login>> get failureOrLoginOption; bool get isSubmitting; bool get showErrorMessages;
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$LoginFormStateCopyWith<LoginFormState> get copyWith => _$LoginFormStateCopyWithImpl<LoginFormState>(this as LoginFormState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
final _this = this as LoginFormState;
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LoginFormState&&(identical(other.phoneNumber, _this.phoneNumber) || other.phoneNumber == _this.phoneNumber)&&(identical(other.password, _this.password) || other.password == _this.password)&&(identical(other.failureOrLoginOption, _this.failureOrLoginOption) || other.failureOrLoginOption == _this.failureOrLoginOption)&&(identical(other.isSubmitting, _this.isSubmitting) || other.isSubmitting == _this.isSubmitting)&&(identical(other.showErrorMessages, _this.showErrorMessages) || other.showErrorMessages == _this.showErrorMessages));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
final _this = this as LoginFormState;
|
||||||
|
return Object.hash(runtimeType,_this.phoneNumber,_this.password,_this.failureOrLoginOption,_this.isSubmitting,_this.showErrorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
final _this = this as LoginFormState;
|
||||||
|
return 'LoginFormState(phoneNumber: ${_this.phoneNumber}, password: ${_this.password}, failureOrLoginOption: ${_this.failureOrLoginOption}, isSubmitting: ${_this.isSubmitting}, showErrorMessages: ${_this.showErrorMessages})';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $LoginFormStateCopyWith<$Res> {
|
||||||
|
factory $LoginFormStateCopyWith(LoginFormState value, $Res Function(LoginFormState) _then) = _$LoginFormStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber, String password, Option<Either<AuthFailure, Login>> failureOrLoginOption, bool isSubmitting, bool showErrorMessages
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$LoginFormStateCopyWithImpl<$Res>
|
||||||
|
implements $LoginFormStateCopyWith<$Res> {
|
||||||
|
_$LoginFormStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final LoginFormState _self;
|
||||||
|
final $Res Function(LoginFormState) _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? phoneNumber = null,Object? password = null,Object? failureOrLoginOption = null,Object? isSubmitting = null,Object? showErrorMessages = null,}) {
|
||||||
|
return _then(LoginFormState(
|
||||||
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,failureOrLoginOption: null == failureOrLoginOption ? _self.failureOrLoginOption : failureOrLoginOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Login>>,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,showErrorMessages: null == showErrorMessages ? _self.showErrorMessages : showErrorMessages // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [LoginFormState].
|
||||||
|
extension LoginFormStatePatterns on LoginFormState {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LoginFormState value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LoginFormState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LoginFormState value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LoginFormState():
|
||||||
|
return $default(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LoginFormState value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LoginFormState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, String password, Option<Either<AuthFailure, Login>> failureOrLoginOption, bool isSubmitting, bool showErrorMessages)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LoginFormState() when $default != null:
|
||||||
|
return $default(_that.phoneNumber,_that.password,_that.failureOrLoginOption,_that.isSubmitting,_that.showErrorMessages);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, String password, Option<Either<AuthFailure, Login>> failureOrLoginOption, bool isSubmitting, bool showErrorMessages) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LoginFormState():
|
||||||
|
return $default(_that.phoneNumber,_that.password,_that.failureOrLoginOption,_that.isSubmitting,_that.showErrorMessages);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, String password, Option<Either<AuthFailure, Login>> failureOrLoginOption, bool isSubmitting, bool showErrorMessages)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LoginFormState() when $default != null:
|
||||||
|
return $default(_that.phoneNumber,_that.password,_that.failureOrLoginOption,_that.isSubmitting,_that.showErrorMessages);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _LoginFormState implements LoginFormState {
|
||||||
|
const _LoginFormState({required this.phoneNumber, required this.password, required this.failureOrLoginOption, this.isSubmitting = false, this.showErrorMessages = false});
|
||||||
|
|
||||||
|
|
||||||
|
@override final String phoneNumber;
|
||||||
|
@override final String password;
|
||||||
|
@override final Option<Either<AuthFailure, Login>> failureOrLoginOption;
|
||||||
|
@override@JsonKey() final bool isSubmitting;
|
||||||
|
@override@JsonKey() final bool showErrorMessages;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$LoginFormStateCopyWith<_LoginFormState> get copyWith => __$LoginFormStateCopyWithImpl<_LoginFormState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LoginFormState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(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 {
|
||||||
|
return Object.hash(runtimeType,phoneNumber,password,failureOrLoginOption,isSubmitting,showErrorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LoginFormState(phoneNumber: $phoneNumber, password: $password, failureOrLoginOption: $failureOrLoginOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$LoginFormStateCopyWith<$Res> implements $LoginFormStateCopyWith<$Res> {
|
||||||
|
factory _$LoginFormStateCopyWith(_LoginFormState value, $Res Function(_LoginFormState) _then) = __$LoginFormStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String phoneNumber, String password, Option<Either<AuthFailure, Login>> failureOrLoginOption, bool isSubmitting, bool showErrorMessages
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$LoginFormStateCopyWithImpl<$Res>
|
||||||
|
implements _$LoginFormStateCopyWith<$Res> {
|
||||||
|
__$LoginFormStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _LoginFormState _self;
|
||||||
|
final $Res Function(_LoginFormState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LoginFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? password = null,Object? failureOrLoginOption = null,Object? isSubmitting = null,Object? showErrorMessages = null,}) {
|
||||||
|
return _then(_LoginFormState(
|
||||||
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,failureOrLoginOption: null == failureOrLoginOption ? _self.failureOrLoginOption : failureOrLoginOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Login>>,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,showErrorMessages: null == showErrorMessages ? _self.showErrorMessages : showErrorMessages // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
part of 'login_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class LoginFormEvent with _$LoginFormEvent {
|
||||||
|
const factory LoginFormEvent.phoneNumberChanged(String phoneNumber) =
|
||||||
|
_PhoneNumberChanged;
|
||||||
|
const factory LoginFormEvent.passwordChanged(String password) =
|
||||||
|
_PasswordChanged;
|
||||||
|
const factory LoginFormEvent.submitted() = _Submitted;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
part of 'login_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class LoginFormState with _$LoginFormState {
|
||||||
|
const factory LoginFormState({
|
||||||
|
required String phoneNumber,
|
||||||
|
required String password,
|
||||||
|
required Option<Either<AuthFailure, Login>> failureOrLoginOption,
|
||||||
|
@Default(false) bool isSubmitting,
|
||||||
|
@Default(false) bool showErrorMessages,
|
||||||
|
}) = _LoginFormState;
|
||||||
|
|
||||||
|
factory LoginFormState.initial() => LoginFormState(
|
||||||
|
phoneNumber: '',
|
||||||
|
password: '',
|
||||||
|
failureOrLoginOption: none(),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
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';
|
||||||
|
import '../../../domain/wallet/wallet.dart';
|
||||||
|
|
||||||
|
part 'logout_form_event.dart';
|
||||||
|
part 'logout_form_state.dart';
|
||||||
|
part 'logout_form_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class LogoutFormBloc extends Bloc<LogoutFormEvent, LogoutFormState> {
|
||||||
|
final IAuthRepository _repository;
|
||||||
|
final IDeviceRepository _deviceRepository;
|
||||||
|
|
||||||
|
LogoutFormBloc(this._repository, this._deviceRepository)
|
||||||
|
: super(LogoutFormState.initial()) {
|
||||||
|
on<LogoutFormEvent>(_onLogoutFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onLogoutFormEvent(
|
||||||
|
LogoutFormEvent event,
|
||||||
|
Emitter<LogoutFormState> emit,
|
||||||
|
) {
|
||||||
|
return event.map(
|
||||||
|
submitted: (e) async {
|
||||||
|
emit(state.copyWith(isSubmitting: true, failureOrAuthOption: none()));
|
||||||
|
// Hapus registrasi push sebelum token login dihapus. Kegagalannya
|
||||||
|
// tidak menghalangi logout.
|
||||||
|
await _deviceRepository.unregister();
|
||||||
|
final failureOrAuth = await _repository.logout();
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
failureOrAuthOption: optionOf(failureOrAuth),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,474 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint, type=warning, deprecated_member_use, deprecated_member_use_from_same_package
|
||||||
|
// 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 'logout_form_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LogoutFormEvent {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LogoutFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LogoutFormEvent()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class $LogoutFormEventCopyWith<$Res> {
|
||||||
|
$LogoutFormEventCopyWith(LogoutFormEvent _, $Res Function(LogoutFormEvent) __);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [LogoutFormEvent].
|
||||||
|
extension LogoutFormEventPatterns on LogoutFormEvent {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Submitted value)? submitted,required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Submitted() when submitted != null:
|
||||||
|
return submitted(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Submitted value) submitted,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Submitted():
|
||||||
|
return submitted(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Submitted value)? submitted,}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Submitted() when submitted != null:
|
||||||
|
return submitted(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? submitted,required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Submitted() when submitted != null:
|
||||||
|
return submitted();case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() submitted,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Submitted():
|
||||||
|
return submitted();case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? submitted,}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _Submitted() when submitted != null:
|
||||||
|
return submitted();case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _Submitted implements LogoutFormEvent {
|
||||||
|
const _Submitted();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Submitted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LogoutFormEvent.submitted()';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LogoutFormState {
|
||||||
|
|
||||||
|
Option<Either<AuthFailure, Unit>> get failureOrAuthOption; bool get isSubmitting;
|
||||||
|
/// Create a copy of LogoutFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$LogoutFormStateCopyWith<LogoutFormState> get copyWith => _$LogoutFormStateCopyWithImpl<LogoutFormState>(this as LogoutFormState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
final _this = this as LogoutFormState;
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LogoutFormState&&(identical(other.failureOrAuthOption, _this.failureOrAuthOption) || other.failureOrAuthOption == _this.failureOrAuthOption)&&(identical(other.isSubmitting, _this.isSubmitting) || other.isSubmitting == _this.isSubmitting));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
final _this = this as LogoutFormState;
|
||||||
|
return Object.hash(runtimeType,_this.failureOrAuthOption,_this.isSubmitting);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
final _this = this as LogoutFormState;
|
||||||
|
return 'LogoutFormState(failureOrAuthOption: ${_this.failureOrAuthOption}, isSubmitting: ${_this.isSubmitting})';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $LogoutFormStateCopyWith<$Res> {
|
||||||
|
factory $LogoutFormStateCopyWith(LogoutFormState value, $Res Function(LogoutFormState) _then) = _$LogoutFormStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
Option<Either<AuthFailure, Unit>> failureOrAuthOption, bool isSubmitting
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$LogoutFormStateCopyWithImpl<$Res>
|
||||||
|
implements $LogoutFormStateCopyWith<$Res> {
|
||||||
|
_$LogoutFormStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final LogoutFormState _self;
|
||||||
|
final $Res Function(LogoutFormState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? failureOrAuthOption = null,Object? isSubmitting = null,}) {
|
||||||
|
return _then(LogoutFormState(
|
||||||
|
failureOrAuthOption: null == failureOrAuthOption ? _self.failureOrAuthOption : failureOrAuthOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Unit>>,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [LogoutFormState].
|
||||||
|
extension LogoutFormStatePatterns on LogoutFormState {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _LogoutFormState value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LogoutFormState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _LogoutFormState value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LogoutFormState():
|
||||||
|
return $default(_that);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _LogoutFormState value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LogoutFormState() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( Option<Either<AuthFailure, Unit>> failureOrAuthOption, bool isSubmitting)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LogoutFormState() when $default != null:
|
||||||
|
return $default(_that.failureOrAuthOption,_that.isSubmitting);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( Option<Either<AuthFailure, Unit>> failureOrAuthOption, bool isSubmitting) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LogoutFormState():
|
||||||
|
return $default(_that.failureOrAuthOption,_that.isSubmitting);case _:
|
||||||
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( Option<Either<AuthFailure, Unit>> failureOrAuthOption, bool isSubmitting)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _LogoutFormState() when $default != null:
|
||||||
|
return $default(_that.failureOrAuthOption,_that.isSubmitting);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _LogoutFormState implements LogoutFormState {
|
||||||
|
const _LogoutFormState({required this.failureOrAuthOption, this.isSubmitting = false});
|
||||||
|
|
||||||
|
|
||||||
|
@override final Option<Either<AuthFailure, Unit>> failureOrAuthOption;
|
||||||
|
@override@JsonKey() final bool isSubmitting;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$LogoutFormStateCopyWith<_LogoutFormState> get copyWith => __$LogoutFormStateCopyWithImpl<_LogoutFormState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LogoutFormState&&(identical(other.failureOrAuthOption, failureOrAuthOption) || other.failureOrAuthOption == failureOrAuthOption)&&(identical(other.isSubmitting, isSubmitting) || other.isSubmitting == isSubmitting));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return Object.hash(runtimeType,failureOrAuthOption,isSubmitting);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LogoutFormState(failureOrAuthOption: $failureOrAuthOption, isSubmitting: $isSubmitting)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$LogoutFormStateCopyWith<$Res> implements $LogoutFormStateCopyWith<$Res> {
|
||||||
|
factory _$LogoutFormStateCopyWith(_LogoutFormState value, $Res Function(_LogoutFormState) _then) = __$LogoutFormStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
Option<Either<AuthFailure, Unit>> failureOrAuthOption, bool isSubmitting
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$LogoutFormStateCopyWithImpl<$Res>
|
||||||
|
implements _$LogoutFormStateCopyWith<$Res> {
|
||||||
|
__$LogoutFormStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _LogoutFormState _self;
|
||||||
|
final $Res Function(_LogoutFormState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LogoutFormState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? failureOrAuthOption = null,Object? isSubmitting = null,}) {
|
||||||
|
return _then(_LogoutFormState(
|
||||||
|
failureOrAuthOption: null == failureOrAuthOption ? _self.failureOrAuthOption : failureOrAuthOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<Either<AuthFailure, Unit>>,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
part of 'logout_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class LogoutFormEvent with _$LogoutFormEvent {
|
||||||
|
const factory LogoutFormEvent.submitted() = _Submitted;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
part of 'logout_form_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class LogoutFormState with _$LogoutFormState {
|
||||||
|
const factory LogoutFormState({
|
||||||
|
required Option<Either<AuthFailure, Unit>> failureOrAuthOption,
|
||||||
|
@Default(false) bool isSubmitting,
|
||||||
|
}) = _LogoutFormState;
|
||||||
|
|
||||||
|
factory LogoutFormState.initial() =>
|
||||||
|
LogoutFormState(failureOrAuthOption: none(), isSubmitting: false);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
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 'register_form_event.dart';
|
||||||
|
part 'register_form_state.dart';
|
||||||
|
part 'register_form_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class RegisterFormBloc extends Bloc<RegisterFormEvent, RegisterFormState> {
|
||||||
|
final IAuthRepository _repository;
|
||||||
|
RegisterFormBloc(this._repository) : super(RegisterFormState.initial()) {
|
||||||
|
on<RegisterFormEvent>(_onRegisterFormEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onRegisterFormEvent(
|
||||||
|
RegisterFormEvent event,
|
||||||
|
Emitter<RegisterFormState> emit,
|
||||||
|
) {
|
||||||
|
return event.map(
|
||||||
|
phoneNumberChanged: (e) async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
phoneNumber: e.phoneNumber,
|
||||||
|
failureOrRegisterOption: none(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
nameChanged: (e) async {
|
||||||
|
emit(state.copyWith(name: e.name, failureOrRegisterOption: none()));
|
||||||
|
},
|
||||||
|
birthDateChanged: (e) async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
birthDate: e.birthDate,
|
||||||
|
failureOrRegisterOption: none(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
submitted: (e) async {
|
||||||
|
Either<AuthFailure, Register>? failureOrRegister;
|
||||||
|
emit(
|
||||||
|
state.copyWith(isSubmitting: true, failureOrRegisterOption: none()),
|
||||||
|
);
|
||||||
|
|
||||||
|
final phoneNumberValid = state.phoneNumber.isNotEmpty;
|
||||||
|
final nameValid = state.name.isNotEmpty;
|
||||||
|
|
||||||
|
if (phoneNumberValid && nameValid) {
|
||||||
|
failureOrRegister = await _repository.register(
|
||||||
|
phoneNumber: state.phoneNumber,
|
||||||
|
name: state.name,
|
||||||
|
birthDate: state.birthDate,
|
||||||
|
);
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isSubmitting: false,
|
||||||
|
failureOrRegisterOption: optionOf(failureOrRegister),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
emit(state.copyWith(showErrorMessages: true, isSubmitting: false));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||