This commit is contained in:
@@ -12,7 +12,7 @@ A POS (Point of Sale) application for business owners, built with Flutter. The p
|
|||||||
- Architecture Overview
|
- Architecture Overview
|
||||||
- Project Structure
|
- Project Structure
|
||||||
- Key Dependencies & Purpose
|
- Key Dependencies & Purpose
|
||||||
- Code Generation
|
- Code Generation (see docs/codegen.md)
|
||||||
- Internationalization (i18n)
|
- Internationalization (i18n)
|
||||||
- Theming & Assets
|
- Theming & Assets
|
||||||
- Environment Configuration (`env.dart`)
|
- Environment Configuration (`env.dart`)
|
||||||
@@ -40,6 +40,7 @@ A POS (Point of Sale) application for business owners, built with Flutter. The p
|
|||||||
|
|
||||||
- Flutter SDK installed as per the official guide (`https://flutter.dev/docs/get-started/install`)
|
- Flutter SDK installed as per the official guide (`https://flutter.dev/docs/get-started/install`)
|
||||||
- Dart version per constraint: ^3.8.1
|
- Dart version per constraint: ^3.8.1
|
||||||
|
- For code generation only: FVM + Flutter 3.41.9 (`dart pub global activate fvm && fvm install 3.41.9`) — see [docs/codegen.md](docs/codegen.md)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
@@ -51,8 +52,16 @@ flutter pub get
|
|||||||
|
|
||||||
### Code generation (required after clone or when annotations change)
|
### Code generation (required after clone or when annotations change)
|
||||||
|
|
||||||
```bash
|
> **Do not run codegen with Flutter 3.47 / Dart 3.13** — every builder crashes with
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
> `Missing implementation of visitDotShorthandPropertyAccess`. Codegen must run on Flutter 3.41.9
|
||||||
|
> (Dart 3.11.5) via FVM. Full setup, commands, and troubleshooting: **[docs/codegen.md](docs/codegen.md)**.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$FVM = "$env:USERPROFILE\fvm\versions\3.41.9\bin"
|
||||||
|
|
||||||
|
& "$FVM\flutter.bat" pub get
|
||||||
|
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
|
flutter pub get # restore lockfile resolution for the global SDK
|
||||||
```
|
```
|
||||||
|
|
||||||
> Re-run whenever you change files using `@RoutePage()`, `@injectable`, `@freezed`, or `@JsonSerializable`.
|
> Re-run whenever you change files using `@RoutePage()`, `@injectable`, `@freezed`, or `@JsonSerializable`.
|
||||||
@@ -179,14 +188,27 @@ Refer to `pubspec.yaml` for full version constraints.
|
|||||||
|
|
||||||
## Code Generation
|
## Code Generation
|
||||||
|
|
||||||
|
**Full guide: [docs/codegen.md](docs/codegen.md)** — read it before your first codegen run.
|
||||||
|
|
||||||
|
Codegen runs on a pinned SDK (Flutter 3.41.9 / Dart 3.11.5 via FVM), not on the global Flutter 3.47:
|
||||||
|
`freezed 2.5.8` caps `analyzer` below 8.0.0, and analyzer 7.7.1 crashes on the dot-shorthand syntax
|
||||||
|
used by Dart 3.13 sources. The app itself still runs and builds with the global SDK.
|
||||||
|
|
||||||
Common commands:
|
Common commands:
|
||||||
|
|
||||||
```bash
|
```powershell
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
$FVM = "$env:USERPROFILE\fvm\versions\3.41.9\bin"
|
||||||
|
|
||||||
|
& "$FVM\flutter.bat" pub get
|
||||||
|
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
# or watch
|
# or watch
|
||||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
& "$FVM\dart.bat" run build_runner watch --delete-conflicting-outputs
|
||||||
|
flutter pub get # restore lockfile resolution for the global SDK
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> `--delete-conflicting-outputs` wipes every generated file first. If you cancel the build midway,
|
||||||
|
> restore them with `git checkout` — see the troubleshooting table in [docs/codegen.md](docs/codegen.md).
|
||||||
|
|
||||||
### Asset generation (flutter_gen_runner)
|
### Asset generation (flutter_gen_runner)
|
||||||
|
|
||||||
`flutter_gen_runner` is integrated with `build_runner`. Running the commands above will also generate typed accessors for assets based on the `flutter_gen` section in `pubspec.yaml`:
|
`flutter_gen_runner` is integrated with `build_runner`. Running the commands above will also generate typed accessors for assets based on the `flutter_gen` section in `pubspec.yaml`:
|
||||||
@@ -255,15 +277,20 @@ flutter pub get
|
|||||||
flutter format .
|
flutter format .
|
||||||
flutter analyze
|
flutter analyze
|
||||||
|
|
||||||
# Code generation (single run / watch)
|
# Localization (safe on the global SDK)
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
flutter gen-l10n
|
||||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
|
||||||
|
|
||||||
# Run by device
|
# Run by device
|
||||||
flutter devices
|
flutter devices
|
||||||
flutter run -d <device-id>
|
flutter run -d <device-id>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Code generation uses the pinned FVM SDK — see [docs/codegen.md](docs/codegen.md):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
& "$env:USERPROFILE\fvm\versions\3.41.9\bin\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Additional Notes
|
## Additional Notes
|
||||||
@@ -316,7 +343,7 @@ Aplikasi Point of Sale (POS) untuk pemilik usaha, dibangun dengan Flutter. Proye
|
|||||||
- Arsitektur & Alur
|
- Arsitektur & Alur
|
||||||
- Struktur Proyek
|
- Struktur Proyek
|
||||||
- Dependensi Utama & Fungsinya
|
- Dependensi Utama & Fungsinya
|
||||||
- Code Generation
|
- Code Generation (lihat docs/codegen.md)
|
||||||
- Internationalization (i18n)
|
- Internationalization (i18n)
|
||||||
- Theming & Assets
|
- Theming & Assets
|
||||||
- Konfigurasi Lingkungan (`env.dart`)
|
- Konfigurasi Lingkungan (`env.dart`)
|
||||||
@@ -344,6 +371,7 @@ Aplikasi Point of Sale (POS) untuk pemilik usaha, dibangun dengan Flutter. Proye
|
|||||||
|
|
||||||
- Flutter SDK terpasang sesuai panduan resmi (`https://flutter.dev/docs/get-started/install`)
|
- Flutter SDK terpasang sesuai panduan resmi (`https://flutter.dev/docs/get-started/install`)
|
||||||
- Versi Dart sesuai constraint: ^3.8.1
|
- Versi Dart sesuai constraint: ^3.8.1
|
||||||
|
- Khusus untuk code generation: FVM + Flutter 3.41.9 (`dart pub global activate fvm && fvm install 3.41.9`) — lihat [docs/codegen.md](docs/codegen.md)
|
||||||
|
|
||||||
### Instalasi
|
### Instalasi
|
||||||
|
|
||||||
@@ -355,8 +383,16 @@ flutter pub get
|
|||||||
|
|
||||||
### Generate kode (wajib setelah clone atau mengubah anotasi)
|
### Generate kode (wajib setelah clone atau mengubah anotasi)
|
||||||
|
|
||||||
```bash
|
> **Jangan jalankan codegen dengan Flutter 3.47 / Dart 3.13** — semua builder crash dengan
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
> `Missing implementation of visitDotShorthandPropertyAccess`. Codegen harus memakai Flutter 3.41.9
|
||||||
|
> (Dart 3.11.5) via FVM. Setup, perintah, dan troubleshooting lengkap: **[docs/codegen.md](docs/codegen.md)**.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$FVM = "$env:USERPROFILE\fvm\versions\3.41.9\bin"
|
||||||
|
|
||||||
|
& "$FVM\flutter.bat" pub get
|
||||||
|
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
|
flutter pub get # kembalikan resolusi lockfile ke SDK global
|
||||||
```
|
```
|
||||||
|
|
||||||
> Jalankan ulang perintah di atas setiap kali Anda mengubah file yang menggunakan anotasi `@RoutePage()`, `@injectable`, `@freezed`, atau `@JsonSerializable`.
|
> Jalankan ulang perintah di atas setiap kali Anda mengubah file yang menggunakan anotasi `@RoutePage()`, `@injectable`, `@freezed`, atau `@JsonSerializable`.
|
||||||
@@ -472,14 +508,27 @@ Catatan versi lengkap tersedia di `pubspec.yaml`.
|
|||||||
|
|
||||||
## Code Generation
|
## Code Generation
|
||||||
|
|
||||||
|
**Panduan lengkap: [docs/codegen.md](docs/codegen.md)** — baca dulu sebelum codegen pertama kali.
|
||||||
|
|
||||||
|
Codegen dijalankan dengan SDK terpisah (Flutter 3.41.9 / Dart 3.11.5 via FVM), bukan Flutter global 3.47:
|
||||||
|
`freezed 2.5.8` mengunci `analyzer` di bawah 8.0.0, dan analyzer 7.7.1 crash pada sintaks *dot-shorthand*
|
||||||
|
milik Dart 3.13. Aplikasinya sendiri tetap di-`run`/`build` dengan SDK global.
|
||||||
|
|
||||||
Perintah umum:
|
Perintah umum:
|
||||||
|
|
||||||
```bash
|
```powershell
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
$FVM = "$env:USERPROFILE\fvm\versions\3.41.9\bin"
|
||||||
|
|
||||||
|
& "$FVM\flutter.bat" pub get
|
||||||
|
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
# atau untuk watch
|
# atau untuk watch
|
||||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
& "$FVM\dart.bat" run build_runner watch --delete-conflicting-outputs
|
||||||
|
flutter pub get # kembalikan resolusi lockfile ke SDK global
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> `--delete-conflicting-outputs` menghapus semua file generated lebih dulu. Kalau build dibatalkan di
|
||||||
|
> tengah jalan, pulihkan dengan `git checkout` — lihat tabel troubleshooting di [docs/codegen.md](docs/codegen.md).
|
||||||
|
|
||||||
Generator yang digunakan:
|
Generator yang digunakan:
|
||||||
|
|
||||||
- AutoRoute: menghasilkan deklarasi router & route.
|
- AutoRoute: menghasilkan deklarasi router & route.
|
||||||
@@ -533,15 +582,20 @@ flutter pub get
|
|||||||
flutter format .
|
flutter format .
|
||||||
flutter analyze
|
flutter analyze
|
||||||
|
|
||||||
# Code generation (sekali jalan / watch)
|
# Localization (aman dengan SDK global)
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
flutter gen-l10n
|
||||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
|
||||||
|
|
||||||
# Run by device
|
# Run by device
|
||||||
flutter devices
|
flutter devices
|
||||||
flutter run -d <device-id>
|
flutter run -d <device-id>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Code generation memakai SDK FVM yang di-pin — lihat [docs/codegen.md](docs/codegen.md):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
& "$env:USERPROFILE\fvm\versions\3.41.9\bin\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Catatan Tambahan
|
## Catatan Tambahan
|
||||||
|
|||||||
@@ -19,3 +19,10 @@ analyzer:
|
|||||||
- test/generated/**
|
- test/generated/**
|
||||||
- "**/**.g.dart"
|
- "**/**.g.dart"
|
||||||
- "**/**.freezed.dart"
|
- "**/**.freezed.dart"
|
||||||
|
- build/**
|
||||||
|
- android/**
|
||||||
|
- ios/**
|
||||||
|
- web/**
|
||||||
|
- windows/**
|
||||||
|
- macos/**
|
||||||
|
- linux/**
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -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
|
||||||
id("com.google.gms.google-services") version "4.4.2" apply false
|
id("com.google.gms.google-services") version "4.4.2" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+163
@@ -0,0 +1,163 @@
|
|||||||
|
# Code Generation (build_runner)
|
||||||
|
|
||||||
|
> **PENTING:** `build_runner` di proyek ini **tidak bisa** dijalankan dengan Flutter 3.47 / Dart 3.13.
|
||||||
|
> Gunakan SDK Flutter 3.41.9 (Dart 3.11.5) lewat FVM. Aplikasinya sendiri tetap di-`run`/`build`
|
||||||
|
> dengan Flutter versi global (3.47).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
PowerShell (Windows):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$FVM = "$env:USERPROFILE\fvm\versions\3.41.9\bin"
|
||||||
|
|
||||||
|
& "$FVM\flutter.bat" pub get # 1. resolve paket dgn Dart 3.11.5
|
||||||
|
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs # 2. generate
|
||||||
|
flutter pub get # 3. balik ke SDK global 3.47
|
||||||
|
```
|
||||||
|
|
||||||
|
Git Bash:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
FVM=~/fvm/versions/3.41.9/bin
|
||||||
|
|
||||||
|
"$FVM/flutter.bat" pub get
|
||||||
|
"$FVM/dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
|
flutter pub get
|
||||||
|
```
|
||||||
|
|
||||||
|
Durasi normal: **±90–120 detik** untuk full build (146 output).
|
||||||
|
|
||||||
|
Setelah itu jalankan `flutter analyze` untuk memastikan hasil generate bersih.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kenapa harus SDK terpisah?
|
||||||
|
|
||||||
|
Kalau codegen dijalankan dengan Flutter global (3.47 / Dart 3.13), semua builder gagal dengan:
|
||||||
|
|
||||||
|
```
|
||||||
|
W SDK language version 3.13.0 is newer than `analyzer` language version 3.9.0.
|
||||||
|
E freezed on lib/application/.../category_analytic_loader_bloc.dart:
|
||||||
|
Exception: Missing implementation of visitDotShorthandPropertyAccess
|
||||||
|
```
|
||||||
|
|
||||||
|
Rantai penyebabnya:
|
||||||
|
|
||||||
|
1. `freezed 2.5.8` membatasi `analyzer <8.0.0`, jadi pub me-resolve ke **analyzer 7.7.1** (language version 3.9).
|
||||||
|
2. Dart 3.13 memakai sintaks *dot-shorthand* (`.value`) di sumber SDK/framework.
|
||||||
|
3. Analyzer 7.7.1 bisa mem-*parse*-nya tapi belum bisa menuliskannya ke summary → crash saat resolve.
|
||||||
|
4. Semua generator (`freezed`, `json_serializable`, `injectable_generator`, `auto_route_generator`) berbagi analyzer yang sama, jadi semuanya ikut mati — termasuk saat men-generate file lama yang tidak diubah.
|
||||||
|
|
||||||
|
Dart 3.11.5 (Flutter 3.41.9) adalah versi tertinggi yang **masih cocok dengan analyzer 7.7.1** sekaligus memenuhi batas `pubspec.lock` (`dart >=3.11.0-0`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Setup sekali di mesin baru
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
dart pub global activate fvm
|
||||||
|
```
|
||||||
|
|
||||||
|
Tambahkan folder binari pub ke PATH agar perintah `fvm` dikenali:
|
||||||
|
`%LOCALAPPDATA%\Pub\Cache\bin`
|
||||||
|
|
||||||
|
Lalu unduh SDK-nya (±1 GB, sekali saja):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
fvm install 3.41.9
|
||||||
|
fvm list # verifikasi
|
||||||
|
```
|
||||||
|
|
||||||
|
SDK tersimpan di `%USERPROFILE%\fvm\versions\3.41.9` dan **tidak** mengubah Flutter global.
|
||||||
|
|
||||||
|
> Kita sengaja **tidak** menjalankan `fvm use`, supaya repo tidak punya `.fvmrc`/`.fvm/`
|
||||||
|
> dan IDE tetap memakai Flutter 3.47 untuk menjalankan aplikasi.
|
||||||
|
> Kalau lebih suka pin per-project, jalankan `fvm use 3.41.9` lalu pakai `fvm dart run build_runner ...`,
|
||||||
|
> dan tambahkan `.fvm/` ke `.gitignore`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Perintah harian
|
||||||
|
|
||||||
|
Semua contoh memakai variabel `$FVM` dari bagian TL;DR.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# build sekali (paling sering dipakai)
|
||||||
|
& "$FVM\dart.bat" run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
|
# mode watch saat banyak mengubah anotasi
|
||||||
|
& "$FVM\dart.bat" run build_runner watch --delete-conflicting-outputs
|
||||||
|
|
||||||
|
# hanya membersihkan output generated
|
||||||
|
& "$FVM\dart.bat" run build_runner clean
|
||||||
|
```
|
||||||
|
|
||||||
|
Wajib generate ulang setiap kali mengubah/menambah file dengan anotasi:
|
||||||
|
|
||||||
|
| Anotasi | Generator | Output |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `@freezed` | freezed | `*.freezed.dart` |
|
||||||
|
| `@JsonSerializable` / `fromJson` di DTO | json_serializable | `*.g.dart` |
|
||||||
|
| `@injectable`, `@LazySingleton` | injectable_generator | `lib/injection.config.dart` |
|
||||||
|
| `@RoutePage()` | auto_route_generator | `lib/presentation/router/app_router.gr.dart` |
|
||||||
|
| asset baru di `assets/` | flutter_gen_runner | `lib/presentation/components/assets/assets.gen.dart` |
|
||||||
|
|
||||||
|
### Localization (i18n) — tidak lewat build_runner
|
||||||
|
|
||||||
|
`flutter gen-l10n` memakai tooling Flutter, bukan analyzer, jadi **aman dijalankan dengan Flutter 3.47**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
flutter gen-l10n
|
||||||
|
```
|
||||||
|
|
||||||
|
Jalankan setiap kali `lib/l10n/app_id.arb` / `app_en.arb` berubah. Hasilnya: `lib/l10n/app_localizations*.dart`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Aturan penting soal `--delete-conflicting-outputs`
|
||||||
|
|
||||||
|
Flag ini **menghapus dulu** semua file generated (±55 file `*.freezed.dart` / `*.g.dart`) sebelum membuat ulang.
|
||||||
|
Kalau proses dibatalkan di tengah jalan, project akan penuh error karena file-nya sudah hilang.
|
||||||
|
|
||||||
|
Pemulihan (semua file generated ikut ter-commit di git):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git status --porcelain | grep -E "^ D" | sed 's/^ D //' | while read -r f; do git checkout -- "$f"; done
|
||||||
|
```
|
||||||
|
|
||||||
|
Tips: jangan pipe output build ke `tail`/`head` — outputnya jadi ter-buffer sampai proses selesai,
|
||||||
|
sehingga terlihat seperti *hang* padahal sedang jalan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
| Gejala | Penyebab | Solusi |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Missing implementation of visitDotShorthandPropertyAccess` | codegen dijalankan dengan Flutter global 3.47 | pakai SDK FVM 3.41.9 |
|
||||||
|
| `Failed to update packages` + dump stack VM | `flutter pub run build_runner` / `fvm spawn ... pub run` | pakai `dart.bat run build_runner`, jangan `flutter pub run` |
|
||||||
|
| Ratusan error “isn't defined” di IDE, file `*.freezed.dart` hilang | build dibatalkan setelah `--delete-conflicting-outputs` | restore lewat `git checkout` (lihat di atas) |
|
||||||
|
| `pub get` gagal / versi paket bergeser | `pubspec.lock` di-resolve oleh SDK berbeda | jalankan `flutter pub get` dengan SDK global setelah codegen selesai |
|
||||||
|
| Build terasa lama di run pertama | asset graph baru dibuat dari nol | wajar, ±90–120 detik; run berikutnya inkremental |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rencana jangka panjang
|
||||||
|
|
||||||
|
Perbaikan permanen = upgrade toolchain codegen supaya jalan native di Dart 3.13:
|
||||||
|
|
||||||
|
- `freezed` 2.5.8 → 3.x, `freezed_annotation` 2.4.x → 3.x
|
||||||
|
- `injectable` 2.x → 3.x, `injectable_generator` 2.7 → 3.x
|
||||||
|
- `auto_route` 9.x → 11.x, `auto_route_generator` 9.x → 10.x
|
||||||
|
- `build_runner` → 2.16.x, `json_serializable` → 6.14.x (analyzer ikut naik ke 13.x)
|
||||||
|
|
||||||
|
Konsekuensinya breaking dan cukup besar, jadi perlu dijadwalkan sendiri:
|
||||||
|
|
||||||
|
- freezed 3 **menghapus** `.map()` / `.when()` / `.maybeWhen()` / `.maybeMap()` → ±49 pemakaian (mayoritas di handler event BLoC) harus diganti pattern matching Dart 3 (`switch`).
|
||||||
|
- ±98 file dengan `@freezed` harus dideklarasikan `abstract class` atau `sealed class`.
|
||||||
|
- Migrasi konfigurasi router (auto_route 11) dan DI (injectable 3).
|
||||||
|
|
||||||
|
Selama migrasi itu belum dikerjakan, gunakan alur FVM di dokumen ini.
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
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/analytic/analytic.dart';
|
||||||
|
import '../../../domain/analytic/repositories/i_analytic_repository.dart';
|
||||||
|
|
||||||
|
part 'profit_sharing_detail_loader_event.dart';
|
||||||
|
part 'profit_sharing_detail_loader_state.dart';
|
||||||
|
part 'profit_sharing_detail_loader_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class ProfitSharingDetailLoaderBloc
|
||||||
|
extends
|
||||||
|
Bloc<ProfitSharingDetailLoaderEvent, ProfitSharingDetailLoaderState> {
|
||||||
|
final IAnalyticRepository _repository;
|
||||||
|
|
||||||
|
ProfitSharingDetailLoaderBloc(this._repository)
|
||||||
|
: super(ProfitSharingDetailLoaderState.initial()) {
|
||||||
|
on<ProfitSharingDetailLoaderEvent>(_onProfitSharingDetailLoaderEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onProfitSharingDetailLoaderEvent(
|
||||||
|
ProfitSharingDetailLoaderEvent event,
|
||||||
|
Emitter<ProfitSharingDetailLoaderState> emit,
|
||||||
|
) {
|
||||||
|
return event.map(
|
||||||
|
expandedCategoryChanged: (e) async {
|
||||||
|
final isSame = state.expandedCategoryId == e.categoryId;
|
||||||
|
emit(state.copyWith(expandedCategoryId: isSame ? '' : e.categoryId));
|
||||||
|
},
|
||||||
|
fetched: (e) async {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
isFetching: true,
|
||||||
|
failureOption: none(),
|
||||||
|
parentCategoryId: e.parentCategoryId,
|
||||||
|
dateFrom: e.dateFrom,
|
||||||
|
dateTo: e.dateTo,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final result = await _repository.getProfitSharingDetail(
|
||||||
|
parentCategoryId: e.parentCategoryId,
|
||||||
|
dateFrom: e.dateFrom,
|
||||||
|
dateTo: e.dateTo,
|
||||||
|
);
|
||||||
|
|
||||||
|
final newState = result.fold(
|
||||||
|
(f) => state.copyWith(failureOption: optionOf(f)),
|
||||||
|
(detail) => state.copyWith(
|
||||||
|
detail: detail,
|
||||||
|
// Sub kategori pertama langsung terbuka supaya produknya kelihatan.
|
||||||
|
expandedCategoryId: detail.categories.isEmpty
|
||||||
|
? ''
|
||||||
|
: detail.categories.first.categoryId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(newState.copyWith(isFetching: false));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+772
@@ -0,0 +1,772 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'profit_sharing_detail_loader_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ProfitSharingDetailLoaderEvent {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)
|
||||||
|
fetched,
|
||||||
|
required TResult Function(String categoryId) expandedCategoryChanged,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)?
|
||||||
|
fetched,
|
||||||
|
TResult? Function(String categoryId)? expandedCategoryChanged,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)?
|
||||||
|
fetched,
|
||||||
|
TResult Function(String categoryId)? expandedCategoryChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
required TResult Function(_ExpandedCategoryChanged value)
|
||||||
|
expandedCategoryChanged,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
TResult? Function(_ExpandedCategoryChanged value)? expandedCategoryChanged,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
TResult Function(_ExpandedCategoryChanged value)? expandedCategoryChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ProfitSharingDetailLoaderEventCopyWith<$Res> {
|
||||||
|
factory $ProfitSharingDetailLoaderEventCopyWith(
|
||||||
|
ProfitSharingDetailLoaderEvent value,
|
||||||
|
$Res Function(ProfitSharingDetailLoaderEvent) then,
|
||||||
|
) =
|
||||||
|
_$ProfitSharingDetailLoaderEventCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
ProfitSharingDetailLoaderEvent
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ProfitSharingDetailLoaderEventCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
$Val extends ProfitSharingDetailLoaderEvent
|
||||||
|
>
|
||||||
|
implements $ProfitSharingDetailLoaderEventCopyWith<$Res> {
|
||||||
|
_$ProfitSharingDetailLoaderEventCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$FetchedImplCopyWith<$Res> {
|
||||||
|
factory _$$FetchedImplCopyWith(
|
||||||
|
_$FetchedImpl value,
|
||||||
|
$Res Function(_$FetchedImpl) then,
|
||||||
|
) = __$$FetchedImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String parentCategoryId, DateTime dateFrom, DateTime dateTo});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$FetchedImplCopyWithImpl<$Res>
|
||||||
|
extends _$ProfitSharingDetailLoaderEventCopyWithImpl<$Res, _$FetchedImpl>
|
||||||
|
implements _$$FetchedImplCopyWith<$Res> {
|
||||||
|
__$$FetchedImplCopyWithImpl(
|
||||||
|
_$FetchedImpl _value,
|
||||||
|
$Res Function(_$FetchedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? parentCategoryId = null,
|
||||||
|
Object? dateFrom = null,
|
||||||
|
Object? dateTo = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$FetchedImpl(
|
||||||
|
parentCategoryId: null == parentCategoryId
|
||||||
|
? _value.parentCategoryId
|
||||||
|
: parentCategoryId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
dateFrom: null == dateFrom
|
||||||
|
? _value.dateFrom
|
||||||
|
: dateFrom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
dateTo: null == dateTo
|
||||||
|
? _value.dateTo
|
||||||
|
: dateTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$FetchedImpl implements _Fetched {
|
||||||
|
const _$FetchedImpl({
|
||||||
|
required this.parentCategoryId,
|
||||||
|
required this.dateFrom,
|
||||||
|
required this.dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String parentCategoryId;
|
||||||
|
@override
|
||||||
|
final DateTime dateFrom;
|
||||||
|
@override
|
||||||
|
final DateTime dateTo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingDetailLoaderEvent.fetched(parentCategoryId: $parentCategoryId, dateFrom: $dateFrom, dateTo: $dateTo)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$FetchedImpl &&
|
||||||
|
(identical(other.parentCategoryId, parentCategoryId) ||
|
||||||
|
other.parentCategoryId == parentCategoryId) &&
|
||||||
|
(identical(other.dateFrom, dateFrom) ||
|
||||||
|
other.dateFrom == dateFrom) &&
|
||||||
|
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
Object.hash(runtimeType, parentCategoryId, dateFrom, dateTo);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$FetchedImplCopyWith<_$FetchedImpl> get copyWith =>
|
||||||
|
__$$FetchedImplCopyWithImpl<_$FetchedImpl>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)
|
||||||
|
fetched,
|
||||||
|
required TResult Function(String categoryId) expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return fetched(parentCategoryId, dateFrom, dateTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)?
|
||||||
|
fetched,
|
||||||
|
TResult? Function(String categoryId)? expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return fetched?.call(parentCategoryId, dateFrom, dateTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)?
|
||||||
|
fetched,
|
||||||
|
TResult Function(String categoryId)? expandedCategoryChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (fetched != null) {
|
||||||
|
return fetched(parentCategoryId, dateFrom, dateTo);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
required TResult Function(_ExpandedCategoryChanged value)
|
||||||
|
expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return fetched(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
TResult? Function(_ExpandedCategoryChanged value)? expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return fetched?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
TResult Function(_ExpandedCategoryChanged value)? expandedCategoryChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (fetched != null) {
|
||||||
|
return fetched(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _Fetched implements ProfitSharingDetailLoaderEvent {
|
||||||
|
const factory _Fetched({
|
||||||
|
required final String parentCategoryId,
|
||||||
|
required final DateTime dateFrom,
|
||||||
|
required final DateTime dateTo,
|
||||||
|
}) = _$FetchedImpl;
|
||||||
|
|
||||||
|
String get parentCategoryId;
|
||||||
|
DateTime get dateFrom;
|
||||||
|
DateTime get dateTo;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$FetchedImplCopyWith<_$FetchedImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$ExpandedCategoryChangedImplCopyWith<$Res> {
|
||||||
|
factory _$$ExpandedCategoryChangedImplCopyWith(
|
||||||
|
_$ExpandedCategoryChangedImpl value,
|
||||||
|
$Res Function(_$ExpandedCategoryChangedImpl) then,
|
||||||
|
) = __$$ExpandedCategoryChangedImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({String categoryId});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$ExpandedCategoryChangedImplCopyWithImpl<$Res>
|
||||||
|
extends
|
||||||
|
_$ProfitSharingDetailLoaderEventCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
_$ExpandedCategoryChangedImpl
|
||||||
|
>
|
||||||
|
implements _$$ExpandedCategoryChangedImplCopyWith<$Res> {
|
||||||
|
__$$ExpandedCategoryChangedImplCopyWithImpl(
|
||||||
|
_$ExpandedCategoryChangedImpl _value,
|
||||||
|
$Res Function(_$ExpandedCategoryChangedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? categoryId = null}) {
|
||||||
|
return _then(
|
||||||
|
_$ExpandedCategoryChangedImpl(
|
||||||
|
null == categoryId
|
||||||
|
? _value.categoryId
|
||||||
|
: categoryId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$ExpandedCategoryChangedImpl implements _ExpandedCategoryChanged {
|
||||||
|
const _$ExpandedCategoryChangedImpl(this.categoryId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String categoryId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingDetailLoaderEvent.expandedCategoryChanged(categoryId: $categoryId)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$ExpandedCategoryChangedImpl &&
|
||||||
|
(identical(other.categoryId, categoryId) ||
|
||||||
|
other.categoryId == categoryId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, categoryId);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$ExpandedCategoryChangedImplCopyWith<_$ExpandedCategoryChangedImpl>
|
||||||
|
get copyWith =>
|
||||||
|
__$$ExpandedCategoryChangedImplCopyWithImpl<
|
||||||
|
_$ExpandedCategoryChangedImpl
|
||||||
|
>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)
|
||||||
|
fetched,
|
||||||
|
required TResult Function(String categoryId) expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return expandedCategoryChanged(categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)?
|
||||||
|
fetched,
|
||||||
|
TResult? Function(String categoryId)? expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return expandedCategoryChanged?.call(categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(
|
||||||
|
String parentCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
)?
|
||||||
|
fetched,
|
||||||
|
TResult Function(String categoryId)? expandedCategoryChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (expandedCategoryChanged != null) {
|
||||||
|
return expandedCategoryChanged(categoryId);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
required TResult Function(_ExpandedCategoryChanged value)
|
||||||
|
expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return expandedCategoryChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
TResult? Function(_ExpandedCategoryChanged value)? expandedCategoryChanged,
|
||||||
|
}) {
|
||||||
|
return expandedCategoryChanged?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
TResult Function(_ExpandedCategoryChanged value)? expandedCategoryChanged,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (expandedCategoryChanged != null) {
|
||||||
|
return expandedCategoryChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _ExpandedCategoryChanged
|
||||||
|
implements ProfitSharingDetailLoaderEvent {
|
||||||
|
const factory _ExpandedCategoryChanged(final String categoryId) =
|
||||||
|
_$ExpandedCategoryChangedImpl;
|
||||||
|
|
||||||
|
String get categoryId;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$ExpandedCategoryChangedImplCopyWith<_$ExpandedCategoryChangedImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ProfitSharingDetailLoaderState {
|
||||||
|
ProfitSharingDetail get detail => throw _privateConstructorUsedError;
|
||||||
|
Option<AnalyticFailure> get failureOption =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
bool get isFetching => throw _privateConstructorUsedError;
|
||||||
|
String get parentCategoryId => throw _privateConstructorUsedError;
|
||||||
|
String get expandedCategoryId => throw _privateConstructorUsedError;
|
||||||
|
DateTime get dateFrom => throw _privateConstructorUsedError;
|
||||||
|
DateTime get dateTo => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$ProfitSharingDetailLoaderStateCopyWith<ProfitSharingDetailLoaderState>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ProfitSharingDetailLoaderStateCopyWith<$Res> {
|
||||||
|
factory $ProfitSharingDetailLoaderStateCopyWith(
|
||||||
|
ProfitSharingDetailLoaderState value,
|
||||||
|
$Res Function(ProfitSharingDetailLoaderState) then,
|
||||||
|
) =
|
||||||
|
_$ProfitSharingDetailLoaderStateCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
ProfitSharingDetailLoaderState
|
||||||
|
>;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
ProfitSharingDetail detail,
|
||||||
|
Option<AnalyticFailure> failureOption,
|
||||||
|
bool isFetching,
|
||||||
|
String parentCategoryId,
|
||||||
|
String expandedCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
$ProfitSharingDetailCopyWith<$Res> get detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ProfitSharingDetailLoaderStateCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
$Val extends ProfitSharingDetailLoaderState
|
||||||
|
>
|
||||||
|
implements $ProfitSharingDetailLoaderStateCopyWith<$Res> {
|
||||||
|
_$ProfitSharingDetailLoaderStateCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? detail = null,
|
||||||
|
Object? failureOption = null,
|
||||||
|
Object? isFetching = null,
|
||||||
|
Object? parentCategoryId = null,
|
||||||
|
Object? expandedCategoryId = null,
|
||||||
|
Object? dateFrom = null,
|
||||||
|
Object? dateTo = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
detail: null == detail
|
||||||
|
? _value.detail
|
||||||
|
: detail // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharingDetail,
|
||||||
|
failureOption: null == failureOption
|
||||||
|
? _value.failureOption
|
||||||
|
: failureOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<AnalyticFailure>,
|
||||||
|
isFetching: null == isFetching
|
||||||
|
? _value.isFetching
|
||||||
|
: isFetching // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
parentCategoryId: null == parentCategoryId
|
||||||
|
? _value.parentCategoryId
|
||||||
|
: parentCategoryId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
expandedCategoryId: null == expandedCategoryId
|
||||||
|
? _value.expandedCategoryId
|
||||||
|
: expandedCategoryId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
dateFrom: null == dateFrom
|
||||||
|
? _value.dateFrom
|
||||||
|
: dateFrom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
dateTo: null == dateTo
|
||||||
|
? _value.dateTo
|
||||||
|
: dateTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ProfitSharingDetailCopyWith<$Res> get detail {
|
||||||
|
return $ProfitSharingDetailCopyWith<$Res>(_value.detail, (value) {
|
||||||
|
return _then(_value.copyWith(detail: value) as $Val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$ProfitSharingDetailLoaderStateImplCopyWith<$Res>
|
||||||
|
implements $ProfitSharingDetailLoaderStateCopyWith<$Res> {
|
||||||
|
factory _$$ProfitSharingDetailLoaderStateImplCopyWith(
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl value,
|
||||||
|
$Res Function(_$ProfitSharingDetailLoaderStateImpl) then,
|
||||||
|
) = __$$ProfitSharingDetailLoaderStateImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
ProfitSharingDetail detail,
|
||||||
|
Option<AnalyticFailure> failureOption,
|
||||||
|
bool isFetching,
|
||||||
|
String parentCategoryId,
|
||||||
|
String expandedCategoryId,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$ProfitSharingDetailCopyWith<$Res> get detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$ProfitSharingDetailLoaderStateImplCopyWithImpl<$Res>
|
||||||
|
extends
|
||||||
|
_$ProfitSharingDetailLoaderStateCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl
|
||||||
|
>
|
||||||
|
implements _$$ProfitSharingDetailLoaderStateImplCopyWith<$Res> {
|
||||||
|
__$$ProfitSharingDetailLoaderStateImplCopyWithImpl(
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl _value,
|
||||||
|
$Res Function(_$ProfitSharingDetailLoaderStateImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? detail = null,
|
||||||
|
Object? failureOption = null,
|
||||||
|
Object? isFetching = null,
|
||||||
|
Object? parentCategoryId = null,
|
||||||
|
Object? expandedCategoryId = null,
|
||||||
|
Object? dateFrom = null,
|
||||||
|
Object? dateTo = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl(
|
||||||
|
detail: null == detail
|
||||||
|
? _value.detail
|
||||||
|
: detail // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharingDetail,
|
||||||
|
failureOption: null == failureOption
|
||||||
|
? _value.failureOption
|
||||||
|
: failureOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<AnalyticFailure>,
|
||||||
|
isFetching: null == isFetching
|
||||||
|
? _value.isFetching
|
||||||
|
: isFetching // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
parentCategoryId: null == parentCategoryId
|
||||||
|
? _value.parentCategoryId
|
||||||
|
: parentCategoryId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
expandedCategoryId: null == expandedCategoryId
|
||||||
|
? _value.expandedCategoryId
|
||||||
|
: expandedCategoryId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
dateFrom: null == dateFrom
|
||||||
|
? _value.dateFrom
|
||||||
|
: dateFrom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
dateTo: null == dateTo
|
||||||
|
? _value.dateTo
|
||||||
|
: dateTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$ProfitSharingDetailLoaderStateImpl
|
||||||
|
extends _ProfitSharingDetailLoaderState {
|
||||||
|
const _$ProfitSharingDetailLoaderStateImpl({
|
||||||
|
required this.detail,
|
||||||
|
required this.failureOption,
|
||||||
|
this.isFetching = false,
|
||||||
|
this.parentCategoryId = '',
|
||||||
|
this.expandedCategoryId = '',
|
||||||
|
required this.dateFrom,
|
||||||
|
required this.dateTo,
|
||||||
|
}) : super._();
|
||||||
|
|
||||||
|
@override
|
||||||
|
final ProfitSharingDetail detail;
|
||||||
|
@override
|
||||||
|
final Option<AnalyticFailure> failureOption;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final bool isFetching;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final String parentCategoryId;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final String expandedCategoryId;
|
||||||
|
@override
|
||||||
|
final DateTime dateFrom;
|
||||||
|
@override
|
||||||
|
final DateTime dateTo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingDetailLoaderState(detail: $detail, failureOption: $failureOption, isFetching: $isFetching, parentCategoryId: $parentCategoryId, expandedCategoryId: $expandedCategoryId, dateFrom: $dateFrom, dateTo: $dateTo)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$ProfitSharingDetailLoaderStateImpl &&
|
||||||
|
(identical(other.detail, detail) || other.detail == detail) &&
|
||||||
|
(identical(other.failureOption, failureOption) ||
|
||||||
|
other.failureOption == failureOption) &&
|
||||||
|
(identical(other.isFetching, isFetching) ||
|
||||||
|
other.isFetching == isFetching) &&
|
||||||
|
(identical(other.parentCategoryId, parentCategoryId) ||
|
||||||
|
other.parentCategoryId == parentCategoryId) &&
|
||||||
|
(identical(other.expandedCategoryId, expandedCategoryId) ||
|
||||||
|
other.expandedCategoryId == expandedCategoryId) &&
|
||||||
|
(identical(other.dateFrom, dateFrom) ||
|
||||||
|
other.dateFrom == dateFrom) &&
|
||||||
|
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
detail,
|
||||||
|
failureOption,
|
||||||
|
isFetching,
|
||||||
|
parentCategoryId,
|
||||||
|
expandedCategoryId,
|
||||||
|
dateFrom,
|
||||||
|
dateTo,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$ProfitSharingDetailLoaderStateImplCopyWith<
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl
|
||||||
|
>
|
||||||
|
get copyWith =>
|
||||||
|
__$$ProfitSharingDetailLoaderStateImplCopyWithImpl<
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl
|
||||||
|
>(this, _$identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _ProfitSharingDetailLoaderState
|
||||||
|
extends ProfitSharingDetailLoaderState {
|
||||||
|
const factory _ProfitSharingDetailLoaderState({
|
||||||
|
required final ProfitSharingDetail detail,
|
||||||
|
required final Option<AnalyticFailure> failureOption,
|
||||||
|
final bool isFetching,
|
||||||
|
final String parentCategoryId,
|
||||||
|
final String expandedCategoryId,
|
||||||
|
required final DateTime dateFrom,
|
||||||
|
required final DateTime dateTo,
|
||||||
|
}) = _$ProfitSharingDetailLoaderStateImpl;
|
||||||
|
const _ProfitSharingDetailLoaderState._() : super._();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ProfitSharingDetail get detail;
|
||||||
|
@override
|
||||||
|
Option<AnalyticFailure> get failureOption;
|
||||||
|
@override
|
||||||
|
bool get isFetching;
|
||||||
|
@override
|
||||||
|
String get parentCategoryId;
|
||||||
|
@override
|
||||||
|
String get expandedCategoryId;
|
||||||
|
@override
|
||||||
|
DateTime get dateFrom;
|
||||||
|
@override
|
||||||
|
DateTime get dateTo;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingDetailLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$ProfitSharingDetailLoaderStateImplCopyWith<
|
||||||
|
_$ProfitSharingDetailLoaderStateImpl
|
||||||
|
>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
part of 'profit_sharing_detail_loader_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingDetailLoaderEvent with _$ProfitSharingDetailLoaderEvent {
|
||||||
|
const factory ProfitSharingDetailLoaderEvent.fetched({
|
||||||
|
required String parentCategoryId,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
}) = _Fetched;
|
||||||
|
|
||||||
|
/// Buka/tutup daftar produk pada satu sub kategori.
|
||||||
|
const factory ProfitSharingDetailLoaderEvent.expandedCategoryChanged(
|
||||||
|
String categoryId,
|
||||||
|
) = _ExpandedCategoryChanged;
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
part of 'profit_sharing_detail_loader_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingDetailLoaderState with _$ProfitSharingDetailLoaderState {
|
||||||
|
const ProfitSharingDetailLoaderState._();
|
||||||
|
|
||||||
|
const factory ProfitSharingDetailLoaderState({
|
||||||
|
required ProfitSharingDetail detail,
|
||||||
|
required Option<AnalyticFailure> failureOption,
|
||||||
|
@Default(false) bool isFetching,
|
||||||
|
@Default('') String parentCategoryId,
|
||||||
|
@Default('') String expandedCategoryId,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
}) = _ProfitSharingDetailLoaderState;
|
||||||
|
|
||||||
|
factory ProfitSharingDetailLoaderState.initial() {
|
||||||
|
final now = DateTime.now();
|
||||||
|
return ProfitSharingDetailLoaderState(
|
||||||
|
detail: ProfitSharingDetail.empty(),
|
||||||
|
failureOption: none(),
|
||||||
|
dateFrom: DateTime(now.year, now.month, 1),
|
||||||
|
dateTo: DateTime(now.year, now.month + 1, 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isExpanded(String categoryId) => expandedCategoryId == categoryId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
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/analytic/analytic.dart';
|
||||||
|
import '../../../domain/analytic/repositories/i_analytic_repository.dart';
|
||||||
|
|
||||||
|
part 'profit_sharing_loader_event.dart';
|
||||||
|
part 'profit_sharing_loader_state.dart';
|
||||||
|
part 'profit_sharing_loader_bloc.freezed.dart';
|
||||||
|
|
||||||
|
@injectable
|
||||||
|
class ProfitSharingLoaderBloc
|
||||||
|
extends Bloc<ProfitSharingLoaderEvent, ProfitSharingLoaderState> {
|
||||||
|
final IAnalyticRepository _repository;
|
||||||
|
|
||||||
|
ProfitSharingLoaderBloc(this._repository)
|
||||||
|
: super(ProfitSharingLoaderState.initial()) {
|
||||||
|
on<ProfitSharingLoaderEvent>(_onProfitSharingLoaderEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onProfitSharingLoaderEvent(
|
||||||
|
ProfitSharingLoaderEvent event,
|
||||||
|
Emitter<ProfitSharingLoaderState> emit,
|
||||||
|
) {
|
||||||
|
return event.map(
|
||||||
|
rangeDateChanged: (e) async {
|
||||||
|
emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo));
|
||||||
|
},
|
||||||
|
periodTypeChanged: (e) async {
|
||||||
|
emit(state.copyWith(periodType: e.periodType));
|
||||||
|
},
|
||||||
|
fetched: (e) async {
|
||||||
|
emit(state.copyWith(isFetching: true, failureOption: none()));
|
||||||
|
|
||||||
|
final result = await _repository.getProfitSharing(
|
||||||
|
dateFrom: state.dateFrom,
|
||||||
|
dateTo: state.dateTo,
|
||||||
|
);
|
||||||
|
|
||||||
|
final newState = result.fold(
|
||||||
|
(f) => state.copyWith(failureOption: optionOf(f)),
|
||||||
|
(profitSharing) => state.copyWith(profitSharing: profitSharing),
|
||||||
|
);
|
||||||
|
|
||||||
|
emit(newState.copyWith(isFetching: false));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+807
@@ -0,0 +1,807 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'profit_sharing_loader_bloc.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ProfitSharingLoaderEvent {
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(DateTime dateFrom, DateTime dateTo)
|
||||||
|
rangeDateChanged,
|
||||||
|
required TResult Function(ProfitSharingPeriodType periodType)
|
||||||
|
periodTypeChanged,
|
||||||
|
required TResult Function() fetched,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult? Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult? Function()? fetched,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult Function()? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_RangeDateChanged value) rangeDateChanged,
|
||||||
|
required TResult Function(_PeriodTypeChanged value) periodTypeChanged,
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult? Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ProfitSharingLoaderEventCopyWith<$Res> {
|
||||||
|
factory $ProfitSharingLoaderEventCopyWith(
|
||||||
|
ProfitSharingLoaderEvent value,
|
||||||
|
$Res Function(ProfitSharingLoaderEvent) then,
|
||||||
|
) = _$ProfitSharingLoaderEventCopyWithImpl<$Res, ProfitSharingLoaderEvent>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ProfitSharingLoaderEventCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
$Val extends ProfitSharingLoaderEvent
|
||||||
|
>
|
||||||
|
implements $ProfitSharingLoaderEventCopyWith<$Res> {
|
||||||
|
_$ProfitSharingLoaderEventCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$RangeDateChangedImplCopyWith<$Res> {
|
||||||
|
factory _$$RangeDateChangedImplCopyWith(
|
||||||
|
_$RangeDateChangedImpl value,
|
||||||
|
$Res Function(_$RangeDateChangedImpl) then,
|
||||||
|
) = __$$RangeDateChangedImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({DateTime dateFrom, DateTime dateTo});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$RangeDateChangedImplCopyWithImpl<$Res>
|
||||||
|
extends _$ProfitSharingLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl>
|
||||||
|
implements _$$RangeDateChangedImplCopyWith<$Res> {
|
||||||
|
__$$RangeDateChangedImplCopyWithImpl(
|
||||||
|
_$RangeDateChangedImpl _value,
|
||||||
|
$Res Function(_$RangeDateChangedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? dateFrom = null, Object? dateTo = null}) {
|
||||||
|
return _then(
|
||||||
|
_$RangeDateChangedImpl(
|
||||||
|
null == dateFrom
|
||||||
|
? _value.dateFrom
|
||||||
|
: dateFrom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
null == dateTo
|
||||||
|
? _value.dateTo
|
||||||
|
: dateTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$RangeDateChangedImpl implements _RangeDateChanged {
|
||||||
|
const _$RangeDateChangedImpl(this.dateFrom, this.dateTo);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final DateTime dateFrom;
|
||||||
|
@override
|
||||||
|
final DateTime dateTo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingLoaderEvent.rangeDateChanged(dateFrom: $dateFrom, dateTo: $dateTo)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$RangeDateChangedImpl &&
|
||||||
|
(identical(other.dateFrom, dateFrom) ||
|
||||||
|
other.dateFrom == dateFrom) &&
|
||||||
|
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, dateFrom, dateTo);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
|
||||||
|
__$$RangeDateChangedImplCopyWithImpl<_$RangeDateChangedImpl>(
|
||||||
|
this,
|
||||||
|
_$identity,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(DateTime dateFrom, DateTime dateTo)
|
||||||
|
rangeDateChanged,
|
||||||
|
required TResult Function(ProfitSharingPeriodType periodType)
|
||||||
|
periodTypeChanged,
|
||||||
|
required TResult Function() fetched,
|
||||||
|
}) {
|
||||||
|
return rangeDateChanged(dateFrom, dateTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult? Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult? Function()? fetched,
|
||||||
|
}) {
|
||||||
|
return rangeDateChanged?.call(dateFrom, dateTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult Function()? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (rangeDateChanged != null) {
|
||||||
|
return rangeDateChanged(dateFrom, dateTo);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_RangeDateChanged value) rangeDateChanged,
|
||||||
|
required TResult Function(_PeriodTypeChanged value) periodTypeChanged,
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
}) {
|
||||||
|
return rangeDateChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult? Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
}) {
|
||||||
|
return rangeDateChanged?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (rangeDateChanged != null) {
|
||||||
|
return rangeDateChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _RangeDateChanged implements ProfitSharingLoaderEvent {
|
||||||
|
const factory _RangeDateChanged(
|
||||||
|
final DateTime dateFrom,
|
||||||
|
final DateTime dateTo,
|
||||||
|
) = _$RangeDateChangedImpl;
|
||||||
|
|
||||||
|
DateTime get dateFrom;
|
||||||
|
DateTime get dateTo;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$RangeDateChangedImplCopyWith<_$RangeDateChangedImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$PeriodTypeChangedImplCopyWith<$Res> {
|
||||||
|
factory _$$PeriodTypeChangedImplCopyWith(
|
||||||
|
_$PeriodTypeChangedImpl value,
|
||||||
|
$Res Function(_$PeriodTypeChangedImpl) then,
|
||||||
|
) = __$$PeriodTypeChangedImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({ProfitSharingPeriodType periodType});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$PeriodTypeChangedImplCopyWithImpl<$Res>
|
||||||
|
extends
|
||||||
|
_$ProfitSharingLoaderEventCopyWithImpl<$Res, _$PeriodTypeChangedImpl>
|
||||||
|
implements _$$PeriodTypeChangedImplCopyWith<$Res> {
|
||||||
|
__$$PeriodTypeChangedImplCopyWithImpl(
|
||||||
|
_$PeriodTypeChangedImpl _value,
|
||||||
|
$Res Function(_$PeriodTypeChangedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? periodType = null}) {
|
||||||
|
return _then(
|
||||||
|
_$PeriodTypeChangedImpl(
|
||||||
|
null == periodType
|
||||||
|
? _value.periodType
|
||||||
|
: periodType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharingPeriodType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$PeriodTypeChangedImpl implements _PeriodTypeChanged {
|
||||||
|
const _$PeriodTypeChangedImpl(this.periodType);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final ProfitSharingPeriodType periodType;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingLoaderEvent.periodTypeChanged(periodType: $periodType)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$PeriodTypeChangedImpl &&
|
||||||
|
(identical(other.periodType, periodType) ||
|
||||||
|
other.periodType == periodType));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType, periodType);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$PeriodTypeChangedImplCopyWith<_$PeriodTypeChangedImpl> get copyWith =>
|
||||||
|
__$$PeriodTypeChangedImplCopyWithImpl<_$PeriodTypeChangedImpl>(
|
||||||
|
this,
|
||||||
|
_$identity,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(DateTime dateFrom, DateTime dateTo)
|
||||||
|
rangeDateChanged,
|
||||||
|
required TResult Function(ProfitSharingPeriodType periodType)
|
||||||
|
periodTypeChanged,
|
||||||
|
required TResult Function() fetched,
|
||||||
|
}) {
|
||||||
|
return periodTypeChanged(periodType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult? Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult? Function()? fetched,
|
||||||
|
}) {
|
||||||
|
return periodTypeChanged?.call(periodType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult Function()? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (periodTypeChanged != null) {
|
||||||
|
return periodTypeChanged(periodType);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_RangeDateChanged value) rangeDateChanged,
|
||||||
|
required TResult Function(_PeriodTypeChanged value) periodTypeChanged,
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
}) {
|
||||||
|
return periodTypeChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult? Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
}) {
|
||||||
|
return periodTypeChanged?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (periodTypeChanged != null) {
|
||||||
|
return periodTypeChanged(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _PeriodTypeChanged implements ProfitSharingLoaderEvent {
|
||||||
|
const factory _PeriodTypeChanged(final ProfitSharingPeriodType periodType) =
|
||||||
|
_$PeriodTypeChangedImpl;
|
||||||
|
|
||||||
|
ProfitSharingPeriodType get periodType;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$PeriodTypeChangedImplCopyWith<_$PeriodTypeChangedImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$FetchedImplCopyWith<$Res> {
|
||||||
|
factory _$$FetchedImplCopyWith(
|
||||||
|
_$FetchedImpl value,
|
||||||
|
$Res Function(_$FetchedImpl) then,
|
||||||
|
) = __$$FetchedImplCopyWithImpl<$Res>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$FetchedImplCopyWithImpl<$Res>
|
||||||
|
extends _$ProfitSharingLoaderEventCopyWithImpl<$Res, _$FetchedImpl>
|
||||||
|
implements _$$FetchedImplCopyWith<$Res> {
|
||||||
|
__$$FetchedImplCopyWithImpl(
|
||||||
|
_$FetchedImpl _value,
|
||||||
|
$Res Function(_$FetchedImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderEvent
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$FetchedImpl implements _Fetched {
|
||||||
|
const _$FetchedImpl();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingLoaderEvent.fetched()';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType && other is _$FetchedImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult when<TResult extends Object?>({
|
||||||
|
required TResult Function(DateTime dateFrom, DateTime dateTo)
|
||||||
|
rangeDateChanged,
|
||||||
|
required TResult Function(ProfitSharingPeriodType periodType)
|
||||||
|
periodTypeChanged,
|
||||||
|
required TResult Function() fetched,
|
||||||
|
}) {
|
||||||
|
return fetched();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult? Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult? Function()? fetched,
|
||||||
|
}) {
|
||||||
|
return fetched?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
|
TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged,
|
||||||
|
TResult Function(ProfitSharingPeriodType periodType)? periodTypeChanged,
|
||||||
|
TResult Function()? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (fetched != null) {
|
||||||
|
return fetched();
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult map<TResult extends Object?>({
|
||||||
|
required TResult Function(_RangeDateChanged value) rangeDateChanged,
|
||||||
|
required TResult Function(_PeriodTypeChanged value) periodTypeChanged,
|
||||||
|
required TResult Function(_Fetched value) fetched,
|
||||||
|
}) {
|
||||||
|
return fetched(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult? mapOrNull<TResult extends Object?>({
|
||||||
|
TResult? Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult? Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult? Function(_Fetched value)? fetched,
|
||||||
|
}) {
|
||||||
|
return fetched?.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@optionalTypeArgs
|
||||||
|
TResult maybeMap<TResult extends Object?>({
|
||||||
|
TResult Function(_RangeDateChanged value)? rangeDateChanged,
|
||||||
|
TResult Function(_PeriodTypeChanged value)? periodTypeChanged,
|
||||||
|
TResult Function(_Fetched value)? fetched,
|
||||||
|
required TResult orElse(),
|
||||||
|
}) {
|
||||||
|
if (fetched != null) {
|
||||||
|
return fetched(this);
|
||||||
|
}
|
||||||
|
return orElse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _Fetched implements ProfitSharingLoaderEvent {
|
||||||
|
const factory _Fetched() = _$FetchedImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ProfitSharingLoaderState {
|
||||||
|
ProfitSharing get profitSharing => throw _privateConstructorUsedError;
|
||||||
|
Option<AnalyticFailure> get failureOption =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
bool get isFetching => throw _privateConstructorUsedError;
|
||||||
|
ProfitSharingPeriodType get periodType => throw _privateConstructorUsedError;
|
||||||
|
DateTime get dateFrom => throw _privateConstructorUsedError;
|
||||||
|
DateTime get dateTo => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$ProfitSharingLoaderStateCopyWith<ProfitSharingLoaderState> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $ProfitSharingLoaderStateCopyWith<$Res> {
|
||||||
|
factory $ProfitSharingLoaderStateCopyWith(
|
||||||
|
ProfitSharingLoaderState value,
|
||||||
|
$Res Function(ProfitSharingLoaderState) then,
|
||||||
|
) = _$ProfitSharingLoaderStateCopyWithImpl<$Res, ProfitSharingLoaderState>;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
ProfitSharing profitSharing,
|
||||||
|
Option<AnalyticFailure> failureOption,
|
||||||
|
bool isFetching,
|
||||||
|
ProfitSharingPeriodType periodType,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
$ProfitSharingCopyWith<$Res> get profitSharing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$ProfitSharingLoaderStateCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
$Val extends ProfitSharingLoaderState
|
||||||
|
>
|
||||||
|
implements $ProfitSharingLoaderStateCopyWith<$Res> {
|
||||||
|
_$ProfitSharingLoaderStateCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? profitSharing = null,
|
||||||
|
Object? failureOption = null,
|
||||||
|
Object? isFetching = null,
|
||||||
|
Object? periodType = null,
|
||||||
|
Object? dateFrom = null,
|
||||||
|
Object? dateTo = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
profitSharing: null == profitSharing
|
||||||
|
? _value.profitSharing
|
||||||
|
: profitSharing // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharing,
|
||||||
|
failureOption: null == failureOption
|
||||||
|
? _value.failureOption
|
||||||
|
: failureOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<AnalyticFailure>,
|
||||||
|
isFetching: null == isFetching
|
||||||
|
? _value.isFetching
|
||||||
|
: isFetching // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
periodType: null == periodType
|
||||||
|
? _value.periodType
|
||||||
|
: periodType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharingPeriodType,
|
||||||
|
dateFrom: null == dateFrom
|
||||||
|
? _value.dateFrom
|
||||||
|
: dateFrom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
dateTo: null == dateTo
|
||||||
|
? _value.dateTo
|
||||||
|
: dateTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ProfitSharingCopyWith<$Res> get profitSharing {
|
||||||
|
return $ProfitSharingCopyWith<$Res>(_value.profitSharing, (value) {
|
||||||
|
return _then(_value.copyWith(profitSharing: value) as $Val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$ProfitSharingLoaderStateImplCopyWith<$Res>
|
||||||
|
implements $ProfitSharingLoaderStateCopyWith<$Res> {
|
||||||
|
factory _$$ProfitSharingLoaderStateImplCopyWith(
|
||||||
|
_$ProfitSharingLoaderStateImpl value,
|
||||||
|
$Res Function(_$ProfitSharingLoaderStateImpl) then,
|
||||||
|
) = __$$ProfitSharingLoaderStateImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
ProfitSharing profitSharing,
|
||||||
|
Option<AnalyticFailure> failureOption,
|
||||||
|
bool isFetching,
|
||||||
|
ProfitSharingPeriodType periodType,
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$ProfitSharingCopyWith<$Res> get profitSharing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$ProfitSharingLoaderStateImplCopyWithImpl<$Res>
|
||||||
|
extends
|
||||||
|
_$ProfitSharingLoaderStateCopyWithImpl<
|
||||||
|
$Res,
|
||||||
|
_$ProfitSharingLoaderStateImpl
|
||||||
|
>
|
||||||
|
implements _$$ProfitSharingLoaderStateImplCopyWith<$Res> {
|
||||||
|
__$$ProfitSharingLoaderStateImplCopyWithImpl(
|
||||||
|
_$ProfitSharingLoaderStateImpl _value,
|
||||||
|
$Res Function(_$ProfitSharingLoaderStateImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? profitSharing = null,
|
||||||
|
Object? failureOption = null,
|
||||||
|
Object? isFetching = null,
|
||||||
|
Object? periodType = null,
|
||||||
|
Object? dateFrom = null,
|
||||||
|
Object? dateTo = null,
|
||||||
|
}) {
|
||||||
|
return _then(
|
||||||
|
_$ProfitSharingLoaderStateImpl(
|
||||||
|
profitSharing: null == profitSharing
|
||||||
|
? _value.profitSharing
|
||||||
|
: profitSharing // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharing,
|
||||||
|
failureOption: null == failureOption
|
||||||
|
? _value.failureOption
|
||||||
|
: failureOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Option<AnalyticFailure>,
|
||||||
|
isFetching: null == isFetching
|
||||||
|
? _value.isFetching
|
||||||
|
: isFetching // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
periodType: null == periodType
|
||||||
|
? _value.periodType
|
||||||
|
: periodType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProfitSharingPeriodType,
|
||||||
|
dateFrom: null == dateFrom
|
||||||
|
? _value.dateFrom
|
||||||
|
: dateFrom // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
dateTo: null == dateTo
|
||||||
|
? _value.dateTo
|
||||||
|
: dateTo // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$ProfitSharingLoaderStateImpl extends _ProfitSharingLoaderState {
|
||||||
|
const _$ProfitSharingLoaderStateImpl({
|
||||||
|
required this.profitSharing,
|
||||||
|
required this.failureOption,
|
||||||
|
this.isFetching = false,
|
||||||
|
this.periodType = ProfitSharingPeriodType.weekly,
|
||||||
|
required this.dateFrom,
|
||||||
|
required this.dateTo,
|
||||||
|
}) : super._();
|
||||||
|
|
||||||
|
@override
|
||||||
|
final ProfitSharing profitSharing;
|
||||||
|
@override
|
||||||
|
final Option<AnalyticFailure> failureOption;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final bool isFetching;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final ProfitSharingPeriodType periodType;
|
||||||
|
@override
|
||||||
|
final DateTime dateFrom;
|
||||||
|
@override
|
||||||
|
final DateTime dateTo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingLoaderState(profitSharing: $profitSharing, failureOption: $failureOption, isFetching: $isFetching, periodType: $periodType, dateFrom: $dateFrom, dateTo: $dateTo)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$ProfitSharingLoaderStateImpl &&
|
||||||
|
(identical(other.profitSharing, profitSharing) ||
|
||||||
|
other.profitSharing == profitSharing) &&
|
||||||
|
(identical(other.failureOption, failureOption) ||
|
||||||
|
other.failureOption == failureOption) &&
|
||||||
|
(identical(other.isFetching, isFetching) ||
|
||||||
|
other.isFetching == isFetching) &&
|
||||||
|
(identical(other.periodType, periodType) ||
|
||||||
|
other.periodType == periodType) &&
|
||||||
|
(identical(other.dateFrom, dateFrom) ||
|
||||||
|
other.dateFrom == dateFrom) &&
|
||||||
|
(identical(other.dateTo, dateTo) || other.dateTo == dateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
profitSharing,
|
||||||
|
failureOption,
|
||||||
|
isFetching,
|
||||||
|
periodType,
|
||||||
|
dateFrom,
|
||||||
|
dateTo,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$ProfitSharingLoaderStateImplCopyWith<_$ProfitSharingLoaderStateImpl>
|
||||||
|
get copyWith =>
|
||||||
|
__$$ProfitSharingLoaderStateImplCopyWithImpl<
|
||||||
|
_$ProfitSharingLoaderStateImpl
|
||||||
|
>(this, _$identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _ProfitSharingLoaderState extends ProfitSharingLoaderState {
|
||||||
|
const factory _ProfitSharingLoaderState({
|
||||||
|
required final ProfitSharing profitSharing,
|
||||||
|
required final Option<AnalyticFailure> failureOption,
|
||||||
|
final bool isFetching,
|
||||||
|
final ProfitSharingPeriodType periodType,
|
||||||
|
required final DateTime dateFrom,
|
||||||
|
required final DateTime dateTo,
|
||||||
|
}) = _$ProfitSharingLoaderStateImpl;
|
||||||
|
const _ProfitSharingLoaderState._() : super._();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ProfitSharing get profitSharing;
|
||||||
|
@override
|
||||||
|
Option<AnalyticFailure> get failureOption;
|
||||||
|
@override
|
||||||
|
bool get isFetching;
|
||||||
|
@override
|
||||||
|
ProfitSharingPeriodType get periodType;
|
||||||
|
@override
|
||||||
|
DateTime get dateFrom;
|
||||||
|
@override
|
||||||
|
DateTime get dateTo;
|
||||||
|
|
||||||
|
/// Create a copy of ProfitSharingLoaderState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$ProfitSharingLoaderStateImplCopyWith<_$ProfitSharingLoaderStateImpl>
|
||||||
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
part of 'profit_sharing_loader_bloc.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingLoaderEvent with _$ProfitSharingLoaderEvent {
|
||||||
|
const factory ProfitSharingLoaderEvent.rangeDateChanged(
|
||||||
|
DateTime dateFrom,
|
||||||
|
DateTime dateTo,
|
||||||
|
) = _RangeDateChanged;
|
||||||
|
const factory ProfitSharingLoaderEvent.periodTypeChanged(
|
||||||
|
ProfitSharingPeriodType periodType,
|
||||||
|
) = _PeriodTypeChanged;
|
||||||
|
const factory ProfitSharingLoaderEvent.fetched() = _Fetched;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
part of 'profit_sharing_loader_bloc.dart';
|
||||||
|
|
||||||
|
/// Tampilan rincian bagi hasil: per minggu atau per bulan.
|
||||||
|
enum ProfitSharingPeriodType { weekly, monthly }
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingLoaderState with _$ProfitSharingLoaderState {
|
||||||
|
const ProfitSharingLoaderState._();
|
||||||
|
|
||||||
|
const factory ProfitSharingLoaderState({
|
||||||
|
required ProfitSharing profitSharing,
|
||||||
|
required Option<AnalyticFailure> failureOption,
|
||||||
|
@Default(false) bool isFetching,
|
||||||
|
@Default(ProfitSharingPeriodType.weekly) ProfitSharingPeriodType periodType,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
}) = _ProfitSharingLoaderState;
|
||||||
|
|
||||||
|
factory ProfitSharingLoaderState.initial() {
|
||||||
|
final now = DateTime.now();
|
||||||
|
return ProfitSharingLoaderState(
|
||||||
|
profitSharing: ProfitSharing.empty(),
|
||||||
|
failureOption: none(),
|
||||||
|
dateFrom: DateTime(now.year, now.month, 1),
|
||||||
|
dateTo: DateTime(now.year, now.month + 1, 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Baris periode sesuai tab yang dipilih, periode kosong disembunyikan.
|
||||||
|
List<ProfitSharingPeriod> get periods {
|
||||||
|
final budget = profitSharing.budget;
|
||||||
|
final list = periodType == ProfitSharingPeriodType.weekly
|
||||||
|
? budget.weekly
|
||||||
|
: budget.monthly;
|
||||||
|
return list.where((e) => e.hasRevenue).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,4 +6,7 @@ extension IntegerExt on int {
|
|||||||
symbol: 'Rp. ',
|
symbol: 'Rp. ',
|
||||||
decimalDigits: 0,
|
decimalDigits: 0,
|
||||||
).format(this);
|
).format(this);
|
||||||
|
|
||||||
|
/// Format ribuan tanpa simbol mata uang, contoh: 1.639
|
||||||
|
String get thousandFormat => NumberFormat.decimalPattern('id').format(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class ApiPath {
|
|||||||
static const String purchasingAnalytic = '/api/v1/analytics/purchasing';
|
static const String purchasingAnalytic = '/api/v1/analytics/purchasing';
|
||||||
static const String exclusiveSummaryAnalytic =
|
static const String exclusiveSummaryAnalytic =
|
||||||
'/api/v1/analytics/exclusive-summary/period';
|
'/api/v1/analytics/exclusive-summary/period';
|
||||||
|
static const String parentCategoryAnalytic =
|
||||||
|
'/api/v1/analytics/parent-categories';
|
||||||
|
|
||||||
// Inventory
|
// Inventory
|
||||||
static const String inventoryReportDetail =
|
static const String inventoryReportDetail =
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ part 'entities/product_analytic_entity.dart';
|
|||||||
part 'entities/payment_method_analytic_entity.dart';
|
part 'entities/payment_method_analytic_entity.dart';
|
||||||
part 'entities/purchasing_analytic_entity.dart';
|
part 'entities/purchasing_analytic_entity.dart';
|
||||||
part 'entities/exclusive_summary_entity.dart';
|
part 'entities/exclusive_summary_entity.dart';
|
||||||
|
part 'entities/profit_sharing_entity.dart';
|
||||||
part 'failures/analytic_failure.dart';
|
part 'failures/analytic_failure.dart';
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
|||||||
|
part of '../analytic.dart';
|
||||||
|
|
||||||
|
/// Bagi hasil (profit sharing) berdasarkan omzet per parent category.
|
||||||
|
@freezed
|
||||||
|
class ProfitSharing with _$ProfitSharing {
|
||||||
|
const factory ProfitSharing({
|
||||||
|
required String organizationId,
|
||||||
|
required String outletId,
|
||||||
|
required String outletName,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
required List<ProfitSharingCategory> categories,
|
||||||
|
required ProfitSharingBudget budget,
|
||||||
|
}) = _ProfitSharing;
|
||||||
|
|
||||||
|
factory ProfitSharing.empty() => ProfitSharing(
|
||||||
|
organizationId: '',
|
||||||
|
outletId: '',
|
||||||
|
outletName: '',
|
||||||
|
dateFrom: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
dateTo: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
categories: [],
|
||||||
|
budget: ProfitSharingBudget.empty(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingCategory with _$ProfitSharingCategory {
|
||||||
|
const ProfitSharingCategory._();
|
||||||
|
|
||||||
|
const factory ProfitSharingCategory({
|
||||||
|
required String parentCategoryId,
|
||||||
|
required String parentCategoryName,
|
||||||
|
required int totalRevenue,
|
||||||
|
required int totalQuantity,
|
||||||
|
required int categoryCount,
|
||||||
|
required int productCount,
|
||||||
|
required int orderCount,
|
||||||
|
required int totalStandardHpp,
|
||||||
|
required int totalFifoHpp,
|
||||||
|
required int totalMovingAverageHpp,
|
||||||
|
}) = _ProfitSharingCategory;
|
||||||
|
|
||||||
|
factory ProfitSharingCategory.empty() => const ProfitSharingCategory(
|
||||||
|
parentCategoryId: '',
|
||||||
|
parentCategoryName: '',
|
||||||
|
totalRevenue: 0,
|
||||||
|
totalQuantity: 0,
|
||||||
|
categoryCount: 0,
|
||||||
|
productCount: 0,
|
||||||
|
orderCount: 0,
|
||||||
|
totalStandardHpp: 0,
|
||||||
|
totalFifoHpp: 0,
|
||||||
|
totalMovingAverageHpp: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Laba kotor memakai HPP standar (acuan yang dipakai di laporan laba rugi).
|
||||||
|
int get grossProfit => totalRevenue - totalStandardHpp;
|
||||||
|
|
||||||
|
double get grossMargin =>
|
||||||
|
totalRevenue == 0 ? 0 : (grossProfit / totalRevenue) * 100;
|
||||||
|
|
||||||
|
/// % HPP standar terhadap omzet.
|
||||||
|
double get standardHppPercentage =>
|
||||||
|
totalRevenue == 0 ? 0 : (totalStandardHpp / totalRevenue) * 100;
|
||||||
|
|
||||||
|
/// % HPP riil (FIFO) terhadap omzet — dipakai untuk status kesehatan margin.
|
||||||
|
double get realHppPercentage =>
|
||||||
|
totalRevenue == 0 ? 0 : (totalFifoHpp / totalRevenue) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingBudget with _$ProfitSharingBudget {
|
||||||
|
const factory ProfitSharingBudget({
|
||||||
|
required ProfitSharingPercentage percentages,
|
||||||
|
required DateTime cutOffFrom,
|
||||||
|
required DateTime cutOffTo,
|
||||||
|
required ProfitSharingPeriod total,
|
||||||
|
required List<ProfitSharingPeriod> weekly,
|
||||||
|
required List<ProfitSharingPeriod> monthly,
|
||||||
|
}) = _ProfitSharingBudget;
|
||||||
|
|
||||||
|
factory ProfitSharingBudget.empty() => ProfitSharingBudget(
|
||||||
|
percentages: ProfitSharingPercentage.empty(),
|
||||||
|
cutOffFrom: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
cutOffTo: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
total: ProfitSharingPeriod.empty(),
|
||||||
|
weekly: [],
|
||||||
|
monthly: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingPercentage with _$ProfitSharingPercentage {
|
||||||
|
const factory ProfitSharingPercentage({
|
||||||
|
required double purchase,
|
||||||
|
required double owner,
|
||||||
|
required double team,
|
||||||
|
}) = _ProfitSharingPercentage;
|
||||||
|
|
||||||
|
factory ProfitSharingPercentage.empty() =>
|
||||||
|
const ProfitSharingPercentage(purchase: 0, owner: 0, team: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Satu baris periode bagi hasil. Dipakai untuk total, mingguan, dan bulanan.
|
||||||
|
/// [month] dan [weekCount] hanya terisi untuk data bulanan.
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingPeriod with _$ProfitSharingPeriod {
|
||||||
|
const ProfitSharingPeriod._();
|
||||||
|
|
||||||
|
const factory ProfitSharingPeriod({
|
||||||
|
required DateTime periodStart,
|
||||||
|
required DateTime periodEnd,
|
||||||
|
required int revenue,
|
||||||
|
required int orderCount,
|
||||||
|
required int limitPurchase,
|
||||||
|
required int limitOwner,
|
||||||
|
required int limitTeam,
|
||||||
|
@Default('') String month,
|
||||||
|
@Default(0) int weekCount,
|
||||||
|
}) = _ProfitSharingPeriod;
|
||||||
|
|
||||||
|
factory ProfitSharingPeriod.empty() => ProfitSharingPeriod(
|
||||||
|
periodStart: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
periodEnd: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
revenue: 0,
|
||||||
|
orderCount: 0,
|
||||||
|
limitPurchase: 0,
|
||||||
|
limitOwner: 0,
|
||||||
|
limitTeam: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
bool get hasRevenue => revenue > 0;
|
||||||
|
|
||||||
|
int get averageOrderValue => orderCount == 0 ? 0 : revenue ~/ orderCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rincian satu kategori induk: ringkasan, sub kategori beserta produknya,
|
||||||
|
/// dan bagi hasil khusus kategori tersebut.
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingDetail with _$ProfitSharingDetail {
|
||||||
|
const factory ProfitSharingDetail({
|
||||||
|
required String organizationId,
|
||||||
|
required String outletId,
|
||||||
|
required String outletName,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
required String parentCategoryId,
|
||||||
|
required String parentCategoryName,
|
||||||
|
required ProfitSharingCategory summary,
|
||||||
|
required List<ProfitSharingSubCategory> categories,
|
||||||
|
required ProfitSharingBudget budget,
|
||||||
|
}) = _ProfitSharingDetail;
|
||||||
|
|
||||||
|
factory ProfitSharingDetail.empty() => ProfitSharingDetail(
|
||||||
|
organizationId: '',
|
||||||
|
outletId: '',
|
||||||
|
outletName: '',
|
||||||
|
dateFrom: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
dateTo: DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
parentCategoryId: '',
|
||||||
|
parentCategoryName: '',
|
||||||
|
summary: ProfitSharingCategory.empty(),
|
||||||
|
categories: [],
|
||||||
|
budget: ProfitSharingBudget.empty(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingSubCategory with _$ProfitSharingSubCategory {
|
||||||
|
const ProfitSharingSubCategory._();
|
||||||
|
|
||||||
|
const factory ProfitSharingSubCategory({
|
||||||
|
required String categoryId,
|
||||||
|
required String categoryName,
|
||||||
|
required int totalRevenue,
|
||||||
|
required int totalQuantity,
|
||||||
|
required int productCount,
|
||||||
|
required int orderCount,
|
||||||
|
required int totalStandardHpp,
|
||||||
|
required int totalFifoHpp,
|
||||||
|
required int totalMovingAverageHpp,
|
||||||
|
required List<ProfitSharingProduct> products,
|
||||||
|
}) = _ProfitSharingSubCategory;
|
||||||
|
|
||||||
|
double get standardHppPercentage =>
|
||||||
|
totalRevenue == 0 ? 0 : (totalStandardHpp / totalRevenue) * 100;
|
||||||
|
|
||||||
|
double get realHppPercentage =>
|
||||||
|
totalRevenue == 0 ? 0 : (totalFifoHpp / totalRevenue) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingProduct with _$ProfitSharingProduct {
|
||||||
|
const ProfitSharingProduct._();
|
||||||
|
|
||||||
|
const factory ProfitSharingProduct({
|
||||||
|
required String productId,
|
||||||
|
required String productName,
|
||||||
|
required String productSku,
|
||||||
|
required int productPrice,
|
||||||
|
required int quantitySold,
|
||||||
|
required int revenue,
|
||||||
|
required double averagePrice,
|
||||||
|
required int orderCount,
|
||||||
|
required double standardHppPerUnit,
|
||||||
|
required int standardHppTotal,
|
||||||
|
required double fifoHppPerUnit,
|
||||||
|
required int fifoHppTotal,
|
||||||
|
required double movingAverageHppPerUnit,
|
||||||
|
required int movingAverageHppTotal,
|
||||||
|
}) = _ProfitSharingProduct;
|
||||||
|
|
||||||
|
double get standardHppPercentage =>
|
||||||
|
revenue == 0 ? 0 : (standardHppTotal / revenue) * 100;
|
||||||
|
|
||||||
|
double get realHppPercentage =>
|
||||||
|
revenue == 0 ? 0 : (fifoHppTotal / revenue) * 100;
|
||||||
|
}
|
||||||
@@ -57,4 +57,18 @@ abstract class IAnalyticRepository {
|
|||||||
required DateTime dateTo,
|
required DateTime dateTo,
|
||||||
String? outletId,
|
String? outletId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Future<Either<AnalyticFailure, ProfitSharing>> getProfitSharing({
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
String? outletId,
|
||||||
|
String groupBy = 'day',
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<Either<AnalyticFailure, ProfitSharingDetail>> getProfitSharingDetail({
|
||||||
|
required String parentCategoryId,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
String? outletId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ part 'dto/product_analytic_dto.dart';
|
|||||||
part 'dto/payment_method_analytic_dto.dart';
|
part 'dto/payment_method_analytic_dto.dart';
|
||||||
part 'dto/purchasing_analytic_dto.dart';
|
part 'dto/purchasing_analytic_dto.dart';
|
||||||
part 'dto/exclusive_summary_dto.dart';
|
part 'dto/exclusive_summary_dto.dart';
|
||||||
|
part 'dto/profit_sharing_dto.dart';
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1121,3 +1121,289 @@ Map<String, dynamic> _$$ExclusiveSummaryTransactionDtoImplToJson(
|
|||||||
'amount': instance.amount,
|
'amount': instance.amount,
|
||||||
'source': instance.source,
|
'source': instance.source,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingDtoImpl _$$ProfitSharingDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingDtoImpl(
|
||||||
|
organizationId: json['organization_id'] as String?,
|
||||||
|
outletId: json['outlet_id'] as String?,
|
||||||
|
outletName: json['outlet_name'] as String?,
|
||||||
|
dateFrom: json['date_from'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['date_from'] as String),
|
||||||
|
dateTo: json['date_to'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['date_to'] as String),
|
||||||
|
data: (json['data'] as List<dynamic>?)
|
||||||
|
?.map((e) => ProfitSharingCategoryDto.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
budget: json['budget'] == null
|
||||||
|
? null
|
||||||
|
: ProfitSharingBudgetDto.fromJson(json['budget'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingDtoImplToJson(
|
||||||
|
_$ProfitSharingDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'organization_id': instance.organizationId,
|
||||||
|
'outlet_id': instance.outletId,
|
||||||
|
'outlet_name': instance.outletName,
|
||||||
|
'date_from': instance.dateFrom?.toIso8601String(),
|
||||||
|
'date_to': instance.dateTo?.toIso8601String(),
|
||||||
|
'data': instance.data,
|
||||||
|
'budget': instance.budget,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingCategoryDtoImpl _$$ProfitSharingCategoryDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingCategoryDtoImpl(
|
||||||
|
parentCategoryId: json['parent_category_id'] as String?,
|
||||||
|
parentCategoryName: json['parent_category_name'] as String?,
|
||||||
|
totalRevenue: json['total_revenue'] as num?,
|
||||||
|
totalQuantity: json['total_quantity'] as num?,
|
||||||
|
categoryCount: json['category_count'] as num?,
|
||||||
|
productCount: json['product_count'] as num?,
|
||||||
|
orderCount: json['order_count'] as num?,
|
||||||
|
totalStandardHpp: json['total_standard_hpp'] as num?,
|
||||||
|
totalFifoHpp: json['total_fifo_hpp'] as num?,
|
||||||
|
totalMovingAverageHpp: json['total_moving_average_hpp'] as num?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingCategoryDtoImplToJson(
|
||||||
|
_$ProfitSharingCategoryDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'parent_category_id': instance.parentCategoryId,
|
||||||
|
'parent_category_name': instance.parentCategoryName,
|
||||||
|
'total_revenue': instance.totalRevenue,
|
||||||
|
'total_quantity': instance.totalQuantity,
|
||||||
|
'category_count': instance.categoryCount,
|
||||||
|
'product_count': instance.productCount,
|
||||||
|
'order_count': instance.orderCount,
|
||||||
|
'total_standard_hpp': instance.totalStandardHpp,
|
||||||
|
'total_fifo_hpp': instance.totalFifoHpp,
|
||||||
|
'total_moving_average_hpp': instance.totalMovingAverageHpp,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingBudgetDtoImpl _$$ProfitSharingBudgetDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingBudgetDtoImpl(
|
||||||
|
percentages: json['percentages'] == null
|
||||||
|
? null
|
||||||
|
: ProfitSharingPercentageDto.fromJson(
|
||||||
|
json['percentages'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
|
cutOffFrom: json['cut_off_from'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['cut_off_from'] as String),
|
||||||
|
cutOffTo: json['cut_off_to'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['cut_off_to'] as String),
|
||||||
|
total: json['total'] == null
|
||||||
|
? null
|
||||||
|
: ProfitSharingPeriodDto.fromJson(json['total'] as Map<String, dynamic>),
|
||||||
|
weekly: (json['weekly'] as List<dynamic>?)
|
||||||
|
?.map((e) => ProfitSharingPeriodDto.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
monthly: (json['monthly'] as List<dynamic>?)
|
||||||
|
?.map((e) => ProfitSharingPeriodDto.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingBudgetDtoImplToJson(
|
||||||
|
_$ProfitSharingBudgetDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'percentages': instance.percentages,
|
||||||
|
'cut_off_from': instance.cutOffFrom?.toIso8601String(),
|
||||||
|
'cut_off_to': instance.cutOffTo?.toIso8601String(),
|
||||||
|
'total': instance.total,
|
||||||
|
'weekly': instance.weekly,
|
||||||
|
'monthly': instance.monthly,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingPercentageDtoImpl _$$ProfitSharingPercentageDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingPercentageDtoImpl(
|
||||||
|
purchase: json['purchase'] as num?,
|
||||||
|
owner: json['owner'] as num?,
|
||||||
|
team: json['team'] as num?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingPercentageDtoImplToJson(
|
||||||
|
_$ProfitSharingPercentageDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'purchase': instance.purchase,
|
||||||
|
'owner': instance.owner,
|
||||||
|
'team': instance.team,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingPeriodDtoImpl _$$ProfitSharingPeriodDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingPeriodDtoImpl(
|
||||||
|
periodStart: json['period_start'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['period_start'] as String),
|
||||||
|
periodEnd: json['period_end'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['period_end'] as String),
|
||||||
|
revenue: json['revenue'] as num?,
|
||||||
|
orderCount: json['order_count'] as num?,
|
||||||
|
limitPurchase: json['limit_purchase'] as num?,
|
||||||
|
limitOwner: json['limit_owner'] as num?,
|
||||||
|
limitTeam: json['limit_team'] as num?,
|
||||||
|
month: json['month'] as String?,
|
||||||
|
weekCount: json['week_count'] as num?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingPeriodDtoImplToJson(
|
||||||
|
_$ProfitSharingPeriodDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'period_start': instance.periodStart?.toIso8601String(),
|
||||||
|
'period_end': instance.periodEnd?.toIso8601String(),
|
||||||
|
'revenue': instance.revenue,
|
||||||
|
'order_count': instance.orderCount,
|
||||||
|
'limit_purchase': instance.limitPurchase,
|
||||||
|
'limit_owner': instance.limitOwner,
|
||||||
|
'limit_team': instance.limitTeam,
|
||||||
|
'month': instance.month,
|
||||||
|
'week_count': instance.weekCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingDetailDtoImpl _$$ProfitSharingDetailDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingDetailDtoImpl(
|
||||||
|
organizationId: json['organization_id'] as String?,
|
||||||
|
outletId: json['outlet_id'] as String?,
|
||||||
|
outletName: json['outlet_name'] as String?,
|
||||||
|
dateFrom: json['date_from'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['date_from'] as String),
|
||||||
|
dateTo: json['date_to'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['date_to'] as String),
|
||||||
|
parentCategoryId: json['parent_category_id'] as String?,
|
||||||
|
parentCategoryName: json['parent_category_name'] as String?,
|
||||||
|
summary: json['summary'] == null
|
||||||
|
? null
|
||||||
|
: ProfitSharingSummaryDto.fromJson(
|
||||||
|
json['summary'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
|
categories: (json['categories'] as List<dynamic>?)
|
||||||
|
?.map(
|
||||||
|
(e) => ProfitSharingSubCategoryDto.fromJson(e as Map<String, dynamic>),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
budget: json['budget'] == null
|
||||||
|
? null
|
||||||
|
: ProfitSharingBudgetDto.fromJson(json['budget'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingDetailDtoImplToJson(
|
||||||
|
_$ProfitSharingDetailDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'organization_id': instance.organizationId,
|
||||||
|
'outlet_id': instance.outletId,
|
||||||
|
'outlet_name': instance.outletName,
|
||||||
|
'date_from': instance.dateFrom?.toIso8601String(),
|
||||||
|
'date_to': instance.dateTo?.toIso8601String(),
|
||||||
|
'parent_category_id': instance.parentCategoryId,
|
||||||
|
'parent_category_name': instance.parentCategoryName,
|
||||||
|
'summary': instance.summary,
|
||||||
|
'categories': instance.categories,
|
||||||
|
'budget': instance.budget,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingSummaryDtoImpl _$$ProfitSharingSummaryDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingSummaryDtoImpl(
|
||||||
|
totalRevenue: json['total_revenue'] as num?,
|
||||||
|
totalQuantity: json['total_quantity'] as num?,
|
||||||
|
categoryCount: json['category_count'] as num?,
|
||||||
|
productCount: json['product_count'] as num?,
|
||||||
|
orderCount: json['order_count'] as num?,
|
||||||
|
totalStandardHpp: json['total_standard_hpp'] as num?,
|
||||||
|
totalFifoHpp: json['total_fifo_hpp'] as num?,
|
||||||
|
totalMovingAverageHpp: json['total_moving_average_hpp'] as num?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingSummaryDtoImplToJson(
|
||||||
|
_$ProfitSharingSummaryDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'total_revenue': instance.totalRevenue,
|
||||||
|
'total_quantity': instance.totalQuantity,
|
||||||
|
'category_count': instance.categoryCount,
|
||||||
|
'product_count': instance.productCount,
|
||||||
|
'order_count': instance.orderCount,
|
||||||
|
'total_standard_hpp': instance.totalStandardHpp,
|
||||||
|
'total_fifo_hpp': instance.totalFifoHpp,
|
||||||
|
'total_moving_average_hpp': instance.totalMovingAverageHpp,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingSubCategoryDtoImpl _$$ProfitSharingSubCategoryDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingSubCategoryDtoImpl(
|
||||||
|
categoryId: json['category_id'] as String?,
|
||||||
|
categoryName: json['category_name'] as String?,
|
||||||
|
totalRevenue: json['total_revenue'] as num?,
|
||||||
|
totalQuantity: json['total_quantity'] as num?,
|
||||||
|
productCount: json['product_count'] as num?,
|
||||||
|
orderCount: json['order_count'] as num?,
|
||||||
|
totalStandardHpp: json['total_standard_hpp'] as num?,
|
||||||
|
totalFifoHpp: json['total_fifo_hpp'] as num?,
|
||||||
|
totalMovingAverageHpp: json['total_moving_average_hpp'] as num?,
|
||||||
|
products: (json['products'] as List<dynamic>?)
|
||||||
|
?.map((e) => ProfitSharingProductDto.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingSubCategoryDtoImplToJson(
|
||||||
|
_$ProfitSharingSubCategoryDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'category_id': instance.categoryId,
|
||||||
|
'category_name': instance.categoryName,
|
||||||
|
'total_revenue': instance.totalRevenue,
|
||||||
|
'total_quantity': instance.totalQuantity,
|
||||||
|
'product_count': instance.productCount,
|
||||||
|
'order_count': instance.orderCount,
|
||||||
|
'total_standard_hpp': instance.totalStandardHpp,
|
||||||
|
'total_fifo_hpp': instance.totalFifoHpp,
|
||||||
|
'total_moving_average_hpp': instance.totalMovingAverageHpp,
|
||||||
|
'products': instance.products,
|
||||||
|
};
|
||||||
|
|
||||||
|
_$ProfitSharingProductDtoImpl _$$ProfitSharingProductDtoImplFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _$ProfitSharingProductDtoImpl(
|
||||||
|
productId: json['product_id'] as String?,
|
||||||
|
productName: json['product_name'] as String?,
|
||||||
|
productSku: json['product_sku'] as String?,
|
||||||
|
productPrice: json['product_price'] as num?,
|
||||||
|
quantitySold: json['quantity_sold'] as num?,
|
||||||
|
revenue: json['revenue'] as num?,
|
||||||
|
averagePrice: json['average_price'] as num?,
|
||||||
|
orderCount: json['order_count'] as num?,
|
||||||
|
standardHppPerUnit: json['standard_hpp_per_unit'] as num?,
|
||||||
|
standardHppTotal: json['standard_hpp_total'] as num?,
|
||||||
|
fifoHppPerUnit: json['fifo_hpp_per_unit'] as num?,
|
||||||
|
fifoHppTotal: json['fifo_hpp_total'] as num?,
|
||||||
|
movingAverageHppPerUnit: json['moving_average_hpp_per_unit'] as num?,
|
||||||
|
movingAverageHppTotal: json['moving_average_hpp_total'] as num?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$ProfitSharingProductDtoImplToJson(
|
||||||
|
_$ProfitSharingProductDtoImpl instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'product_id': instance.productId,
|
||||||
|
'product_name': instance.productName,
|
||||||
|
'product_sku': instance.productSku,
|
||||||
|
'product_price': instance.productPrice,
|
||||||
|
'quantity_sold': instance.quantitySold,
|
||||||
|
'revenue': instance.revenue,
|
||||||
|
'average_price': instance.averagePrice,
|
||||||
|
'order_count': instance.orderCount,
|
||||||
|
'standard_hpp_per_unit': instance.standardHppPerUnit,
|
||||||
|
'standard_hpp_total': instance.standardHppTotal,
|
||||||
|
'fifo_hpp_per_unit': instance.fifoHppPerUnit,
|
||||||
|
'fifo_hpp_total': instance.fifoHppTotal,
|
||||||
|
'moving_average_hpp_per_unit': instance.movingAverageHppPerUnit,
|
||||||
|
'moving_average_hpp_total': instance.movingAverageHppTotal,
|
||||||
|
};
|
||||||
|
|||||||
@@ -295,4 +295,74 @@ class AnalyticRemoteDataProvider {
|
|||||||
return DC.error(AnalyticFailure.serverError(e));
|
return DC.error(AnalyticFailure.serverError(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<DC<AnalyticFailure, ProfitSharingDto>> fetchProfitSharing({
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
String? outletId,
|
||||||
|
String groupBy = 'day',
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final Map<String, dynamic> params = {
|
||||||
|
'date_from': dateFrom.toServerDate,
|
||||||
|
'date_to': dateTo.toServerDate,
|
||||||
|
'group_by': groupBy,
|
||||||
|
};
|
||||||
|
if (outletId != null) params['outlet_id'] = outletId;
|
||||||
|
|
||||||
|
final response = await _apiClient.get(
|
||||||
|
ApiPath.parentCategoryAnalytic,
|
||||||
|
params: params,
|
||||||
|
headers: getAuthorizationHeader(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.data['data'] == null) {
|
||||||
|
return DC.error(AnalyticFailure.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
final dto = ProfitSharingDto.fromJson(response.data['data']);
|
||||||
|
|
||||||
|
return DC.data(dto);
|
||||||
|
} on ApiFailure catch (e, s) {
|
||||||
|
log('fetchProfitSharingError', name: _logName, error: e, stackTrace: s);
|
||||||
|
return DC.error(AnalyticFailure.serverError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DC<AnalyticFailure, ProfitSharingDetailDto>> fetchProfitSharingDetail({
|
||||||
|
required String parentCategoryId,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
String? outletId,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final Map<String, dynamic> params = {
|
||||||
|
'date_from': dateFrom.toServerDate,
|
||||||
|
'date_to': dateTo.toServerDate,
|
||||||
|
};
|
||||||
|
if (outletId != null) params['outlet_id'] = outletId;
|
||||||
|
|
||||||
|
final response = await _apiClient.get(
|
||||||
|
'${ApiPath.parentCategoryAnalytic}/$parentCategoryId',
|
||||||
|
params: params,
|
||||||
|
headers: getAuthorizationHeader(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.data['data'] == null) {
|
||||||
|
return DC.error(AnalyticFailure.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
final dto = ProfitSharingDetailDto.fromJson(response.data['data']);
|
||||||
|
|
||||||
|
return DC.data(dto);
|
||||||
|
} on ApiFailure catch (e, s) {
|
||||||
|
log(
|
||||||
|
'fetchProfitSharingDetailError',
|
||||||
|
name: _logName,
|
||||||
|
error: e,
|
||||||
|
stackTrace: s,
|
||||||
|
);
|
||||||
|
return DC.error(AnalyticFailure.serverError(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,294 @@
|
|||||||
|
part of '../analytic_dtos.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingDto with _$ProfitSharingDto {
|
||||||
|
const ProfitSharingDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingDto({
|
||||||
|
@JsonKey(name: 'organization_id') String? organizationId,
|
||||||
|
@JsonKey(name: 'outlet_id') String? outletId,
|
||||||
|
@JsonKey(name: 'outlet_name') String? outletName,
|
||||||
|
@JsonKey(name: 'date_from') DateTime? dateFrom,
|
||||||
|
@JsonKey(name: 'date_to') DateTime? dateTo,
|
||||||
|
@JsonKey(name: 'data') List<ProfitSharingCategoryDto>? data,
|
||||||
|
@JsonKey(name: 'budget') ProfitSharingBudgetDto? budget,
|
||||||
|
}) = _ProfitSharingDto;
|
||||||
|
|
||||||
|
factory ProfitSharingDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharing toDomain() => ProfitSharing(
|
||||||
|
organizationId: organizationId ?? '',
|
||||||
|
outletId: outletId ?? '',
|
||||||
|
outletName: outletName ?? '',
|
||||||
|
dateFrom: dateFrom?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
dateTo: dateTo?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
categories: data?.map((e) => e.toDomain()).toList() ?? [],
|
||||||
|
budget: budget?.toDomain() ?? ProfitSharingBudget.empty(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingCategoryDto with _$ProfitSharingCategoryDto {
|
||||||
|
const ProfitSharingCategoryDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingCategoryDto({
|
||||||
|
@JsonKey(name: 'parent_category_id') String? parentCategoryId,
|
||||||
|
@JsonKey(name: 'parent_category_name') String? parentCategoryName,
|
||||||
|
@JsonKey(name: 'total_revenue') num? totalRevenue,
|
||||||
|
@JsonKey(name: 'total_quantity') num? totalQuantity,
|
||||||
|
@JsonKey(name: 'category_count') num? categoryCount,
|
||||||
|
@JsonKey(name: 'product_count') num? productCount,
|
||||||
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
|
@JsonKey(name: 'total_standard_hpp') num? totalStandardHpp,
|
||||||
|
@JsonKey(name: 'total_fifo_hpp') num? totalFifoHpp,
|
||||||
|
@JsonKey(name: 'total_moving_average_hpp') num? totalMovingAverageHpp,
|
||||||
|
}) = _ProfitSharingCategoryDto;
|
||||||
|
|
||||||
|
factory ProfitSharingCategoryDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingCategoryDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingCategory toDomain() => ProfitSharingCategory(
|
||||||
|
parentCategoryId: parentCategoryId ?? '',
|
||||||
|
parentCategoryName: parentCategoryName ?? '',
|
||||||
|
totalRevenue: totalRevenue?.toInt() ?? 0,
|
||||||
|
totalQuantity: totalQuantity?.toInt() ?? 0,
|
||||||
|
categoryCount: categoryCount?.toInt() ?? 0,
|
||||||
|
productCount: productCount?.toInt() ?? 0,
|
||||||
|
orderCount: orderCount?.toInt() ?? 0,
|
||||||
|
totalStandardHpp: totalStandardHpp?.toInt() ?? 0,
|
||||||
|
totalFifoHpp: totalFifoHpp?.toInt() ?? 0,
|
||||||
|
totalMovingAverageHpp: totalMovingAverageHpp?.toInt() ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingBudgetDto with _$ProfitSharingBudgetDto {
|
||||||
|
const ProfitSharingBudgetDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingBudgetDto({
|
||||||
|
@JsonKey(name: 'percentages') ProfitSharingPercentageDto? percentages,
|
||||||
|
@JsonKey(name: 'cut_off_from') DateTime? cutOffFrom,
|
||||||
|
@JsonKey(name: 'cut_off_to') DateTime? cutOffTo,
|
||||||
|
@JsonKey(name: 'total') ProfitSharingPeriodDto? total,
|
||||||
|
@JsonKey(name: 'weekly') List<ProfitSharingPeriodDto>? weekly,
|
||||||
|
@JsonKey(name: 'monthly') List<ProfitSharingPeriodDto>? monthly,
|
||||||
|
}) = _ProfitSharingBudgetDto;
|
||||||
|
|
||||||
|
factory ProfitSharingBudgetDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingBudgetDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingBudget toDomain() => ProfitSharingBudget(
|
||||||
|
percentages: percentages?.toDomain() ?? ProfitSharingPercentage.empty(),
|
||||||
|
cutOffFrom: cutOffFrom?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
cutOffTo: cutOffTo?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
total: total?.toDomain() ?? ProfitSharingPeriod.empty(),
|
||||||
|
weekly: weekly?.map((e) => e.toDomain()).toList() ?? [],
|
||||||
|
monthly: monthly?.map((e) => e.toDomain()).toList() ?? [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingPercentageDto with _$ProfitSharingPercentageDto {
|
||||||
|
const ProfitSharingPercentageDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingPercentageDto({
|
||||||
|
@JsonKey(name: 'purchase') num? purchase,
|
||||||
|
@JsonKey(name: 'owner') num? owner,
|
||||||
|
@JsonKey(name: 'team') num? team,
|
||||||
|
}) = _ProfitSharingPercentageDto;
|
||||||
|
|
||||||
|
factory ProfitSharingPercentageDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingPercentageDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingPercentage toDomain() => ProfitSharingPercentage(
|
||||||
|
purchase: purchase?.toDouble() ?? 0,
|
||||||
|
owner: owner?.toDouble() ?? 0,
|
||||||
|
team: team?.toDouble() ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingPeriodDto with _$ProfitSharingPeriodDto {
|
||||||
|
const ProfitSharingPeriodDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingPeriodDto({
|
||||||
|
@JsonKey(name: 'period_start') DateTime? periodStart,
|
||||||
|
@JsonKey(name: 'period_end') DateTime? periodEnd,
|
||||||
|
@JsonKey(name: 'revenue') num? revenue,
|
||||||
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
|
@JsonKey(name: 'limit_purchase') num? limitPurchase,
|
||||||
|
@JsonKey(name: 'limit_owner') num? limitOwner,
|
||||||
|
@JsonKey(name: 'limit_team') num? limitTeam,
|
||||||
|
@JsonKey(name: 'month') String? month,
|
||||||
|
@JsonKey(name: 'week_count') num? weekCount,
|
||||||
|
}) = _ProfitSharingPeriodDto;
|
||||||
|
|
||||||
|
factory ProfitSharingPeriodDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingPeriodDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingPeriod toDomain() => ProfitSharingPeriod(
|
||||||
|
periodStart:
|
||||||
|
periodStart?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
periodEnd: periodEnd?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
revenue: revenue?.toInt() ?? 0,
|
||||||
|
orderCount: orderCount?.toInt() ?? 0,
|
||||||
|
limitPurchase: limitPurchase?.toInt() ?? 0,
|
||||||
|
limitOwner: limitOwner?.toInt() ?? 0,
|
||||||
|
limitTeam: limitTeam?.toInt() ?? 0,
|
||||||
|
month: month ?? '',
|
||||||
|
weekCount: weekCount?.toInt() ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingDetailDto with _$ProfitSharingDetailDto {
|
||||||
|
const ProfitSharingDetailDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingDetailDto({
|
||||||
|
@JsonKey(name: 'organization_id') String? organizationId,
|
||||||
|
@JsonKey(name: 'outlet_id') String? outletId,
|
||||||
|
@JsonKey(name: 'outlet_name') String? outletName,
|
||||||
|
@JsonKey(name: 'date_from') DateTime? dateFrom,
|
||||||
|
@JsonKey(name: 'date_to') DateTime? dateTo,
|
||||||
|
@JsonKey(name: 'parent_category_id') String? parentCategoryId,
|
||||||
|
@JsonKey(name: 'parent_category_name') String? parentCategoryName,
|
||||||
|
@JsonKey(name: 'summary') ProfitSharingSummaryDto? summary,
|
||||||
|
@JsonKey(name: 'categories') List<ProfitSharingSubCategoryDto>? categories,
|
||||||
|
@JsonKey(name: 'budget') ProfitSharingBudgetDto? budget,
|
||||||
|
}) = _ProfitSharingDetailDto;
|
||||||
|
|
||||||
|
factory ProfitSharingDetailDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingDetailDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingDetail toDomain() => ProfitSharingDetail(
|
||||||
|
organizationId: organizationId ?? '',
|
||||||
|
outletId: outletId ?? '',
|
||||||
|
outletName: outletName ?? '',
|
||||||
|
dateFrom: dateFrom?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
dateTo: dateTo?.toLocal() ?? DateTime.fromMillisecondsSinceEpoch(0),
|
||||||
|
parentCategoryId: parentCategoryId ?? '',
|
||||||
|
parentCategoryName: parentCategoryName ?? '',
|
||||||
|
summary:
|
||||||
|
summary?.toDomain(
|
||||||
|
parentCategoryId: parentCategoryId ?? '',
|
||||||
|
parentCategoryName: parentCategoryName ?? '',
|
||||||
|
) ??
|
||||||
|
ProfitSharingCategory.empty(),
|
||||||
|
categories: categories?.map((e) => e.toDomain()).toList() ?? [],
|
||||||
|
budget: budget?.toDomain() ?? ProfitSharingBudget.empty(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ringkasan kategori induk pada endpoint detail — bentuknya sama dengan item
|
||||||
|
/// pada endpoint daftar, hanya saja id & nama kategori ada di level atas.
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingSummaryDto with _$ProfitSharingSummaryDto {
|
||||||
|
const ProfitSharingSummaryDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingSummaryDto({
|
||||||
|
@JsonKey(name: 'total_revenue') num? totalRevenue,
|
||||||
|
@JsonKey(name: 'total_quantity') num? totalQuantity,
|
||||||
|
@JsonKey(name: 'category_count') num? categoryCount,
|
||||||
|
@JsonKey(name: 'product_count') num? productCount,
|
||||||
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
|
@JsonKey(name: 'total_standard_hpp') num? totalStandardHpp,
|
||||||
|
@JsonKey(name: 'total_fifo_hpp') num? totalFifoHpp,
|
||||||
|
@JsonKey(name: 'total_moving_average_hpp') num? totalMovingAverageHpp,
|
||||||
|
}) = _ProfitSharingSummaryDto;
|
||||||
|
|
||||||
|
factory ProfitSharingSummaryDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingSummaryDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingCategory toDomain({
|
||||||
|
required String parentCategoryId,
|
||||||
|
required String parentCategoryName,
|
||||||
|
}) => ProfitSharingCategory(
|
||||||
|
parentCategoryId: parentCategoryId,
|
||||||
|
parentCategoryName: parentCategoryName,
|
||||||
|
totalRevenue: totalRevenue?.toInt() ?? 0,
|
||||||
|
totalQuantity: totalQuantity?.toInt() ?? 0,
|
||||||
|
categoryCount: categoryCount?.toInt() ?? 0,
|
||||||
|
productCount: productCount?.toInt() ?? 0,
|
||||||
|
orderCount: orderCount?.toInt() ?? 0,
|
||||||
|
totalStandardHpp: totalStandardHpp?.toInt() ?? 0,
|
||||||
|
totalFifoHpp: totalFifoHpp?.toInt() ?? 0,
|
||||||
|
totalMovingAverageHpp: totalMovingAverageHpp?.toInt() ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingSubCategoryDto with _$ProfitSharingSubCategoryDto {
|
||||||
|
const ProfitSharingSubCategoryDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingSubCategoryDto({
|
||||||
|
@JsonKey(name: 'category_id') String? categoryId,
|
||||||
|
@JsonKey(name: 'category_name') String? categoryName,
|
||||||
|
@JsonKey(name: 'total_revenue') num? totalRevenue,
|
||||||
|
@JsonKey(name: 'total_quantity') num? totalQuantity,
|
||||||
|
@JsonKey(name: 'product_count') num? productCount,
|
||||||
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
|
@JsonKey(name: 'total_standard_hpp') num? totalStandardHpp,
|
||||||
|
@JsonKey(name: 'total_fifo_hpp') num? totalFifoHpp,
|
||||||
|
@JsonKey(name: 'total_moving_average_hpp') num? totalMovingAverageHpp,
|
||||||
|
@JsonKey(name: 'products') List<ProfitSharingProductDto>? products,
|
||||||
|
}) = _ProfitSharingSubCategoryDto;
|
||||||
|
|
||||||
|
factory ProfitSharingSubCategoryDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingSubCategoryDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingSubCategory toDomain() => ProfitSharingSubCategory(
|
||||||
|
categoryId: categoryId ?? '',
|
||||||
|
categoryName: categoryName ?? '',
|
||||||
|
totalRevenue: totalRevenue?.toInt() ?? 0,
|
||||||
|
totalQuantity: totalQuantity?.toInt() ?? 0,
|
||||||
|
productCount: productCount?.toInt() ?? 0,
|
||||||
|
orderCount: orderCount?.toInt() ?? 0,
|
||||||
|
totalStandardHpp: totalStandardHpp?.toInt() ?? 0,
|
||||||
|
totalFifoHpp: totalFifoHpp?.toInt() ?? 0,
|
||||||
|
totalMovingAverageHpp: totalMovingAverageHpp?.toInt() ?? 0,
|
||||||
|
products: products?.map((e) => e.toDomain()).toList() ?? [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class ProfitSharingProductDto with _$ProfitSharingProductDto {
|
||||||
|
const ProfitSharingProductDto._();
|
||||||
|
|
||||||
|
const factory ProfitSharingProductDto({
|
||||||
|
@JsonKey(name: 'product_id') String? productId,
|
||||||
|
@JsonKey(name: 'product_name') String? productName,
|
||||||
|
@JsonKey(name: 'product_sku') String? productSku,
|
||||||
|
@JsonKey(name: 'product_price') num? productPrice,
|
||||||
|
@JsonKey(name: 'quantity_sold') num? quantitySold,
|
||||||
|
@JsonKey(name: 'revenue') num? revenue,
|
||||||
|
@JsonKey(name: 'average_price') num? averagePrice,
|
||||||
|
@JsonKey(name: 'order_count') num? orderCount,
|
||||||
|
@JsonKey(name: 'standard_hpp_per_unit') num? standardHppPerUnit,
|
||||||
|
@JsonKey(name: 'standard_hpp_total') num? standardHppTotal,
|
||||||
|
@JsonKey(name: 'fifo_hpp_per_unit') num? fifoHppPerUnit,
|
||||||
|
@JsonKey(name: 'fifo_hpp_total') num? fifoHppTotal,
|
||||||
|
@JsonKey(name: 'moving_average_hpp_per_unit') num? movingAverageHppPerUnit,
|
||||||
|
@JsonKey(name: 'moving_average_hpp_total') num? movingAverageHppTotal,
|
||||||
|
}) = _ProfitSharingProductDto;
|
||||||
|
|
||||||
|
factory ProfitSharingProductDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfitSharingProductDtoFromJson(json);
|
||||||
|
|
||||||
|
ProfitSharingProduct toDomain() => ProfitSharingProduct(
|
||||||
|
productId: productId ?? '',
|
||||||
|
productName: productName ?? '',
|
||||||
|
productSku: productSku ?? '',
|
||||||
|
productPrice: productPrice?.toInt() ?? 0,
|
||||||
|
quantitySold: quantitySold?.toInt() ?? 0,
|
||||||
|
revenue: revenue?.toInt() ?? 0,
|
||||||
|
averagePrice: averagePrice?.toDouble() ?? 0,
|
||||||
|
orderCount: orderCount?.toInt() ?? 0,
|
||||||
|
standardHppPerUnit: standardHppPerUnit?.toDouble() ?? 0,
|
||||||
|
standardHppTotal: standardHppTotal?.toInt() ?? 0,
|
||||||
|
fifoHppPerUnit: fifoHppPerUnit?.toDouble() ?? 0,
|
||||||
|
fifoHppTotal: fifoHppTotal?.toInt() ?? 0,
|
||||||
|
movingAverageHppPerUnit: movingAverageHppPerUnit?.toDouble() ?? 0,
|
||||||
|
movingAverageHppTotal: movingAverageHppTotal?.toInt() ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -220,4 +220,50 @@ class AnalyticRepository implements IAnalyticRepository {
|
|||||||
return left(const AnalyticFailure.unexpectedError());
|
return left(const AnalyticFailure.unexpectedError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Either<AnalyticFailure, ProfitSharing>> getProfitSharing({
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
String? outletId,
|
||||||
|
String groupBy = 'day',
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final result = await _dataProvider.fetchProfitSharing(
|
||||||
|
dateFrom: dateFrom,
|
||||||
|
dateTo: dateTo,
|
||||||
|
outletId: _resolveOutletId(outletId),
|
||||||
|
groupBy: groupBy,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.hasError) return left(result.error!);
|
||||||
|
return right(result.data!.toDomain());
|
||||||
|
} catch (e, s) {
|
||||||
|
log('getProfitSharingError', name: _logName, error: e, stackTrace: s);
|
||||||
|
return left(const AnalyticFailure.unexpectedError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Either<AnalyticFailure, ProfitSharingDetail>> getProfitSharingDetail({
|
||||||
|
required String parentCategoryId,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
String? outletId,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final result = await _dataProvider.fetchProfitSharingDetail(
|
||||||
|
parentCategoryId: parentCategoryId,
|
||||||
|
dateFrom: dateFrom,
|
||||||
|
dateTo: dateTo,
|
||||||
|
outletId: _resolveOutletId(outletId),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.hasError) return left(result.error!);
|
||||||
|
return right(result.data!.toDomain());
|
||||||
|
} catch (e, s) {
|
||||||
|
log('getProfitSharingDetailError', name: _logName, error: e, stackTrace: s);
|
||||||
|
return left(const AnalyticFailure.unexpectedError());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ import 'package:apskel_owner_flutter/application/analytic/product_analytic_loade
|
|||||||
as _i221;
|
as _i221;
|
||||||
import 'package:apskel_owner_flutter/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart'
|
import 'package:apskel_owner_flutter/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart'
|
||||||
as _i11;
|
as _i11;
|
||||||
|
import 'package:apskel_owner_flutter/application/analytic/profit_sharing_detail_loader/profit_sharing_detail_loader_bloc.dart'
|
||||||
|
as _i400;
|
||||||
|
import 'package:apskel_owner_flutter/application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart'
|
||||||
|
as _i631;
|
||||||
import 'package:apskel_owner_flutter/application/analytic/purchasing_analytic_loader/purchasing_analytic_loader_bloc.dart'
|
import 'package:apskel_owner_flutter/application/analytic/purchasing_analytic_loader/purchasing_analytic_loader_bloc.dart'
|
||||||
as _i755;
|
as _i755;
|
||||||
import 'package:apskel_owner_flutter/application/analytic/sales_loader/sales_loader_bloc.dart'
|
import 'package:apskel_owner_flutter/application/analytic/sales_loader/sales_loader_bloc.dart'
|
||||||
@@ -290,6 +294,13 @@ extension GetItInjectableX on _i174.GetIt {
|
|||||||
gh.factory<_i11.ProfitLossLoaderBloc>(
|
gh.factory<_i11.ProfitLossLoaderBloc>(
|
||||||
() => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()),
|
() => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()),
|
||||||
);
|
);
|
||||||
|
gh.factory<_i631.ProfitSharingLoaderBloc>(
|
||||||
|
() => _i631.ProfitSharingLoaderBloc(gh<_i477.IAnalyticRepository>()),
|
||||||
|
);
|
||||||
|
gh.factory<_i400.ProfitSharingDetailLoaderBloc>(
|
||||||
|
() =>
|
||||||
|
_i400.ProfitSharingDetailLoaderBloc(gh<_i477.IAnalyticRepository>()),
|
||||||
|
);
|
||||||
gh.factory<_i945.AuthBloc>(
|
gh.factory<_i945.AuthBloc>(
|
||||||
() => _i945.AuthBloc(gh<_i49.IAuthRepository>()),
|
() => _i945.AuthBloc(gh<_i49.IAuthRepository>()),
|
||||||
);
|
);
|
||||||
|
|||||||
+63
-1
@@ -538,5 +538,67 @@
|
|||||||
"no_data_yet": "No data yet",
|
"no_data_yet": "No data yet",
|
||||||
"@no_data_yet": {},
|
"@no_data_yet": {},
|
||||||
"total_inventory_value": "Total Inventory Value",
|
"total_inventory_value": "Total Inventory Value",
|
||||||
"@total_inventory_value": {}
|
"@total_inventory_value": {},
|
||||||
|
"profit_sharing": "Profit Sharing",
|
||||||
|
"@profit_sharing": {},
|
||||||
|
"profit_sharing_desc": "Revenue allocation for purchasing, owner, and team",
|
||||||
|
"@profit_sharing_desc": {},
|
||||||
|
"profit_sharing_allocation": "Profit Sharing Allocation",
|
||||||
|
"@profit_sharing_allocation": {},
|
||||||
|
"share_purchase": "Purchasing",
|
||||||
|
"@share_purchase": {},
|
||||||
|
"share_owner": "Owner",
|
||||||
|
"@share_owner": {},
|
||||||
|
"share_team": "Team",
|
||||||
|
"@share_team": {},
|
||||||
|
"weekly": "Weekly",
|
||||||
|
"@weekly": {},
|
||||||
|
"monthly": "Monthly",
|
||||||
|
"@monthly": {},
|
||||||
|
"period_breakdown": "Period Breakdown",
|
||||||
|
"@period_breakdown": {},
|
||||||
|
"revenue_by_brand": "Revenue by Brand",
|
||||||
|
"@revenue_by_brand": {},
|
||||||
|
"week_count": "{count} weeks",
|
||||||
|
"@week_count": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"type": "int",
|
||||||
|
"example": "5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"order_count_label": "{count} orders",
|
||||||
|
"@order_count_label": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"type": "int",
|
||||||
|
"example": "328"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gross_margin": "Gross Margin",
|
||||||
|
"@gross_margin": {},
|
||||||
|
"parent_category_summary": "Parent Category Summary",
|
||||||
|
"@parent_category_summary": {},
|
||||||
|
"sub_category": "Sub Category",
|
||||||
|
"@sub_category": {},
|
||||||
|
"qty": "Qty",
|
||||||
|
"@qty": {},
|
||||||
|
"std_hpp": "Std HPP",
|
||||||
|
"@std_hpp": {},
|
||||||
|
"real_hpp": "Real HPP",
|
||||||
|
"@real_hpp": {},
|
||||||
|
"status": "Status",
|
||||||
|
"@status": {},
|
||||||
|
"grand_total": "TOTAL",
|
||||||
|
"@grand_total": {},
|
||||||
|
"status_healthy": "Healthy",
|
||||||
|
"@status_healthy": {},
|
||||||
|
"status_watch": "Watch",
|
||||||
|
"@status_watch": {},
|
||||||
|
"status_critical": "Unhealthy",
|
||||||
|
"@status_critical": {},
|
||||||
|
"tap_row_for_detail": "Tap a card to see sub category and product details",
|
||||||
|
"@tap_row_for_detail": {}
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-1
@@ -538,5 +538,67 @@
|
|||||||
"no_data_yet": "Belum ada data",
|
"no_data_yet": "Belum ada data",
|
||||||
"@no_data_yet": {},
|
"@no_data_yet": {},
|
||||||
"total_inventory_value": "Total Nilai Inventori",
|
"total_inventory_value": "Total Nilai Inventori",
|
||||||
"@total_inventory_value": {}
|
"@total_inventory_value": {},
|
||||||
|
"profit_sharing": "Bagi Hasil",
|
||||||
|
"@profit_sharing": {},
|
||||||
|
"profit_sharing_desc": "Alokasi omzet untuk belanja, owner, dan tim",
|
||||||
|
"@profit_sharing_desc": {},
|
||||||
|
"profit_sharing_allocation": "Alokasi Bagi Hasil",
|
||||||
|
"@profit_sharing_allocation": {},
|
||||||
|
"share_purchase": "Belanja",
|
||||||
|
"@share_purchase": {},
|
||||||
|
"share_owner": "Owner",
|
||||||
|
"@share_owner": {},
|
||||||
|
"share_team": "Tim",
|
||||||
|
"@share_team": {},
|
||||||
|
"weekly": "Mingguan",
|
||||||
|
"@weekly": {},
|
||||||
|
"monthly": "Bulanan",
|
||||||
|
"@monthly": {},
|
||||||
|
"period_breakdown": "Rincian Periode",
|
||||||
|
"@period_breakdown": {},
|
||||||
|
"revenue_by_brand": "Omzet per Brand",
|
||||||
|
"@revenue_by_brand": {},
|
||||||
|
"week_count": "{count} minggu",
|
||||||
|
"@week_count": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"type": "int",
|
||||||
|
"example": "5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"order_count_label": "{count} pesanan",
|
||||||
|
"@order_count_label": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {
|
||||||
|
"type": "int",
|
||||||
|
"example": "328"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gross_margin": "Margin Kotor",
|
||||||
|
"@gross_margin": {},
|
||||||
|
"parent_category_summary": "Ringkasan Kategori Induk",
|
||||||
|
"@parent_category_summary": {},
|
||||||
|
"sub_category": "Sub Kategori",
|
||||||
|
"@sub_category": {},
|
||||||
|
"qty": "Qty",
|
||||||
|
"@qty": {},
|
||||||
|
"std_hpp": "Std HPP",
|
||||||
|
"@std_hpp": {},
|
||||||
|
"real_hpp": "Real HPP",
|
||||||
|
"@real_hpp": {},
|
||||||
|
"status": "Status",
|
||||||
|
"@status": {},
|
||||||
|
"grand_total": "TOTAL",
|
||||||
|
"@grand_total": {},
|
||||||
|
"status_healthy": "Sehat",
|
||||||
|
"@status_healthy": {},
|
||||||
|
"status_watch": "Waspada",
|
||||||
|
"@status_watch": {},
|
||||||
|
"status_critical": "Tidak Sehat",
|
||||||
|
"@status_critical": {},
|
||||||
|
"tap_row_for_detail": "Ketuk kartu untuk melihat rincian sub kategori dan produk",
|
||||||
|
"@tap_row_for_detail": {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1564,6 +1564,150 @@ abstract class AppLocalizations {
|
|||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Total Inventory Value'**
|
/// **'Total Inventory Value'**
|
||||||
String get total_inventory_value;
|
String get total_inventory_value;
|
||||||
|
|
||||||
|
/// No description provided for @profit_sharing.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Profit Sharing'**
|
||||||
|
String get profit_sharing;
|
||||||
|
|
||||||
|
/// No description provided for @profit_sharing_desc.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Revenue allocation for purchasing, owner, and team'**
|
||||||
|
String get profit_sharing_desc;
|
||||||
|
|
||||||
|
/// No description provided for @profit_sharing_allocation.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Profit Sharing Allocation'**
|
||||||
|
String get profit_sharing_allocation;
|
||||||
|
|
||||||
|
/// No description provided for @share_purchase.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Purchasing'**
|
||||||
|
String get share_purchase;
|
||||||
|
|
||||||
|
/// No description provided for @share_owner.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Owner'**
|
||||||
|
String get share_owner;
|
||||||
|
|
||||||
|
/// No description provided for @share_team.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Team'**
|
||||||
|
String get share_team;
|
||||||
|
|
||||||
|
/// No description provided for @weekly.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Weekly'**
|
||||||
|
String get weekly;
|
||||||
|
|
||||||
|
/// No description provided for @monthly.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Monthly'**
|
||||||
|
String get monthly;
|
||||||
|
|
||||||
|
/// No description provided for @period_breakdown.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Period Breakdown'**
|
||||||
|
String get period_breakdown;
|
||||||
|
|
||||||
|
/// No description provided for @revenue_by_brand.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Revenue by Brand'**
|
||||||
|
String get revenue_by_brand;
|
||||||
|
|
||||||
|
/// No description provided for @week_count.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'{count} weeks'**
|
||||||
|
String week_count(int count);
|
||||||
|
|
||||||
|
/// No description provided for @order_count_label.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'{count} orders'**
|
||||||
|
String order_count_label(int count);
|
||||||
|
|
||||||
|
/// No description provided for @gross_margin.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Gross Margin'**
|
||||||
|
String get gross_margin;
|
||||||
|
|
||||||
|
/// No description provided for @parent_category_summary.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Parent Category Summary'**
|
||||||
|
String get parent_category_summary;
|
||||||
|
|
||||||
|
/// No description provided for @sub_category.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Sub Category'**
|
||||||
|
String get sub_category;
|
||||||
|
|
||||||
|
/// No description provided for @qty.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Qty'**
|
||||||
|
String get qty;
|
||||||
|
|
||||||
|
/// No description provided for @std_hpp.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Std HPP'**
|
||||||
|
String get std_hpp;
|
||||||
|
|
||||||
|
/// No description provided for @real_hpp.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Real HPP'**
|
||||||
|
String get real_hpp;
|
||||||
|
|
||||||
|
/// No description provided for @status.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Status'**
|
||||||
|
String get status;
|
||||||
|
|
||||||
|
/// No description provided for @grand_total.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'TOTAL'**
|
||||||
|
String get grand_total;
|
||||||
|
|
||||||
|
/// No description provided for @status_healthy.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Healthy'**
|
||||||
|
String get status_healthy;
|
||||||
|
|
||||||
|
/// No description provided for @status_watch.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Watch'**
|
||||||
|
String get status_watch;
|
||||||
|
|
||||||
|
/// No description provided for @status_critical.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Unhealthy'**
|
||||||
|
String get status_critical;
|
||||||
|
|
||||||
|
/// No description provided for @tap_row_for_detail.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Tap a card to see sub category and product details'**
|
||||||
|
String get tap_row_for_detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
|||||||
@@ -756,4 +756,80 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get total_inventory_value => 'Total Inventory Value';
|
String get total_inventory_value => 'Total Inventory Value';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get profit_sharing => 'Profit Sharing';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get profit_sharing_desc => 'Revenue allocation for purchasing, owner, and team';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get profit_sharing_allocation => 'Profit Sharing Allocation';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get share_purchase => 'Purchasing';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get share_owner => 'Owner';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get share_team => 'Team';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get weekly => 'Weekly';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get monthly => 'Monthly';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get period_breakdown => 'Period Breakdown';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get revenue_by_brand => 'Revenue by Brand';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String week_count(int count) {
|
||||||
|
return '$count weeks';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String order_count_label(int count) {
|
||||||
|
return '$count orders';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get gross_margin => 'Gross Margin';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get parent_category_summary => 'Parent Category Summary';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sub_category => 'Sub Category';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get qty => 'Qty';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get std_hpp => 'Std HPP';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get real_hpp => 'Real HPP';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status => 'Status';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get grand_total => 'TOTAL';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status_healthy => 'Healthy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status_watch => 'Watch';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status_critical => 'Unhealthy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tap_row_for_detail => 'Tap a card to see sub category and product details';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -756,4 +756,80 @@ class AppLocalizationsId extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get total_inventory_value => 'Total Nilai Inventori';
|
String get total_inventory_value => 'Total Nilai Inventori';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get profit_sharing => 'Bagi Hasil';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get profit_sharing_desc => 'Alokasi omzet untuk belanja, owner, dan tim';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get profit_sharing_allocation => 'Alokasi Bagi Hasil';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get share_purchase => 'Belanja';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get share_owner => 'Owner';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get share_team => 'Tim';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get weekly => 'Mingguan';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get monthly => 'Bulanan';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get period_breakdown => 'Rincian Periode';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get revenue_by_brand => 'Omzet per Brand';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String week_count(int count) {
|
||||||
|
return '$count minggu';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String order_count_label(int count) {
|
||||||
|
return '$count pesanan';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get gross_margin => 'Margin Kotor';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get parent_category_summary => 'Ringkasan Kategori Induk';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sub_category => 'Sub Kategori';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get qty => 'Qty';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get std_hpp => 'Std HPP';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get real_hpp => 'Real HPP';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status => 'Status';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get grand_total => 'TOTAL';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status_healthy => 'Sehat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status_watch => 'Waspada';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get status_critical => 'Tidak Sehat';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tap_row_for_detail => 'Ketuk kartu untuk melihat rincian sub kategori dan produk';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import 'widgets/feature.dart';
|
|||||||
import 'widgets/header.dart';
|
import 'widgets/header.dart';
|
||||||
import 'widgets/home_top_products.dart';
|
import 'widgets/home_top_products.dart';
|
||||||
import 'widgets/home_warnings.dart';
|
import 'widgets/home_warnings.dart';
|
||||||
|
import 'widgets/profit_sharing_banner.dart';
|
||||||
import 'widgets/stats.dart';
|
import 'widgets/stats.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
@@ -201,6 +202,7 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
HomeFeature(),
|
HomeFeature(),
|
||||||
|
HomeProfitSharingBanner(),
|
||||||
HomeWarnings(),
|
HomeWarnings(),
|
||||||
HomeStats(overview: state.dashboard.overview),
|
HomeStats(overview: state.dashboard.overview),
|
||||||
HomeTopProducts(
|
HomeTopProducts(
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hugeicons/hugeicons.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import '../../../router/app_router.gr.dart';
|
||||||
|
|
||||||
|
/// Pintu masuk ke halaman bagi hasil dari beranda.
|
||||||
|
class HomeProfitSharingBanner extends StatelessWidget {
|
||||||
|
const HomeProfitSharingBanner({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(AppValue.radius),
|
||||||
|
onTap: () => context.router.push(const ProfitSharingRoute()),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: const LinearGradient(
|
||||||
|
colors: AppColor.primaryGradient,
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(AppValue.radius),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.primary.withOpacity(0.25),
|
||||||
|
blurRadius: 12,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.18),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: const HugeIcon(
|
||||||
|
icon: HugeIcons.strokeRoundedPieChart,
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(14),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.profit_sharing,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
context.lang.profit_sharing_desc,
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.8),
|
||||||
|
),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
const Icon(
|
||||||
|
Icons.chevron_right_rounded,
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
|
import '../../../application/analytic/profit_sharing_detail_loader/profit_sharing_detail_loader_bloc.dart';
|
||||||
|
import '../../../common/extension/extension.dart';
|
||||||
|
import '../../../common/theme/theme.dart';
|
||||||
|
import '../../../domain/analytic/analytic.dart';
|
||||||
|
import '../../../injection.dart';
|
||||||
|
import '../../components/spacer/spacer.dart';
|
||||||
|
import 'widgets/profit_sharing_allocation.dart';
|
||||||
|
import 'widgets/profit_sharing_detail_header.dart';
|
||||||
|
import 'widgets/profit_sharing_status.dart';
|
||||||
|
import 'widgets/profit_sharing_subcategories.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class ProfitSharingDetailPage extends StatelessWidget
|
||||||
|
implements AutoRouteWrapper {
|
||||||
|
final String parentCategoryId;
|
||||||
|
final String parentCategoryName;
|
||||||
|
final DateTime dateFrom;
|
||||||
|
final DateTime dateTo;
|
||||||
|
|
||||||
|
const ProfitSharingDetailPage({
|
||||||
|
super.key,
|
||||||
|
required this.parentCategoryId,
|
||||||
|
required this.parentCategoryName,
|
||||||
|
required this.dateFrom,
|
||||||
|
required this.dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget wrappedRoute(BuildContext context) => BlocProvider(
|
||||||
|
create: (_) => getIt<ProfitSharingDetailLoaderBloc>()..add(_fetchEvent()),
|
||||||
|
child: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
ProfitSharingDetailLoaderEvent _fetchEvent() =>
|
||||||
|
ProfitSharingDetailLoaderEvent.fetched(
|
||||||
|
parentCategoryId: parentCategoryId,
|
||||||
|
dateFrom: dateFrom,
|
||||||
|
dateTo: dateTo,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: AppColor.background,
|
||||||
|
body:
|
||||||
|
BlocBuilder<
|
||||||
|
ProfitSharingDetailLoaderBloc,
|
||||||
|
ProfitSharingDetailLoaderState
|
||||||
|
>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return RefreshIndicator(
|
||||||
|
backgroundColor: AppColor.white,
|
||||||
|
color: AppColor.primary,
|
||||||
|
onRefresh: () async {
|
||||||
|
context.read<ProfitSharingDetailLoaderBloc>().add(
|
||||||
|
_fetchEvent(),
|
||||||
|
);
|
||||||
|
await context
|
||||||
|
.read<ProfitSharingDetailLoaderBloc>()
|
||||||
|
.stream
|
||||||
|
.firstWhere((s) => !s.isFetching);
|
||||||
|
},
|
||||||
|
child: CustomScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: ProfitSharingDetailHeader(
|
||||||
|
state: state,
|
||||||
|
fallbackTitle: parentCategoryName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
if (state.isFetching)
|
||||||
|
SliverToBoxAdapter(child: _buildShimmer())
|
||||||
|
else ...[
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: _SummaryCard(summary: state.detail.summary),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: ProfitSharingAllocation(
|
||||||
|
budget: state.detail.budget,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: ProfitSharingSubCategories(
|
||||||
|
categories: state.detail.categories,
|
||||||
|
expandedCategoryId: state.expandedCategoryId,
|
||||||
|
onToggle: (categoryId) =>
|
||||||
|
context.read<ProfitSharingDetailLoaderBloc>().add(
|
||||||
|
ProfitSharingDetailLoaderEvent.expandedCategoryChanged(
|
||||||
|
categoryId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SizedBox(height: 100)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildShimmer() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_shimmerBox(height: 160),
|
||||||
|
const SpaceHeight(16),
|
||||||
|
_shimmerBox(height: 240),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _shimmerBox({required double height}) {
|
||||||
|
return Shimmer.fromColors(
|
||||||
|
baseColor: Colors.grey[300]!,
|
||||||
|
highlightColor: Colors.grey[100]!,
|
||||||
|
child: Container(
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SummaryCard extends StatelessWidget {
|
||||||
|
final ProfitSharingCategory summary;
|
||||||
|
|
||||||
|
const _SummaryCard({required this.summary});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.textLight.withOpacity(0.08),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.summary,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.sub_category,
|
||||||
|
value: '${summary.categoryCount}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.products,
|
||||||
|
value: '${summary.productCount}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.orders,
|
||||||
|
value: summary.orderCount.thousandFormat,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 12),
|
||||||
|
child: Divider(height: 1, color: AppColor.borderLight),
|
||||||
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.std_hpp,
|
||||||
|
value: formatPercent(summary.standardHppPercentage),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.real_hpp,
|
||||||
|
value: formatPercent(summary.realHppPercentage),
|
||||||
|
valueColor: statusColor(summary.realHppPercentage),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.gross_profit,
|
||||||
|
value: summary.grossProfit.currencyFormatRp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
|
import '../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart';
|
||||||
|
import '../../../common/theme/theme.dart';
|
||||||
|
import '../../../injection.dart';
|
||||||
|
import '../../components/field/date_range_picker_field.dart';
|
||||||
|
import '../../components/spacer/spacer.dart';
|
||||||
|
import '../../router/app_router.gr.dart';
|
||||||
|
import 'widgets/profit_sharing_allocation.dart';
|
||||||
|
import 'widgets/profit_sharing_categories.dart';
|
||||||
|
import 'widgets/profit_sharing_header.dart';
|
||||||
|
import 'widgets/profit_sharing_periods.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class ProfitSharingPage extends StatefulWidget implements AutoRouteWrapper {
|
||||||
|
const ProfitSharingPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ProfitSharingPage> createState() => _ProfitSharingPageState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget wrappedRoute(BuildContext context) => BlocProvider(
|
||||||
|
create: (_) =>
|
||||||
|
getIt<ProfitSharingLoaderBloc>()
|
||||||
|
..add(ProfitSharingLoaderEvent.fetched()),
|
||||||
|
child: this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfitSharingPageState extends State<ProfitSharingPage>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _fadeController;
|
||||||
|
late Animation<double> _fadeAnimation;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_fadeController = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
|
||||||
|
_fadeAnimation = Tween<double>(
|
||||||
|
begin: 0.0,
|
||||||
|
end: 1.0,
|
||||||
|
).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeIn));
|
||||||
|
|
||||||
|
_fadeController.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_fadeController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: AppColor.background,
|
||||||
|
body: BlocListener<ProfitSharingLoaderBloc, ProfitSharingLoaderState>(
|
||||||
|
listenWhen: (previous, current) =>
|
||||||
|
previous.dateFrom != current.dateFrom ||
|
||||||
|
previous.dateTo != current.dateTo,
|
||||||
|
listener: (context, state) {
|
||||||
|
context.read<ProfitSharingLoaderBloc>().add(
|
||||||
|
const ProfitSharingLoaderEvent.fetched(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: BlocBuilder<ProfitSharingLoaderBloc, ProfitSharingLoaderState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return RefreshIndicator(
|
||||||
|
backgroundColor: AppColor.white,
|
||||||
|
color: AppColor.primary,
|
||||||
|
onRefresh: () async {
|
||||||
|
context.read<ProfitSharingLoaderBloc>().add(
|
||||||
|
const ProfitSharingLoaderEvent.fetched(),
|
||||||
|
);
|
||||||
|
await context.read<ProfitSharingLoaderBloc>().stream.firstWhere(
|
||||||
|
(s) => !s.isFetching,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: CustomScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: _fadeAnimation,
|
||||||
|
child: ProfitSharingHeader(state: state),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: _fadeAnimation,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: DateRangePickerField(
|
||||||
|
startDate: state.dateFrom,
|
||||||
|
endDate: state.dateTo,
|
||||||
|
onChanged: (startDate, endDate) {
|
||||||
|
if (startDate == null || endDate == null) return;
|
||||||
|
context.read<ProfitSharingLoaderBloc>().add(
|
||||||
|
ProfitSharingLoaderEvent.rangeDateChanged(
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (state.isFetching)
|
||||||
|
SliverToBoxAdapter(child: _buildShimmer())
|
||||||
|
else ...[
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: _fadeAnimation,
|
||||||
|
child: ProfitSharingCategories(
|
||||||
|
categories: state.profitSharing.categories,
|
||||||
|
onCategoryTap: (category) => context.router.push(
|
||||||
|
ProfitSharingDetailRoute(
|
||||||
|
parentCategoryId: category.parentCategoryId,
|
||||||
|
parentCategoryName: category.parentCategoryName,
|
||||||
|
dateFrom: state.dateFrom,
|
||||||
|
dateTo: state.dateTo,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: _fadeAnimation,
|
||||||
|
child: ProfitSharingAllocation(
|
||||||
|
budget: state.profitSharing.budget,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SpaceHeight(16)),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: _fadeAnimation,
|
||||||
|
child: ProfitSharingPeriods(
|
||||||
|
state: state,
|
||||||
|
onPeriodTypeChanged: (type) {
|
||||||
|
context.read<ProfitSharingLoaderBloc>().add(
|
||||||
|
ProfitSharingLoaderEvent.periodTypeChanged(type),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
const SliverToBoxAdapter(child: SizedBox(height: 100)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildShimmer() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_shimmerBox(height: 240),
|
||||||
|
const SpaceHeight(16),
|
||||||
|
_shimmerBox(height: 300),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _shimmerBox({required double height}) {
|
||||||
|
return Shimmer.fromColors(
|
||||||
|
baseColor: Colors.grey[300]!,
|
||||||
|
highlightColor: Colors.grey[100]!,
|
||||||
|
child: Container(
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
/// Label rentang periode ringkas, contoh: "27 Jul - 2 Agu 2026".
|
||||||
|
String formatPeriodLabel(DateTime from, DateTime to) {
|
||||||
|
final dayMonth = DateFormat('d MMM', 'id_ID');
|
||||||
|
final dayMonthYear = DateFormat('d MMM yyyy', 'id_ID');
|
||||||
|
|
||||||
|
if (from.year == to.year && from.month == to.month && from.day == to.day) {
|
||||||
|
return dayMonthYear.format(from);
|
||||||
|
}
|
||||||
|
if (from.year == to.year) {
|
||||||
|
return '${dayMonth.format(from)} - ${dayMonthYear.format(to)}';
|
||||||
|
}
|
||||||
|
return '${dayMonthYear.format(from)} - ${dayMonthYear.format(to)}';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Label bulan dari format API "2026-08" menjadi "Agustus 2026".
|
||||||
|
String formatMonthLabel(String month, DateTime fallback) {
|
||||||
|
final parts = month.split('-');
|
||||||
|
if (parts.length == 2) {
|
||||||
|
final year = int.tryParse(parts[0]);
|
||||||
|
final monthNumber = int.tryParse(parts[1]);
|
||||||
|
if (year != null && monthNumber != null) {
|
||||||
|
return DateFormat(
|
||||||
|
'MMMM yyyy',
|
||||||
|
'id_ID',
|
||||||
|
).format(DateTime(year, monthNumber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DateFormat('MMMM yyyy', 'id_ID').format(fallback);
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../../domain/analytic/analytic.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
|
||||||
|
/// Warna tetap untuk tiap pos bagi hasil supaya konsisten di semua bagian.
|
||||||
|
class ProfitSharingColor {
|
||||||
|
static const Color purchase = Color(0xFF2196F3);
|
||||||
|
static const Color owner = Color(0xFF4CAF50);
|
||||||
|
static const Color team = Color(0xFFFF9800);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfitSharingAllocation extends StatelessWidget {
|
||||||
|
final ProfitSharingBudget budget;
|
||||||
|
|
||||||
|
const ProfitSharingAllocation({super.key, required this.budget});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final total = budget.total;
|
||||||
|
final percentages = budget.percentages;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.textLight.withOpacity(0.08),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.profit_sharing_allocation,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
ProfitSharingBar(
|
||||||
|
purchase: percentages.purchase,
|
||||||
|
owner: percentages.owner,
|
||||||
|
team: percentages.team,
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(20),
|
||||||
|
|
||||||
|
_row(
|
||||||
|
context: context,
|
||||||
|
color: ProfitSharingColor.purchase,
|
||||||
|
label: context.lang.share_purchase,
|
||||||
|
percentage: percentages.purchase,
|
||||||
|
amount: total.limitPurchase,
|
||||||
|
),
|
||||||
|
const Divider(height: 24, color: AppColor.borderLight),
|
||||||
|
_row(
|
||||||
|
context: context,
|
||||||
|
color: ProfitSharingColor.owner,
|
||||||
|
label: context.lang.share_owner,
|
||||||
|
percentage: percentages.owner,
|
||||||
|
amount: total.limitOwner,
|
||||||
|
),
|
||||||
|
const Divider(height: 24, color: AppColor.borderLight),
|
||||||
|
_row(
|
||||||
|
context: context,
|
||||||
|
color: ProfitSharingColor.team,
|
||||||
|
label: context.lang.share_team,
|
||||||
|
percentage: percentages.team,
|
||||||
|
amount: total.limitTeam,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _row({
|
||||||
|
required BuildContext context,
|
||||||
|
required Color color,
|
||||||
|
required String label,
|
||||||
|
required double percentage,
|
||||||
|
required int amount,
|
||||||
|
}) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
const SpaceWidth(10),
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color.withOpacity(0.12),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'${percentage.toStringAsFixed(percentage % 1 == 0 ? 0 : 1)}%',
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: color,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
amount.currencyFormatRp,
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bar proporsi belanja / owner / tim.
|
||||||
|
class ProfitSharingBar extends StatelessWidget {
|
||||||
|
final double purchase;
|
||||||
|
final double owner;
|
||||||
|
final double team;
|
||||||
|
final double height;
|
||||||
|
|
||||||
|
const ProfitSharingBar({
|
||||||
|
super.key,
|
||||||
|
required this.purchase,
|
||||||
|
required this.owner,
|
||||||
|
required this.team,
|
||||||
|
this.height = 12,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final total = purchase + owner + team;
|
||||||
|
if (total <= 0) {
|
||||||
|
return Container(
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.borderLight,
|
||||||
|
borderRadius: BorderRadius.circular(height),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(height),
|
||||||
|
child: SizedBox(
|
||||||
|
height: height,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
_segment(purchase, ProfitSharingColor.purchase),
|
||||||
|
_segment(owner, ProfitSharingColor.owner),
|
||||||
|
_segment(team, ProfitSharingColor.team),
|
||||||
|
].whereType<Widget>().toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Segmen dilewati saat porsinya 0 supaya Expanded tidak dipakai dengan flex 0.
|
||||||
|
Widget? _segment(double value, Color color) {
|
||||||
|
final flex = (value * 100).round();
|
||||||
|
if (flex <= 0) return null;
|
||||||
|
return Expanded(
|
||||||
|
flex: flex,
|
||||||
|
child: Container(color: color),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,324 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../../domain/analytic/analytic.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import 'profit_sharing_status.dart';
|
||||||
|
|
||||||
|
/// Ringkasan omzet & HPP per kategori induk (parent category).
|
||||||
|
/// Tiap kartu bisa diketuk untuk melihat rincian sub kategori & produknya.
|
||||||
|
class ProfitSharingCategories extends StatelessWidget {
|
||||||
|
final List<ProfitSharingCategory> categories;
|
||||||
|
final ValueChanged<ProfitSharingCategory> onCategoryTap;
|
||||||
|
|
||||||
|
const ProfitSharingCategories({
|
||||||
|
super.key,
|
||||||
|
required this.categories,
|
||||||
|
required this.onCategoryTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final sorted = [...categories]
|
||||||
|
..sort((a, b) => b.totalRevenue.compareTo(a.totalRevenue));
|
||||||
|
|
||||||
|
final totalRevenue = sorted.fold<int>(0, (sum, e) => sum + e.totalRevenue);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.textLight.withOpacity(0.08),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.parent_category_summary,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
context.lang.tap_row_for_detail,
|
||||||
|
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
if (sorted.isEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 24),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
context.lang.no_data_yet,
|
||||||
|
style: AppStyle.sm.copyWith(color: AppColor.textSecondary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else ...[
|
||||||
|
...sorted.map(
|
||||||
|
(category) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: _CategoryCard(
|
||||||
|
category: category,
|
||||||
|
share: totalRevenue == 0
|
||||||
|
? 0
|
||||||
|
: category.totalRevenue / totalRevenue,
|
||||||
|
onTap: () => onCategoryTap(category),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_TotalCard(categories: sorted),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CategoryCard extends StatelessWidget {
|
||||||
|
final ProfitSharingCategory category;
|
||||||
|
final double share;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
const _CategoryCard({
|
||||||
|
required this.category,
|
||||||
|
required this.share,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.background,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: AppColor.borderLight),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
category.parentCategoryName,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
ProfitSharingStatusBadge(
|
||||||
|
realHppPercentage: category.realHppPercentage,
|
||||||
|
),
|
||||||
|
const Icon(
|
||||||
|
Icons.chevron_right_rounded,
|
||||||
|
color: AppColor.textSecondary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(8),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
category.totalRevenue.currencyFormatRp,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
color: AppColor.primary,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
formatPercent(share * 100),
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.textSecondary,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(8),
|
||||||
|
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
value: share.clamp(0.0, 1.0),
|
||||||
|
minHeight: 6,
|
||||||
|
backgroundColor: AppColor.borderLight,
|
||||||
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
|
AppColor.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(12),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.qty,
|
||||||
|
value: category.totalQuantity.thousandFormat,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.products,
|
||||||
|
value: '${category.productCount}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.sub_category,
|
||||||
|
value: '${category.categoryCount}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: Divider(height: 1, color: AppColor.border),
|
||||||
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.std_hpp,
|
||||||
|
value: formatPercent(category.standardHppPercentage),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.real_hpp,
|
||||||
|
value: formatPercent(category.realHppPercentage),
|
||||||
|
valueColor: statusColor(category.realHppPercentage),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TotalCard extends StatelessWidget {
|
||||||
|
final List<ProfitSharingCategory> categories;
|
||||||
|
|
||||||
|
const _TotalCard({required this.categories});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final totalQuantity = categories.fold<int>(
|
||||||
|
0,
|
||||||
|
(sum, e) => sum + e.totalQuantity,
|
||||||
|
);
|
||||||
|
final totalRevenue = categories.fold<int>(
|
||||||
|
0,
|
||||||
|
(sum, e) => sum + e.totalRevenue,
|
||||||
|
);
|
||||||
|
final totalStandardHpp = categories.fold<int>(
|
||||||
|
0,
|
||||||
|
(sum, e) => sum + e.totalStandardHpp,
|
||||||
|
);
|
||||||
|
final totalFifoHpp = categories.fold<int>(
|
||||||
|
0,
|
||||||
|
(sum, e) => sum + e.totalFifoHpp,
|
||||||
|
);
|
||||||
|
|
||||||
|
double percentOf(int hpp) =>
|
||||||
|
totalRevenue == 0 ? 0 : (hpp / totalRevenue) * 100;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.primary.withOpacity(0.06),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
context.lang.grand_total,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
totalRevenue.currencyFormatRp,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
color: AppColor.primary,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(12),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.qty,
|
||||||
|
value: totalQuantity.thousandFormat,
|
||||||
|
isBold: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.std_hpp,
|
||||||
|
value: formatPercent(percentOf(totalStandardHpp)),
|
||||||
|
isBold: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.real_hpp,
|
||||||
|
value: formatPercent(percentOf(totalFifoHpp)),
|
||||||
|
isBold: true,
|
||||||
|
valueColor: statusColor(percentOf(totalFifoHpp)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
|
import '../../../../application/analytic/profit_sharing_detail_loader/profit_sharing_detail_loader_bloc.dart';
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import 'period_label.dart';
|
||||||
|
import 'profit_sharing_status.dart';
|
||||||
|
|
||||||
|
class ProfitSharingDetailHeader extends StatelessWidget {
|
||||||
|
final ProfitSharingDetailLoaderState state;
|
||||||
|
final String fallbackTitle;
|
||||||
|
|
||||||
|
const ProfitSharingDetailHeader({
|
||||||
|
super.key,
|
||||||
|
required this.state,
|
||||||
|
required this.fallbackTitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final detail = state.detail;
|
||||||
|
final summary = detail.summary;
|
||||||
|
final title = detail.parentCategoryName.isNotEmpty
|
||||||
|
? detail.parentCategoryName
|
||||||
|
: fallbackTitle;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: AppColor.primaryGradient,
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(24),
|
||||||
|
bottomRight: Radius.circular(24),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
bottom: false,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => context.router.maybePop(),
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.15),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.chevron_left_rounded,
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: AppStyle.xl.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
formatPeriodLabel(state.dateFrom, state.dateTo),
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.75),
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(24),
|
||||||
|
|
||||||
|
if (state.isFetching)
|
||||||
|
_shimmerBox(width: 220, height: 36)
|
||||||
|
else
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
summary.totalRevenue.currencyFormatRp,
|
||||||
|
style: AppStyle.h1.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
fontSize: 30,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ProfitSharingStatusBadge(
|
||||||
|
realHppPercentage: summary.realHppPercentage,
|
||||||
|
onDarkBackground: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(4),
|
||||||
|
Text(
|
||||||
|
context.lang.total_revenue,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.75),
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
if (state.isFetching)
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
_shimmerBox(width: 120, height: 32, radius: 20),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
_shimmerBox(width: 120, height: 32, radius: 20),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
_chip(
|
||||||
|
'${context.lang.qty} ${summary.totalQuantity.thousandFormat}',
|
||||||
|
),
|
||||||
|
_chip(context.lang.order_count_label(summary.orderCount)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _chip(String label) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.15),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
border: Border.all(color: AppColor.textWhite.withOpacity(0.25)),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _shimmerBox({
|
||||||
|
required double width,
|
||||||
|
required double height,
|
||||||
|
double radius = 8,
|
||||||
|
}) {
|
||||||
|
return Shimmer.fromColors(
|
||||||
|
baseColor: AppColor.textWhite.withOpacity(0.3),
|
||||||
|
highlightColor: AppColor.textWhite.withOpacity(0.6),
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.3),
|
||||||
|
borderRadius: BorderRadius.circular(radius),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:shimmer/shimmer.dart';
|
||||||
|
|
||||||
|
import '../../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart';
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
|
||||||
|
class ProfitSharingHeader extends StatelessWidget {
|
||||||
|
final ProfitSharingLoaderState state;
|
||||||
|
|
||||||
|
const ProfitSharingHeader({super.key, required this.state});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final budget = state.profitSharing.budget;
|
||||||
|
final outletLabel = state.profitSharing.outletName.isNotEmpty
|
||||||
|
? state.profitSharing.outletName
|
||||||
|
: context.lang.all_outlets;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: AppColor.primaryGradient,
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(24),
|
||||||
|
bottomRight: Radius.circular(24),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
bottom: false,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 24),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (context.router.canPop()) ...[
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => context.router.maybePop(),
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.15),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.chevron_left_rounded,
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(12),
|
||||||
|
],
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.profit_sharing,
|
||||||
|
style: AppStyle.xl.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
outletLabel,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.75),
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(24),
|
||||||
|
|
||||||
|
state.isFetching
|
||||||
|
? _shimmerBox(width: 220, height: 36)
|
||||||
|
: Text(
|
||||||
|
budget.total.revenue.currencyFormatRp,
|
||||||
|
style: AppStyle.h1.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
fontSize: 32,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(4),
|
||||||
|
Text(
|
||||||
|
context.lang.total_revenue,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.75),
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
state.isFetching
|
||||||
|
? _shimmerBox(width: 140, height: 32, radius: 20)
|
||||||
|
: _chip(
|
||||||
|
context.lang.order_count_label(budget.total.orderCount),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _chip(String label) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.15),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
border: Border.all(color: AppColor.textWhite.withOpacity(0.25)),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textWhite,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _shimmerBox({
|
||||||
|
required double width,
|
||||||
|
required double height,
|
||||||
|
double radius = 8,
|
||||||
|
}) {
|
||||||
|
return Shimmer.fromColors(
|
||||||
|
baseColor: AppColor.textWhite.withOpacity(0.3),
|
||||||
|
highlightColor: AppColor.textWhite.withOpacity(0.6),
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.textWhite.withOpacity(0.3),
|
||||||
|
borderRadius: BorderRadius.circular(radius),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../application/analytic/profit_sharing_loader/profit_sharing_loader_bloc.dart';
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../../domain/analytic/analytic.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import 'period_label.dart';
|
||||||
|
import 'profit_sharing_allocation.dart';
|
||||||
|
|
||||||
|
class ProfitSharingPeriods extends StatelessWidget {
|
||||||
|
final ProfitSharingLoaderState state;
|
||||||
|
final ValueChanged<ProfitSharingPeriodType> onPeriodTypeChanged;
|
||||||
|
|
||||||
|
const ProfitSharingPeriods({
|
||||||
|
super.key,
|
||||||
|
required this.state,
|
||||||
|
required this.onPeriodTypeChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final periods = state.periods;
|
||||||
|
final percentages = state.profitSharing.budget.percentages;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.textLight.withOpacity(0.08),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.period_breakdown,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
_tabs(context),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
if (periods.isEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 24),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
context.lang.no_data_yet,
|
||||||
|
style: AppStyle.sm.copyWith(color: AppColor.textSecondary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
...periods.map(
|
||||||
|
(period) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: _PeriodCard(period: period, percentages: percentages),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _tabs(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.background,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
_tab(
|
||||||
|
context: context,
|
||||||
|
label: context.lang.weekly,
|
||||||
|
type: ProfitSharingPeriodType.weekly,
|
||||||
|
),
|
||||||
|
_tab(
|
||||||
|
context: context,
|
||||||
|
label: context.lang.monthly,
|
||||||
|
type: ProfitSharingPeriodType.monthly,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _tab({
|
||||||
|
required BuildContext context,
|
||||||
|
required String label,
|
||||||
|
required ProfitSharingPeriodType type,
|
||||||
|
}) {
|
||||||
|
final isSelected = state.periodType == type;
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => onPeriodTypeChanged(type),
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isSelected ? AppColor.primary : Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: isSelected ? AppColor.textWhite : AppColor.textSecondary,
|
||||||
|
fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PeriodCard extends StatelessWidget {
|
||||||
|
final ProfitSharingPeriod period;
|
||||||
|
final ProfitSharingPercentage percentages;
|
||||||
|
|
||||||
|
const _PeriodCard({required this.period, required this.percentages});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final isMonthly = period.month.isNotEmpty;
|
||||||
|
|
||||||
|
final title = isMonthly
|
||||||
|
? formatMonthLabel(period.month, period.periodStart)
|
||||||
|
: formatPeriodLabel(period.periodStart, period.periodEnd);
|
||||||
|
|
||||||
|
final subtitle = isMonthly
|
||||||
|
? '${formatPeriodLabel(period.periodStart, period.periodEnd)} - ${context.lang.week_count(period.weekCount)}'
|
||||||
|
: context.lang.order_count_label(period.orderCount);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.background,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: AppColor.borderLight),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
subtitle,
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.textSecondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
Text(
|
||||||
|
period.revenue.currencyFormatRp,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: AppColor.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(12),
|
||||||
|
|
||||||
|
ProfitSharingBar(
|
||||||
|
purchase: percentages.purchase,
|
||||||
|
owner: percentages.owner,
|
||||||
|
team: percentages.team,
|
||||||
|
height: 6,
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(12),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
_share(
|
||||||
|
context.lang.share_purchase,
|
||||||
|
period.limitPurchase,
|
||||||
|
ProfitSharingColor.purchase,
|
||||||
|
),
|
||||||
|
_share(
|
||||||
|
context.lang.share_owner,
|
||||||
|
period.limitOwner,
|
||||||
|
ProfitSharingColor.owner,
|
||||||
|
),
|
||||||
|
_share(
|
||||||
|
context.lang.share_team,
|
||||||
|
period.limitTeam,
|
||||||
|
ProfitSharingColor.team,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _share(String label, int amount, Color color) {
|
||||||
|
return Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
const SpaceWidth(6),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
amount.currencyFormatRp,
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
|
||||||
|
/// Ambang kesehatan berdasarkan % HPP riil terhadap omzet.
|
||||||
|
/// Ubah di sini kalau target margin bisnis berubah.
|
||||||
|
class HppThreshold {
|
||||||
|
static const double healthy = 70;
|
||||||
|
static const double watch = 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatPercent(double value) => '${value.toStringAsFixed(1)}%';
|
||||||
|
|
||||||
|
Color statusColor(double realHppPercentage) {
|
||||||
|
if (realHppPercentage <= HppThreshold.healthy) return AppColor.success;
|
||||||
|
if (realHppPercentage <= HppThreshold.watch) return AppColor.warning;
|
||||||
|
return AppColor.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
String statusLabel(BuildContext context, double realHppPercentage) {
|
||||||
|
if (realHppPercentage <= HppThreshold.healthy) {
|
||||||
|
return context.lang.status_healthy;
|
||||||
|
}
|
||||||
|
if (realHppPercentage <= HppThreshold.watch) return context.lang.status_watch;
|
||||||
|
return context.lang.status_critical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pill status margin (Sehat / Waspada / Tidak Sehat).
|
||||||
|
class ProfitSharingStatusBadge extends StatelessWidget {
|
||||||
|
final double realHppPercentage;
|
||||||
|
final bool onDarkBackground;
|
||||||
|
|
||||||
|
const ProfitSharingStatusBadge({
|
||||||
|
super.key,
|
||||||
|
required this.realHppPercentage,
|
||||||
|
this.onDarkBackground = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final color = statusColor(realHppPercentage);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: onDarkBackground
|
||||||
|
? AppColor.textWhite.withOpacity(0.18)
|
||||||
|
: color.withOpacity(0.12),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
border: onDarkBackground
|
||||||
|
? Border.all(color: AppColor.textWhite.withOpacity(0.3))
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
statusLabel(context, realHppPercentage),
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: onDarkBackground ? AppColor.textWhite : color,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Label kecil dua baris: judul di atas, nilai di bawah.
|
||||||
|
class ProfitSharingMetric extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final String value;
|
||||||
|
final Color? valueColor;
|
||||||
|
final bool isBold;
|
||||||
|
|
||||||
|
const ProfitSharingMetric({
|
||||||
|
super.key,
|
||||||
|
required this.label,
|
||||||
|
required this.value,
|
||||||
|
this.valueColor,
|
||||||
|
this.isBold = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: valueColor ?? AppColor.textPrimary,
|
||||||
|
fontWeight: isBold ? FontWeight.w800 : FontWeight.w600,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,311 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../../../common/extension/extension.dart';
|
||||||
|
import '../../../../common/theme/theme.dart';
|
||||||
|
import '../../../../domain/analytic/analytic.dart';
|
||||||
|
import '../../../components/spacer/spacer.dart';
|
||||||
|
import 'profit_sharing_status.dart';
|
||||||
|
|
||||||
|
/// Daftar sub kategori; tiap kartu bisa dibuka untuk melihat produknya.
|
||||||
|
class ProfitSharingSubCategories extends StatelessWidget {
|
||||||
|
final List<ProfitSharingSubCategory> categories;
|
||||||
|
final String expandedCategoryId;
|
||||||
|
final ValueChanged<String> onToggle;
|
||||||
|
|
||||||
|
const ProfitSharingSubCategories({
|
||||||
|
super.key,
|
||||||
|
required this.categories,
|
||||||
|
required this.expandedCategoryId,
|
||||||
|
required this.onToggle,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final sorted = [...categories]
|
||||||
|
..sort((a, b) => b.totalRevenue.compareTo(a.totalRevenue));
|
||||||
|
|
||||||
|
final totalRevenue = sorted.fold<int>(0, (sum, e) => sum + e.totalRevenue);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: AppColor.textLight.withOpacity(0.08),
|
||||||
|
spreadRadius: 1,
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.lang.sub_category,
|
||||||
|
style: AppStyle.lg.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(16),
|
||||||
|
|
||||||
|
if (sorted.isEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 24),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
context.lang.no_data_yet,
|
||||||
|
style: AppStyle.sm.copyWith(color: AppColor.textSecondary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
...sorted.map(
|
||||||
|
(category) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: _SubCategoryCard(
|
||||||
|
category: category,
|
||||||
|
share: totalRevenue == 0
|
||||||
|
? 0
|
||||||
|
: category.totalRevenue / totalRevenue,
|
||||||
|
isExpanded: expandedCategoryId == category.categoryId,
|
||||||
|
onToggle: () => onToggle(category.categoryId),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SubCategoryCard extends StatelessWidget {
|
||||||
|
final ProfitSharingSubCategory category;
|
||||||
|
final double share;
|
||||||
|
final bool isExpanded;
|
||||||
|
final VoidCallback onToggle;
|
||||||
|
|
||||||
|
const _SubCategoryCard({
|
||||||
|
required this.category,
|
||||||
|
required this.share,
|
||||||
|
required this.isExpanded,
|
||||||
|
required this.onToggle,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.background,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: AppColor.borderLight),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: onToggle,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
category.categoryName,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
Text(
|
||||||
|
category.totalRevenue.currencyFormatRp,
|
||||||
|
style: AppStyle.md.copyWith(
|
||||||
|
color: AppColor.primary,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedRotation(
|
||||||
|
turns: isExpanded ? 0.5 : 0,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.keyboard_arrow_down_rounded,
|
||||||
|
color: AppColor.textSecondary,
|
||||||
|
size: 22,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(8),
|
||||||
|
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
value: share.clamp(0.0, 1.0),
|
||||||
|
minHeight: 5,
|
||||||
|
backgroundColor: AppColor.borderLight,
|
||||||
|
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||||
|
AppColor.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SpaceHeight(12),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.qty,
|
||||||
|
value: category.totalQuantity.thousandFormat,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.products,
|
||||||
|
value: '${category.productCount}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ProfitSharingMetric(
|
||||||
|
label: context.lang.real_hpp,
|
||||||
|
value: formatPercent(category.realHppPercentage),
|
||||||
|
valueColor: statusColor(category.realHppPercentage),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
AnimatedCrossFade(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
crossFadeState: isExpanded
|
||||||
|
? CrossFadeState.showFirst
|
||||||
|
: CrossFadeState.showSecond,
|
||||||
|
firstChild: _ProductList(products: category.products),
|
||||||
|
secondChild: const SizedBox(width: double.infinity),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProductList extends StatelessWidget {
|
||||||
|
final List<ProfitSharingProduct> products;
|
||||||
|
|
||||||
|
const _ProductList({required this.products});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final sorted = [...products]
|
||||||
|
..sort((a, b) => b.revenue.compareTo(a.revenue));
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.fromLTRB(14, 0, 14, 14),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Divider(height: 1, color: AppColor.border),
|
||||||
|
const SpaceHeight(10),
|
||||||
|
...sorted.map((product) => _ProductRow(product: product)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProductRow extends StatelessWidget {
|
||||||
|
final ProfitSharingProduct product;
|
||||||
|
|
||||||
|
const _ProductRow({required this.product});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final color = statusColor(product.realHppPercentage);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(top: 4),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColor.primary.withOpacity(0.08),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'${product.quantitySold}x',
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: AppColor.primary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(10),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
product.productName,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
'${product.productSku} · @${product.averagePrice.round().currencyFormatRp}',
|
||||||
|
style: AppStyle.xs.copyWith(color: AppColor.textSecondary),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SpaceWidth(8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
product.revenue.currencyFormatRp,
|
||||||
|
style: AppStyle.sm.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
'${context.lang.real_hpp} ${formatPercent(product.realHppPercentage)}',
|
||||||
|
style: AppStyle.xs.copyWith(
|
||||||
|
color: color,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,6 +50,10 @@ class AppRouter extends RootStackRouter {
|
|||||||
// Finance page
|
// Finance page
|
||||||
AutoRoute(page: FinanceRoute.page),
|
AutoRoute(page: FinanceRoute.page),
|
||||||
|
|
||||||
|
// Profit Sharing
|
||||||
|
AutoRoute(page: ProfitSharingRoute.page),
|
||||||
|
AutoRoute(page: ProfitSharingDetailRoute.page),
|
||||||
|
|
||||||
// Exclusive Summary
|
// Exclusive Summary
|
||||||
AutoRoute(page: ExclusiveSummaryRoute.page),
|
AutoRoute(page: ExclusiveSummaryRoute.page),
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
|
|
||||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
import 'package:apskel_owner_flutter/domain/order/order.dart' as _i29;
|
import 'package:apskel_owner_flutter/domain/order/order.dart' as _i31;
|
||||||
import 'package:apskel_owner_flutter/domain/user/user.dart' as _i30;
|
import 'package:apskel_owner_flutter/domain/user/user.dart' as _i32;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/about_app/about_app_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/about_app/about_app_page.dart'
|
||||||
as _i1;
|
as _i1;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/auth/login/login_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/auth/login/login_page.dart'
|
||||||
@@ -53,28 +53,32 @@ import 'package:apskel_owner_flutter/presentation/pages/profile/pages/profile_ed
|
|||||||
as _i20;
|
as _i20;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/profile/profile_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/profile/profile_page.dart'
|
||||||
as _i21;
|
as _i21;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/purchase/purchase_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/profit_sharing/profit_sharing_detail_page.dart'
|
||||||
as _i22;
|
as _i22;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/report/report_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/profit_sharing/profit_sharing_page.dart'
|
||||||
as _i23;
|
as _i23;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/sales/sales_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/purchase/purchase_page.dart'
|
||||||
as _i24;
|
as _i24;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/schedule/schedule_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/report/report_page.dart'
|
||||||
as _i25;
|
as _i25;
|
||||||
import 'package:apskel_owner_flutter/presentation/pages/splash/splash_page.dart'
|
import 'package:apskel_owner_flutter/presentation/pages/sales/sales_page.dart'
|
||||||
as _i26;
|
as _i26;
|
||||||
import 'package:auto_route/auto_route.dart' as _i27;
|
import 'package:apskel_owner_flutter/presentation/pages/schedule/schedule_page.dart'
|
||||||
import 'package:flutter/material.dart' as _i28;
|
as _i27;
|
||||||
|
import 'package:apskel_owner_flutter/presentation/pages/splash/splash_page.dart'
|
||||||
|
as _i28;
|
||||||
|
import 'package:auto_route/auto_route.dart' as _i29;
|
||||||
|
import 'package:flutter/material.dart' as _i30;
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i1.AboutAppPage]
|
/// [_i1.AboutAppPage]
|
||||||
class AboutAppRoute extends _i27.PageRouteInfo<void> {
|
class AboutAppRoute extends _i29.PageRouteInfo<void> {
|
||||||
const AboutAppRoute({List<_i27.PageRouteInfo>? children})
|
const AboutAppRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(AboutAppRoute.name, initialChildren: children);
|
: super(AboutAppRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'AboutAppRoute';
|
static const String name = 'AboutAppRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i1.AboutAppPage();
|
return const _i1.AboutAppPage();
|
||||||
@@ -84,13 +88,13 @@ class AboutAppRoute extends _i27.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i2.ComingSoonPage]
|
/// [_i2.ComingSoonPage]
|
||||||
class ComingSoonRoute extends _i27.PageRouteInfo<void> {
|
class ComingSoonRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ComingSoonRoute({List<_i27.PageRouteInfo>? children})
|
const ComingSoonRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ComingSoonRoute.name, initialChildren: children);
|
: super(ComingSoonRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ComingSoonRoute';
|
static const String name = 'ComingSoonRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i2.ComingSoonPage();
|
return const _i2.ComingSoonPage();
|
||||||
@@ -100,29 +104,29 @@ class ComingSoonRoute extends _i27.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i3.CustomerPage]
|
/// [_i3.CustomerPage]
|
||||||
class CustomerRoute extends _i27.PageRouteInfo<void> {
|
class CustomerRoute extends _i29.PageRouteInfo<void> {
|
||||||
const CustomerRoute({List<_i27.PageRouteInfo>? children})
|
const CustomerRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(CustomerRoute.name, initialChildren: children);
|
: super(CustomerRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'CustomerRoute';
|
static const String name = 'CustomerRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i3.CustomerPage());
|
return _i29.WrappedRoute(child: const _i3.CustomerPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i4.DailyTasksFormPage]
|
/// [_i4.DailyTasksFormPage]
|
||||||
class DailyTasksFormRoute extends _i27.PageRouteInfo<void> {
|
class DailyTasksFormRoute extends _i29.PageRouteInfo<void> {
|
||||||
const DailyTasksFormRoute({List<_i27.PageRouteInfo>? children})
|
const DailyTasksFormRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(DailyTasksFormRoute.name, initialChildren: children);
|
: super(DailyTasksFormRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'DailyTasksFormRoute';
|
static const String name = 'DailyTasksFormRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i4.DailyTasksFormPage();
|
return const _i4.DailyTasksFormPage();
|
||||||
@@ -132,32 +136,32 @@ class DailyTasksFormRoute extends _i27.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i5.DownloadReportPage]
|
/// [_i5.DownloadReportPage]
|
||||||
class DownloadReportRoute extends _i27.PageRouteInfo<void> {
|
class DownloadReportRoute extends _i29.PageRouteInfo<void> {
|
||||||
const DownloadReportRoute({List<_i27.PageRouteInfo>? children})
|
const DownloadReportRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(DownloadReportRoute.name, initialChildren: children);
|
: super(DownloadReportRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'DownloadReportRoute';
|
static const String name = 'DownloadReportRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i5.DownloadReportPage());
|
return _i29.WrappedRoute(child: const _i5.DownloadReportPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i6.ErrorPage]
|
/// [_i6.ErrorPage]
|
||||||
class ErrorRoute extends _i27.PageRouteInfo<ErrorRouteArgs> {
|
class ErrorRoute extends _i29.PageRouteInfo<ErrorRouteArgs> {
|
||||||
ErrorRoute({
|
ErrorRoute({
|
||||||
_i28.Key? key,
|
_i30.Key? key,
|
||||||
String? title,
|
String? title,
|
||||||
String? message,
|
String? message,
|
||||||
_i28.VoidCallback? onRetry,
|
_i30.VoidCallback? onRetry,
|
||||||
_i28.VoidCallback? onBack,
|
_i30.VoidCallback? onBack,
|
||||||
String? errorCode,
|
String? errorCode,
|
||||||
_i28.IconData? errorIcon,
|
_i30.IconData? errorIcon,
|
||||||
List<_i27.PageRouteInfo>? children,
|
List<_i29.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
ErrorRoute.name,
|
ErrorRoute.name,
|
||||||
args: ErrorRouteArgs(
|
args: ErrorRouteArgs(
|
||||||
@@ -174,7 +178,7 @@ class ErrorRoute extends _i27.PageRouteInfo<ErrorRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'ErrorRoute';
|
static const String name = 'ErrorRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<ErrorRouteArgs>(
|
final args = data.argsAs<ErrorRouteArgs>(
|
||||||
@@ -204,19 +208,19 @@ class ErrorRouteArgs {
|
|||||||
this.errorIcon,
|
this.errorIcon,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i28.Key? key;
|
final _i30.Key? key;
|
||||||
|
|
||||||
final String? title;
|
final String? title;
|
||||||
|
|
||||||
final String? message;
|
final String? message;
|
||||||
|
|
||||||
final _i28.VoidCallback? onRetry;
|
final _i30.VoidCallback? onRetry;
|
||||||
|
|
||||||
final _i28.VoidCallback? onBack;
|
final _i30.VoidCallback? onBack;
|
||||||
|
|
||||||
final String? errorCode;
|
final String? errorCode;
|
||||||
|
|
||||||
final _i28.IconData? errorIcon;
|
final _i30.IconData? errorIcon;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@@ -226,77 +230,77 @@ class ErrorRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i7.ExclusiveSummaryPage]
|
/// [_i7.ExclusiveSummaryPage]
|
||||||
class ExclusiveSummaryRoute extends _i27.PageRouteInfo<void> {
|
class ExclusiveSummaryRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ExclusiveSummaryRoute({List<_i27.PageRouteInfo>? children})
|
const ExclusiveSummaryRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ExclusiveSummaryRoute.name, initialChildren: children);
|
: super(ExclusiveSummaryRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ExclusiveSummaryRoute';
|
static const String name = 'ExclusiveSummaryRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i7.ExclusiveSummaryPage());
|
return _i29.WrappedRoute(child: const _i7.ExclusiveSummaryPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i8.FinancePage]
|
/// [_i8.FinancePage]
|
||||||
class FinanceRoute extends _i27.PageRouteInfo<void> {
|
class FinanceRoute extends _i29.PageRouteInfo<void> {
|
||||||
const FinanceRoute({List<_i27.PageRouteInfo>? children})
|
const FinanceRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(FinanceRoute.name, initialChildren: children);
|
: super(FinanceRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'FinanceRoute';
|
static const String name = 'FinanceRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i8.FinancePage());
|
return _i29.WrappedRoute(child: const _i8.FinancePage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i9.HomePage]
|
/// [_i9.HomePage]
|
||||||
class HomeRoute extends _i27.PageRouteInfo<void> {
|
class HomeRoute extends _i29.PageRouteInfo<void> {
|
||||||
const HomeRoute({List<_i27.PageRouteInfo>? children})
|
const HomeRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(HomeRoute.name, initialChildren: children);
|
: super(HomeRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'HomeRoute';
|
static const String name = 'HomeRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i9.HomePage());
|
return _i29.WrappedRoute(child: const _i9.HomePage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i10.InventoryPage]
|
/// [_i10.InventoryPage]
|
||||||
class InventoryRoute extends _i27.PageRouteInfo<void> {
|
class InventoryRoute extends _i29.PageRouteInfo<void> {
|
||||||
const InventoryRoute({List<_i27.PageRouteInfo>? children})
|
const InventoryRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(InventoryRoute.name, initialChildren: children);
|
: super(InventoryRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'InventoryRoute';
|
static const String name = 'InventoryRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i10.InventoryPage());
|
return _i29.WrappedRoute(child: const _i10.InventoryPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i11.LanguagePage]
|
/// [_i11.LanguagePage]
|
||||||
class LanguageRoute extends _i27.PageRouteInfo<void> {
|
class LanguageRoute extends _i29.PageRouteInfo<void> {
|
||||||
const LanguageRoute({List<_i27.PageRouteInfo>? children})
|
const LanguageRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(LanguageRoute.name, initialChildren: children);
|
: super(LanguageRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'LanguageRoute';
|
static const String name = 'LanguageRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i11.LanguagePage();
|
return const _i11.LanguagePage();
|
||||||
@@ -306,29 +310,29 @@ class LanguageRoute extends _i27.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i12.LoginPage]
|
/// [_i12.LoginPage]
|
||||||
class LoginRoute extends _i27.PageRouteInfo<void> {
|
class LoginRoute extends _i29.PageRouteInfo<void> {
|
||||||
const LoginRoute({List<_i27.PageRouteInfo>? children})
|
const LoginRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(LoginRoute.name, initialChildren: children);
|
: super(LoginRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'LoginRoute';
|
static const String name = 'LoginRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i12.LoginPage());
|
return _i29.WrappedRoute(child: const _i12.LoginPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i13.MainPage]
|
/// [_i13.MainPage]
|
||||||
class MainRoute extends _i27.PageRouteInfo<void> {
|
class MainRoute extends _i29.PageRouteInfo<void> {
|
||||||
const MainRoute({List<_i27.PageRouteInfo>? children})
|
const MainRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(MainRoute.name, initialChildren: children);
|
: super(MainRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'MainRoute';
|
static const String name = 'MainRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i13.MainPage();
|
return const _i13.MainPage();
|
||||||
@@ -338,11 +342,11 @@ class MainRoute extends _i27.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i14.OrderDetailPage]
|
/// [_i14.OrderDetailPage]
|
||||||
class OrderDetailRoute extends _i27.PageRouteInfo<OrderDetailRouteArgs> {
|
class OrderDetailRoute extends _i29.PageRouteInfo<OrderDetailRouteArgs> {
|
||||||
OrderDetailRoute({
|
OrderDetailRoute({
|
||||||
_i28.Key? key,
|
_i30.Key? key,
|
||||||
required _i29.Order order,
|
required _i31.Order order,
|
||||||
List<_i27.PageRouteInfo>? children,
|
List<_i29.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
OrderDetailRoute.name,
|
OrderDetailRoute.name,
|
||||||
args: OrderDetailRouteArgs(key: key, order: order),
|
args: OrderDetailRouteArgs(key: key, order: order),
|
||||||
@@ -351,7 +355,7 @@ class OrderDetailRoute extends _i27.PageRouteInfo<OrderDetailRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'OrderDetailRoute';
|
static const String name = 'OrderDetailRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<OrderDetailRouteArgs>();
|
final args = data.argsAs<OrderDetailRouteArgs>();
|
||||||
@@ -363,9 +367,9 @@ class OrderDetailRoute extends _i27.PageRouteInfo<OrderDetailRouteArgs> {
|
|||||||
class OrderDetailRouteArgs {
|
class OrderDetailRouteArgs {
|
||||||
const OrderDetailRouteArgs({this.key, required this.order});
|
const OrderDetailRouteArgs({this.key, required this.order});
|
||||||
|
|
||||||
final _i28.Key? key;
|
final _i30.Key? key;
|
||||||
|
|
||||||
final _i29.Order order;
|
final _i31.Order order;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@@ -375,91 +379,91 @@ class OrderDetailRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i15.OrderPage]
|
/// [_i15.OrderPage]
|
||||||
class OrderRoute extends _i27.PageRouteInfo<void> {
|
class OrderRoute extends _i29.PageRouteInfo<void> {
|
||||||
const OrderRoute({List<_i27.PageRouteInfo>? children})
|
const OrderRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(OrderRoute.name, initialChildren: children);
|
: super(OrderRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'OrderRoute';
|
static const String name = 'OrderRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i15.OrderPage());
|
return _i29.WrappedRoute(child: const _i15.OrderPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i16.OutletInformationPage]
|
/// [_i16.OutletInformationPage]
|
||||||
class OutletInformationRoute extends _i27.PageRouteInfo<void> {
|
class OutletInformationRoute extends _i29.PageRouteInfo<void> {
|
||||||
const OutletInformationRoute({List<_i27.PageRouteInfo>? children})
|
const OutletInformationRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(OutletInformationRoute.name, initialChildren: children);
|
: super(OutletInformationRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'OutletInformationRoute';
|
static const String name = 'OutletInformationRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i16.OutletInformationPage());
|
return _i29.WrappedRoute(child: const _i16.OutletInformationPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i17.ProductAnalyticPage]
|
/// [_i17.ProductAnalyticPage]
|
||||||
class ProductAnalyticRoute extends _i27.PageRouteInfo<void> {
|
class ProductAnalyticRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ProductAnalyticRoute({List<_i27.PageRouteInfo>? children})
|
const ProductAnalyticRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ProductAnalyticRoute.name, initialChildren: children);
|
: super(ProductAnalyticRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ProductAnalyticRoute';
|
static const String name = 'ProductAnalyticRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i17.ProductAnalyticPage());
|
return _i29.WrappedRoute(child: const _i17.ProductAnalyticPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i18.ProductPage]
|
/// [_i18.ProductPage]
|
||||||
class ProductRoute extends _i27.PageRouteInfo<void> {
|
class ProductRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ProductRoute({List<_i27.PageRouteInfo>? children})
|
const ProductRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ProductRoute.name, initialChildren: children);
|
: super(ProductRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ProductRoute';
|
static const String name = 'ProductRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i18.ProductPage());
|
return _i29.WrappedRoute(child: const _i18.ProductPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i19.ProfileChangePasswordPage]
|
/// [_i19.ProfileChangePasswordPage]
|
||||||
class ProfileChangePasswordRoute extends _i27.PageRouteInfo<void> {
|
class ProfileChangePasswordRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ProfileChangePasswordRoute({List<_i27.PageRouteInfo>? children})
|
const ProfileChangePasswordRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ProfileChangePasswordRoute.name, initialChildren: children);
|
: super(ProfileChangePasswordRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ProfileChangePasswordRoute';
|
static const String name = 'ProfileChangePasswordRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i19.ProfileChangePasswordPage());
|
return _i29.WrappedRoute(child: const _i19.ProfileChangePasswordPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i20.ProfileEditPage]
|
/// [_i20.ProfileEditPage]
|
||||||
class ProfileEditRoute extends _i27.PageRouteInfo<ProfileEditRouteArgs> {
|
class ProfileEditRoute extends _i29.PageRouteInfo<ProfileEditRouteArgs> {
|
||||||
ProfileEditRoute({
|
ProfileEditRoute({
|
||||||
_i28.Key? key,
|
_i30.Key? key,
|
||||||
required _i30.User user,
|
required _i32.User user,
|
||||||
List<_i27.PageRouteInfo>? children,
|
List<_i29.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
ProfileEditRoute.name,
|
ProfileEditRoute.name,
|
||||||
args: ProfileEditRouteArgs(key: key, user: user),
|
args: ProfileEditRouteArgs(key: key, user: user),
|
||||||
@@ -468,11 +472,11 @@ class ProfileEditRoute extends _i27.PageRouteInfo<ProfileEditRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'ProfileEditRoute';
|
static const String name = 'ProfileEditRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<ProfileEditRouteArgs>();
|
final args = data.argsAs<ProfileEditRouteArgs>();
|
||||||
return _i27.WrappedRoute(
|
return _i29.WrappedRoute(
|
||||||
child: _i20.ProfileEditPage(key: args.key, user: args.user),
|
child: _i20.ProfileEditPage(key: args.key, user: args.user),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -482,9 +486,9 @@ class ProfileEditRoute extends _i27.PageRouteInfo<ProfileEditRouteArgs> {
|
|||||||
class ProfileEditRouteArgs {
|
class ProfileEditRouteArgs {
|
||||||
const ProfileEditRouteArgs({this.key, required this.user});
|
const ProfileEditRouteArgs({this.key, required this.user});
|
||||||
|
|
||||||
final _i28.Key? key;
|
final _i30.Key? key;
|
||||||
|
|
||||||
final _i30.User user;
|
final _i32.User user;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@@ -494,96 +498,179 @@ class ProfileEditRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i21.ProfilePage]
|
/// [_i21.ProfilePage]
|
||||||
class ProfileRoute extends _i27.PageRouteInfo<void> {
|
class ProfileRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ProfileRoute({List<_i27.PageRouteInfo>? children})
|
const ProfileRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ProfileRoute.name, initialChildren: children);
|
: super(ProfileRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ProfileRoute';
|
static const String name = 'ProfileRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i21.ProfilePage());
|
return _i29.WrappedRoute(child: const _i21.ProfilePage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i22.PurchasePage]
|
/// [_i22.ProfitSharingDetailPage]
|
||||||
class PurchaseRoute extends _i27.PageRouteInfo<void> {
|
class ProfitSharingDetailRoute
|
||||||
const PurchaseRoute({List<_i27.PageRouteInfo>? children})
|
extends _i29.PageRouteInfo<ProfitSharingDetailRouteArgs> {
|
||||||
|
ProfitSharingDetailRoute({
|
||||||
|
_i30.Key? key,
|
||||||
|
required String parentCategoryId,
|
||||||
|
required String parentCategoryName,
|
||||||
|
required DateTime dateFrom,
|
||||||
|
required DateTime dateTo,
|
||||||
|
List<_i29.PageRouteInfo>? children,
|
||||||
|
}) : super(
|
||||||
|
ProfitSharingDetailRoute.name,
|
||||||
|
args: ProfitSharingDetailRouteArgs(
|
||||||
|
key: key,
|
||||||
|
parentCategoryId: parentCategoryId,
|
||||||
|
parentCategoryName: parentCategoryName,
|
||||||
|
dateFrom: dateFrom,
|
||||||
|
dateTo: dateTo,
|
||||||
|
),
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
|
static const String name = 'ProfitSharingDetailRoute';
|
||||||
|
|
||||||
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
|
name,
|
||||||
|
builder: (data) {
|
||||||
|
final args = data.argsAs<ProfitSharingDetailRouteArgs>();
|
||||||
|
return _i29.WrappedRoute(
|
||||||
|
child: _i22.ProfitSharingDetailPage(
|
||||||
|
key: args.key,
|
||||||
|
parentCategoryId: args.parentCategoryId,
|
||||||
|
parentCategoryName: args.parentCategoryName,
|
||||||
|
dateFrom: args.dateFrom,
|
||||||
|
dateTo: args.dateTo,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfitSharingDetailRouteArgs {
|
||||||
|
const ProfitSharingDetailRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.parentCategoryId,
|
||||||
|
required this.parentCategoryName,
|
||||||
|
required this.dateFrom,
|
||||||
|
required this.dateTo,
|
||||||
|
});
|
||||||
|
|
||||||
|
final _i30.Key? key;
|
||||||
|
|
||||||
|
final String parentCategoryId;
|
||||||
|
|
||||||
|
final String parentCategoryName;
|
||||||
|
|
||||||
|
final DateTime dateFrom;
|
||||||
|
|
||||||
|
final DateTime dateTo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfitSharingDetailRouteArgs{key: $key, parentCategoryId: $parentCategoryId, parentCategoryName: $parentCategoryName, dateFrom: $dateFrom, dateTo: $dateTo}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// generated route for
|
||||||
|
/// [_i23.ProfitSharingPage]
|
||||||
|
class ProfitSharingRoute extends _i29.PageRouteInfo<void> {
|
||||||
|
const ProfitSharingRoute({List<_i29.PageRouteInfo>? children})
|
||||||
|
: super(ProfitSharingRoute.name, initialChildren: children);
|
||||||
|
|
||||||
|
static const String name = 'ProfitSharingRoute';
|
||||||
|
|
||||||
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
|
name,
|
||||||
|
builder: (data) {
|
||||||
|
return _i29.WrappedRoute(child: const _i23.ProfitSharingPage());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// generated route for
|
||||||
|
/// [_i24.PurchasePage]
|
||||||
|
class PurchaseRoute extends _i29.PageRouteInfo<void> {
|
||||||
|
const PurchaseRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(PurchaseRoute.name, initialChildren: children);
|
: super(PurchaseRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'PurchaseRoute';
|
static const String name = 'PurchaseRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i22.PurchasePage());
|
return _i29.WrappedRoute(child: const _i24.PurchasePage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i23.ReportPage]
|
/// [_i25.ReportPage]
|
||||||
class ReportRoute extends _i27.PageRouteInfo<void> {
|
class ReportRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ReportRoute({List<_i27.PageRouteInfo>? children})
|
const ReportRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ReportRoute.name, initialChildren: children);
|
: super(ReportRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ReportRoute';
|
static const String name = 'ReportRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i23.ReportPage());
|
return _i29.WrappedRoute(child: const _i25.ReportPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i24.SalesPage]
|
/// [_i26.SalesPage]
|
||||||
class SalesRoute extends _i27.PageRouteInfo<void> {
|
class SalesRoute extends _i29.PageRouteInfo<void> {
|
||||||
const SalesRoute({List<_i27.PageRouteInfo>? children})
|
const SalesRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(SalesRoute.name, initialChildren: children);
|
: super(SalesRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'SalesRoute';
|
static const String name = 'SalesRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return _i27.WrappedRoute(child: const _i24.SalesPage());
|
return _i29.WrappedRoute(child: const _i26.SalesPage());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i25.SchedulePage]
|
/// [_i27.SchedulePage]
|
||||||
class ScheduleRoute extends _i27.PageRouteInfo<void> {
|
class ScheduleRoute extends _i29.PageRouteInfo<void> {
|
||||||
const ScheduleRoute({List<_i27.PageRouteInfo>? children})
|
const ScheduleRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(ScheduleRoute.name, initialChildren: children);
|
: super(ScheduleRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'ScheduleRoute';
|
static const String name = 'ScheduleRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i25.SchedulePage();
|
return const _i27.SchedulePage();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i26.SplashPage]
|
/// [_i28.SplashPage]
|
||||||
class SplashRoute extends _i27.PageRouteInfo<void> {
|
class SplashRoute extends _i29.PageRouteInfo<void> {
|
||||||
const SplashRoute({List<_i27.PageRouteInfo>? children})
|
const SplashRoute({List<_i29.PageRouteInfo>? children})
|
||||||
: super(SplashRoute.name, initialChildren: children);
|
: super(SplashRoute.name, initialChildren: children);
|
||||||
|
|
||||||
static const String name = 'SplashRoute';
|
static const String name = 'SplashRoute';
|
||||||
|
|
||||||
static _i27.PageInfo page = _i27.PageInfo(
|
static _i29.PageInfo page = _i29.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i26.SplashPage();
|
return const _i28.SplashPage();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -841,10 +841,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.20.2"
|
version: "0.20.3"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -937,10 +937,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.19"
|
version: "0.12.20"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -953,10 +953,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
|
sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.19.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1526,10 +1526,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
|
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.11"
|
version: "0.7.12"
|
||||||
time:
|
time:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1662,10 +1662,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.4.2"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1747,5 +1747,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.10.0-0 <4.0.0"
|
dart: ">=3.11.0-0 <4.0.0"
|
||||||
flutter: ">=3.29.0"
|
flutter: ">=3.29.0"
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ description: "A new Flutter project."
|
|||||||
|
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.0.4+10
|
version: 1.0.4+11
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.8.1
|
sdk: ^3.8.1
|
||||||
|
|||||||
Reference in New Issue
Block a user