diff --git a/README.md b/README.md index ad8462f..76ed710 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,565 @@ -# apskel_owner_flutter +## Apskel Owner Flutter -A new Flutter project. +A POS (Point of Sale) application for business owners, built with Flutter. The project follows a layered architecture (presentation → application → domain → infrastructure) with dependency injection, state management, automated routing, internationalization, and code generation. -## Getting Started +--- -This project is a starting point for a Flutter application. +### Contents -A few resources to get you started if this is your first Flutter project: +- Technical Summary +- Requirements & Setup +- Running the App +- Architecture Overview +- Project Structure +- Key Dependencies & Purpose +- Code Generation +- Internationalization (i18n) +- Theming & Assets +- Environment Configuration (`env.dart`) +- Development Practices -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) +--- -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +## Technical Summary + +- SDK: Flutter (Material) with Dart ^3.8.1 +- Targets: Android, iOS, Web, Desktop (Windows, macOS, Linux) +- State management: `flutter_bloc` +- Routing: `auto_route` +- Dependency Injection: `get_it` + `injectable` +- HTTP Client: `dio` (+ `awesome_dio_interceptor`) +- Data class & serialization: `freezed` + `json_serializable` +- Localization: `flutter_localizations`, `l10n/*.arb` +- Assets generation: `flutter_gen` + +--- + +## Requirements & Setup + +### Prerequisites + +- Flutter SDK installed as per the official guide (`https://flutter.dev/docs/get-started/install`) +- Dart version per constraint: ^3.8.1 + +### Installation + +```bash +git clone +cd apskel_owner_flutter +flutter pub get +``` + +### Code generation (required after clone or when annotations change) + +```bash +flutter pub run build_runner build --delete-conflicting-outputs +``` + +> Re-run whenever you change files using `@RoutePage()`, `@injectable`, `@freezed`, or `@JsonSerializable`. + +--- + +## Running the App + +```bash +flutter run +``` + +Select a specific device/platform: + +```bash +flutter run -d chrome +flutter run -d ios +flutter run -d android +``` + +Example release builds: + +```bash +flutter build apk --release +flutter build ios --release +flutter build web --release +``` + +--- + +## Architecture Overview + +The codebase follows a clean, layered approach that separates concerns and keeps features modular and testable: + +- Presentation (`lib/presentation`): Widgets, pages/screens, and the `AutoRoute` router. Contains only UI code and wiring to BLoC/Cubit. +- Application (`lib/application`): BLoC/Cubit and application-level orchestration. Holds input validation, state transitions, and calls into the Domain layer. +- Domain (`lib/domain`): Pure business logic. Entities, value objects, repository interfaces, and (optional) use-cases. No framework dependencies. +- Infrastructure (`lib/infrastructure`): Repository implementations, DTOs, and data sources (HTTP/DB). Performs `dio` calls and mappings between DTOs and Domain entities. +- Common (`lib/common`): Cross-cutting helpers such as API base, DI setup, constants, extensions, theme, validators, and utilities. + +Data flow in a feature: + +1. UI triggers an intent/event in Presentation → +2. Application layer BLoC/Cubit handles the event and calls a repository/use-case from Domain → +3. Infrastructure implements the repository, performs network calls via `dio`, and maps results → +4. Data is converted to Domain entities and returned to Application → +5. Application updates state, Presentation rebuilds UI accordingly. + +Cross-cutting concerns: + +- Dependency Injection: `get_it` + `injectable` auto-register services/repositories (`injection.dart`, `injection.config.dart`). +- Routing: `auto_route` defines typed routes, generated into router files in `presentation/router`. +- State: `flutter_bloc` models states/events and isolates side-effects in BLoCs/Cubits. +- Networking: `dio` with interceptors for logging and error handling. +- Error handling: functional style with `dartz` (`Either`, `Option`) or well-defined BLoC states. +- i18n: ARB files in `lib/l10n/` and generated localization delegates. +- Theming: centralized theme under `lib/common/theme/` with shared design tokens. +- Assets: managed under `assets/` and referenced via FlutterGen outputs at `lib/presentation/components/assets/`. + +--- + +## Project Structure + +``` +lib/ + application/ # BLoC/cubit per feature (analytic, auth, product, etc.) + common/ + api/ # Base API client, endpoint helper + constant/ # Application constants + di/ # Dependency injection setup (get_it, injectable) + extension/ # Extensions + function/ # General utility functions + network/ # Connectivity checks, handlers + painter/ # Custom painters + theme/ # Colors, text styles, theming + url/ # Base URL/endpoints + utils/ # Other helpers + validator/ # Input validators + domain/ + / # Entities, repo interfaces, (use-cases if present) + infrastructure/ + / # Repo implementations, DTOs, API calls + l10n/ # ARB sources for i18n + generated localizations + presentation/ + components/ # Reusable widgets + pages/ # Feature pages/screens + router/ # AutoRoute definitions + env.dart # Environment configuration (BASE_URL, etc.) + injection.dart # DI entry point + injection.config.dart # DI generated + main.dart # Application entry point +assets/ + images/, icons/, json/, fonts/ +``` + +--- + +## Key Dependencies & Purpose + +Runtime: + +- `auto_route`: Automated, typed routing based on annotations. +- `flutter_bloc`: State management with BLoC/Cubit. +- `get_it`, `injectable`: Service locator + codegen for DI. +- `dio`, `awesome_dio_interceptor`: HTTP client + logging interceptor. +- `freezed_annotation`, `json_annotation`: Annotations for immutable data classes & JSON. +- `dartz`: Functional types (Either, Option) for explicit error handling. +- `connectivity_plus`, `device_info_plus`, `package_info_plus`: Device and connectivity info. +- `shared_preferences`: Local key-value storage. +- `image_picker`, `permission_handler`, `open_file`, `url_launcher`: OS/device integrations. +- UI: `flutter_svg`, `line_icons`, `flutter_spinkit`, `fl_chart`, `another_flushbar`, `table_calendar`, `shimmer`, `cached_network_image`, `syncfusion_flutter_datepicker`, `pdf`. + +Dev: + +- `build_runner`: Code generation orchestration. +- `auto_route_generator`, `injectable_generator`, `freezed`, `json_serializable`: Related generators. +- `flutter_gen_runner`: Typed asset access generator. +- `flutter_lints`: Recommended Flutter lints. +- `flutter_launcher_icons`: Launcher icon generation. + +Refer to `pubspec.yaml` for full version constraints. + +--- + +## Code Generation + +Common commands: + +```bash +flutter pub run build_runner build --delete-conflicting-outputs +# or watch +flutter pub run build_runner watch --delete-conflicting-outputs +``` + +### 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`: + +- Output path: `lib/presentation/components/assets/` +- SVG integration: enabled (`flutter_svg: true`) + +Usage in code example (after generation): + +```dart +// Example usage +// import 'presentation/components/assets/assets.gen.dart'; +// Image.asset(Assets.images.logo.path); +``` + +Generators used: + +- AutoRoute: Generates router and typed routes. +- Injectable: Generates DI registrations (`injection.config.dart`). +- Freezed: Generates immutable data classes, copyWith, unions, etc. +- Json Serializable: Generates toJson/fromJson for DTOs. +- FlutterGen: Generates static asset access under `lib/presentation/components/assets/`. + +--- + +## Internationalization (i18n) + +- Source files live in `lib/l10n/app_*.arb` (e.g., `app_en.arb`, `app_id.arb`). +- To add a language: create `app_.arb`, then run code generation. +- Ensure `MaterialApp` is wired with `localizationsDelegates` and `supportedLocales` (already prepared). + +--- + +## Theming & Assets + +- Theme files live under `lib/common/theme/`. +- Fonts: `Quicksand` family is declared in `pubspec.yaml`. +- Assets: `assets/images/`, `assets/icons/`, `assets/json/` – referenced via FlutterGen outputs at `lib/presentation/components/assets/`. + +--- + +## Environment Configuration (`env.dart`) + +The `lib/env.dart` file stores configuration values such as base URLs and debug flags. Adjust per environment (development/production) using flavors, environment variables, or branching as preferred by the team. + +--- + +## Development Practices + +- Routing: Define routes in `presentation/router`, then run code generation. +- DI: Annotate services/repositories with `@injectable`/`@LazySingleton`, generate code, and call `configureDependencies()` early in app startup. +- BLoC: Keep UI logic in the `application` layer and use `BlocBuilder`/`BlocListener` in the `presentation` layer. +- DTO ↔ Entity: Mapping resides in the `infrastructure` layer to keep domain pure. +- Error handling: Prefer `Either`/`Option` (`dartz`) or well-structured BLoC states. +- Linting: Follow `analysis_options.yaml`. + +--- + +## Useful Commands + +```bash +# Install dependencies +flutter pub get + +# Format & Analyze +flutter format . +flutter analyze + +# Code generation (single run / watch) +flutter pub run build_runner build --delete-conflicting-outputs +flutter pub run build_runner watch --delete-conflicting-outputs + +# Run by device +flutter devices +flutter run -d +``` + +--- + +## Additional Notes + +- Launcher icons configured via `launcher_icon.yaml`. +- Platform-specific configuration (Android/iOS/Web/Desktop) resides in respective platform folders. +- Review `analysis_options.yaml` for code style and lint rules. + +--- + +## Launcher Icons + +Configured via `launcher_icon.yaml` at the repository root. To (re)generate launcher icons, run: + +```bash +dart run flutter_launcher_icons -f launcher_icon.yaml +``` + +If you prefer the Flutter shim: + +```bash +flutter pub run flutter_launcher_icons -f launcher_icon.yaml +``` + +Ensure you have the package in `dev_dependencies` (`flutter_launcher_icons`). + +## Contributing + +1. Branch off `main`. +2. Make focused changes and provide a clear PR description. +3. Ensure build, lints, and codegen are clean before opening the PR. + +--- + +## License + +This project is private/internal. Contact the repository owner for usage permissions. + +## Apskel Owner Flutter + +Aplikasi Point of Sale (POS) untuk pemilik usaha, dibangun dengan Flutter. Proyek ini menerapkan arsitektur berlapis (presentation → application → domain → infrastructure) dengan dependency injection, state management, routing terotomasi, internationalization, dan code generation. + +--- + +### Isi Dokumen + +- Ringkasan Teknis +- Persyaratan & Setup +- Menjalankan Aplikasi +- Arsitektur & Alur +- Struktur Proyek +- Dependensi Utama & Fungsinya +- Code Generation +- Internationalization (i18n) +- Theming & Assets +- Konfigurasi Lingkungan (`env.dart`) +- Praktik Pengembangan + +--- + +## Ringkasan Teknis + +- SDK: Flutter (Material) dengan Dart ^3.8.1 +- Target platform: Android, iOS, Web, Desktop (Windows, macOS, Linux) +- State management: `flutter_bloc` +- Routing: `auto_route` +- Dependency Injection: `get_it` + `injectable` +- HTTP Client: `dio` (+ `awesome_dio_interceptor`) +- Data class & serialization: `freezed` + `json_serializable` +- Localization: `flutter_localizations`, `l10n/*.arb` +- Assets generation: `flutter_gen` + +--- + +## Persyaratan & Setup + +### Prasyarat + +- Flutter SDK terpasang sesuai panduan resmi (`https://flutter.dev/docs/get-started/install`) +- Versi Dart sesuai constraint: ^3.8.1 + +### Instalasi + +```bash +git clone +cd apskel_owner_flutter +flutter pub get +``` + +### Generate kode (wajib setelah clone atau mengubah anotasi) + +```bash +flutter pub run build_runner build --delete-conflicting-outputs +``` + +> Jalankan ulang perintah di atas setiap kali Anda mengubah file yang menggunakan anotasi `@RoutePage()`, `@injectable`, `@freezed`, atau `@JsonSerializable`. + +--- + +## Menjalankan Aplikasi + +```bash +flutter run +``` + +Menentukan platform/target tertentu: + +```bash +flutter run -d chrome +flutter run -d ios +flutter run -d android +``` + +Build release contoh: + +```bash +flutter build apk --release +flutter build ios --release +flutter build web --release +``` + +--- + +## Arsitektur & Alur + +Proyek mengikuti layering yang jelas: + +- Presentation (`lib/presentation`): UI, widget, halaman, router. +- Application (`lib/application`): BLoC/cubit, use-case orkestra ringan, validasi input UI. +- Domain (`lib/domain`): Entitas, value object, repository interface, use-case (jika ada). +- Infrastructure (`lib/infrastructure`): Implementasi repository, data source (API/DB), mapping DTO. +- Common (`lib/common`): Utilitas umum, konstanta, theme, API base, DI bootstrap, extension, dll. + +Alur umum: + +1. UI memicu event → +2. BLoC di layer Application memanggil use-case/repo (Domain) → +3. Implementasi repo (Infrastructure) melakukan HTTP via `dio` → +4. Response dipetakan menjadi entity/domain → +5. State di-update kembali ke UI. + +--- + +## Struktur Proyek + +``` +lib/ + application/ # BLoC/cubit per fitur (analytic, auth, product, dst.) + common/ + api/ # Base API client, endpoint helper + constant/ # Konstanta aplikasi + di/ # Setup dependency injection (get_it, injectable) + extension/ # Extension util + function/ # Fungsi util umum + network/ # Cek konektivitas, handler + painter/ # Custom painter + theme/ # Warna, text styles, theming + url/ # Base URL/endpoint + utils/ # Helper lain + validator/ # Validator input + domain/ + / # Entity, repo interface, (use-case bila ada) + infrastructure/ + / # Repo implementation, DTO, pemanggilan API + l10n/ # Berkas ARB untuk i18n + generated localizations + presentation/ + components/ # Widget reusable + pages/ # Halaman/layar fitur + router/ # Definisi AutoRoute + env.dart # Konfigurasi environment (BASE_URL, dsb) + injection.dart # Entry point DI + injection.config.dart # DI generated + main.dart # Entrypoint aplikasi +assets/ + images/, icons/, json/, fonts/ +``` + +--- + +## Dependensi Utama & Fungsinya + +Runtime: + +- `auto_route`: Routing terotomasi berbasis anotasi. +- `flutter_bloc`: State management dengan BLoC/Cubit. +- `get_it`, `injectable`: Service locator + codegen untuk DI. +- `dio`, `awesome_dio_interceptor`: HTTP client + logging interceptor. +- `freezed_annotation`, `json_annotation`: Anotasi untuk data class immutable & JSON. +- `dartz`: Functional types (Either, Option) untuk error handling yang eksplisit. +- `connectivity_plus`, `device_info_plus`, `package_info_plus`: Info perangkat & konektivitas. +- `shared_preferences`: Penyimpanan key-value lokal. +- `image_picker`, `permission_handler`, `open_file`, `url_launcher`: Integrasi perangkat/OS. +- UI: `flutter_svg`, `line_icons`, `flutter_spinkit`, `fl_chart`, `another_flushbar`, `table_calendar`, `shimmer`, `cached_network_image`, `syncfusion_flutter_datepicker`, `pdf`. + +Dev: + +- `build_runner`: Orkestrasi code generation. +- `auto_route_generator`, `injectable_generator`, `freezed`, `json_serializable`: Generator terkait. +- `flutter_gen_runner`: Generator akses asset terketik. +- `flutter_lints`: Linter rekomendasi Flutter. +- `flutter_launcher_icons`: Generate icon launcher. + +Catatan versi lengkap tersedia di `pubspec.yaml`. + +--- + +## Code Generation + +Perintah umum: + +```bash +flutter pub run build_runner build --delete-conflicting-outputs +# atau untuk watch +flutter pub run build_runner watch --delete-conflicting-outputs +``` + +Generator yang digunakan: + +- AutoRoute: menghasilkan deklarasi router & route. +- Injectable: menghasilkan registrasi DI (`injection.config.dart`). +- Freezed: menghasilkan data class immutable, copyWith, union, dsb. +- Json Serializable: menghasilkan toJson/fromJson untuk DTO. +- FlutterGen: menghasilkan akses asset statis di `lib/presentation/components/assets/`. + +--- + +## Internationalization (i18n) + +- Berkas sumber ada di `lib/l10n/app_*.arb` (contoh: `app_en.arb`, `app_id.arb`). +- Bahasa baru: tambahkan `app_.arb`, jalankan code generation. +- Pastikan `MaterialApp` menggunakan `localizationsDelegates` dan `supportedLocales` (sudah disiapkan). + +--- + +## Theming & Assets + +- Theme ada di `lib/common/theme/`. +- Font: keluarga `Quicksand` dideklarasikan di `pubspec.yaml`. +- Assets: `assets/images/`, `assets/icons/`, `assets/json/` – akses via FlutterGen yang dihasilkan ke `lib/presentation/components/assets/`. + +--- + +## Konfigurasi Lingkungan (`env.dart`) + +File `lib/env.dart` menyimpan nilai konfigurasi seperti base URL, flag debug, dll. Sesuaikan untuk development/production (bisa dengan flavor, env var, atau branch khusus sesuai kebutuhan tim). + +--- + +## Praktik Pengembangan + +- Routing: definisikan route di `presentation/router`, jalankan codegen. +- DI: daftarkan service/repository dengan anotasi `@injectable`/`@LazySingleton`, lalu generate, dan panggil `configureDependencies()` di awal aplikasi. +- BLoC: simpan logic UI di layer `application` dan gunakan `BlocBuilder`/`BlocListener` di layer `presentation`. +- DTO ↔ Entity: mapping berada di layer `infrastructure` untuk menjaga domain tetap bersih. +- Error handling: gunakan `Either`/`Option` (`dartz`) atau state terstruktur di BLoC. +- Lint: patuhi aturan `analysis_options.yaml`. + +--- + +## Perintah Berguna + +```bash +# Install dependencies +flutter pub get + +# Format & Analyze +flutter format . +flutter analyze + +# Code generation (sekali jalan / watch) +flutter pub run build_runner build --delete-conflicting-outputs +flutter pub run build_runner watch --delete-conflicting-outputs + +# Run by device +flutter devices +flutter run -d +``` + +--- + +## Catatan Tambahan + +- Icon launcher dikonfigurasi di `launcher_icon.yaml` (gunakan `flutter pub run flutter_launcher_icons` bila diperlukan). +- Konfigurasi platform (Android/iOS/Web/Desktop) berada pada folder platform terkait. +- Pastikan meninjau `analysis_options.yaml` untuk standar code style dan lints. + +--- + +## Kontribusi + +1. Buat branch dari `main`. +2. Lakukan perubahan terfokus dan sertakan deskripsi yang jelas pada PR. +3. Pastikan build, lints, dan codegen bersih sebelum mengajukan PR. + +--- + +## Lisensi + +Proyek ini bersifat privat/internal. Hubungi pemilik repositori untuk detail izin penggunaan. diff --git a/analysis_options.yaml b/analysis_options.yaml index c4d2cef..a69a437 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -13,6 +13,8 @@ analyzer: sort_unnamed_constructors_first: ignore invalid_annotation_target: ignore use_build_context_synchronously: ignore + deprecated_member_use: ignore + depend_on_referenced_packages: ignore exclude: - test/generated/** - "**/**.g.dart" diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index a733c42..5a7213f 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -3,14 +3,16 @@ plugins { id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") + id("com.google.gms.google-services") } android { - namespace = "com.example.apskel_owner_flutter" + namespace = "com.apskel.enaklo_owner" compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion + ndkVersion = "27.0.12077973" compileOptions { + isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } @@ -21,7 +23,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.apskel_owner_flutter" + applicationId = "com.apskel.enaklo_owner" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = flutter.minSdkVersion @@ -42,3 +44,7 @@ android { flutter { source = "../.." } + +dependencies { + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") +} diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..4ba90e6 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,48 @@ +{ + "project_info": { + "project_number": "765730035527", + "project_id": "apskel-pos-v2", + "storage_bucket": "apskel-pos-v2.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:765730035527:android:beffb797b781e715241e62", + "android_client_info": { + "package_name": "com.apskel.enaklo_owner" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyAOZwVSQwUeeM9BjcyTOK9GUh8AmTWucuc" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:765730035527:android:498defd7071336dd241e62", + "android_client_info": { + "package_name": "com.apskel.pos" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyAOZwVSQwUeeM9BjcyTOK9GUh8AmTWucuc" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8ccc061..80f9dd1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,19 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #FF6B35 \ No newline at end of file diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index ab39a10..0bb8e82 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -20,6 +20,7 @@ plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("com.android.application") version "8.7.3" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false + id("com.google.gms.google-services") version "4.4.2" apply false } include(":app") diff --git a/assets/icons/ic-report-product.png b/assets/icons/ic-report-product.png new file mode 100644 index 0000000..d5c008f Binary files /dev/null and b/assets/icons/ic-report-product.png differ diff --git a/assets/icons/ic-report-profit-loss.png b/assets/icons/ic-report-profit-loss.png new file mode 100644 index 0000000..a24d838 Binary files /dev/null and b/assets/icons/ic-report-profit-loss.png differ diff --git a/assets/icons/ic-report-purchase.png b/assets/icons/ic-report-purchase.png new file mode 100644 index 0000000..3d97aa5 Binary files /dev/null and b/assets/icons/ic-report-purchase.png differ diff --git a/assets/icons/ic-report-sales.png b/assets/icons/ic-report-sales.png new file mode 100644 index 0000000..11daa81 Binary files /dev/null and b/assets/icons/ic-report-sales.png differ diff --git a/assets/images/ic_notification.png b/assets/images/ic_notification.png new file mode 100644 index 0000000..63967d0 Binary files /dev/null and b/assets/images/ic_notification.png differ diff --git a/assets/images/logo.png b/assets/images/logo.png index 93f2c08..ddc7ef9 100644 Binary files a/assets/images/logo.png and b/assets/images/logo.png differ diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..4dcfde9 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,4 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: + - shared_preferences: true \ No newline at end of file diff --git a/ios/Podfile b/ios/Podfile index e549ee2..c2c1dc5 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +platform :ios, '14.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..04667cf --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,181 @@ +PODS: + - connectivity_plus (0.0.1): + - Flutter + - device_info_plus (0.0.1): + - Flutter + - Firebase/CoreOnly (10.25.0): + - FirebaseCore (= 10.25.0) + - Firebase/Messaging (10.25.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 10.25.0) + - firebase_core (2.32.0): + - Firebase/CoreOnly (= 10.25.0) + - Flutter + - firebase_messaging (14.7.10): + - Firebase/Messaging (= 10.25.0) + - firebase_core + - Flutter + - FirebaseCore (10.25.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.12) + - GoogleUtilities/Logger (~> 7.12) + - FirebaseCoreInternal (10.29.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseInstallations (10.29.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.25.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.3) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30911.0, >= 2.30908.0) + - Flutter (1.0.0) + - flutter_local_notifications (0.0.1): + - Flutter + - GoogleDataTransport (9.4.1): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30911.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (7.13.3): + - GoogleUtilities/Privacy + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (7.13.3): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.13.3)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (7.13.3) + - GoogleUtilities/Reachability (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - image_picker_ios (0.0.1): + - Flutter + - nanopb (2.30910.0): + - nanopb/decode (= 2.30910.0) + - nanopb/encode (= 2.30910.0) + - nanopb/decode (2.30910.0) + - nanopb/encode (2.30910.0) + - open_file_ios (0.0.1): + - Flutter + - package_info_plus (0.4.5): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.3.0): + - Flutter + - PromisesObjC (2.4.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - sqflite_darwin (0.0.4): + - Flutter + - FlutterMacOS + - url_launcher_ios (0.0.1): + - Flutter + +DEPENDENCIES: + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) + - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - open_file_ios (from `.symlinks/plugins/open_file_ios/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + +SPEC REPOS: + trunk: + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - GoogleDataTransport + - GoogleUtilities + - nanopb + - PromisesObjC + +EXTERNAL SOURCES: + connectivity_plus: + :path: ".symlinks/plugins/connectivity_plus/ios" + device_info_plus: + :path: ".symlinks/plugins/device_info_plus/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" + open_file_ios: + :path: ".symlinks/plugins/open_file_ios/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sqflite_darwin: + :path: ".symlinks/plugins/sqflite_darwin/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + +SPEC CHECKSUMS: + connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d + device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 + Firebase: 0312a2352584f782ea56f66d91606891d4607f06 + firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197 + firebase_messaging: 1541105e2a2a6ef8bd869bcc44157d31e82f3a50 + FirebaseCore: 7ec4d0484817f12c3373955bc87762d96842d483 + FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 + FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd + FirebaseMessaging: 88950ba9485052891ebe26f6c43a52bb62248952 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_local_notifications: df98d66e515e1ca797af436137b4459b160ad8c9 + GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a + GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 + image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + nanopb: 438bc412db1928dac798aa6fd75726007be04262 + open_file_ios: 461db5853723763573e140de3193656f91990d9e + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + +PODFILE CHECKSUM: e30f02f9d1c72c47bb6344a0a748c9d268180865 + +COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index e17b8a2..a4d20be 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -8,12 +8,15 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 227E95452FB25185003AAE6C /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 227E95442FB25185003AAE6C /* GoogleService-Info.plist */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 989F8AA016A730C566E93749 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6F295F1D6E4BB0819A8681 /* Pods_RunnerTests.framework */; }; + F18848A41F5DE1108211F920 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B7ABC3D9AD3883EDD2E44FB /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,14 +43,22 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0B9C91DAD8EC48930CF79A70 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 159A415F4811E2794AA4092B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 1CE6759F37E82B0362B2E241 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 227E95442FB25185003AAE6C /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3A6F295F1D6E4BB0819A8681 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B7ABC3D9AD3883EDD2E44FB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C70A9D33D5F6D7EAE05A508 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7F8F2B65C01EDDD64346C756 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -55,13 +66,23 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E6E423C7625C032FDEFB6799 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 6BBDF52C0DFCF2DFA69EB9C3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 989F8AA016A730C566E93749 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F18848A41F5DE1108211F920 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -76,6 +97,15 @@ path = RunnerTests; sourceTree = ""; }; + 4DBA9259FD070A034AF146BB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3B7ABC3D9AD3883EDD2E44FB /* Pods_Runner.framework */, + 3A6F295F1D6E4BB0819A8681 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +124,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + F771B77E516695BE7A4B0AEA /* Pods */, + 4DBA9259FD070A034AF146BB /* Frameworks */, ); sourceTree = ""; }; @@ -109,6 +141,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 227E95442FB25185003AAE6C /* GoogleService-Info.plist */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -121,6 +154,19 @@ path = Runner; sourceTree = ""; }; + F771B77E516695BE7A4B0AEA /* Pods */ = { + isa = PBXGroup; + children = ( + 3C70A9D33D5F6D7EAE05A508 /* Pods-Runner.debug.xcconfig */, + 1CE6759F37E82B0362B2E241 /* Pods-Runner.release.xcconfig */, + 159A415F4811E2794AA4092B /* Pods-Runner.profile.xcconfig */, + E6E423C7625C032FDEFB6799 /* Pods-RunnerTests.debug.xcconfig */, + 7F8F2B65C01EDDD64346C756 /* Pods-RunnerTests.release.xcconfig */, + 0B9C91DAD8EC48930CF79A70 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -128,8 +174,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 81D20024DBE321C19417AE73 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + 6BBDF52C0DFCF2DFA69EB9C3 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +193,15 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + ACC8E6F2D63F11FFC05DF00A /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 77740562F72074B1BD58B4C5 /* [CP] Embed Pods Frameworks */, + E2768009FD8B9B6235B4E16A /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -214,6 +265,7 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 227E95452FB25185003AAE6C /* GoogleService-Info.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -238,6 +290,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 77740562F72074B1BD58B4C5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 81D20024DBE321C19417AE73 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +344,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + ACC8E6F2D63F11FFC05DF00A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E2768009FD8B9B6235B4E16A /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -362,13 +492,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 5TRC3M8UZG; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.apskelOwnerFlutter; + PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -378,13 +510,14 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E6E423C7625C032FDEFB6799 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.apskelOwnerFlutter.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklo.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -395,13 +528,14 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7F8F2B65C01EDDD64346C756 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.apskelOwnerFlutter.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklo.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; @@ -410,13 +544,14 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0B9C91DAD8EC48930CF79A70 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.apskelOwnerFlutter.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklo.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; @@ -541,13 +676,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 5TRC3M8UZG; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.apskelOwnerFlutter; + PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -563,13 +700,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 5TRC3M8UZG; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.apskelOwnerFlutter; + PRODUCT_BUNDLE_IDENTIFIER = com.apskel.enaklo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 6266644..a725045 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,5 +1,6 @@ import Flutter import UIKit +import UserNotifications @main @objc class AppDelegate: FlutterAppDelegate { @@ -7,7 +8,28 @@ import UIKit _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + // Set notification delegate so notifications show in foreground & background + UNUserNotificationCenter.current().delegate = self + GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + // Called when a notification is delivered while app is in foreground + override func userNotificationCenter( + _ center: UNUserNotificationCenter, + willPresent notification: UNNotification, + withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void + ) { + completionHandler([.banner, .badge, .sound]) + } + + // Called when user taps a notification (foreground or background) + override func userNotificationCenter( + _ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse, + withCompletionHandler completionHandler: @escaping () -> Void + ) { + completionHandler() + } } diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index 1db7ead..02b59ab 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png index 8e144ce..bf4e387 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 6316890..e8f7929 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index aae451f..30b543a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png index 3cb23a6..314c558 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index 2dcd41a..f877e0d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 4f6198a..12bbd9c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 6316890..e8f7929 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index a98c5fd..39a413c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 03ff2ff..13dff73 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png index b6525a6..4b77f71 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png index 125c04b..21c8c59 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png index 023043b..6baf3b5 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png index c9b2d52..37afe2b 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 03ff2ff..13dff73 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index 2363ed4..0cec7eb 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png index 92dc668..60b9e56 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png index 2407101..022fbd6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 31bac3f..4292e01 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 095f3f0..a4c148c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 7b22e10..6ad1bd8 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..bf0e33d --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,30 @@ + + + + + API_KEY + AIzaSyCb6teTjGKytZmAZc2aMJrpaW484tm93jY + GCM_SENDER_ID + 765730035527 + PLIST_VERSION + 1 + BUNDLE_ID + com.apskel.enaklo + PROJECT_ID + apskel-pos-v2 + STORAGE_BUCKET + apskel-pos-v2.firebasestorage.app + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:765730035527:ios:c87f91e28b33766e241e62 + + \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index eb9dffe..2b97686 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - Apskel Owner Flutter + Enaklo Owner CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -45,5 +45,11 @@ UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + fetch + remote-notification + diff --git a/lib/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart b/lib/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart new file mode 100644 index 0000000..eb99bfd --- /dev/null +++ b/lib/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart @@ -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 'category_analytic_loader_event.dart'; +part 'category_analytic_loader_state.dart'; +part 'category_analytic_loader_bloc.freezed.dart'; + +@injectable +class CategoryAnalyticLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + + CategoryAnalyticLoaderBloc(this._repository) + : super(CategoryAnalyticLoaderState.initial()) { + on(_onCategoryAnalyticLoaderEvent); + } + + Future _onCategoryAnalyticLoaderEvent( + CategoryAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionCategoryAnalytic: none(), + ), + ); + + final result = await _repository.getCategory( + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionCategoryAnalytic: optionOf(f)), + (categoryAnalytic) => + state.copyWith(categoryAnalytic: categoryAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/category_analytic_loader/category_analytic_loader_bloc.freezed.dart b/lib/application/analytic/category_analytic_loader/category_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..41a5c79 --- /dev/null +++ b/lib/application/analytic/category_analytic_loader/category_analytic_loader_bloc.freezed.dart @@ -0,0 +1,401 @@ +// 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 'category_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$CategoryAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryAnalyticLoaderEventCopyWith<$Res> { + factory $CategoryAnalyticLoaderEventCopyWith( + CategoryAnalyticLoaderEvent value, + $Res Function(CategoryAnalyticLoaderEvent) then, + ) = + _$CategoryAnalyticLoaderEventCopyWithImpl< + $Res, + CategoryAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$CategoryAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends CategoryAnalyticLoaderEvent +> + implements $CategoryAnalyticLoaderEventCopyWith<$Res> { + _$CategoryAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryAnalyticLoaderEvent + /// 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>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$CategoryAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'CategoryAnalyticLoaderEvent.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({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements CategoryAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$CategoryAnalyticLoaderState { + CategoryAnalytic get categoryAnalytic => throw _privateConstructorUsedError; + Option get failureOptionCategoryAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of CategoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryAnalyticLoaderStateCopyWith<$Res> { + factory $CategoryAnalyticLoaderStateCopyWith( + CategoryAnalyticLoaderState value, + $Res Function(CategoryAnalyticLoaderState) then, + ) = + _$CategoryAnalyticLoaderStateCopyWithImpl< + $Res, + CategoryAnalyticLoaderState + >; + @useResult + $Res call({ + CategoryAnalytic categoryAnalytic, + Option failureOptionCategoryAnalytic, + bool isFetching, + }); + + $CategoryAnalyticCopyWith<$Res> get categoryAnalytic; +} + +/// @nodoc +class _$CategoryAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends CategoryAnalyticLoaderState +> + implements $CategoryAnalyticLoaderStateCopyWith<$Res> { + _$CategoryAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryAnalytic = null, + Object? failureOptionCategoryAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + categoryAnalytic: null == categoryAnalytic + ? _value.categoryAnalytic + : categoryAnalytic // ignore: cast_nullable_to_non_nullable + as CategoryAnalytic, + failureOptionCategoryAnalytic: null == failureOptionCategoryAnalytic + ? _value.failureOptionCategoryAnalytic + : failureOptionCategoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of CategoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $CategoryAnalyticCopyWith<$Res> get categoryAnalytic { + return $CategoryAnalyticCopyWith<$Res>(_value.categoryAnalytic, (value) { + return _then(_value.copyWith(categoryAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$CategoryAnalyticLoaderStateImplCopyWith<$Res> + implements $CategoryAnalyticLoaderStateCopyWith<$Res> { + factory _$$CategoryAnalyticLoaderStateImplCopyWith( + _$CategoryAnalyticLoaderStateImpl value, + $Res Function(_$CategoryAnalyticLoaderStateImpl) then, + ) = __$$CategoryAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + CategoryAnalytic categoryAnalytic, + Option failureOptionCategoryAnalytic, + bool isFetching, + }); + + @override + $CategoryAnalyticCopyWith<$Res> get categoryAnalytic; +} + +/// @nodoc +class __$$CategoryAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$CategoryAnalyticLoaderStateCopyWithImpl< + $Res, + _$CategoryAnalyticLoaderStateImpl + > + implements _$$CategoryAnalyticLoaderStateImplCopyWith<$Res> { + __$$CategoryAnalyticLoaderStateImplCopyWithImpl( + _$CategoryAnalyticLoaderStateImpl _value, + $Res Function(_$CategoryAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryAnalytic = null, + Object? failureOptionCategoryAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _$CategoryAnalyticLoaderStateImpl( + categoryAnalytic: null == categoryAnalytic + ? _value.categoryAnalytic + : categoryAnalytic // ignore: cast_nullable_to_non_nullable + as CategoryAnalytic, + failureOptionCategoryAnalytic: null == failureOptionCategoryAnalytic + ? _value.failureOptionCategoryAnalytic + : failureOptionCategoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$CategoryAnalyticLoaderStateImpl + implements _CategoryAnalyticLoaderState { + const _$CategoryAnalyticLoaderStateImpl({ + required this.categoryAnalytic, + required this.failureOptionCategoryAnalytic, + this.isFetching = false, + }); + + @override + final CategoryAnalytic categoryAnalytic; + @override + final Option failureOptionCategoryAnalytic; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'CategoryAnalyticLoaderState(categoryAnalytic: $categoryAnalytic, failureOptionCategoryAnalytic: $failureOptionCategoryAnalytic, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryAnalyticLoaderStateImpl && + (identical(other.categoryAnalytic, categoryAnalytic) || + other.categoryAnalytic == categoryAnalytic) && + (identical( + other.failureOptionCategoryAnalytic, + failureOptionCategoryAnalytic, + ) || + other.failureOptionCategoryAnalytic == + failureOptionCategoryAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + categoryAnalytic, + failureOptionCategoryAnalytic, + isFetching, + ); + + /// Create a copy of CategoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryAnalyticLoaderStateImplCopyWith<_$CategoryAnalyticLoaderStateImpl> + get copyWith => + __$$CategoryAnalyticLoaderStateImplCopyWithImpl< + _$CategoryAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _CategoryAnalyticLoaderState + implements CategoryAnalyticLoaderState { + const factory _CategoryAnalyticLoaderState({ + required final CategoryAnalytic categoryAnalytic, + required final Option failureOptionCategoryAnalytic, + final bool isFetching, + }) = _$CategoryAnalyticLoaderStateImpl; + + @override + CategoryAnalytic get categoryAnalytic; + @override + Option get failureOptionCategoryAnalytic; + @override + bool get isFetching; + + /// Create a copy of CategoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryAnalyticLoaderStateImplCopyWith<_$CategoryAnalyticLoaderStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/category_analytic_loader/category_analytic_loader_event.dart b/lib/application/analytic/category_analytic_loader/category_analytic_loader_event.dart new file mode 100644 index 0000000..87c2994 --- /dev/null +++ b/lib/application/analytic/category_analytic_loader/category_analytic_loader_event.dart @@ -0,0 +1,6 @@ +part of 'category_analytic_loader_bloc.dart'; + +@freezed +class CategoryAnalyticLoaderEvent with _$CategoryAnalyticLoaderEvent { + const factory CategoryAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/category_analytic_loader/category_analytic_loader_state.dart b/lib/application/analytic/category_analytic_loader/category_analytic_loader_state.dart new file mode 100644 index 0000000..0754233 --- /dev/null +++ b/lib/application/analytic/category_analytic_loader/category_analytic_loader_state.dart @@ -0,0 +1,15 @@ +part of 'category_analytic_loader_bloc.dart'; + +@freezed +class CategoryAnalyticLoaderState with _$CategoryAnalyticLoaderState { + const factory CategoryAnalyticLoaderState({ + required CategoryAnalytic categoryAnalytic, + required Option failureOptionCategoryAnalytic, + @Default(false) bool isFetching, + }) = _CategoryAnalyticLoaderState; + + factory CategoryAnalyticLoaderState.initial() => CategoryAnalyticLoaderState( + categoryAnalytic: CategoryAnalytic.empty(), + failureOptionCategoryAnalytic: none(), + ); +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart new file mode 100644 index 0000000..264695b --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart @@ -0,0 +1,53 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.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 'dashboard_analytic_loader_event.dart'; +part 'dashboard_analytic_loader_state.dart'; +part 'dashboard_analytic_loader_bloc.freezed.dart'; + +@injectable +class DashboardAnalyticLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + DashboardAnalyticLoaderBloc(this._repository) + : super(DashboardAnalyticLoaderState.initial()) { + on(_onDashboardAnalyticLoaderEvent); + } + + Future _onDashboardAnalyticLoaderEvent( + DashboardAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + rangeDateChanged: (e) async { + emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo)); + }, + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionDashboardAnalytic: none(), + ), + ); + + final result = await _repository.getDashboard( + dateFrom: state.dateFrom, + dateTo: state.dateTo, + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionDashboardAnalytic: optionOf(f)), + (dashboardAnalytic) => + state.copyWith(dashboardAnalytic: dashboardAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.freezed.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..a11d71d --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.freezed.dart @@ -0,0 +1,626 @@ +// 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 'dashboard_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$DashboardAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticLoaderEventCopyWith<$Res> { + factory $DashboardAnalyticLoaderEventCopyWith( + DashboardAnalyticLoaderEvent value, + $Res Function(DashboardAnalyticLoaderEvent) then, + ) = + _$DashboardAnalyticLoaderEventCopyWithImpl< + $Res, + DashboardAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$DashboardAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends DashboardAnalyticLoaderEvent +> + implements $DashboardAnalyticLoaderEventCopyWith<$Res> { + _$DashboardAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalyticLoaderEvent + /// 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 + _$DashboardAnalyticLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl> + implements _$$RangeDateChangedImplCopyWith<$Res> { + __$$RangeDateChangedImplCopyWithImpl( + _$RangeDateChangedImpl _value, + $Res Function(_$RangeDateChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticLoaderEvent + /// 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 'DashboardAnalyticLoaderEvent.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 DashboardAnalyticLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return rangeDateChanged(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return rangeDateChanged?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return rangeDateChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return rangeDateChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(this); + } + return orElse(); + } +} + +abstract class _RangeDateChanged implements DashboardAnalyticLoaderEvent { + const factory _RangeDateChanged( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$RangeDateChangedImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of DashboardAnalyticLoaderEvent + /// 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 _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$DashboardAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'DashboardAnalyticLoaderEvent.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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements DashboardAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$DashboardAnalyticLoaderState { + DashboardAnalytic get dashboardAnalytic => throw _privateConstructorUsedError; + Option get failureOptionDashboardAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticLoaderStateCopyWith<$Res> { + factory $DashboardAnalyticLoaderStateCopyWith( + DashboardAnalyticLoaderState value, + $Res Function(DashboardAnalyticLoaderState) then, + ) = + _$DashboardAnalyticLoaderStateCopyWithImpl< + $Res, + DashboardAnalyticLoaderState + >; + @useResult + $Res call({ + DashboardAnalytic dashboardAnalytic, + Option failureOptionDashboardAnalytic, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + $DashboardAnalyticCopyWith<$Res> get dashboardAnalytic; +} + +/// @nodoc +class _$DashboardAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends DashboardAnalyticLoaderState +> + implements $DashboardAnalyticLoaderStateCopyWith<$Res> { + _$DashboardAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? dashboardAnalytic = null, + Object? failureOptionDashboardAnalytic = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _value.copyWith( + dashboardAnalytic: null == dashboardAnalytic + ? _value.dashboardAnalytic + : dashboardAnalytic // ignore: cast_nullable_to_non_nullable + as DashboardAnalytic, + failureOptionDashboardAnalytic: + null == failureOptionDashboardAnalytic + ? _value.failureOptionDashboardAnalytic + : failureOptionDashboardAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardAnalyticCopyWith<$Res> get dashboardAnalytic { + return $DashboardAnalyticCopyWith<$Res>(_value.dashboardAnalytic, (value) { + return _then(_value.copyWith(dashboardAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$DashboardAnalyticLoaderStateImplCopyWith<$Res> + implements $DashboardAnalyticLoaderStateCopyWith<$Res> { + factory _$$DashboardAnalyticLoaderStateImplCopyWith( + _$DashboardAnalyticLoaderStateImpl value, + $Res Function(_$DashboardAnalyticLoaderStateImpl) then, + ) = __$$DashboardAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + DashboardAnalytic dashboardAnalytic, + Option failureOptionDashboardAnalytic, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + @override + $DashboardAnalyticCopyWith<$Res> get dashboardAnalytic; +} + +/// @nodoc +class __$$DashboardAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$DashboardAnalyticLoaderStateCopyWithImpl< + $Res, + _$DashboardAnalyticLoaderStateImpl + > + implements _$$DashboardAnalyticLoaderStateImplCopyWith<$Res> { + __$$DashboardAnalyticLoaderStateImplCopyWithImpl( + _$DashboardAnalyticLoaderStateImpl _value, + $Res Function(_$DashboardAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? dashboardAnalytic = null, + Object? failureOptionDashboardAnalytic = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _$DashboardAnalyticLoaderStateImpl( + dashboardAnalytic: null == dashboardAnalytic + ? _value.dashboardAnalytic + : dashboardAnalytic // ignore: cast_nullable_to_non_nullable + as DashboardAnalytic, + failureOptionDashboardAnalytic: null == failureOptionDashboardAnalytic + ? _value.failureOptionDashboardAnalytic + : failureOptionDashboardAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 _$DashboardAnalyticLoaderStateImpl + implements _DashboardAnalyticLoaderState { + const _$DashboardAnalyticLoaderStateImpl({ + required this.dashboardAnalytic, + required this.failureOptionDashboardAnalytic, + this.isFetching = false, + required this.dateFrom, + required this.dateTo, + }); + + @override + final DashboardAnalytic dashboardAnalytic; + @override + final Option failureOptionDashboardAnalytic; + @override + @JsonKey() + final bool isFetching; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'DashboardAnalyticLoaderState(dashboardAnalytic: $dashboardAnalytic, failureOptionDashboardAnalytic: $failureOptionDashboardAnalytic, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardAnalyticLoaderStateImpl && + (identical(other.dashboardAnalytic, dashboardAnalytic) || + other.dashboardAnalytic == dashboardAnalytic) && + (identical( + other.failureOptionDashboardAnalytic, + failureOptionDashboardAnalytic, + ) || + other.failureOptionDashboardAnalytic == + failureOptionDashboardAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + dashboardAnalytic, + failureOptionDashboardAnalytic, + isFetching, + dateFrom, + dateTo, + ); + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardAnalyticLoaderStateImplCopyWith< + _$DashboardAnalyticLoaderStateImpl + > + get copyWith => + __$$DashboardAnalyticLoaderStateImplCopyWithImpl< + _$DashboardAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _DashboardAnalyticLoaderState + implements DashboardAnalyticLoaderState { + const factory _DashboardAnalyticLoaderState({ + required final DashboardAnalytic dashboardAnalytic, + required final Option failureOptionDashboardAnalytic, + final bool isFetching, + required final DateTime dateFrom, + required final DateTime dateTo, + }) = _$DashboardAnalyticLoaderStateImpl; + + @override + DashboardAnalytic get dashboardAnalytic; + @override + Option get failureOptionDashboardAnalytic; + @override + bool get isFetching; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + + /// Create a copy of DashboardAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardAnalyticLoaderStateImplCopyWith< + _$DashboardAnalyticLoaderStateImpl + > + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_event.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_event.dart new file mode 100644 index 0000000..5787cbe --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_event.dart @@ -0,0 +1,10 @@ +part of 'dashboard_analytic_loader_bloc.dart'; + +@freezed +class DashboardAnalyticLoaderEvent with _$DashboardAnalyticLoaderEvent { + const factory DashboardAnalyticLoaderEvent.rangeDateChanged( + DateTime dateFrom, + DateTime dateTo, + ) = _RangeDateChanged; + const factory DashboardAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_state.dart b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_state.dart new file mode 100644 index 0000000..6507cf8 --- /dev/null +++ b/lib/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_state.dart @@ -0,0 +1,20 @@ +part of 'dashboard_analytic_loader_bloc.dart'; + +@freezed +class DashboardAnalyticLoaderState with _$DashboardAnalyticLoaderState { + const factory DashboardAnalyticLoaderState({ + required DashboardAnalytic dashboardAnalytic, + required Option failureOptionDashboardAnalytic, + @Default(false) bool isFetching, + required DateTime dateFrom, + required DateTime dateTo, + }) = _DashboardAnalyticLoaderState; + + factory DashboardAnalyticLoaderState.initial() => + DashboardAnalyticLoaderState( + dashboardAnalytic: DashboardAnalytic.empty(), + failureOptionDashboardAnalytic: none(), + dateFrom: DateTime.now(), + dateTo: DateTime.now(), + ); +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart new file mode 100644 index 0000000..65dc0a8 --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart @@ -0,0 +1,53 @@ +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 'inventory_analytic_loader_event.dart'; +part 'inventory_analytic_loader_state.dart'; +part 'inventory_analytic_loader_bloc.freezed.dart'; + +@injectable +class InventoryAnalyticLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + InventoryAnalyticLoaderBloc(this._repository) + : super(InventoryAnalyticLoaderState.initial()) { + on(_onInventoryAnalyticLoaderEvent); + } + + Future _onInventoryAnalyticLoaderEvent( + InventoryAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + rangeDateChanged: (e) async { + emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo)); + }, + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionInventoryAnalytic: none(), + ), + ); + + final result = await _repository.getInventory( + dateFrom: state.dateFrom, + dateTo: state.dateTo, + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionInventoryAnalytic: optionOf(f)), + (inventoryAnalytic) => + state.copyWith(inventoryAnalytic: inventoryAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.freezed.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..9a6d650 --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.freezed.dart @@ -0,0 +1,626 @@ +// 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 'inventory_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$InventoryAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticLoaderEventCopyWith<$Res> { + factory $InventoryAnalyticLoaderEventCopyWith( + InventoryAnalyticLoaderEvent value, + $Res Function(InventoryAnalyticLoaderEvent) then, + ) = + _$InventoryAnalyticLoaderEventCopyWithImpl< + $Res, + InventoryAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$InventoryAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends InventoryAnalyticLoaderEvent +> + implements $InventoryAnalyticLoaderEventCopyWith<$Res> { + _$InventoryAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalyticLoaderEvent + /// 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 + _$InventoryAnalyticLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl> + implements _$$RangeDateChangedImplCopyWith<$Res> { + __$$RangeDateChangedImplCopyWithImpl( + _$RangeDateChangedImpl _value, + $Res Function(_$RangeDateChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticLoaderEvent + /// 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 'InventoryAnalyticLoaderEvent.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 InventoryAnalyticLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return rangeDateChanged(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return rangeDateChanged?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return rangeDateChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return rangeDateChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(this); + } + return orElse(); + } +} + +abstract class _RangeDateChanged implements InventoryAnalyticLoaderEvent { + const factory _RangeDateChanged( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$RangeDateChangedImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of InventoryAnalyticLoaderEvent + /// 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 _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$InventoryAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'InventoryAnalyticLoaderEvent.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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements InventoryAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$InventoryAnalyticLoaderState { + InventoryAnalytic get inventoryAnalytic => throw _privateConstructorUsedError; + Option get failureOptionInventoryAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticLoaderStateCopyWith<$Res> { + factory $InventoryAnalyticLoaderStateCopyWith( + InventoryAnalyticLoaderState value, + $Res Function(InventoryAnalyticLoaderState) then, + ) = + _$InventoryAnalyticLoaderStateCopyWithImpl< + $Res, + InventoryAnalyticLoaderState + >; + @useResult + $Res call({ + InventoryAnalytic inventoryAnalytic, + Option failureOptionInventoryAnalytic, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic; +} + +/// @nodoc +class _$InventoryAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends InventoryAnalyticLoaderState +> + implements $InventoryAnalyticLoaderStateCopyWith<$Res> { + _$InventoryAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inventoryAnalytic = null, + Object? failureOptionInventoryAnalytic = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _value.copyWith( + inventoryAnalytic: null == inventoryAnalytic + ? _value.inventoryAnalytic + : inventoryAnalytic // ignore: cast_nullable_to_non_nullable + as InventoryAnalytic, + failureOptionInventoryAnalytic: + null == failureOptionInventoryAnalytic + ? _value.failureOptionInventoryAnalytic + : failureOptionInventoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic { + return $InventoryAnalyticCopyWith<$Res>(_value.inventoryAnalytic, (value) { + return _then(_value.copyWith(inventoryAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryAnalyticLoaderStateImplCopyWith<$Res> + implements $InventoryAnalyticLoaderStateCopyWith<$Res> { + factory _$$InventoryAnalyticLoaderStateImplCopyWith( + _$InventoryAnalyticLoaderStateImpl value, + $Res Function(_$InventoryAnalyticLoaderStateImpl) then, + ) = __$$InventoryAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + InventoryAnalytic inventoryAnalytic, + Option failureOptionInventoryAnalytic, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + @override + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic; +} + +/// @nodoc +class __$$InventoryAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$InventoryAnalyticLoaderStateCopyWithImpl< + $Res, + _$InventoryAnalyticLoaderStateImpl + > + implements _$$InventoryAnalyticLoaderStateImplCopyWith<$Res> { + __$$InventoryAnalyticLoaderStateImplCopyWithImpl( + _$InventoryAnalyticLoaderStateImpl _value, + $Res Function(_$InventoryAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inventoryAnalytic = null, + Object? failureOptionInventoryAnalytic = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _$InventoryAnalyticLoaderStateImpl( + inventoryAnalytic: null == inventoryAnalytic + ? _value.inventoryAnalytic + : inventoryAnalytic // ignore: cast_nullable_to_non_nullable + as InventoryAnalytic, + failureOptionInventoryAnalytic: null == failureOptionInventoryAnalytic + ? _value.failureOptionInventoryAnalytic + : failureOptionInventoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 _$InventoryAnalyticLoaderStateImpl + implements _InventoryAnalyticLoaderState { + const _$InventoryAnalyticLoaderStateImpl({ + required this.inventoryAnalytic, + required this.failureOptionInventoryAnalytic, + this.isFetching = false, + required this.dateFrom, + required this.dateTo, + }); + + @override + final InventoryAnalytic inventoryAnalytic; + @override + final Option failureOptionInventoryAnalytic; + @override + @JsonKey() + final bool isFetching; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'InventoryAnalyticLoaderState(inventoryAnalytic: $inventoryAnalytic, failureOptionInventoryAnalytic: $failureOptionInventoryAnalytic, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryAnalyticLoaderStateImpl && + (identical(other.inventoryAnalytic, inventoryAnalytic) || + other.inventoryAnalytic == inventoryAnalytic) && + (identical( + other.failureOptionInventoryAnalytic, + failureOptionInventoryAnalytic, + ) || + other.failureOptionInventoryAnalytic == + failureOptionInventoryAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + inventoryAnalytic, + failureOptionInventoryAnalytic, + isFetching, + dateFrom, + dateTo, + ); + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryAnalyticLoaderStateImplCopyWith< + _$InventoryAnalyticLoaderStateImpl + > + get copyWith => + __$$InventoryAnalyticLoaderStateImplCopyWithImpl< + _$InventoryAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _InventoryAnalyticLoaderState + implements InventoryAnalyticLoaderState { + const factory _InventoryAnalyticLoaderState({ + required final InventoryAnalytic inventoryAnalytic, + required final Option failureOptionInventoryAnalytic, + final bool isFetching, + required final DateTime dateFrom, + required final DateTime dateTo, + }) = _$InventoryAnalyticLoaderStateImpl; + + @override + InventoryAnalytic get inventoryAnalytic; + @override + Option get failureOptionInventoryAnalytic; + @override + bool get isFetching; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + + /// Create a copy of InventoryAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryAnalyticLoaderStateImplCopyWith< + _$InventoryAnalyticLoaderStateImpl + > + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_event.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_event.dart new file mode 100644 index 0000000..5d9a844 --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_event.dart @@ -0,0 +1,10 @@ +part of 'inventory_analytic_loader_bloc.dart'; + +@freezed +class InventoryAnalyticLoaderEvent with _$InventoryAnalyticLoaderEvent { + const factory InventoryAnalyticLoaderEvent.rangeDateChanged( + DateTime dateFrom, + DateTime dateTo, + ) = _RangeDateChanged; + const factory InventoryAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_state.dart b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_state.dart new file mode 100644 index 0000000..b71a7dc --- /dev/null +++ b/lib/application/analytic/inventory_analytic_loader/inventory_analytic_loader_state.dart @@ -0,0 +1,20 @@ +part of 'inventory_analytic_loader_bloc.dart'; + +@freezed +class InventoryAnalyticLoaderState with _$InventoryAnalyticLoaderState { + const factory InventoryAnalyticLoaderState({ + required InventoryAnalytic inventoryAnalytic, + required Option failureOptionInventoryAnalytic, + @Default(false) bool isFetching, + required DateTime dateFrom, + required DateTime dateTo, + }) = _InventoryAnalyticLoaderState; + + factory InventoryAnalyticLoaderState.initial() => + InventoryAnalyticLoaderState( + inventoryAnalytic: InventoryAnalytic.empty(), + failureOptionInventoryAnalytic: none(), + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); +} diff --git a/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart new file mode 100644 index 0000000..ff03c25 --- /dev/null +++ b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart @@ -0,0 +1,55 @@ +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 'payment_method_analytic_loader_event.dart'; +part 'payment_method_analytic_loader_state.dart'; +part 'payment_method_analytic_loader_bloc.freezed.dart'; + +@injectable +class PaymentMethodAnalyticLoaderBloc + extends + Bloc< + PaymentMethodAnalyticLoaderEvent, + PaymentMethodAnalyticLoaderState + > { + final IAnalyticRepository _repository; + PaymentMethodAnalyticLoaderBloc(this._repository) + : super(PaymentMethodAnalyticLoaderState.initial()) { + on(_onPaymentMethodAnalyticLoaderEvent); + } + + Future _onPaymentMethodAnalyticLoaderEvent( + PaymentMethodAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionPaymentMethodAnalytic: none(), + ), + ); + + final result = await _repository.getPaymentMethod( + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); + + var data = result.fold( + (f) => + state.copyWith(failureOptionPaymentMethodAnalytic: optionOf(f)), + (paymentMethodAnalytic) => + state.copyWith(paymentMethodAnalytic: paymentMethodAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.freezed.dart b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..376f974 --- /dev/null +++ b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.freezed.dart @@ -0,0 +1,410 @@ +// 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 'payment_method_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$PaymentMethodAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodAnalyticLoaderEventCopyWith<$Res> { + factory $PaymentMethodAnalyticLoaderEventCopyWith( + PaymentMethodAnalyticLoaderEvent value, + $Res Function(PaymentMethodAnalyticLoaderEvent) then, + ) = + _$PaymentMethodAnalyticLoaderEventCopyWithImpl< + $Res, + PaymentMethodAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$PaymentMethodAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends PaymentMethodAnalyticLoaderEvent +> + implements $PaymentMethodAnalyticLoaderEventCopyWith<$Res> { + _$PaymentMethodAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodAnalyticLoaderEvent + /// 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>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$PaymentMethodAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'PaymentMethodAnalyticLoaderEvent.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({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements PaymentMethodAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$PaymentMethodAnalyticLoaderState { + PaymentMethodAnalytic get paymentMethodAnalytic => + throw _privateConstructorUsedError; + Option get failureOptionPaymentMethodAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodAnalyticLoaderStateCopyWith<$Res> { + factory $PaymentMethodAnalyticLoaderStateCopyWith( + PaymentMethodAnalyticLoaderState value, + $Res Function(PaymentMethodAnalyticLoaderState) then, + ) = + _$PaymentMethodAnalyticLoaderStateCopyWithImpl< + $Res, + PaymentMethodAnalyticLoaderState + >; + @useResult + $Res call({ + PaymentMethodAnalytic paymentMethodAnalytic, + Option failureOptionPaymentMethodAnalytic, + bool isFetching, + }); + + $PaymentMethodAnalyticCopyWith<$Res> get paymentMethodAnalytic; +} + +/// @nodoc +class _$PaymentMethodAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends PaymentMethodAnalyticLoaderState +> + implements $PaymentMethodAnalyticLoaderStateCopyWith<$Res> { + _$PaymentMethodAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodAnalytic = null, + Object? failureOptionPaymentMethodAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + paymentMethodAnalytic: null == paymentMethodAnalytic + ? _value.paymentMethodAnalytic + : paymentMethodAnalytic // ignore: cast_nullable_to_non_nullable + as PaymentMethodAnalytic, + failureOptionPaymentMethodAnalytic: + null == failureOptionPaymentMethodAnalytic + ? _value.failureOptionPaymentMethodAnalytic + : failureOptionPaymentMethodAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of PaymentMethodAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $PaymentMethodAnalyticCopyWith<$Res> get paymentMethodAnalytic { + return $PaymentMethodAnalyticCopyWith<$Res>(_value.paymentMethodAnalytic, ( + value, + ) { + return _then(_value.copyWith(paymentMethodAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$PaymentMethodAnalyticLoaderStateImplCopyWith<$Res> + implements $PaymentMethodAnalyticLoaderStateCopyWith<$Res> { + factory _$$PaymentMethodAnalyticLoaderStateImplCopyWith( + _$PaymentMethodAnalyticLoaderStateImpl value, + $Res Function(_$PaymentMethodAnalyticLoaderStateImpl) then, + ) = __$$PaymentMethodAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + PaymentMethodAnalytic paymentMethodAnalytic, + Option failureOptionPaymentMethodAnalytic, + bool isFetching, + }); + + @override + $PaymentMethodAnalyticCopyWith<$Res> get paymentMethodAnalytic; +} + +/// @nodoc +class __$$PaymentMethodAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$PaymentMethodAnalyticLoaderStateCopyWithImpl< + $Res, + _$PaymentMethodAnalyticLoaderStateImpl + > + implements _$$PaymentMethodAnalyticLoaderStateImplCopyWith<$Res> { + __$$PaymentMethodAnalyticLoaderStateImplCopyWithImpl( + _$PaymentMethodAnalyticLoaderStateImpl _value, + $Res Function(_$PaymentMethodAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodAnalytic = null, + Object? failureOptionPaymentMethodAnalytic = null, + Object? isFetching = null, + }) { + return _then( + _$PaymentMethodAnalyticLoaderStateImpl( + paymentMethodAnalytic: null == paymentMethodAnalytic + ? _value.paymentMethodAnalytic + : paymentMethodAnalytic // ignore: cast_nullable_to_non_nullable + as PaymentMethodAnalytic, + failureOptionPaymentMethodAnalytic: + null == failureOptionPaymentMethodAnalytic + ? _value.failureOptionPaymentMethodAnalytic + : failureOptionPaymentMethodAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$PaymentMethodAnalyticLoaderStateImpl + implements _PaymentMethodAnalyticLoaderState { + const _$PaymentMethodAnalyticLoaderStateImpl({ + required this.paymentMethodAnalytic, + required this.failureOptionPaymentMethodAnalytic, + this.isFetching = false, + }); + + @override + final PaymentMethodAnalytic paymentMethodAnalytic; + @override + final Option failureOptionPaymentMethodAnalytic; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'PaymentMethodAnalyticLoaderState(paymentMethodAnalytic: $paymentMethodAnalytic, failureOptionPaymentMethodAnalytic: $failureOptionPaymentMethodAnalytic, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodAnalyticLoaderStateImpl && + (identical(other.paymentMethodAnalytic, paymentMethodAnalytic) || + other.paymentMethodAnalytic == paymentMethodAnalytic) && + (identical( + other.failureOptionPaymentMethodAnalytic, + failureOptionPaymentMethodAnalytic, + ) || + other.failureOptionPaymentMethodAnalytic == + failureOptionPaymentMethodAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodAnalytic, + failureOptionPaymentMethodAnalytic, + isFetching, + ); + + /// Create a copy of PaymentMethodAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodAnalyticLoaderStateImplCopyWith< + _$PaymentMethodAnalyticLoaderStateImpl + > + get copyWith => + __$$PaymentMethodAnalyticLoaderStateImplCopyWithImpl< + _$PaymentMethodAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _PaymentMethodAnalyticLoaderState + implements PaymentMethodAnalyticLoaderState { + const factory _PaymentMethodAnalyticLoaderState({ + required final PaymentMethodAnalytic paymentMethodAnalytic, + required final Option failureOptionPaymentMethodAnalytic, + final bool isFetching, + }) = _$PaymentMethodAnalyticLoaderStateImpl; + + @override + PaymentMethodAnalytic get paymentMethodAnalytic; + @override + Option get failureOptionPaymentMethodAnalytic; + @override + bool get isFetching; + + /// Create a copy of PaymentMethodAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodAnalyticLoaderStateImplCopyWith< + _$PaymentMethodAnalyticLoaderStateImpl + > + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_event.dart b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_event.dart new file mode 100644 index 0000000..04e5543 --- /dev/null +++ b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_event.dart @@ -0,0 +1,6 @@ +part of 'payment_method_analytic_loader_bloc.dart'; + +@freezed +class PaymentMethodAnalyticLoaderEvent with _$PaymentMethodAnalyticLoaderEvent { + const factory PaymentMethodAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_state.dart b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_state.dart new file mode 100644 index 0000000..62cb5cd --- /dev/null +++ b/lib/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_state.dart @@ -0,0 +1,16 @@ +part of 'payment_method_analytic_loader_bloc.dart'; + +@freezed +class PaymentMethodAnalyticLoaderState with _$PaymentMethodAnalyticLoaderState { + const factory PaymentMethodAnalyticLoaderState({ + required PaymentMethodAnalytic paymentMethodAnalytic, + required Option failureOptionPaymentMethodAnalytic, + @Default(false) bool isFetching, + }) = _PaymentMethodAnalyticLoaderState; + + factory PaymentMethodAnalyticLoaderState.initial() => + PaymentMethodAnalyticLoaderState( + paymentMethodAnalytic: PaymentMethodAnalytic.empty(), + failureOptionPaymentMethodAnalytic: none(), + ); +} diff --git a/lib/application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart b/lib/application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart new file mode 100644 index 0000000..f793510 --- /dev/null +++ b/lib/application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart @@ -0,0 +1,52 @@ +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 'product_analytic_loader_event.dart'; +part 'product_analytic_loader_state.dart'; +part 'product_analytic_loader_bloc.freezed.dart'; + +@injectable +class ProductAnalyticLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + ProductAnalyticLoaderBloc(this._repository) + : super(ProductAnalyticLoaderState.initial()) { + on(_onProductAnalyticLoaderEvent); + } + + Future _onProductAnalyticLoaderEvent( + ProductAnalyticLoaderEvent event, + Emitter emit, + ) { + return event.map( + rangeDateChanged: (e) async { + emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo)); + }, + fetched: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionProductAnalytic: none(), + ), + ); + + final result = await _repository.getProduct( + dateFrom: state.dateFrom, + dateTo: state.dateTo, + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionProductAnalytic: optionOf(f)), + (productAnalytic) => state.copyWith(productAnalytic: productAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/product_analytic_loader/product_analytic_loader_bloc.freezed.dart b/lib/application/analytic/product_analytic_loader/product_analytic_loader_bloc.freezed.dart new file mode 100644 index 0000000..05fec87 --- /dev/null +++ b/lib/application/analytic/product_analytic_loader/product_analytic_loader_bloc.freezed.dart @@ -0,0 +1,620 @@ +// 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 'product_analytic_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$ProductAnalyticLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductAnalyticLoaderEventCopyWith<$Res> { + factory $ProductAnalyticLoaderEventCopyWith( + ProductAnalyticLoaderEvent value, + $Res Function(ProductAnalyticLoaderEvent) then, + ) = + _$ProductAnalyticLoaderEventCopyWithImpl< + $Res, + ProductAnalyticLoaderEvent + >; +} + +/// @nodoc +class _$ProductAnalyticLoaderEventCopyWithImpl< + $Res, + $Val extends ProductAnalyticLoaderEvent +> + implements $ProductAnalyticLoaderEventCopyWith<$Res> { + _$ProductAnalyticLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductAnalyticLoaderEvent + /// 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 + _$ProductAnalyticLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl> + implements _$$RangeDateChangedImplCopyWith<$Res> { + __$$RangeDateChangedImplCopyWithImpl( + _$RangeDateChangedImpl _value, + $Res Function(_$RangeDateChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalyticLoaderEvent + /// 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 'ProductAnalyticLoaderEvent.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 ProductAnalyticLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return rangeDateChanged(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return rangeDateChanged?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return rangeDateChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return rangeDateChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(this); + } + return orElse(); + } +} + +abstract class _RangeDateChanged implements ProductAnalyticLoaderEvent { + const factory _RangeDateChanged( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$RangeDateChangedImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of ProductAnalyticLoaderEvent + /// 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 _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$ProductAnalyticLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalyticLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'ProductAnalyticLoaderEvent.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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements ProductAnalyticLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$ProductAnalyticLoaderState { + ProductAnalytic get productAnalytic => throw _privateConstructorUsedError; + Option get failureOptionProductAnalytic => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + + /// Create a copy of ProductAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductAnalyticLoaderStateCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductAnalyticLoaderStateCopyWith<$Res> { + factory $ProductAnalyticLoaderStateCopyWith( + ProductAnalyticLoaderState value, + $Res Function(ProductAnalyticLoaderState) then, + ) = + _$ProductAnalyticLoaderStateCopyWithImpl< + $Res, + ProductAnalyticLoaderState + >; + @useResult + $Res call({ + ProductAnalytic productAnalytic, + Option failureOptionProductAnalytic, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + $ProductAnalyticCopyWith<$Res> get productAnalytic; +} + +/// @nodoc +class _$ProductAnalyticLoaderStateCopyWithImpl< + $Res, + $Val extends ProductAnalyticLoaderState +> + implements $ProductAnalyticLoaderStateCopyWith<$Res> { + _$ProductAnalyticLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productAnalytic = null, + Object? failureOptionProductAnalytic = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _value.copyWith( + productAnalytic: null == productAnalytic + ? _value.productAnalytic + : productAnalytic // ignore: cast_nullable_to_non_nullable + as ProductAnalytic, + failureOptionProductAnalytic: null == failureOptionProductAnalytic + ? _value.failureOptionProductAnalytic + : failureOptionProductAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 ProductAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProductAnalyticCopyWith<$Res> get productAnalytic { + return $ProductAnalyticCopyWith<$Res>(_value.productAnalytic, (value) { + return _then(_value.copyWith(productAnalytic: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProductAnalyticLoaderStateImplCopyWith<$Res> + implements $ProductAnalyticLoaderStateCopyWith<$Res> { + factory _$$ProductAnalyticLoaderStateImplCopyWith( + _$ProductAnalyticLoaderStateImpl value, + $Res Function(_$ProductAnalyticLoaderStateImpl) then, + ) = __$$ProductAnalyticLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + ProductAnalytic productAnalytic, + Option failureOptionProductAnalytic, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + @override + $ProductAnalyticCopyWith<$Res> get productAnalytic; +} + +/// @nodoc +class __$$ProductAnalyticLoaderStateImplCopyWithImpl<$Res> + extends + _$ProductAnalyticLoaderStateCopyWithImpl< + $Res, + _$ProductAnalyticLoaderStateImpl + > + implements _$$ProductAnalyticLoaderStateImplCopyWith<$Res> { + __$$ProductAnalyticLoaderStateImplCopyWithImpl( + _$ProductAnalyticLoaderStateImpl _value, + $Res Function(_$ProductAnalyticLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productAnalytic = null, + Object? failureOptionProductAnalytic = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _$ProductAnalyticLoaderStateImpl( + productAnalytic: null == productAnalytic + ? _value.productAnalytic + : productAnalytic // ignore: cast_nullable_to_non_nullable + as ProductAnalytic, + failureOptionProductAnalytic: null == failureOptionProductAnalytic + ? _value.failureOptionProductAnalytic + : failureOptionProductAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 _$ProductAnalyticLoaderStateImpl implements _ProductAnalyticLoaderState { + const _$ProductAnalyticLoaderStateImpl({ + required this.productAnalytic, + required this.failureOptionProductAnalytic, + this.isFetching = false, + required this.dateFrom, + required this.dateTo, + }); + + @override + final ProductAnalytic productAnalytic; + @override + final Option failureOptionProductAnalytic; + @override + @JsonKey() + final bool isFetching; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'ProductAnalyticLoaderState(productAnalytic: $productAnalytic, failureOptionProductAnalytic: $failureOptionProductAnalytic, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductAnalyticLoaderStateImpl && + (identical(other.productAnalytic, productAnalytic) || + other.productAnalytic == productAnalytic) && + (identical( + other.failureOptionProductAnalytic, + failureOptionProductAnalytic, + ) || + other.failureOptionProductAnalytic == + failureOptionProductAnalytic) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + productAnalytic, + failureOptionProductAnalytic, + isFetching, + dateFrom, + dateTo, + ); + + /// Create a copy of ProductAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductAnalyticLoaderStateImplCopyWith<_$ProductAnalyticLoaderStateImpl> + get copyWith => + __$$ProductAnalyticLoaderStateImplCopyWithImpl< + _$ProductAnalyticLoaderStateImpl + >(this, _$identity); +} + +abstract class _ProductAnalyticLoaderState + implements ProductAnalyticLoaderState { + const factory _ProductAnalyticLoaderState({ + required final ProductAnalytic productAnalytic, + required final Option failureOptionProductAnalytic, + final bool isFetching, + required final DateTime dateFrom, + required final DateTime dateTo, + }) = _$ProductAnalyticLoaderStateImpl; + + @override + ProductAnalytic get productAnalytic; + @override + Option get failureOptionProductAnalytic; + @override + bool get isFetching; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + + /// Create a copy of ProductAnalyticLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductAnalyticLoaderStateImplCopyWith<_$ProductAnalyticLoaderStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/product_analytic_loader/product_analytic_loader_event.dart b/lib/application/analytic/product_analytic_loader/product_analytic_loader_event.dart new file mode 100644 index 0000000..b707a93 --- /dev/null +++ b/lib/application/analytic/product_analytic_loader/product_analytic_loader_event.dart @@ -0,0 +1,10 @@ +part of 'product_analytic_loader_bloc.dart'; + +@freezed +class ProductAnalyticLoaderEvent with _$ProductAnalyticLoaderEvent { + const factory ProductAnalyticLoaderEvent.rangeDateChanged( + DateTime dateFrom, + DateTime dateTo, + ) = _RangeDateChanged; + const factory ProductAnalyticLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/product_analytic_loader/product_analytic_loader_state.dart b/lib/application/analytic/product_analytic_loader/product_analytic_loader_state.dart new file mode 100644 index 0000000..94b349a --- /dev/null +++ b/lib/application/analytic/product_analytic_loader/product_analytic_loader_state.dart @@ -0,0 +1,19 @@ +part of 'product_analytic_loader_bloc.dart'; + +@freezed +class ProductAnalyticLoaderState with _$ProductAnalyticLoaderState { + const factory ProductAnalyticLoaderState({ + required ProductAnalytic productAnalytic, + required Option failureOptionProductAnalytic, + @Default(false) bool isFetching, + required DateTime dateFrom, + required DateTime dateTo, + }) = _ProductAnalyticLoaderState; + + factory ProductAnalyticLoaderState.initial() => ProductAnalyticLoaderState( + productAnalytic: ProductAnalytic.empty(), + failureOptionProductAnalytic: none(), + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); +} diff --git a/lib/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart b/lib/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart new file mode 100644 index 0000000..a16ffd7 --- /dev/null +++ b/lib/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart @@ -0,0 +1,47 @@ +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_loss_loader_event.dart'; +part 'profit_loss_loader_state.dart'; +part 'profit_loss_loader_bloc.freezed.dart'; + +@injectable +class ProfitLossLoaderBloc + extends Bloc { + final IAnalyticRepository _repository; + ProfitLossLoaderBloc(this._repository) + : super(ProfitLossLoaderState.initial()) { + on(_onProfitLossLoaderEvent); + } + + Future _onProfitLossLoaderEvent( + ProfitLossLoaderEvent event, + Emitter emit, + ) { + return event.map( + rangeDateChanged: (e) async { + emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo)); + }, + fetched: (e) async { + emit(state.copyWith(isFetching: true, failureOptionProfitLoss: none())); + + final result = await _repository.getProfitLoss( + dateFrom: state.dateFrom, + dateTo: state.dateTo, + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionProfitLoss: optionOf(f)), + (profitLoss) => state.copyWith(profitLoss: profitLoss), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/profit_loss_loader/profit_loss_loader_bloc.freezed.dart b/lib/application/analytic/profit_loss_loader/profit_loss_loader_bloc.freezed.dart new file mode 100644 index 0000000..601e958 --- /dev/null +++ b/lib/application/analytic/profit_loss_loader/profit_loss_loader_bloc.freezed.dart @@ -0,0 +1,607 @@ +// 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_loss_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$ProfitLossLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossLoaderEventCopyWith<$Res> { + factory $ProfitLossLoaderEventCopyWith( + ProfitLossLoaderEvent value, + $Res Function(ProfitLossLoaderEvent) then, + ) = _$ProfitLossLoaderEventCopyWithImpl<$Res, ProfitLossLoaderEvent>; +} + +/// @nodoc +class _$ProfitLossLoaderEventCopyWithImpl< + $Res, + $Val extends ProfitLossLoaderEvent +> + implements $ProfitLossLoaderEventCopyWith<$Res> { + _$ProfitLossLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossLoaderEvent + /// 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 _$ProfitLossLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl> + implements _$$RangeDateChangedImplCopyWith<$Res> { + __$$RangeDateChangedImplCopyWithImpl( + _$RangeDateChangedImpl _value, + $Res Function(_$RangeDateChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossLoaderEvent + /// 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 'ProfitLossLoaderEvent.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 ProfitLossLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return rangeDateChanged(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return rangeDateChanged?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return rangeDateChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return rangeDateChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(this); + } + return orElse(); + } +} + +abstract class _RangeDateChanged implements ProfitLossLoaderEvent { + const factory _RangeDateChanged( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$RangeDateChangedImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of ProfitLossLoaderEvent + /// 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 _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$ProfitLossLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'ProfitLossLoaderEvent.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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fetched, + }) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fetched, + }) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements ProfitLossLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$ProfitLossLoaderState { + ProfitLossAnalytic get profitLoss => throw _privateConstructorUsedError; + Option get failureOptionProfitLoss => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossLoaderStateCopyWith<$Res> { + factory $ProfitLossLoaderStateCopyWith( + ProfitLossLoaderState value, + $Res Function(ProfitLossLoaderState) then, + ) = _$ProfitLossLoaderStateCopyWithImpl<$Res, ProfitLossLoaderState>; + @useResult + $Res call({ + ProfitLossAnalytic profitLoss, + Option failureOptionProfitLoss, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + $ProfitLossAnalyticCopyWith<$Res> get profitLoss; +} + +/// @nodoc +class _$ProfitLossLoaderStateCopyWithImpl< + $Res, + $Val extends ProfitLossLoaderState +> + implements $ProfitLossLoaderStateCopyWith<$Res> { + _$ProfitLossLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? profitLoss = null, + Object? failureOptionProfitLoss = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _value.copyWith( + profitLoss: null == profitLoss + ? _value.profitLoss + : profitLoss // ignore: cast_nullable_to_non_nullable + as ProfitLossAnalytic, + failureOptionProfitLoss: null == failureOptionProfitLoss + ? _value.failureOptionProfitLoss + : failureOptionProfitLoss // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossAnalyticCopyWith<$Res> get profitLoss { + return $ProfitLossAnalyticCopyWith<$Res>(_value.profitLoss, (value) { + return _then(_value.copyWith(profitLoss: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProfitLossLoaderStateImplCopyWith<$Res> + implements $ProfitLossLoaderStateCopyWith<$Res> { + factory _$$ProfitLossLoaderStateImplCopyWith( + _$ProfitLossLoaderStateImpl value, + $Res Function(_$ProfitLossLoaderStateImpl) then, + ) = __$$ProfitLossLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + ProfitLossAnalytic profitLoss, + Option failureOptionProfitLoss, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + @override + $ProfitLossAnalyticCopyWith<$Res> get profitLoss; +} + +/// @nodoc +class __$$ProfitLossLoaderStateImplCopyWithImpl<$Res> + extends + _$ProfitLossLoaderStateCopyWithImpl<$Res, _$ProfitLossLoaderStateImpl> + implements _$$ProfitLossLoaderStateImplCopyWith<$Res> { + __$$ProfitLossLoaderStateImplCopyWithImpl( + _$ProfitLossLoaderStateImpl _value, + $Res Function(_$ProfitLossLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? profitLoss = null, + Object? failureOptionProfitLoss = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _$ProfitLossLoaderStateImpl( + profitLoss: null == profitLoss + ? _value.profitLoss + : profitLoss // ignore: cast_nullable_to_non_nullable + as ProfitLossAnalytic, + failureOptionProfitLoss: null == failureOptionProfitLoss + ? _value.failureOptionProfitLoss + : failureOptionProfitLoss // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 _$ProfitLossLoaderStateImpl implements _ProfitLossLoaderState { + const _$ProfitLossLoaderStateImpl({ + required this.profitLoss, + required this.failureOptionProfitLoss, + this.isFetching = false, + required this.dateFrom, + required this.dateTo, + }); + + @override + final ProfitLossAnalytic profitLoss; + @override + final Option failureOptionProfitLoss; + @override + @JsonKey() + final bool isFetching; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'ProfitLossLoaderState(profitLoss: $profitLoss, failureOptionProfitLoss: $failureOptionProfitLoss, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossLoaderStateImpl && + (identical(other.profitLoss, profitLoss) || + other.profitLoss == profitLoss) && + (identical( + other.failureOptionProfitLoss, + failureOptionProfitLoss, + ) || + other.failureOptionProfitLoss == failureOptionProfitLoss) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + profitLoss, + failureOptionProfitLoss, + isFetching, + dateFrom, + dateTo, + ); + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossLoaderStateImplCopyWith<_$ProfitLossLoaderStateImpl> + get copyWith => + __$$ProfitLossLoaderStateImplCopyWithImpl<_$ProfitLossLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossLoaderState implements ProfitLossLoaderState { + const factory _ProfitLossLoaderState({ + required final ProfitLossAnalytic profitLoss, + required final Option failureOptionProfitLoss, + final bool isFetching, + required final DateTime dateFrom, + required final DateTime dateTo, + }) = _$ProfitLossLoaderStateImpl; + + @override + ProfitLossAnalytic get profitLoss; + @override + Option get failureOptionProfitLoss; + @override + bool get isFetching; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + + /// Create a copy of ProfitLossLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossLoaderStateImplCopyWith<_$ProfitLossLoaderStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/profit_loss_loader/profit_loss_loader_event.dart b/lib/application/analytic/profit_loss_loader/profit_loss_loader_event.dart new file mode 100644 index 0000000..5164378 --- /dev/null +++ b/lib/application/analytic/profit_loss_loader/profit_loss_loader_event.dart @@ -0,0 +1,10 @@ +part of 'profit_loss_loader_bloc.dart'; + +@freezed +class ProfitLossLoaderEvent with _$ProfitLossLoaderEvent { + const factory ProfitLossLoaderEvent.rangeDateChanged( + DateTime dateFrom, + DateTime dateTo, + ) = _RangeDateChanged; + const factory ProfitLossLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/analytic/profit_loss_loader/profit_loss_loader_state.dart b/lib/application/analytic/profit_loss_loader/profit_loss_loader_state.dart new file mode 100644 index 0000000..1465648 --- /dev/null +++ b/lib/application/analytic/profit_loss_loader/profit_loss_loader_state.dart @@ -0,0 +1,19 @@ +part of 'profit_loss_loader_bloc.dart'; + +@freezed +class ProfitLossLoaderState with _$ProfitLossLoaderState { + const factory ProfitLossLoaderState({ + required ProfitLossAnalytic profitLoss, + required Option failureOptionProfitLoss, + @Default(false) bool isFetching, + required DateTime dateFrom, + required DateTime dateTo, + }) = _ProfitLossLoaderState; + + factory ProfitLossLoaderState.initial() => ProfitLossLoaderState( + profitLoss: ProfitLossAnalytic.empty(), + failureOptionProfitLoss: none(), + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); +} diff --git a/lib/application/analytic/sales_loader/sales_loader_bloc.dart b/lib/application/analytic/sales_loader/sales_loader_bloc.dart new file mode 100644 index 0000000..e30dde8 --- /dev/null +++ b/lib/application/analytic/sales_loader/sales_loader_bloc.dart @@ -0,0 +1,46 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.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 'sales_loader_event.dart'; +part 'sales_loader_state.dart'; +part 'sales_loader_bloc.freezed.dart'; + +@injectable +class SalesLoaderBloc extends Bloc { + final IAnalyticRepository _analyticRepository; + SalesLoaderBloc(this._analyticRepository) + : super(SalesLoaderState.initial()) { + on(_onSalesLoaderEvent); + } + + Future _onSalesLoaderEvent( + SalesLoaderEvent event, + Emitter emit, + ) { + return event.map( + rangeDateChanged: (e) async { + emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo)); + }, + fectched: (e) async { + emit(state.copyWith(isFetching: true, failureOptionSales: none())); + + final result = await _analyticRepository.getSales( + dateFrom: state.dateFrom, + dateTo: state.dateTo, + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionSales: optionOf(f)), + (sales) => state.copyWith(sales: sales), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/analytic/sales_loader/sales_loader_bloc.freezed.dart b/lib/application/analytic/sales_loader/sales_loader_bloc.freezed.dart new file mode 100644 index 0000000..e0ce519 --- /dev/null +++ b/lib/application/analytic/sales_loader/sales_loader_bloc.freezed.dart @@ -0,0 +1,595 @@ +// 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 'sales_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$SalesLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fectched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fectched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fectched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fectched value) fectched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fectched value)? fectched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fectched value)? fectched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesLoaderEventCopyWith<$Res> { + factory $SalesLoaderEventCopyWith( + SalesLoaderEvent value, + $Res Function(SalesLoaderEvent) then, + ) = _$SalesLoaderEventCopyWithImpl<$Res, SalesLoaderEvent>; +} + +/// @nodoc +class _$SalesLoaderEventCopyWithImpl<$Res, $Val extends SalesLoaderEvent> + implements $SalesLoaderEventCopyWith<$Res> { + _$SalesLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesLoaderEvent + /// 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 _$SalesLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl> + implements _$$RangeDateChangedImplCopyWith<$Res> { + __$$RangeDateChangedImplCopyWithImpl( + _$RangeDateChangedImpl _value, + $Res Function(_$RangeDateChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesLoaderEvent + /// 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 'SalesLoaderEvent.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 SalesLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fectched, + }) { + return rangeDateChanged(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fectched, + }) { + return rangeDateChanged?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fectched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fectched value) fectched, + }) { + return rangeDateChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fectched value)? fectched, + }) { + return rangeDateChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fectched value)? fectched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(this); + } + return orElse(); + } +} + +abstract class _RangeDateChanged implements SalesLoaderEvent { + const factory _RangeDateChanged( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$RangeDateChangedImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of SalesLoaderEvent + /// 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 _$$FectchedImplCopyWith<$Res> { + factory _$$FectchedImplCopyWith( + _$FectchedImpl value, + $Res Function(_$FectchedImpl) then, + ) = __$$FectchedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FectchedImplCopyWithImpl<$Res> + extends _$SalesLoaderEventCopyWithImpl<$Res, _$FectchedImpl> + implements _$$FectchedImplCopyWith<$Res> { + __$$FectchedImplCopyWithImpl( + _$FectchedImpl _value, + $Res Function(_$FectchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FectchedImpl implements _Fectched { + const _$FectchedImpl(); + + @override + String toString() { + return 'SalesLoaderEvent.fectched()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FectchedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function() fectched, + }) { + return fectched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function()? fectched, + }) { + return fectched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function()? fectched, + required TResult orElse(), + }) { + if (fectched != null) { + return fectched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_Fectched value) fectched, + }) { + return fectched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_Fectched value)? fectched, + }) { + return fectched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_Fectched value)? fectched, + required TResult orElse(), + }) { + if (fectched != null) { + return fectched(this); + } + return orElse(); + } +} + +abstract class _Fectched implements SalesLoaderEvent { + const factory _Fectched() = _$FectchedImpl; +} + +/// @nodoc +mixin _$SalesLoaderState { + SalesAnalytic get sales => throw _privateConstructorUsedError; + Option get failureOptionSales => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + + /// Create a copy of SalesLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesLoaderStateCopyWith<$Res> { + factory $SalesLoaderStateCopyWith( + SalesLoaderState value, + $Res Function(SalesLoaderState) then, + ) = _$SalesLoaderStateCopyWithImpl<$Res, SalesLoaderState>; + @useResult + $Res call({ + SalesAnalytic sales, + Option failureOptionSales, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + $SalesAnalyticCopyWith<$Res> get sales; +} + +/// @nodoc +class _$SalesLoaderStateCopyWithImpl<$Res, $Val extends SalesLoaderState> + implements $SalesLoaderStateCopyWith<$Res> { + _$SalesLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? sales = null, + Object? failureOptionSales = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _value.copyWith( + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as SalesAnalytic, + failureOptionSales: null == failureOptionSales + ? _value.failureOptionSales + : failureOptionSales // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 SalesLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SalesAnalyticCopyWith<$Res> get sales { + return $SalesAnalyticCopyWith<$Res>(_value.sales, (value) { + return _then(_value.copyWith(sales: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SalesLoaderStateImplCopyWith<$Res> + implements $SalesLoaderStateCopyWith<$Res> { + factory _$$SalesLoaderStateImplCopyWith( + _$SalesLoaderStateImpl value, + $Res Function(_$SalesLoaderStateImpl) then, + ) = __$$SalesLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + SalesAnalytic sales, + Option failureOptionSales, + bool isFetching, + DateTime dateFrom, + DateTime dateTo, + }); + + @override + $SalesAnalyticCopyWith<$Res> get sales; +} + +/// @nodoc +class __$$SalesLoaderStateImplCopyWithImpl<$Res> + extends _$SalesLoaderStateCopyWithImpl<$Res, _$SalesLoaderStateImpl> + implements _$$SalesLoaderStateImplCopyWith<$Res> { + __$$SalesLoaderStateImplCopyWithImpl( + _$SalesLoaderStateImpl _value, + $Res Function(_$SalesLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? sales = null, + Object? failureOptionSales = null, + Object? isFetching = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _$SalesLoaderStateImpl( + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as SalesAnalytic, + failureOptionSales: null == failureOptionSales + ? _value.failureOptionSales + : failureOptionSales // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + 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 _$SalesLoaderStateImpl implements _SalesLoaderState { + const _$SalesLoaderStateImpl({ + required this.sales, + required this.failureOptionSales, + this.isFetching = false, + required this.dateFrom, + required this.dateTo, + }); + + @override + final SalesAnalytic sales; + @override + final Option failureOptionSales; + @override + @JsonKey() + final bool isFetching; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'SalesLoaderState(sales: $sales, failureOptionSales: $failureOptionSales, isFetching: $isFetching, dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesLoaderStateImpl && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.failureOptionSales, failureOptionSales) || + other.failureOptionSales == failureOptionSales) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + sales, + failureOptionSales, + isFetching, + dateFrom, + dateTo, + ); + + /// Create a copy of SalesLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesLoaderStateImplCopyWith<_$SalesLoaderStateImpl> get copyWith => + __$$SalesLoaderStateImplCopyWithImpl<_$SalesLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _SalesLoaderState implements SalesLoaderState { + const factory _SalesLoaderState({ + required final SalesAnalytic sales, + required final Option failureOptionSales, + final bool isFetching, + required final DateTime dateFrom, + required final DateTime dateTo, + }) = _$SalesLoaderStateImpl; + + @override + SalesAnalytic get sales; + @override + Option get failureOptionSales; + @override + bool get isFetching; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + + /// Create a copy of SalesLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesLoaderStateImplCopyWith<_$SalesLoaderStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/analytic/sales_loader/sales_loader_event.dart b/lib/application/analytic/sales_loader/sales_loader_event.dart new file mode 100644 index 0000000..a70390b --- /dev/null +++ b/lib/application/analytic/sales_loader/sales_loader_event.dart @@ -0,0 +1,10 @@ +part of 'sales_loader_bloc.dart'; + +@freezed +class SalesLoaderEvent with _$SalesLoaderEvent { + const factory SalesLoaderEvent.rangeDateChanged( + DateTime dateFrom, + DateTime dateTo, + ) = _RangeDateChanged; + const factory SalesLoaderEvent.fectched() = _Fectched; +} diff --git a/lib/application/analytic/sales_loader/sales_loader_state.dart b/lib/application/analytic/sales_loader/sales_loader_state.dart new file mode 100644 index 0000000..7cbe4f3 --- /dev/null +++ b/lib/application/analytic/sales_loader/sales_loader_state.dart @@ -0,0 +1,19 @@ +part of 'sales_loader_bloc.dart'; + +@freezed +class SalesLoaderState with _$SalesLoaderState { + const factory SalesLoaderState({ + required SalesAnalytic sales, + required Option failureOptionSales, + @Default(false) bool isFetching, + required DateTime dateFrom, + required DateTime dateTo, + }) = _SalesLoaderState; + + factory SalesLoaderState.initial() => SalesLoaderState( + sales: SalesAnalytic.empty(), + failureOptionSales: none(), + dateFrom: DateTime.now().subtract(const Duration(days: 30)), + dateTo: DateTime.now(), + ); +} diff --git a/lib/application/auth/auth_bloc.dart b/lib/application/auth/auth_bloc.dart new file mode 100644 index 0000000..f85a681 --- /dev/null +++ b/lib/application/auth/auth_bloc.dart @@ -0,0 +1,50 @@ +import 'package:dartz/dartz.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../domain/auth/auth.dart'; +import '../../domain/user/user.dart'; + +part 'auth_event.dart'; +part 'auth_state.dart'; +part 'auth_bloc.freezed.dart'; + +@injectable +class AuthBloc extends Bloc { + final IAuthRepository _repository; + AuthBloc(this._repository) : super(AuthState.initial()) { + on(_onAuthEvent); + } + + Future _onAuthEvent(AuthEvent event, Emitter emit) { + return event.map( + fetchCurrentUser: (e) async { + emit(state.copyWith(failureOption: none())); + + final token = await _repository.hasToken(); + + final failureOrAuth = await _repository.currentUser(); + + failureOrAuth.fold( + (f) => emit( + state.copyWith( + failureOption: optionOf(f), + status: token + ? AuthStatus.authenticated() + : AuthStatus.unauthenticated(), + ), + ), + (user) => emit( + state.copyWith( + user: user, + status: token + ? AuthStatus.authenticated() + : AuthStatus.unauthenticated(), + ), + ), + ); + }, + ); + } +} diff --git a/lib/application/auth/auth_bloc.freezed.dart b/lib/application/auth/auth_bloc.freezed.dart new file mode 100644 index 0000000..7fd3e02 --- /dev/null +++ b/lib/application/auth/auth_bloc.freezed.dart @@ -0,0 +1,806 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'auth_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$AuthEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetchCurrentUser, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchCurrentUser, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchCurrentUser, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchCurrentUser value) fetchCurrentUser, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchCurrentUser value)? fetchCurrentUser, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchCurrentUser value)? fetchCurrentUser, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthEventCopyWith<$Res> { + factory $AuthEventCopyWith(AuthEvent value, $Res Function(AuthEvent) then) = + _$AuthEventCopyWithImpl<$Res, AuthEvent>; +} + +/// @nodoc +class _$AuthEventCopyWithImpl<$Res, $Val extends AuthEvent> + implements $AuthEventCopyWith<$Res> { + _$AuthEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchCurrentUserImplCopyWith<$Res> { + factory _$$FetchCurrentUserImplCopyWith( + _$FetchCurrentUserImpl value, + $Res Function(_$FetchCurrentUserImpl) then, + ) = __$$FetchCurrentUserImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchCurrentUserImplCopyWithImpl<$Res> + extends _$AuthEventCopyWithImpl<$Res, _$FetchCurrentUserImpl> + implements _$$FetchCurrentUserImplCopyWith<$Res> { + __$$FetchCurrentUserImplCopyWithImpl( + _$FetchCurrentUserImpl _value, + $Res Function(_$FetchCurrentUserImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchCurrentUserImpl implements _FetchCurrentUser { + const _$FetchCurrentUserImpl(); + + @override + String toString() { + return 'AuthEvent.fetchCurrentUser()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchCurrentUserImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() fetchCurrentUser, + }) { + return fetchCurrentUser(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchCurrentUser, + }) { + return fetchCurrentUser?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchCurrentUser, + required TResult orElse(), + }) { + if (fetchCurrentUser != null) { + return fetchCurrentUser(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchCurrentUser value) fetchCurrentUser, + }) { + return fetchCurrentUser(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchCurrentUser value)? fetchCurrentUser, + }) { + return fetchCurrentUser?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchCurrentUser value)? fetchCurrentUser, + required TResult orElse(), + }) { + if (fetchCurrentUser != null) { + return fetchCurrentUser(this); + } + return orElse(); + } +} + +abstract class _FetchCurrentUser implements AuthEvent { + const factory _FetchCurrentUser() = _$FetchCurrentUserImpl; +} + +/// @nodoc +mixin _$AuthState { + User get user => throw _privateConstructorUsedError; + AuthStatus get status => throw _privateConstructorUsedError; + Option get failureOption => throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AuthStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthStateCopyWith<$Res> { + factory $AuthStateCopyWith(AuthState value, $Res Function(AuthState) then) = + _$AuthStateCopyWithImpl<$Res, AuthState>; + @useResult + $Res call({ + User user, + AuthStatus status, + Option failureOption, + bool isFetching, + }); + + $UserCopyWith<$Res> get user; + $AuthStatusCopyWith<$Res> get status; +} + +/// @nodoc +class _$AuthStateCopyWithImpl<$Res, $Val extends AuthState> + implements $AuthStateCopyWith<$Res> { + _$AuthStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? user = null, + Object? status = null, + Object? failureOption = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + user: null == user + ? _value.user + : user // ignore: cast_nullable_to_non_nullable + as User, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as AuthStatus, + failureOption: null == failureOption + ? _value.failureOption + : failureOption // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $UserCopyWith<$Res> get user { + return $UserCopyWith<$Res>(_value.user, (value) { + return _then(_value.copyWith(user: value) as $Val); + }); + } + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $AuthStatusCopyWith<$Res> get status { + return $AuthStatusCopyWith<$Res>(_value.status, (value) { + return _then(_value.copyWith(status: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$AuthStateImplCopyWith<$Res> + implements $AuthStateCopyWith<$Res> { + factory _$$AuthStateImplCopyWith( + _$AuthStateImpl value, + $Res Function(_$AuthStateImpl) then, + ) = __$$AuthStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + User user, + AuthStatus status, + Option failureOption, + bool isFetching, + }); + + @override + $UserCopyWith<$Res> get user; + @override + $AuthStatusCopyWith<$Res> get status; +} + +/// @nodoc +class __$$AuthStateImplCopyWithImpl<$Res> + extends _$AuthStateCopyWithImpl<$Res, _$AuthStateImpl> + implements _$$AuthStateImplCopyWith<$Res> { + __$$AuthStateImplCopyWithImpl( + _$AuthStateImpl _value, + $Res Function(_$AuthStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? user = null, + Object? status = null, + Object? failureOption = null, + Object? isFetching = null, + }) { + return _then( + _$AuthStateImpl( + user: null == user + ? _value.user + : user // ignore: cast_nullable_to_non_nullable + as User, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as AuthStatus, + failureOption: null == failureOption + ? _value.failureOption + : failureOption // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$AuthStateImpl extends _AuthState { + const _$AuthStateImpl({ + required this.user, + this.status = const AuthStatus.initial(), + required this.failureOption, + this.isFetching = false, + }) : super._(); + + @override + final User user; + @override + @JsonKey() + final AuthStatus status; + @override + final Option failureOption; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'AuthState(user: $user, status: $status, failureOption: $failureOption, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AuthStateImpl && + (identical(other.user, user) || other.user == user) && + (identical(other.status, status) || other.status == status) && + (identical(other.failureOption, failureOption) || + other.failureOption == failureOption) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => + Object.hash(runtimeType, user, status, failureOption, isFetching); + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AuthStateImplCopyWith<_$AuthStateImpl> get copyWith => + __$$AuthStateImplCopyWithImpl<_$AuthStateImpl>(this, _$identity); +} + +abstract class _AuthState extends AuthState { + const factory _AuthState({ + required final User user, + final AuthStatus status, + required final Option failureOption, + final bool isFetching, + }) = _$AuthStateImpl; + const _AuthState._() : super._(); + + @override + User get user; + @override + AuthStatus get status; + @override + Option get failureOption; + @override + bool get isFetching; + + /// Create a copy of AuthState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AuthStateImplCopyWith<_$AuthStateImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$AuthStatus { + @optionalTypeArgs + TResult when({ + required TResult Function() authenticated, + required TResult Function() unauthenticated, + required TResult Function() initial, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? authenticated, + TResult? Function()? unauthenticated, + TResult? Function()? initial, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? authenticated, + TResult Function()? unauthenticated, + TResult Function()? initial, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Authenticated value) authenticated, + required TResult Function(_Unauthenticated value) unauthenticated, + required TResult Function(_Initial value) initial, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Authenticated value)? authenticated, + TResult? Function(_Unauthenticated value)? unauthenticated, + TResult? Function(_Initial value)? initial, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Authenticated value)? authenticated, + TResult Function(_Unauthenticated value)? unauthenticated, + TResult Function(_Initial value)? initial, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthStatusCopyWith<$Res> { + factory $AuthStatusCopyWith( + AuthStatus value, + $Res Function(AuthStatus) then, + ) = _$AuthStatusCopyWithImpl<$Res, AuthStatus>; +} + +/// @nodoc +class _$AuthStatusCopyWithImpl<$Res, $Val extends AuthStatus> + implements $AuthStatusCopyWith<$Res> { + _$AuthStatusCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthStatus + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$AuthenticatedImplCopyWith<$Res> { + factory _$$AuthenticatedImplCopyWith( + _$AuthenticatedImpl value, + $Res Function(_$AuthenticatedImpl) then, + ) = __$$AuthenticatedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$AuthenticatedImplCopyWithImpl<$Res> + extends _$AuthStatusCopyWithImpl<$Res, _$AuthenticatedImpl> + implements _$$AuthenticatedImplCopyWith<$Res> { + __$$AuthenticatedImplCopyWithImpl( + _$AuthenticatedImpl _value, + $Res Function(_$AuthenticatedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthStatus + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$AuthenticatedImpl implements _Authenticated { + const _$AuthenticatedImpl(); + + @override + String toString() { + return 'AuthStatus.authenticated()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$AuthenticatedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() authenticated, + required TResult Function() unauthenticated, + required TResult Function() initial, + }) { + return authenticated(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? authenticated, + TResult? Function()? unauthenticated, + TResult? Function()? initial, + }) { + return authenticated?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? authenticated, + TResult Function()? unauthenticated, + TResult Function()? initial, + required TResult orElse(), + }) { + if (authenticated != null) { + return authenticated(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Authenticated value) authenticated, + required TResult Function(_Unauthenticated value) unauthenticated, + required TResult Function(_Initial value) initial, + }) { + return authenticated(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Authenticated value)? authenticated, + TResult? Function(_Unauthenticated value)? unauthenticated, + TResult? Function(_Initial value)? initial, + }) { + return authenticated?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Authenticated value)? authenticated, + TResult Function(_Unauthenticated value)? unauthenticated, + TResult Function(_Initial value)? initial, + required TResult orElse(), + }) { + if (authenticated != null) { + return authenticated(this); + } + return orElse(); + } +} + +abstract class _Authenticated implements AuthStatus { + const factory _Authenticated() = _$AuthenticatedImpl; +} + +/// @nodoc +abstract class _$$UnauthenticatedImplCopyWith<$Res> { + factory _$$UnauthenticatedImplCopyWith( + _$UnauthenticatedImpl value, + $Res Function(_$UnauthenticatedImpl) then, + ) = __$$UnauthenticatedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnauthenticatedImplCopyWithImpl<$Res> + extends _$AuthStatusCopyWithImpl<$Res, _$UnauthenticatedImpl> + implements _$$UnauthenticatedImplCopyWith<$Res> { + __$$UnauthenticatedImplCopyWithImpl( + _$UnauthenticatedImpl _value, + $Res Function(_$UnauthenticatedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthStatus + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnauthenticatedImpl implements _Unauthenticated { + const _$UnauthenticatedImpl(); + + @override + String toString() { + return 'AuthStatus.unauthenticated()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnauthenticatedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() authenticated, + required TResult Function() unauthenticated, + required TResult Function() initial, + }) { + return unauthenticated(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? authenticated, + TResult? Function()? unauthenticated, + TResult? Function()? initial, + }) { + return unauthenticated?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? authenticated, + TResult Function()? unauthenticated, + TResult Function()? initial, + required TResult orElse(), + }) { + if (unauthenticated != null) { + return unauthenticated(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Authenticated value) authenticated, + required TResult Function(_Unauthenticated value) unauthenticated, + required TResult Function(_Initial value) initial, + }) { + return unauthenticated(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Authenticated value)? authenticated, + TResult? Function(_Unauthenticated value)? unauthenticated, + TResult? Function(_Initial value)? initial, + }) { + return unauthenticated?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Authenticated value)? authenticated, + TResult Function(_Unauthenticated value)? unauthenticated, + TResult Function(_Initial value)? initial, + required TResult orElse(), + }) { + if (unauthenticated != null) { + return unauthenticated(this); + } + return orElse(); + } +} + +abstract class _Unauthenticated implements AuthStatus { + const factory _Unauthenticated() = _$UnauthenticatedImpl; +} + +/// @nodoc +abstract class _$$InitialImplCopyWith<$Res> { + factory _$$InitialImplCopyWith( + _$InitialImpl value, + $Res Function(_$InitialImpl) then, + ) = __$$InitialImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$InitialImplCopyWithImpl<$Res> + extends _$AuthStatusCopyWithImpl<$Res, _$InitialImpl> + implements _$$InitialImplCopyWith<$Res> { + __$$InitialImplCopyWithImpl( + _$InitialImpl _value, + $Res Function(_$InitialImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthStatus + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$InitialImpl implements _Initial { + const _$InitialImpl(); + + @override + String toString() { + return 'AuthStatus.initial()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$InitialImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() authenticated, + required TResult Function() unauthenticated, + required TResult Function() initial, + }) { + return initial(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? authenticated, + TResult? Function()? unauthenticated, + TResult? Function()? initial, + }) { + return initial?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? authenticated, + TResult Function()? unauthenticated, + TResult Function()? initial, + required TResult orElse(), + }) { + if (initial != null) { + return initial(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Authenticated value) authenticated, + required TResult Function(_Unauthenticated value) unauthenticated, + required TResult Function(_Initial value) initial, + }) { + return initial(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Authenticated value)? authenticated, + TResult? Function(_Unauthenticated value)? unauthenticated, + TResult? Function(_Initial value)? initial, + }) { + return initial?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Authenticated value)? authenticated, + TResult Function(_Unauthenticated value)? unauthenticated, + TResult Function(_Initial value)? initial, + required TResult orElse(), + }) { + if (initial != null) { + return initial(this); + } + return orElse(); + } +} + +abstract class _Initial implements AuthStatus { + const factory _Initial() = _$InitialImpl; +} diff --git a/lib/application/auth/auth_event.dart b/lib/application/auth/auth_event.dart new file mode 100644 index 0000000..6c3c293 --- /dev/null +++ b/lib/application/auth/auth_event.dart @@ -0,0 +1,6 @@ +part of 'auth_bloc.dart'; + +@freezed +class AuthEvent with _$AuthEvent { + const factory AuthEvent.fetchCurrentUser() = _FetchCurrentUser; +} diff --git a/lib/application/auth/auth_state.dart b/lib/application/auth/auth_state.dart new file mode 100644 index 0000000..483740d --- /dev/null +++ b/lib/application/auth/auth_state.dart @@ -0,0 +1,26 @@ +part of 'auth_bloc.dart'; + +@freezed +class AuthState with _$AuthState { + const AuthState._(); + + const factory AuthState({ + required User user, + @Default(AuthStatus.initial()) AuthStatus status, + required Option failureOption, + @Default(false) bool isFetching, + }) = _AuthState; + + factory AuthState.initial() => + AuthState(user: User.empty(), failureOption: none()); + + bool get isAuthenticated => status == const AuthStatus.authenticated(); + bool get isInitial => status == const AuthStatus.initial(); +} + +@freezed +sealed class AuthStatus with _$AuthStatus { + const factory AuthStatus.authenticated() = _Authenticated; + const factory AuthStatus.unauthenticated() = _Unauthenticated; + const factory AuthStatus.initial() = _Initial; +} diff --git a/lib/application/auth/login_form/login_form_bloc.dart b/lib/application/auth/login_form/login_form_bloc.dart new file mode 100644 index 0000000..e7e0b25 --- /dev/null +++ b/lib/application/auth/login_form/login_form_bloc.dart @@ -0,0 +1,76 @@ +// ignore: depend_on_referenced_packages; +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 '../../../common/utils/device_info_service.dart'; +import '../../../common/utils/fcm_service.dart'; +import '../../../domain/auth/auth.dart'; + +part 'login_form_event.dart'; +part 'login_form_state.dart'; +part 'login_form_bloc.freezed.dart'; + +@injectable +class LoginFormBloc extends Bloc { + final IAuthRepository _repository; + final DeviceInfoService _deviceInfoService; + final FcmService _fcmService; + + LoginFormBloc(this._repository, this._deviceInfoService, this._fcmService) + : super(LoginFormState.initial()) { + on(_onLoginFormEvent); + } + + Future _onLoginFormEvent( + LoginFormEvent event, + Emitter emit, + ) { + return event.map( + emailChanged: (e) async { + emit(state.copyWith(email: e.email, failureOrAuthOption: none())); + }, + passwordChanged: (e) async { + emit(state.copyWith(password: e.password, failureOrAuthOption: none())); + }, + submitted: (e) async { + Either? failureOrAuth; + emit(state.copyWith(isSubmitting: true, failureOrAuthOption: none())); + + final emailValid = state.email.isNotEmpty; + final passwordValid = state.password.isNotEmpty; + + if (emailValid && passwordValid) { + // Ambil device info dan FCM token secara paralel + final results = await Future.wait([ + _deviceInfoService.getDeviceInfo(), + _fcmService.getToken(), + ]); + + final deviceInfo = results[0] as DeviceInfo; + final fcmToken = results[1] as String?; + + failureOrAuth = await _repository.login( + email: state.email, + password: state.password, + deviceId: deviceInfo.deviceId, + deviceName: deviceInfo.deviceName, + deviceType: deviceInfo.deviceType, + platform: deviceInfo.platform, + osVersion: deviceInfo.osVersion, + appVersion: deviceInfo.appVersion, + fcmToken: fcmToken, + ); + emit( + state.copyWith( + isSubmitting: false, + failureOrAuthOption: optionOf(failureOrAuth), + ), + ); + } + emit(state.copyWith(showErrorMessages: true, isSubmitting: false)); + }, + ); + } +} diff --git a/lib/application/auth/login_form/login_form_bloc.freezed.dart b/lib/application/auth/login_form/login_form_bloc.freezed.dart new file mode 100644 index 0000000..8bdc3cc --- /dev/null +++ b/lib/application/auth/login_form/login_form_bloc.freezed.dart @@ -0,0 +1,734 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'login_form_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models', +); + +/// @nodoc +mixin _$LoginFormEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String email) emailChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String email)? emailChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String email)? emailChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_EmailChanged value) emailChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_EmailChanged value)? emailChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_EmailChanged value)? emailChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LoginFormEventCopyWith<$Res> { + factory $LoginFormEventCopyWith( + LoginFormEvent value, + $Res Function(LoginFormEvent) then, + ) = _$LoginFormEventCopyWithImpl<$Res, LoginFormEvent>; +} + +/// @nodoc +class _$LoginFormEventCopyWithImpl<$Res, $Val extends LoginFormEvent> + implements $LoginFormEventCopyWith<$Res> { + _$LoginFormEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$EmailChangedImplCopyWith<$Res> { + factory _$$EmailChangedImplCopyWith( + _$EmailChangedImpl value, + $Res Function(_$EmailChangedImpl) then, + ) = __$$EmailChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String email}); +} + +/// @nodoc +class __$$EmailChangedImplCopyWithImpl<$Res> + extends _$LoginFormEventCopyWithImpl<$Res, _$EmailChangedImpl> + implements _$$EmailChangedImplCopyWith<$Res> { + __$$EmailChangedImplCopyWithImpl( + _$EmailChangedImpl _value, + $Res Function(_$EmailChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? email = null}) { + return _then( + _$EmailChangedImpl( + null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$EmailChangedImpl implements _EmailChanged { + const _$EmailChangedImpl(this.email); + + @override + final String email; + + @override + String toString() { + return 'LoginFormEvent.emailChanged(email: $email)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$EmailChangedImpl && + (identical(other.email, email) || other.email == email)); + } + + @override + int get hashCode => Object.hash(runtimeType, email); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$EmailChangedImplCopyWith<_$EmailChangedImpl> get copyWith => + __$$EmailChangedImplCopyWithImpl<_$EmailChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String email) emailChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) { + return emailChanged(email); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String email)? emailChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) { + return emailChanged?.call(email); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String email)? emailChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (emailChanged != null) { + return emailChanged(email); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_EmailChanged value) emailChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return emailChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_EmailChanged value)? emailChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return emailChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_EmailChanged value)? emailChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (emailChanged != null) { + return emailChanged(this); + } + return orElse(); + } +} + +abstract class _EmailChanged implements LoginFormEvent { + const factory _EmailChanged(final String email) = _$EmailChangedImpl; + + String get email; + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$EmailChangedImplCopyWith<_$EmailChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$PasswordChangedImplCopyWith<$Res> { + factory _$$PasswordChangedImplCopyWith( + _$PasswordChangedImpl value, + $Res Function(_$PasswordChangedImpl) then, + ) = __$$PasswordChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String password}); +} + +/// @nodoc +class __$$PasswordChangedImplCopyWithImpl<$Res> + extends _$LoginFormEventCopyWithImpl<$Res, _$PasswordChangedImpl> + implements _$$PasswordChangedImplCopyWith<$Res> { + __$$PasswordChangedImplCopyWithImpl( + _$PasswordChangedImpl _value, + $Res Function(_$PasswordChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? password = null}) { + return _then( + _$PasswordChangedImpl( + null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$PasswordChangedImpl implements _PasswordChanged { + const _$PasswordChangedImpl(this.password); + + @override + final String password; + + @override + String toString() { + return 'LoginFormEvent.passwordChanged(password: $password)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PasswordChangedImpl && + (identical(other.password, password) || + other.password == password)); + } + + @override + int get hashCode => Object.hash(runtimeType, password); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PasswordChangedImplCopyWith<_$PasswordChangedImpl> get copyWith => + __$$PasswordChangedImplCopyWithImpl<_$PasswordChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String email) emailChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) { + return passwordChanged(password); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String email)? emailChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) { + return passwordChanged?.call(password); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String email)? emailChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (passwordChanged != null) { + return passwordChanged(password); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_EmailChanged value) emailChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return passwordChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_EmailChanged value)? emailChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return passwordChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_EmailChanged value)? emailChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (passwordChanged != null) { + return passwordChanged(this); + } + return orElse(); + } +} + +abstract class _PasswordChanged implements LoginFormEvent { + const factory _PasswordChanged(final String password) = _$PasswordChangedImpl; + + String get password; + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PasswordChangedImplCopyWith<_$PasswordChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$SubmittedImplCopyWith<$Res> { + factory _$$SubmittedImplCopyWith( + _$SubmittedImpl value, + $Res Function(_$SubmittedImpl) then, + ) = __$$SubmittedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SubmittedImplCopyWithImpl<$Res> + extends _$LoginFormEventCopyWithImpl<$Res, _$SubmittedImpl> + implements _$$SubmittedImplCopyWith<$Res> { + __$$SubmittedImplCopyWithImpl( + _$SubmittedImpl _value, + $Res Function(_$SubmittedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SubmittedImpl implements _Submitted { + const _$SubmittedImpl(); + + @override + String toString() { + return 'LoginFormEvent.submitted()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SubmittedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String email) emailChanged, + required TResult Function(String password) passwordChanged, + required TResult Function() submitted, + }) { + return submitted(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String email)? emailChanged, + TResult? Function(String password)? passwordChanged, + TResult? Function()? submitted, + }) { + return submitted?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String email)? emailChanged, + TResult Function(String password)? passwordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_EmailChanged value) emailChanged, + required TResult Function(_PasswordChanged value) passwordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return submitted(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_EmailChanged value)? emailChanged, + TResult? Function(_PasswordChanged value)? passwordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return submitted?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_EmailChanged value)? emailChanged, + TResult Function(_PasswordChanged value)? passwordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(this); + } + return orElse(); + } +} + +abstract class _Submitted implements LoginFormEvent { + const factory _Submitted() = _$SubmittedImpl; +} + +/// @nodoc +mixin _$LoginFormState { + String get email => throw _privateConstructorUsedError; + String get password => throw _privateConstructorUsedError; + Option> get failureOrAuthOption => + throw _privateConstructorUsedError; + bool get isSubmitting => throw _privateConstructorUsedError; + bool get showErrorMessages => throw _privateConstructorUsedError; + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LoginFormStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LoginFormStateCopyWith<$Res> { + factory $LoginFormStateCopyWith( + LoginFormState value, + $Res Function(LoginFormState) then, + ) = _$LoginFormStateCopyWithImpl<$Res, LoginFormState>; + @useResult + $Res call({ + String email, + String password, + Option> failureOrAuthOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class _$LoginFormStateCopyWithImpl<$Res, $Val extends LoginFormState> + implements $LoginFormStateCopyWith<$Res> { + _$LoginFormStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? email = null, + Object? password = null, + Object? failureOrAuthOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _value.copyWith( + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + failureOrAuthOption: null == failureOrAuthOption + ? _value.failureOrAuthOption + : failureOrAuthOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$LoginFormStateImplCopyWith<$Res> + implements $LoginFormStateCopyWith<$Res> { + factory _$$LoginFormStateImplCopyWith( + _$LoginFormStateImpl value, + $Res Function(_$LoginFormStateImpl) then, + ) = __$$LoginFormStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String email, + String password, + Option> failureOrAuthOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class __$$LoginFormStateImplCopyWithImpl<$Res> + extends _$LoginFormStateCopyWithImpl<$Res, _$LoginFormStateImpl> + implements _$$LoginFormStateImplCopyWith<$Res> { + __$$LoginFormStateImplCopyWithImpl( + _$LoginFormStateImpl _value, + $Res Function(_$LoginFormStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? email = null, + Object? password = null, + Object? failureOrAuthOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _$LoginFormStateImpl( + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + password: null == password + ? _value.password + : password // ignore: cast_nullable_to_non_nullable + as String, + failureOrAuthOption: null == failureOrAuthOption + ? _value.failureOrAuthOption + : failureOrAuthOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$LoginFormStateImpl implements _LoginFormState { + const _$LoginFormStateImpl({ + required this.email, + required this.password, + required this.failureOrAuthOption, + this.isSubmitting = false, + this.showErrorMessages = false, + }); + + @override + final String email; + @override + final String password; + @override + final Option> failureOrAuthOption; + @override + @JsonKey() + final bool isSubmitting; + @override + @JsonKey() + final bool showErrorMessages; + + @override + String toString() { + return 'LoginFormState(email: $email, password: $password, failureOrAuthOption: $failureOrAuthOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LoginFormStateImpl && + (identical(other.email, email) || other.email == email) && + (identical(other.password, password) || + other.password == password) && + (identical(other.failureOrAuthOption, failureOrAuthOption) || + other.failureOrAuthOption == failureOrAuthOption) && + (identical(other.isSubmitting, isSubmitting) || + other.isSubmitting == isSubmitting) && + (identical(other.showErrorMessages, showErrorMessages) || + other.showErrorMessages == showErrorMessages)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + email, + password, + failureOrAuthOption, + isSubmitting, + showErrorMessages, + ); + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LoginFormStateImplCopyWith<_$LoginFormStateImpl> get copyWith => + __$$LoginFormStateImplCopyWithImpl<_$LoginFormStateImpl>( + this, + _$identity, + ); +} + +abstract class _LoginFormState implements LoginFormState { + const factory _LoginFormState({ + required final String email, + required final String password, + required final Option> failureOrAuthOption, + final bool isSubmitting, + final bool showErrorMessages, + }) = _$LoginFormStateImpl; + + @override + String get email; + @override + String get password; + @override + Option> get failureOrAuthOption; + @override + bool get isSubmitting; + @override + bool get showErrorMessages; + + /// Create a copy of LoginFormState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LoginFormStateImplCopyWith<_$LoginFormStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/auth/login_form/login_form_event.dart b/lib/application/auth/login_form/login_form_event.dart new file mode 100644 index 0000000..4294a96 --- /dev/null +++ b/lib/application/auth/login_form/login_form_event.dart @@ -0,0 +1,9 @@ +part of 'login_form_bloc.dart'; + +@freezed +sealed class LoginFormEvent with _$LoginFormEvent { + const factory LoginFormEvent.emailChanged(String email) = _EmailChanged; + const factory LoginFormEvent.passwordChanged(String password) = + _PasswordChanged; + const factory LoginFormEvent.submitted() = _Submitted; +} diff --git a/lib/application/auth/login_form/login_form_state.dart b/lib/application/auth/login_form/login_form_state.dart new file mode 100644 index 0000000..c917b8b --- /dev/null +++ b/lib/application/auth/login_form/login_form_state.dart @@ -0,0 +1,15 @@ +part of 'login_form_bloc.dart'; + +@freezed +class LoginFormState with _$LoginFormState { + const factory LoginFormState({ + required String email, + required String password, + required Option> failureOrAuthOption, + @Default(false) bool isSubmitting, + @Default(false) bool showErrorMessages, + }) = _LoginFormState; + + factory LoginFormState.initial() => + LoginFormState(email: '', password: '', failureOrAuthOption: none()); +} diff --git a/lib/application/auth/logout_form/logout_form_bloc.dart b/lib/application/auth/logout_form/logout_form_bloc.dart new file mode 100644 index 0000000..89a9959 --- /dev/null +++ b/lib/application/auth/logout_form/logout_form_bloc.dart @@ -0,0 +1,36 @@ +import 'package:dartz/dartz.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/auth/auth.dart'; + +part 'logout_form_event.dart'; +part 'logout_form_state.dart'; +part 'logout_form_bloc.freezed.dart'; + +@injectable +class LogoutFormBloc extends Bloc { + final IAuthRepository _repository; + LogoutFormBloc(this._repository) : super(LogoutFormState.initial()) { + on(_onLogoutFormEvent); + } + + Future _onLogoutFormEvent( + LogoutFormEvent event, + Emitter emit, + ) { + return event.map( + submitted: (e) async { + emit(state.copyWith(isSubmitting: true, failureOrAuthOption: none())); + final failureOrAuth = await _repository.logout(); + emit( + state.copyWith( + isSubmitting: false, + failureOrAuthOption: optionOf(failureOrAuth), + ), + ); + }, + ); + } +} diff --git a/lib/application/auth/logout_form/logout_form_bloc.freezed.dart b/lib/application/auth/logout_form/logout_form_bloc.freezed.dart new file mode 100644 index 0000000..2bdad02 --- /dev/null +++ b/lib/application/auth/logout_form/logout_form_bloc.freezed.dart @@ -0,0 +1,335 @@ +// 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 'logout_form_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$LogoutFormEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Submitted value) submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Submitted value)? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LogoutFormEventCopyWith<$Res> { + factory $LogoutFormEventCopyWith( + LogoutFormEvent value, + $Res Function(LogoutFormEvent) then, + ) = _$LogoutFormEventCopyWithImpl<$Res, LogoutFormEvent>; +} + +/// @nodoc +class _$LogoutFormEventCopyWithImpl<$Res, $Val extends LogoutFormEvent> + implements $LogoutFormEventCopyWith<$Res> { + _$LogoutFormEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LogoutFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$SubmittedImplCopyWith<$Res> { + factory _$$SubmittedImplCopyWith( + _$SubmittedImpl value, + $Res Function(_$SubmittedImpl) then, + ) = __$$SubmittedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SubmittedImplCopyWithImpl<$Res> + extends _$LogoutFormEventCopyWithImpl<$Res, _$SubmittedImpl> + implements _$$SubmittedImplCopyWith<$Res> { + __$$SubmittedImplCopyWithImpl( + _$SubmittedImpl _value, + $Res Function(_$SubmittedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LogoutFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SubmittedImpl implements _Submitted { + const _$SubmittedImpl(); + + @override + String toString() { + return 'LogoutFormEvent.submitted()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SubmittedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() submitted, + }) { + return submitted(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? submitted, + }) { + return submitted?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Submitted value) submitted, + }) { + return submitted(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Submitted value)? submitted, + }) { + return submitted?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(this); + } + return orElse(); + } +} + +abstract class _Submitted implements LogoutFormEvent { + const factory _Submitted() = _$SubmittedImpl; +} + +/// @nodoc +mixin _$LogoutFormState { + Option> get failureOrAuthOption => + throw _privateConstructorUsedError; + bool get isSubmitting => throw _privateConstructorUsedError; + + /// Create a copy of LogoutFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LogoutFormStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LogoutFormStateCopyWith<$Res> { + factory $LogoutFormStateCopyWith( + LogoutFormState value, + $Res Function(LogoutFormState) then, + ) = _$LogoutFormStateCopyWithImpl<$Res, LogoutFormState>; + @useResult + $Res call({ + Option> failureOrAuthOption, + bool isSubmitting, + }); +} + +/// @nodoc +class _$LogoutFormStateCopyWithImpl<$Res, $Val extends LogoutFormState> + implements $LogoutFormStateCopyWith<$Res> { + _$LogoutFormStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LogoutFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failureOrAuthOption = null, Object? isSubmitting = null}) { + return _then( + _value.copyWith( + failureOrAuthOption: null == failureOrAuthOption + ? _value.failureOrAuthOption + : failureOrAuthOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$LogoutFormStateImplCopyWith<$Res> + implements $LogoutFormStateCopyWith<$Res> { + factory _$$LogoutFormStateImplCopyWith( + _$LogoutFormStateImpl value, + $Res Function(_$LogoutFormStateImpl) then, + ) = __$$LogoutFormStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + Option> failureOrAuthOption, + bool isSubmitting, + }); +} + +/// @nodoc +class __$$LogoutFormStateImplCopyWithImpl<$Res> + extends _$LogoutFormStateCopyWithImpl<$Res, _$LogoutFormStateImpl> + implements _$$LogoutFormStateImplCopyWith<$Res> { + __$$LogoutFormStateImplCopyWithImpl( + _$LogoutFormStateImpl _value, + $Res Function(_$LogoutFormStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LogoutFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failureOrAuthOption = null, Object? isSubmitting = null}) { + return _then( + _$LogoutFormStateImpl( + failureOrAuthOption: null == failureOrAuthOption + ? _value.failureOrAuthOption + : failureOrAuthOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$LogoutFormStateImpl implements _LogoutFormState { + const _$LogoutFormStateImpl({ + required this.failureOrAuthOption, + this.isSubmitting = false, + }); + + @override + final Option> failureOrAuthOption; + @override + @JsonKey() + final bool isSubmitting; + + @override + String toString() { + return 'LogoutFormState(failureOrAuthOption: $failureOrAuthOption, isSubmitting: $isSubmitting)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LogoutFormStateImpl && + (identical(other.failureOrAuthOption, failureOrAuthOption) || + other.failureOrAuthOption == failureOrAuthOption) && + (identical(other.isSubmitting, isSubmitting) || + other.isSubmitting == isSubmitting)); + } + + @override + int get hashCode => + Object.hash(runtimeType, failureOrAuthOption, isSubmitting); + + /// Create a copy of LogoutFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LogoutFormStateImplCopyWith<_$LogoutFormStateImpl> get copyWith => + __$$LogoutFormStateImplCopyWithImpl<_$LogoutFormStateImpl>( + this, + _$identity, + ); +} + +abstract class _LogoutFormState implements LogoutFormState { + const factory _LogoutFormState({ + required final Option> failureOrAuthOption, + final bool isSubmitting, + }) = _$LogoutFormStateImpl; + + @override + Option> get failureOrAuthOption; + @override + bool get isSubmitting; + + /// Create a copy of LogoutFormState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LogoutFormStateImplCopyWith<_$LogoutFormStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/auth/logout_form/logout_form_event.dart b/lib/application/auth/logout_form/logout_form_event.dart new file mode 100644 index 0000000..606bf91 --- /dev/null +++ b/lib/application/auth/logout_form/logout_form_event.dart @@ -0,0 +1,6 @@ +part of 'logout_form_bloc.dart'; + +@freezed +class LogoutFormEvent with _$LogoutFormEvent { + const factory LogoutFormEvent.submitted() = _Submitted; +} diff --git a/lib/application/auth/logout_form/logout_form_state.dart b/lib/application/auth/logout_form/logout_form_state.dart new file mode 100644 index 0000000..613c5e1 --- /dev/null +++ b/lib/application/auth/logout_form/logout_form_state.dart @@ -0,0 +1,12 @@ +part of 'logout_form_bloc.dart'; + +@freezed +class LogoutFormState with _$LogoutFormState { + const factory LogoutFormState({ + required Option> failureOrAuthOption, + @Default(false) bool isSubmitting, + }) = _LogoutFormState; + + factory LogoutFormState.initial() => + LogoutFormState(failureOrAuthOption: none(), isSubmitting: false); +} diff --git a/lib/application/category/category_loader/category_loader_bloc.dart b/lib/application/category/category_loader/category_loader_bloc.dart new file mode 100644 index 0000000..884f36c --- /dev/null +++ b/lib/application/category/category_loader/category_loader_bloc.dart @@ -0,0 +1,55 @@ +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/category/category.dart'; + +part 'category_loader_event.dart'; +part 'category_loader_state.dart'; +part 'category_loader_bloc.freezed.dart'; + +@injectable +class CategoryLoaderBloc + extends Bloc { + final ICategoryRepository _repository; + CategoryLoaderBloc(this._repository) : super(CategoryLoaderState.initial()) { + on(_onCategoryLoaderEvent); + } + + Future _onCategoryLoaderEvent( + CategoryLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit(state.copyWith(isFetching: true, failureOptionCategory: none())); + + final result = await _repository.get(); + + result.fold( + (f) { + emit( + state.copyWith( + isFetching: false, + failureOptionCategory: optionOf(f), + ), + ); + }, + (categories) { + // tambahkan "All Data" di awal list + final updatedCategories = [Category.addAllData(), ...categories]; + + emit( + state.copyWith( + isFetching: false, + categories: updatedCategories, + failureOptionCategory: none(), + ), + ); + }, + ); + }, + ); + } +} diff --git a/lib/application/category/category_loader/category_loader_bloc.freezed.dart b/lib/application/category/category_loader/category_loader_bloc.freezed.dart new file mode 100644 index 0000000..5599123 --- /dev/null +++ b/lib/application/category/category_loader/category_loader_bloc.freezed.dart @@ -0,0 +1,370 @@ +// 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 'category_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$CategoryLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryLoaderEventCopyWith<$Res> { + factory $CategoryLoaderEventCopyWith( + CategoryLoaderEvent value, + $Res Function(CategoryLoaderEvent) then, + ) = _$CategoryLoaderEventCopyWithImpl<$Res, CategoryLoaderEvent>; +} + +/// @nodoc +class _$CategoryLoaderEventCopyWithImpl<$Res, $Val extends CategoryLoaderEvent> + implements $CategoryLoaderEventCopyWith<$Res> { + _$CategoryLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryLoaderEvent + /// 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>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$CategoryLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'CategoryLoaderEvent.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({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements CategoryLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$CategoryLoaderState { + List get categories => throw _privateConstructorUsedError; + Option get failureOptionCategory => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of CategoryLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryLoaderStateCopyWith<$Res> { + factory $CategoryLoaderStateCopyWith( + CategoryLoaderState value, + $Res Function(CategoryLoaderState) then, + ) = _$CategoryLoaderStateCopyWithImpl<$Res, CategoryLoaderState>; + @useResult + $Res call({ + List categories, + Option failureOptionCategory, + bool isFetching, + }); +} + +/// @nodoc +class _$CategoryLoaderStateCopyWithImpl<$Res, $Val extends CategoryLoaderState> + implements $CategoryLoaderStateCopyWith<$Res> { + _$CategoryLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categories = null, + Object? failureOptionCategory = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + categories: null == categories + ? _value.categories + : categories // ignore: cast_nullable_to_non_nullable + as List, + failureOptionCategory: null == failureOptionCategory + ? _value.failureOptionCategory + : failureOptionCategory // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryLoaderStateImplCopyWith<$Res> + implements $CategoryLoaderStateCopyWith<$Res> { + factory _$$CategoryLoaderStateImplCopyWith( + _$CategoryLoaderStateImpl value, + $Res Function(_$CategoryLoaderStateImpl) then, + ) = __$$CategoryLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + List categories, + Option failureOptionCategory, + bool isFetching, + }); +} + +/// @nodoc +class __$$CategoryLoaderStateImplCopyWithImpl<$Res> + extends _$CategoryLoaderStateCopyWithImpl<$Res, _$CategoryLoaderStateImpl> + implements _$$CategoryLoaderStateImplCopyWith<$Res> { + __$$CategoryLoaderStateImplCopyWithImpl( + _$CategoryLoaderStateImpl _value, + $Res Function(_$CategoryLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categories = null, + Object? failureOptionCategory = null, + Object? isFetching = null, + }) { + return _then( + _$CategoryLoaderStateImpl( + categories: null == categories + ? _value._categories + : categories // ignore: cast_nullable_to_non_nullable + as List, + failureOptionCategory: null == failureOptionCategory + ? _value.failureOptionCategory + : failureOptionCategory // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$CategoryLoaderStateImpl implements _CategoryLoaderState { + const _$CategoryLoaderStateImpl({ + required final List categories, + required this.failureOptionCategory, + this.isFetching = false, + }) : _categories = categories; + + final List _categories; + @override + List get categories { + if (_categories is EqualUnmodifiableListView) return _categories; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_categories); + } + + @override + final Option failureOptionCategory; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'CategoryLoaderState(categories: $categories, failureOptionCategory: $failureOptionCategory, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryLoaderStateImpl && + const DeepCollectionEquality().equals( + other._categories, + _categories, + ) && + (identical(other.failureOptionCategory, failureOptionCategory) || + other.failureOptionCategory == failureOptionCategory) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_categories), + failureOptionCategory, + isFetching, + ); + + /// Create a copy of CategoryLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryLoaderStateImplCopyWith<_$CategoryLoaderStateImpl> get copyWith => + __$$CategoryLoaderStateImplCopyWithImpl<_$CategoryLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _CategoryLoaderState implements CategoryLoaderState { + const factory _CategoryLoaderState({ + required final List categories, + required final Option failureOptionCategory, + final bool isFetching, + }) = _$CategoryLoaderStateImpl; + + @override + List get categories; + @override + Option get failureOptionCategory; + @override + bool get isFetching; + + /// Create a copy of CategoryLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryLoaderStateImplCopyWith<_$CategoryLoaderStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/category/category_loader/category_loader_event.dart b/lib/application/category/category_loader/category_loader_event.dart new file mode 100644 index 0000000..2c154e1 --- /dev/null +++ b/lib/application/category/category_loader/category_loader_event.dart @@ -0,0 +1,6 @@ +part of 'category_loader_bloc.dart'; + +@freezed +class CategoryLoaderEvent with _$CategoryLoaderEvent { + const factory CategoryLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/category/category_loader/category_loader_state.dart b/lib/application/category/category_loader/category_loader_state.dart new file mode 100644 index 0000000..e3295ea --- /dev/null +++ b/lib/application/category/category_loader/category_loader_state.dart @@ -0,0 +1,13 @@ +part of 'category_loader_bloc.dart'; + +@freezed +class CategoryLoaderState with _$CategoryLoaderState { + const factory CategoryLoaderState({ + required List categories, + required Option failureOptionCategory, + @Default(false) bool isFetching, + }) = _CategoryLoaderState; + + factory CategoryLoaderState.initial() => + CategoryLoaderState(categories: [], failureOptionCategory: none()); +} diff --git a/lib/application/customer/customer_loader/customer_loader_bloc.dart b/lib/application/customer/customer_loader/customer_loader_bloc.dart new file mode 100644 index 0000000..a176b56 --- /dev/null +++ b/lib/application/customer/customer_loader/customer_loader_bloc.dart @@ -0,0 +1,87 @@ +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/customer/customer.dart'; + +part 'customer_loader_event.dart'; +part 'customer_loader_state.dart'; +part 'customer_loader_bloc.freezed.dart'; + +@injectable +class CustomerLoaderBloc + extends Bloc { + final ICustomerRepository _repository; + CustomerLoaderBloc(this._repository) : super(CustomerLoaderState.initial()) { + on(_onCustomerLoaderEvent); + } + + Future _onCustomerLoaderEvent( + CustomerLoaderEvent event, + Emitter emit, + ) { + return event.map( + searchChanged: (e) async { + emit(state.copyWith(search: e.search)); + }, + fetched: (e) async { + var newState = state; + + if (e.isRefresh) { + newState = state.copyWith(isFetching: true); + + emit(newState); + } + + newState = await _mapFetchedToState(state, isRefresh: e.isRefresh); + + emit(newState); + }, + ); + } + + Future _mapFetchedToState( + CustomerLoaderState state, { + bool isRefresh = false, + }) async { + state = state.copyWith(isFetching: false); + + if (state.hasReachedMax && state.customers.isNotEmpty && !isRefresh) { + return state; + } + + if (isRefresh) { + state = state.copyWith( + page: 1, + failureOptionCustomer: none(), + hasReachedMax: false, + customers: [], + ); + } + + final failureOrCustomer = await _repository.get( + page: state.page, + search: state.search, + ); + + state = failureOrCustomer.fold( + (f) { + if (state.customers.isNotEmpty) { + return state.copyWith(hasReachedMax: true); + } + return state.copyWith(failureOptionCustomer: optionOf(f)); + }, + (customers) { + return state.copyWith( + customers: List.from(state.customers)..addAll(customers), + failureOptionCustomer: none(), + page: state.page + 1, + hasReachedMax: customers.length < 10, + ); + }, + ); + + return state; + } +} diff --git a/lib/application/customer/customer_loader/customer_loader_bloc.freezed.dart b/lib/application/customer/customer_loader/customer_loader_bloc.freezed.dart new file mode 100644 index 0000000..d612039 --- /dev/null +++ b/lib/application/customer/customer_loader/customer_loader_bloc.freezed.dart @@ -0,0 +1,653 @@ +// 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 'customer_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$CustomerLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CustomerLoaderEventCopyWith<$Res> { + factory $CustomerLoaderEventCopyWith( + CustomerLoaderEvent value, + $Res Function(CustomerLoaderEvent) then, + ) = _$CustomerLoaderEventCopyWithImpl<$Res, CustomerLoaderEvent>; +} + +/// @nodoc +class _$CustomerLoaderEventCopyWithImpl<$Res, $Val extends CustomerLoaderEvent> + implements $CustomerLoaderEventCopyWith<$Res> { + _$CustomerLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CustomerLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$SearchChangedImplCopyWith<$Res> { + factory _$$SearchChangedImplCopyWith( + _$SearchChangedImpl value, + $Res Function(_$SearchChangedImpl) then, + ) = __$$SearchChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String search}); +} + +/// @nodoc +class __$$SearchChangedImplCopyWithImpl<$Res> + extends _$CustomerLoaderEventCopyWithImpl<$Res, _$SearchChangedImpl> + implements _$$SearchChangedImplCopyWith<$Res> { + __$$SearchChangedImplCopyWithImpl( + _$SearchChangedImpl _value, + $Res Function(_$SearchChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? search = null}) { + return _then( + _$SearchChangedImpl( + null == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$SearchChangedImpl implements _SearchChanged { + const _$SearchChangedImpl(this.search); + + @override + final String search; + + @override + String toString() { + return 'CustomerLoaderEvent.searchChanged(search: $search)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SearchChangedImpl && + (identical(other.search, search) || other.search == search)); + } + + @override + int get hashCode => Object.hash(runtimeType, search); + + /// Create a copy of CustomerLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + __$$SearchChangedImplCopyWithImpl<_$SearchChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return searchChanged(search); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return searchChanged?.call(search); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(search); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) { + return searchChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return searchChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(this); + } + return orElse(); + } +} + +abstract class _SearchChanged implements CustomerLoaderEvent { + const factory _SearchChanged(final String search) = _$SearchChangedImpl; + + String get search; + + /// Create a copy of CustomerLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; + @useResult + $Res call({bool isRefresh}); +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$CustomerLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? isRefresh = null}) { + return _then( + _$FetchedImpl( + isRefresh: null == isRefresh + ? _value.isRefresh + : isRefresh // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl({this.isRefresh = false}); + + @override + @JsonKey() + final bool isRefresh; + + @override + String toString() { + return 'CustomerLoaderEvent.fetched(isRefresh: $isRefresh)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FetchedImpl && + (identical(other.isRefresh, isRefresh) || + other.isRefresh == isRefresh)); + } + + @override + int get hashCode => Object.hash(runtimeType, isRefresh); + + /// Create a copy of CustomerLoaderEvent + /// 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({ + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return fetched(isRefresh); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return fetched?.call(isRefresh); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(isRefresh); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements CustomerLoaderEvent { + const factory _Fetched({final bool isRefresh}) = _$FetchedImpl; + + bool get isRefresh; + + /// Create a copy of CustomerLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FetchedImplCopyWith<_$FetchedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$CustomerLoaderState { + List get customers => throw _privateConstructorUsedError; + Option get failureOptionCustomer => + throw _privateConstructorUsedError; + String? get categoryId => throw _privateConstructorUsedError; + String? get search => throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + bool get hasReachedMax => throw _privateConstructorUsedError; + int get page => throw _privateConstructorUsedError; + + /// Create a copy of CustomerLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CustomerLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CustomerLoaderStateCopyWith<$Res> { + factory $CustomerLoaderStateCopyWith( + CustomerLoaderState value, + $Res Function(CustomerLoaderState) then, + ) = _$CustomerLoaderStateCopyWithImpl<$Res, CustomerLoaderState>; + @useResult + $Res call({ + List customers, + Option failureOptionCustomer, + String? categoryId, + String? search, + bool isFetching, + bool hasReachedMax, + int page, + }); +} + +/// @nodoc +class _$CustomerLoaderStateCopyWithImpl<$Res, $Val extends CustomerLoaderState> + implements $CustomerLoaderStateCopyWith<$Res> { + _$CustomerLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CustomerLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? customers = null, + Object? failureOptionCustomer = null, + Object? categoryId = freezed, + Object? search = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + }) { + return _then( + _value.copyWith( + customers: null == customers + ? _value.customers + : customers // ignore: cast_nullable_to_non_nullable + as List, + failureOptionCustomer: null == failureOptionCustomer + ? _value.failureOptionCustomer + : failureOptionCustomer // ignore: cast_nullable_to_non_nullable + as Option, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CustomerLoaderStateImplCopyWith<$Res> + implements $CustomerLoaderStateCopyWith<$Res> { + factory _$$CustomerLoaderStateImplCopyWith( + _$CustomerLoaderStateImpl value, + $Res Function(_$CustomerLoaderStateImpl) then, + ) = __$$CustomerLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + List customers, + Option failureOptionCustomer, + String? categoryId, + String? search, + bool isFetching, + bool hasReachedMax, + int page, + }); +} + +/// @nodoc +class __$$CustomerLoaderStateImplCopyWithImpl<$Res> + extends _$CustomerLoaderStateCopyWithImpl<$Res, _$CustomerLoaderStateImpl> + implements _$$CustomerLoaderStateImplCopyWith<$Res> { + __$$CustomerLoaderStateImplCopyWithImpl( + _$CustomerLoaderStateImpl _value, + $Res Function(_$CustomerLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? customers = null, + Object? failureOptionCustomer = null, + Object? categoryId = freezed, + Object? search = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + }) { + return _then( + _$CustomerLoaderStateImpl( + customers: null == customers + ? _value._customers + : customers // ignore: cast_nullable_to_non_nullable + as List, + failureOptionCustomer: null == failureOptionCustomer + ? _value.failureOptionCustomer + : failureOptionCustomer // ignore: cast_nullable_to_non_nullable + as Option, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$CustomerLoaderStateImpl implements _CustomerLoaderState { + const _$CustomerLoaderStateImpl({ + required final List customers, + required this.failureOptionCustomer, + this.categoryId, + this.search, + this.isFetching = false, + this.hasReachedMax = false, + this.page = 1, + }) : _customers = customers; + + final List _customers; + @override + List get customers { + if (_customers is EqualUnmodifiableListView) return _customers; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_customers); + } + + @override + final Option failureOptionCustomer; + @override + final String? categoryId; + @override + final String? search; + @override + @JsonKey() + final bool isFetching; + @override + @JsonKey() + final bool hasReachedMax; + @override + @JsonKey() + final int page; + + @override + String toString() { + return 'CustomerLoaderState(customers: $customers, failureOptionCustomer: $failureOptionCustomer, categoryId: $categoryId, search: $search, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CustomerLoaderStateImpl && + const DeepCollectionEquality().equals( + other._customers, + _customers, + ) && + (identical(other.failureOptionCustomer, failureOptionCustomer) || + other.failureOptionCustomer == failureOptionCustomer) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.search, search) || other.search == search) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.hasReachedMax, hasReachedMax) || + other.hasReachedMax == hasReachedMax) && + (identical(other.page, page) || other.page == page)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_customers), + failureOptionCustomer, + categoryId, + search, + isFetching, + hasReachedMax, + page, + ); + + /// Create a copy of CustomerLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CustomerLoaderStateImplCopyWith<_$CustomerLoaderStateImpl> get copyWith => + __$$CustomerLoaderStateImplCopyWithImpl<_$CustomerLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _CustomerLoaderState implements CustomerLoaderState { + const factory _CustomerLoaderState({ + required final List customers, + required final Option failureOptionCustomer, + final String? categoryId, + final String? search, + final bool isFetching, + final bool hasReachedMax, + final int page, + }) = _$CustomerLoaderStateImpl; + + @override + List get customers; + @override + Option get failureOptionCustomer; + @override + String? get categoryId; + @override + String? get search; + @override + bool get isFetching; + @override + bool get hasReachedMax; + @override + int get page; + + /// Create a copy of CustomerLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CustomerLoaderStateImplCopyWith<_$CustomerLoaderStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/customer/customer_loader/customer_loader_event.dart b/lib/application/customer/customer_loader/customer_loader_event.dart new file mode 100644 index 0000000..82ebd41 --- /dev/null +++ b/lib/application/customer/customer_loader/customer_loader_event.dart @@ -0,0 +1,9 @@ +part of 'customer_loader_bloc.dart'; + +@freezed +class CustomerLoaderEvent with _$CustomerLoaderEvent { + const factory CustomerLoaderEvent.searchChanged(String search) = + _SearchChanged; + const factory CustomerLoaderEvent.fetched({@Default(false) bool isRefresh}) = + _Fetched; +} diff --git a/lib/application/customer/customer_loader/customer_loader_state.dart b/lib/application/customer/customer_loader/customer_loader_state.dart new file mode 100644 index 0000000..4cad298 --- /dev/null +++ b/lib/application/customer/customer_loader/customer_loader_state.dart @@ -0,0 +1,17 @@ +part of 'customer_loader_bloc.dart'; + +@freezed +class CustomerLoaderState with _$CustomerLoaderState { + const factory CustomerLoaderState({ + required List customers, + required Option failureOptionCustomer, + String? categoryId, + String? search, + @Default(false) bool isFetching, + @Default(false) bool hasReachedMax, + @Default(1) int page, + }) = _CustomerLoaderState; + + factory CustomerLoaderState.initial() => + CustomerLoaderState(customers: [], failureOptionCustomer: none()); +} diff --git a/lib/application/home/home_bloc.dart b/lib/application/home/home_bloc.dart new file mode 100644 index 0000000..fc0e385 --- /dev/null +++ b/lib/application/home/home_bloc.dart @@ -0,0 +1,38 @@ +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 'home_event.dart'; +part 'home_state.dart'; +part 'home_bloc.freezed.dart'; + +@injectable +class HomeBloc extends Bloc { + final IAnalyticRepository _analyticRepository; + HomeBloc(this._analyticRepository) : super(HomeState.initial()) { + on(_onHomeEvent); + } + Future _onHomeEvent(HomeEvent event, Emitter emit) { + return event.map( + fetchedDashboard: (e) async { + emit(state.copyWith(isFetching: true, failureOptionDashboard: none())); + + final result = await _analyticRepository.getDashboard( + dateFrom: DateTime.now(), + dateTo: DateTime.now(), + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionDashboard: optionOf(f)), + (dashboard) => state.copyWith(dashboard: dashboard), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/home/home_bloc.freezed.dart b/lib/application/home/home_bloc.freezed.dart new file mode 100644 index 0000000..6ad0699 --- /dev/null +++ b/lib/application/home/home_bloc.freezed.dart @@ -0,0 +1,370 @@ +// 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 'home_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$HomeEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedDashboard, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedDashboard, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedDashboard, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedDashboard value) fetchedDashboard, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedDashboard value)? fetchedDashboard, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedDashboard value)? fetchedDashboard, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $HomeEventCopyWith<$Res> { + factory $HomeEventCopyWith(HomeEvent value, $Res Function(HomeEvent) then) = + _$HomeEventCopyWithImpl<$Res, HomeEvent>; +} + +/// @nodoc +class _$HomeEventCopyWithImpl<$Res, $Val extends HomeEvent> + implements $HomeEventCopyWith<$Res> { + _$HomeEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of HomeEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchedDashboardImplCopyWith<$Res> { + factory _$$FetchedDashboardImplCopyWith( + _$FetchedDashboardImpl value, + $Res Function(_$FetchedDashboardImpl) then, + ) = __$$FetchedDashboardImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedDashboardImplCopyWithImpl<$Res> + extends _$HomeEventCopyWithImpl<$Res, _$FetchedDashboardImpl> + implements _$$FetchedDashboardImplCopyWith<$Res> { + __$$FetchedDashboardImplCopyWithImpl( + _$FetchedDashboardImpl _value, + $Res Function(_$FetchedDashboardImpl) _then, + ) : super(_value, _then); + + /// Create a copy of HomeEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedDashboardImpl implements _FetchedDashboard { + const _$FetchedDashboardImpl(); + + @override + String toString() { + return 'HomeEvent.fetchedDashboard()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchedDashboardImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedDashboard, + }) { + return fetchedDashboard(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedDashboard, + }) { + return fetchedDashboard?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedDashboard, + required TResult orElse(), + }) { + if (fetchedDashboard != null) { + return fetchedDashboard(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedDashboard value) fetchedDashboard, + }) { + return fetchedDashboard(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedDashboard value)? fetchedDashboard, + }) { + return fetchedDashboard?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedDashboard value)? fetchedDashboard, + required TResult orElse(), + }) { + if (fetchedDashboard != null) { + return fetchedDashboard(this); + } + return orElse(); + } +} + +abstract class _FetchedDashboard implements HomeEvent { + const factory _FetchedDashboard() = _$FetchedDashboardImpl; +} + +/// @nodoc +mixin _$HomeState { + DashboardAnalytic get dashboard => throw _privateConstructorUsedError; + Option get failureOptionDashboard => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of HomeState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $HomeStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $HomeStateCopyWith<$Res> { + factory $HomeStateCopyWith(HomeState value, $Res Function(HomeState) then) = + _$HomeStateCopyWithImpl<$Res, HomeState>; + @useResult + $Res call({ + DashboardAnalytic dashboard, + Option failureOptionDashboard, + bool isFetching, + }); + + $DashboardAnalyticCopyWith<$Res> get dashboard; +} + +/// @nodoc +class _$HomeStateCopyWithImpl<$Res, $Val extends HomeState> + implements $HomeStateCopyWith<$Res> { + _$HomeStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of HomeState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? dashboard = null, + Object? failureOptionDashboard = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + dashboard: null == dashboard + ? _value.dashboard + : dashboard // ignore: cast_nullable_to_non_nullable + as DashboardAnalytic, + failureOptionDashboard: null == failureOptionDashboard + ? _value.failureOptionDashboard + : failureOptionDashboard // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of HomeState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardAnalyticCopyWith<$Res> get dashboard { + return $DashboardAnalyticCopyWith<$Res>(_value.dashboard, (value) { + return _then(_value.copyWith(dashboard: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$HomeStateImplCopyWith<$Res> + implements $HomeStateCopyWith<$Res> { + factory _$$HomeStateImplCopyWith( + _$HomeStateImpl value, + $Res Function(_$HomeStateImpl) then, + ) = __$$HomeStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + DashboardAnalytic dashboard, + Option failureOptionDashboard, + bool isFetching, + }); + + @override + $DashboardAnalyticCopyWith<$Res> get dashboard; +} + +/// @nodoc +class __$$HomeStateImplCopyWithImpl<$Res> + extends _$HomeStateCopyWithImpl<$Res, _$HomeStateImpl> + implements _$$HomeStateImplCopyWith<$Res> { + __$$HomeStateImplCopyWithImpl( + _$HomeStateImpl _value, + $Res Function(_$HomeStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of HomeState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? dashboard = null, + Object? failureOptionDashboard = null, + Object? isFetching = null, + }) { + return _then( + _$HomeStateImpl( + dashboard: null == dashboard + ? _value.dashboard + : dashboard // ignore: cast_nullable_to_non_nullable + as DashboardAnalytic, + failureOptionDashboard: null == failureOptionDashboard + ? _value.failureOptionDashboard + : failureOptionDashboard // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$HomeStateImpl implements _HomeState { + const _$HomeStateImpl({ + required this.dashboard, + required this.failureOptionDashboard, + this.isFetching = false, + }); + + @override + final DashboardAnalytic dashboard; + @override + final Option failureOptionDashboard; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'HomeState(dashboard: $dashboard, failureOptionDashboard: $failureOptionDashboard, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$HomeStateImpl && + (identical(other.dashboard, dashboard) || + other.dashboard == dashboard) && + (identical(other.failureOptionDashboard, failureOptionDashboard) || + other.failureOptionDashboard == failureOptionDashboard) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => + Object.hash(runtimeType, dashboard, failureOptionDashboard, isFetching); + + /// Create a copy of HomeState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$HomeStateImplCopyWith<_$HomeStateImpl> get copyWith => + __$$HomeStateImplCopyWithImpl<_$HomeStateImpl>(this, _$identity); +} + +abstract class _HomeState implements HomeState { + const factory _HomeState({ + required final DashboardAnalytic dashboard, + required final Option failureOptionDashboard, + final bool isFetching, + }) = _$HomeStateImpl; + + @override + DashboardAnalytic get dashboard; + @override + Option get failureOptionDashboard; + @override + bool get isFetching; + + /// Create a copy of HomeState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$HomeStateImplCopyWith<_$HomeStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/home/home_event.dart b/lib/application/home/home_event.dart new file mode 100644 index 0000000..5f3909d --- /dev/null +++ b/lib/application/home/home_event.dart @@ -0,0 +1,6 @@ +part of 'home_bloc.dart'; + +@freezed +class HomeEvent with _$HomeEvent { + const factory HomeEvent.fetchedDashboard() = _FetchedDashboard; +} diff --git a/lib/application/home/home_state.dart b/lib/application/home/home_state.dart new file mode 100644 index 0000000..7b0901a --- /dev/null +++ b/lib/application/home/home_state.dart @@ -0,0 +1,15 @@ +part of 'home_bloc.dart'; + +@freezed +class HomeState with _$HomeState { + const factory HomeState({ + required DashboardAnalytic dashboard, + required Option failureOptionDashboard, + @Default(false) bool isFetching, + }) = _HomeState; + + factory HomeState.initial() => HomeState( + dashboard: DashboardAnalytic.empty(), + failureOptionDashboard: none(), + ); +} diff --git a/lib/application/language/language_bloc.dart b/lib/application/language/language_bloc.dart new file mode 100644 index 0000000..db5b347 --- /dev/null +++ b/lib/application/language/language_bloc.dart @@ -0,0 +1,50 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../common/constant/local_storage_key.dart'; +import '../../domain/language/language.dart'; +import '../../infrastructure/language/language.dart'; + +part 'language_event.dart'; +part 'language_state.dart'; +part 'language_bloc.freezed.dart'; + +@injectable +class LanguageBloc extends Bloc { + final SharedPreferences _prefs; + LanguageBloc(this._prefs) : super(LanguageState.initial()) { + on(_onLanguageEvent); + } + + Future _onLanguageEvent( + LanguageEvent event, + Emitter emit, + ) async { + switch (event) { + case _ChangeLanguage(:final language): + await _prefs.setString( + LocalStorageKey.lang, + language.locale.languageCode, + ); + emit(state.copyWith(language: language)); + break; + + case _LoadLanguage(): + final selectedLanguage = _prefs.getString(LocalStorageKey.lang); + + final lang = languages.firstWhere( + (item) => item.locale.languageCode == selectedLanguage, + orElse: () => Language.indonesian(), + ); + + emit( + state.copyWith( + language: selectedLanguage != null ? lang : Language.indonesian(), + ), + ); + break; + } + } +} diff --git a/lib/application/language/language_bloc.freezed.dart b/lib/application/language/language_bloc.freezed.dart new file mode 100644 index 0000000..3366671 --- /dev/null +++ b/lib/application/language/language_bloc.freezed.dart @@ -0,0 +1,488 @@ +// 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 'language_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$LanguageEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(Language language) changeLanguage, + required TResult Function() loadLanguage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(Language language)? changeLanguage, + TResult? Function()? loadLanguage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(Language language)? changeLanguage, + TResult Function()? loadLanguage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ChangeLanguage value) changeLanguage, + required TResult Function(_LoadLanguage value) loadLanguage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ChangeLanguage value)? changeLanguage, + TResult? Function(_LoadLanguage value)? loadLanguage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ChangeLanguage value)? changeLanguage, + TResult Function(_LoadLanguage value)? loadLanguage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LanguageEventCopyWith<$Res> { + factory $LanguageEventCopyWith( + LanguageEvent value, + $Res Function(LanguageEvent) then, + ) = _$LanguageEventCopyWithImpl<$Res, LanguageEvent>; +} + +/// @nodoc +class _$LanguageEventCopyWithImpl<$Res, $Val extends LanguageEvent> + implements $LanguageEventCopyWith<$Res> { + _$LanguageEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LanguageEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ChangeLanguageImplCopyWith<$Res> { + factory _$$ChangeLanguageImplCopyWith( + _$ChangeLanguageImpl value, + $Res Function(_$ChangeLanguageImpl) then, + ) = __$$ChangeLanguageImplCopyWithImpl<$Res>; + @useResult + $Res call({Language language}); + + $LanguageCopyWith<$Res> get language; +} + +/// @nodoc +class __$$ChangeLanguageImplCopyWithImpl<$Res> + extends _$LanguageEventCopyWithImpl<$Res, _$ChangeLanguageImpl> + implements _$$ChangeLanguageImplCopyWith<$Res> { + __$$ChangeLanguageImplCopyWithImpl( + _$ChangeLanguageImpl _value, + $Res Function(_$ChangeLanguageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LanguageEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? language = null}) { + return _then( + _$ChangeLanguageImpl( + null == language + ? _value.language + : language // ignore: cast_nullable_to_non_nullable + as Language, + ), + ); + } + + /// Create a copy of LanguageEvent + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LanguageCopyWith<$Res> get language { + return $LanguageCopyWith<$Res>(_value.language, (value) { + return _then(_value.copyWith(language: value)); + }); + } +} + +/// @nodoc + +class _$ChangeLanguageImpl implements _ChangeLanguage { + const _$ChangeLanguageImpl(this.language); + + @override + final Language language; + + @override + String toString() { + return 'LanguageEvent.changeLanguage(language: $language)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChangeLanguageImpl && + (identical(other.language, language) || + other.language == language)); + } + + @override + int get hashCode => Object.hash(runtimeType, language); + + /// Create a copy of LanguageEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ChangeLanguageImplCopyWith<_$ChangeLanguageImpl> get copyWith => + __$$ChangeLanguageImplCopyWithImpl<_$ChangeLanguageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(Language language) changeLanguage, + required TResult Function() loadLanguage, + }) { + return changeLanguage(language); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(Language language)? changeLanguage, + TResult? Function()? loadLanguage, + }) { + return changeLanguage?.call(language); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(Language language)? changeLanguage, + TResult Function()? loadLanguage, + required TResult orElse(), + }) { + if (changeLanguage != null) { + return changeLanguage(language); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ChangeLanguage value) changeLanguage, + required TResult Function(_LoadLanguage value) loadLanguage, + }) { + return changeLanguage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ChangeLanguage value)? changeLanguage, + TResult? Function(_LoadLanguage value)? loadLanguage, + }) { + return changeLanguage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ChangeLanguage value)? changeLanguage, + TResult Function(_LoadLanguage value)? loadLanguage, + required TResult orElse(), + }) { + if (changeLanguage != null) { + return changeLanguage(this); + } + return orElse(); + } +} + +abstract class _ChangeLanguage implements LanguageEvent { + const factory _ChangeLanguage(final Language language) = _$ChangeLanguageImpl; + + Language get language; + + /// Create a copy of LanguageEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ChangeLanguageImplCopyWith<_$ChangeLanguageImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$LoadLanguageImplCopyWith<$Res> { + factory _$$LoadLanguageImplCopyWith( + _$LoadLanguageImpl value, + $Res Function(_$LoadLanguageImpl) then, + ) = __$$LoadLanguageImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$LoadLanguageImplCopyWithImpl<$Res> + extends _$LanguageEventCopyWithImpl<$Res, _$LoadLanguageImpl> + implements _$$LoadLanguageImplCopyWith<$Res> { + __$$LoadLanguageImplCopyWithImpl( + _$LoadLanguageImpl _value, + $Res Function(_$LoadLanguageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LanguageEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$LoadLanguageImpl implements _LoadLanguage { + const _$LoadLanguageImpl(); + + @override + String toString() { + return 'LanguageEvent.loadLanguage()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$LoadLanguageImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(Language language) changeLanguage, + required TResult Function() loadLanguage, + }) { + return loadLanguage(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(Language language)? changeLanguage, + TResult? Function()? loadLanguage, + }) { + return loadLanguage?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(Language language)? changeLanguage, + TResult Function()? loadLanguage, + required TResult orElse(), + }) { + if (loadLanguage != null) { + return loadLanguage(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ChangeLanguage value) changeLanguage, + required TResult Function(_LoadLanguage value) loadLanguage, + }) { + return loadLanguage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ChangeLanguage value)? changeLanguage, + TResult? Function(_LoadLanguage value)? loadLanguage, + }) { + return loadLanguage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ChangeLanguage value)? changeLanguage, + TResult Function(_LoadLanguage value)? loadLanguage, + required TResult orElse(), + }) { + if (loadLanguage != null) { + return loadLanguage(this); + } + return orElse(); + } +} + +abstract class _LoadLanguage implements LanguageEvent { + const factory _LoadLanguage() = _$LoadLanguageImpl; +} + +/// @nodoc +mixin _$LanguageState { + Language get language => throw _privateConstructorUsedError; + + /// Create a copy of LanguageState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LanguageStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LanguageStateCopyWith<$Res> { + factory $LanguageStateCopyWith( + LanguageState value, + $Res Function(LanguageState) then, + ) = _$LanguageStateCopyWithImpl<$Res, LanguageState>; + @useResult + $Res call({Language language}); + + $LanguageCopyWith<$Res> get language; +} + +/// @nodoc +class _$LanguageStateCopyWithImpl<$Res, $Val extends LanguageState> + implements $LanguageStateCopyWith<$Res> { + _$LanguageStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LanguageState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? language = null}) { + return _then( + _value.copyWith( + language: null == language + ? _value.language + : language // ignore: cast_nullable_to_non_nullable + as Language, + ) + as $Val, + ); + } + + /// Create a copy of LanguageState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LanguageCopyWith<$Res> get language { + return $LanguageCopyWith<$Res>(_value.language, (value) { + return _then(_value.copyWith(language: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$LanguageStateImplCopyWith<$Res> + implements $LanguageStateCopyWith<$Res> { + factory _$$LanguageStateImplCopyWith( + _$LanguageStateImpl value, + $Res Function(_$LanguageStateImpl) then, + ) = __$$LanguageStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({Language language}); + + @override + $LanguageCopyWith<$Res> get language; +} + +/// @nodoc +class __$$LanguageStateImplCopyWithImpl<$Res> + extends _$LanguageStateCopyWithImpl<$Res, _$LanguageStateImpl> + implements _$$LanguageStateImplCopyWith<$Res> { + __$$LanguageStateImplCopyWithImpl( + _$LanguageStateImpl _value, + $Res Function(_$LanguageStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of LanguageState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? language = null}) { + return _then( + _$LanguageStateImpl( + language: null == language + ? _value.language + : language // ignore: cast_nullable_to_non_nullable + as Language, + ), + ); + } +} + +/// @nodoc + +class _$LanguageStateImpl implements _LanguageState { + const _$LanguageStateImpl({required this.language}); + + @override + final Language language; + + @override + String toString() { + return 'LanguageState(language: $language)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LanguageStateImpl && + (identical(other.language, language) || + other.language == language)); + } + + @override + int get hashCode => Object.hash(runtimeType, language); + + /// Create a copy of LanguageState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LanguageStateImplCopyWith<_$LanguageStateImpl> get copyWith => + __$$LanguageStateImplCopyWithImpl<_$LanguageStateImpl>(this, _$identity); +} + +abstract class _LanguageState implements LanguageState { + const factory _LanguageState({required final Language language}) = + _$LanguageStateImpl; + + @override + Language get language; + + /// Create a copy of LanguageState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LanguageStateImplCopyWith<_$LanguageStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/language/language_event.dart b/lib/application/language/language_event.dart new file mode 100644 index 0000000..08374c7 --- /dev/null +++ b/lib/application/language/language_event.dart @@ -0,0 +1,8 @@ +part of 'language_bloc.dart'; + +@freezed +class LanguageEvent with _$LanguageEvent { + const factory LanguageEvent.changeLanguage(Language language) = + _ChangeLanguage; + const factory LanguageEvent.loadLanguage() = _LoadLanguage; +} diff --git a/lib/application/language/language_state.dart b/lib/application/language/language_state.dart new file mode 100644 index 0000000..df17325 --- /dev/null +++ b/lib/application/language/language_state.dart @@ -0,0 +1,9 @@ +part of 'language_bloc.dart'; + +@freezed +abstract class LanguageState with _$LanguageState { + const factory LanguageState({required Language language}) = _LanguageState; + + factory LanguageState.initial() => + LanguageState(language: Language.indonesian()); +} diff --git a/lib/application/order/order_loader/order_loader_bloc.dart b/lib/application/order/order_loader/order_loader_bloc.dart new file mode 100644 index 0000000..6f39707 --- /dev/null +++ b/lib/application/order/order_loader/order_loader_bloc.dart @@ -0,0 +1,99 @@ +import 'package:dartz/dartz.dart' hide Order; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart' hide Order; + +import '../../../domain/order/order.dart'; + +part 'order_loader_event.dart'; +part 'order_loader_state.dart'; +part 'order_loader_bloc.freezed.dart'; + +@injectable +class OrderLoaderBloc extends Bloc { + final IOrderRepository _repository; + OrderLoaderBloc(this._repository) : super(OrderLoaderState.initial()) { + on(_onOrderLoaderEvent); + } + + Future _onOrderLoaderEvent( + OrderLoaderEvent event, + Emitter emit, + ) { + return event.map( + rangeDateChanged: (e) async { + emit(state.copyWith(dateFrom: e.dateFrom, dateTo: e.dateTo)); + }, + statusChanged: (e) async { + emit(state.copyWith(status: e.status)); + }, + searchChanged: (e) async { + emit(state.copyWith(search: e.search)); + }, + outletChanged: (e) async { + emit(state.copyWith(outletId: e.outletId)); + }, + fetched: (e) async { + var newState = state; + + if (e.isRefresh) { + newState = state.copyWith(isFetching: true); + + emit(newState); + } + + newState = await _mapFetchedToState(state, isRefresh: e.isRefresh); + + emit(newState); + }, + ); + } + + Future _mapFetchedToState( + OrderLoaderState state, { + bool isRefresh = false, + }) async { + state = state.copyWith(isFetching: false); + + if (state.hasReachedMax && state.orders.isNotEmpty && !isRefresh) { + return state; + } + + if (isRefresh) { + state = state.copyWith( + page: 1, + failureOptionOrder: none(), + hasReachedMax: false, + orders: [], + ); + } + + final failureOrOrder = await _repository.get( + status: state.status == 'all' ? null : state.status, + page: state.page, + search: state.search, + outletId: state.outletId, + dateFrom: state.dateFrom, + dateTo: state.dateTo, + ); + + state = failureOrOrder.fold( + (f) { + if (state.orders.isNotEmpty) { + return state.copyWith(hasReachedMax: true); + } + return state.copyWith(failureOptionOrder: optionOf(f)); + }, + (orders) { + return state.copyWith( + orders: List.from(state.orders)..addAll(orders), + failureOptionOrder: none(), + page: state.page + 1, + hasReachedMax: orders.length < 10, + ); + }, + ); + + return state; + } +} diff --git a/lib/application/order/order_loader/order_loader_bloc.freezed.dart b/lib/application/order/order_loader/order_loader_bloc.freezed.dart new file mode 100644 index 0000000..5ac54a8 --- /dev/null +++ b/lib/application/order/order_loader/order_loader_bloc.freezed.dart @@ -0,0 +1,1270 @@ +// 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 'order_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$OrderLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function(String status) statusChanged, + required TResult Function(String search) searchChanged, + required TResult Function(String? outletId) outletChanged, + required TResult Function(bool isRefresh) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function(String status)? statusChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(String? outletId)? outletChanged, + TResult? Function(bool isRefresh)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function(String status)? statusChanged, + TResult Function(String search)? searchChanged, + TResult Function(String? outletId)? outletChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_StatusChanged value) statusChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_OutletChanged value) outletChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_StatusChanged value)? statusChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_OutletChanged value)? outletChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_StatusChanged value)? statusChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_OutletChanged value)? outletChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderLoaderEventCopyWith<$Res> { + factory $OrderLoaderEventCopyWith( + OrderLoaderEvent value, + $Res Function(OrderLoaderEvent) then, + ) = _$OrderLoaderEventCopyWithImpl<$Res, OrderLoaderEvent>; +} + +/// @nodoc +class _$OrderLoaderEventCopyWithImpl<$Res, $Val extends OrderLoaderEvent> + implements $OrderLoaderEventCopyWith<$Res> { + _$OrderLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderLoaderEvent + /// 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 _$OrderLoaderEventCopyWithImpl<$Res, _$RangeDateChangedImpl> + implements _$$RangeDateChangedImplCopyWith<$Res> { + __$$RangeDateChangedImplCopyWithImpl( + _$RangeDateChangedImpl _value, + $Res Function(_$RangeDateChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderLoaderEvent + /// 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 'OrderLoaderEvent.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 OrderLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function(String status) statusChanged, + required TResult Function(String search) searchChanged, + required TResult Function(String? outletId) outletChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return rangeDateChanged(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function(String status)? statusChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(String? outletId)? outletChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return rangeDateChanged?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function(String status)? statusChanged, + TResult Function(String search)? searchChanged, + TResult Function(String? outletId)? outletChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_StatusChanged value) statusChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_OutletChanged value) outletChanged, + required TResult Function(_Fetched value) fetched, + }) { + return rangeDateChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_StatusChanged value)? statusChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_OutletChanged value)? outletChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return rangeDateChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_StatusChanged value)? statusChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_OutletChanged value)? outletChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (rangeDateChanged != null) { + return rangeDateChanged(this); + } + return orElse(); + } +} + +abstract class _RangeDateChanged implements OrderLoaderEvent { + const factory _RangeDateChanged( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$RangeDateChangedImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of OrderLoaderEvent + /// 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 _$$StatusChangedImplCopyWith<$Res> { + factory _$$StatusChangedImplCopyWith( + _$StatusChangedImpl value, + $Res Function(_$StatusChangedImpl) then, + ) = __$$StatusChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String status}); +} + +/// @nodoc +class __$$StatusChangedImplCopyWithImpl<$Res> + extends _$OrderLoaderEventCopyWithImpl<$Res, _$StatusChangedImpl> + implements _$$StatusChangedImplCopyWith<$Res> { + __$$StatusChangedImplCopyWithImpl( + _$StatusChangedImpl _value, + $Res Function(_$StatusChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? status = null}) { + return _then( + _$StatusChangedImpl( + null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$StatusChangedImpl implements _StatusChanged { + const _$StatusChangedImpl(this.status); + + @override + final String status; + + @override + String toString() { + return 'OrderLoaderEvent.statusChanged(status: $status)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$StatusChangedImpl && + (identical(other.status, status) || other.status == status)); + } + + @override + int get hashCode => Object.hash(runtimeType, status); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$StatusChangedImplCopyWith<_$StatusChangedImpl> get copyWith => + __$$StatusChangedImplCopyWithImpl<_$StatusChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function(String status) statusChanged, + required TResult Function(String search) searchChanged, + required TResult Function(String? outletId) outletChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return statusChanged(status); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function(String status)? statusChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(String? outletId)? outletChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return statusChanged?.call(status); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function(String status)? statusChanged, + TResult Function(String search)? searchChanged, + TResult Function(String? outletId)? outletChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (statusChanged != null) { + return statusChanged(status); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_StatusChanged value) statusChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_OutletChanged value) outletChanged, + required TResult Function(_Fetched value) fetched, + }) { + return statusChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_StatusChanged value)? statusChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_OutletChanged value)? outletChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return statusChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_StatusChanged value)? statusChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_OutletChanged value)? outletChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (statusChanged != null) { + return statusChanged(this); + } + return orElse(); + } +} + +abstract class _StatusChanged implements OrderLoaderEvent { + const factory _StatusChanged(final String status) = _$StatusChangedImpl; + + String get status; + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$StatusChangedImplCopyWith<_$StatusChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$SearchChangedImplCopyWith<$Res> { + factory _$$SearchChangedImplCopyWith( + _$SearchChangedImpl value, + $Res Function(_$SearchChangedImpl) then, + ) = __$$SearchChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String search}); +} + +/// @nodoc +class __$$SearchChangedImplCopyWithImpl<$Res> + extends _$OrderLoaderEventCopyWithImpl<$Res, _$SearchChangedImpl> + implements _$$SearchChangedImplCopyWith<$Res> { + __$$SearchChangedImplCopyWithImpl( + _$SearchChangedImpl _value, + $Res Function(_$SearchChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? search = null}) { + return _then( + _$SearchChangedImpl( + null == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$SearchChangedImpl implements _SearchChanged { + const _$SearchChangedImpl(this.search); + + @override + final String search; + + @override + String toString() { + return 'OrderLoaderEvent.searchChanged(search: $search)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SearchChangedImpl && + (identical(other.search, search) || other.search == search)); + } + + @override + int get hashCode => Object.hash(runtimeType, search); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + __$$SearchChangedImplCopyWithImpl<_$SearchChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function(String status) statusChanged, + required TResult Function(String search) searchChanged, + required TResult Function(String? outletId) outletChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return searchChanged(search); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function(String status)? statusChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(String? outletId)? outletChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return searchChanged?.call(search); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function(String status)? statusChanged, + TResult Function(String search)? searchChanged, + TResult Function(String? outletId)? outletChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(search); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_StatusChanged value) statusChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_OutletChanged value) outletChanged, + required TResult Function(_Fetched value) fetched, + }) { + return searchChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_StatusChanged value)? statusChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_OutletChanged value)? outletChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return searchChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_StatusChanged value)? statusChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_OutletChanged value)? outletChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(this); + } + return orElse(); + } +} + +abstract class _SearchChanged implements OrderLoaderEvent { + const factory _SearchChanged(final String search) = _$SearchChangedImpl; + + String get search; + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$OutletChangedImplCopyWith<$Res> { + factory _$$OutletChangedImplCopyWith( + _$OutletChangedImpl value, + $Res Function(_$OutletChangedImpl) then, + ) = __$$OutletChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String? outletId}); +} + +/// @nodoc +class __$$OutletChangedImplCopyWithImpl<$Res> + extends _$OrderLoaderEventCopyWithImpl<$Res, _$OutletChangedImpl> + implements _$$OutletChangedImplCopyWith<$Res> { + __$$OutletChangedImplCopyWithImpl( + _$OutletChangedImpl _value, + $Res Function(_$OutletChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? outletId = freezed}) { + return _then( + _$OutletChangedImpl( + freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc + +class _$OutletChangedImpl implements _OutletChanged { + const _$OutletChangedImpl(this.outletId); + + @override + final String? outletId; + + @override + String toString() { + return 'OrderLoaderEvent.outletChanged(outletId: $outletId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OutletChangedImpl && + (identical(other.outletId, outletId) || + other.outletId == outletId)); + } + + @override + int get hashCode => Object.hash(runtimeType, outletId); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OutletChangedImplCopyWith<_$OutletChangedImpl> get copyWith => + __$$OutletChangedImplCopyWithImpl<_$OutletChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function(String status) statusChanged, + required TResult Function(String search) searchChanged, + required TResult Function(String? outletId) outletChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return outletChanged(outletId); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function(String status)? statusChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(String? outletId)? outletChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return outletChanged?.call(outletId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function(String status)? statusChanged, + TResult Function(String search)? searchChanged, + TResult Function(String? outletId)? outletChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (outletChanged != null) { + return outletChanged(outletId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_StatusChanged value) statusChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_OutletChanged value) outletChanged, + required TResult Function(_Fetched value) fetched, + }) { + return outletChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_StatusChanged value)? statusChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_OutletChanged value)? outletChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return outletChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_StatusChanged value)? statusChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_OutletChanged value)? outletChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (outletChanged != null) { + return outletChanged(this); + } + return orElse(); + } +} + +abstract class _OutletChanged implements OrderLoaderEvent { + const factory _OutletChanged(final String? outletId) = _$OutletChangedImpl; + + String? get outletId; + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OutletChangedImplCopyWith<_$OutletChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; + @useResult + $Res call({bool isRefresh}); +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$OrderLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? isRefresh = null}) { + return _then( + _$FetchedImpl( + isRefresh: null == isRefresh + ? _value.isRefresh + : isRefresh // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl({this.isRefresh = false}); + + @override + @JsonKey() + final bool isRefresh; + + @override + String toString() { + return 'OrderLoaderEvent.fetched(isRefresh: $isRefresh)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FetchedImpl && + (identical(other.isRefresh, isRefresh) || + other.isRefresh == isRefresh)); + } + + @override + int get hashCode => Object.hash(runtimeType, isRefresh); + + /// Create a copy of OrderLoaderEvent + /// 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({ + required TResult Function(DateTime dateFrom, DateTime dateTo) + rangeDateChanged, + required TResult Function(String status) statusChanged, + required TResult Function(String search) searchChanged, + required TResult Function(String? outletId) outletChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return fetched(isRefresh); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult? Function(String status)? statusChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(String? outletId)? outletChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return fetched?.call(isRefresh); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(DateTime dateFrom, DateTime dateTo)? rangeDateChanged, + TResult Function(String status)? statusChanged, + TResult Function(String search)? searchChanged, + TResult Function(String? outletId)? outletChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(isRefresh); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_RangeDateChanged value) rangeDateChanged, + required TResult Function(_StatusChanged value) statusChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_OutletChanged value) outletChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_RangeDateChanged value)? rangeDateChanged, + TResult? Function(_StatusChanged value)? statusChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_OutletChanged value)? outletChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_RangeDateChanged value)? rangeDateChanged, + TResult Function(_StatusChanged value)? statusChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_OutletChanged value)? outletChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements OrderLoaderEvent { + const factory _Fetched({final bool isRefresh}) = _$FetchedImpl; + + bool get isRefresh; + + /// Create a copy of OrderLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FetchedImplCopyWith<_$FetchedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$OrderLoaderState { + List get orders => throw _privateConstructorUsedError; + Option get failureOptionOrder => + throw _privateConstructorUsedError; + String get status => throw _privateConstructorUsedError; + String? get search => throw _privateConstructorUsedError; + String? get outletId => throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + bool get hasReachedMax => throw _privateConstructorUsedError; + int get page => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + + /// Create a copy of OrderLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderLoaderStateCopyWith<$Res> { + factory $OrderLoaderStateCopyWith( + OrderLoaderState value, + $Res Function(OrderLoaderState) then, + ) = _$OrderLoaderStateCopyWithImpl<$Res, OrderLoaderState>; + @useResult + $Res call({ + List orders, + Option failureOptionOrder, + String status, + String? search, + String? outletId, + bool isFetching, + bool hasReachedMax, + int page, + DateTime dateFrom, + DateTime dateTo, + }); +} + +/// @nodoc +class _$OrderLoaderStateCopyWithImpl<$Res, $Val extends OrderLoaderState> + implements $OrderLoaderStateCopyWith<$Res> { + _$OrderLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? orders = null, + Object? failureOptionOrder = null, + Object? status = null, + Object? search = freezed, + Object? outletId = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _value.copyWith( + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as List, + failureOptionOrder: null == failureOptionOrder + ? _value.failureOptionOrder + : failureOptionOrder // ignore: cast_nullable_to_non_nullable + as Option, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + 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, + ); + } +} + +/// @nodoc +abstract class _$$OrderLoaderStateImplCopyWith<$Res> + implements $OrderLoaderStateCopyWith<$Res> { + factory _$$OrderLoaderStateImplCopyWith( + _$OrderLoaderStateImpl value, + $Res Function(_$OrderLoaderStateImpl) then, + ) = __$$OrderLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + List orders, + Option failureOptionOrder, + String status, + String? search, + String? outletId, + bool isFetching, + bool hasReachedMax, + int page, + DateTime dateFrom, + DateTime dateTo, + }); +} + +/// @nodoc +class __$$OrderLoaderStateImplCopyWithImpl<$Res> + extends _$OrderLoaderStateCopyWithImpl<$Res, _$OrderLoaderStateImpl> + implements _$$OrderLoaderStateImplCopyWith<$Res> { + __$$OrderLoaderStateImplCopyWithImpl( + _$OrderLoaderStateImpl _value, + $Res Function(_$OrderLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? orders = null, + Object? failureOptionOrder = null, + Object? status = null, + Object? search = freezed, + Object? outletId = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + Object? dateFrom = null, + Object? dateTo = null, + }) { + return _then( + _$OrderLoaderStateImpl( + orders: null == orders + ? _value._orders + : orders // ignore: cast_nullable_to_non_nullable + as List, + failureOptionOrder: null == failureOptionOrder + ? _value.failureOptionOrder + : failureOptionOrder // ignore: cast_nullable_to_non_nullable + as Option, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + 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 _$OrderLoaderStateImpl implements _OrderLoaderState { + const _$OrderLoaderStateImpl({ + required final List orders, + required this.failureOptionOrder, + required this.status, + this.search, + this.outletId, + this.isFetching = false, + this.hasReachedMax = false, + this.page = 1, + required this.dateFrom, + required this.dateTo, + }) : _orders = orders; + + final List _orders; + @override + List get orders { + if (_orders is EqualUnmodifiableListView) return _orders; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_orders); + } + + @override + final Option failureOptionOrder; + @override + final String status; + @override + final String? search; + @override + final String? outletId; + @override + @JsonKey() + final bool isFetching; + @override + @JsonKey() + final bool hasReachedMax; + @override + @JsonKey() + final int page; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'OrderLoaderState(orders: $orders, failureOptionOrder: $failureOptionOrder, status: $status, search: $search, outletId: $outletId, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page, dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderLoaderStateImpl && + const DeepCollectionEquality().equals(other._orders, _orders) && + (identical(other.failureOptionOrder, failureOptionOrder) || + other.failureOptionOrder == failureOptionOrder) && + (identical(other.status, status) || other.status == status) && + (identical(other.search, search) || other.search == search) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.hasReachedMax, hasReachedMax) || + other.hasReachedMax == hasReachedMax) && + (identical(other.page, page) || other.page == page) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_orders), + failureOptionOrder, + status, + search, + outletId, + isFetching, + hasReachedMax, + page, + dateFrom, + dateTo, + ); + + /// Create a copy of OrderLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderLoaderStateImplCopyWith<_$OrderLoaderStateImpl> get copyWith => + __$$OrderLoaderStateImplCopyWithImpl<_$OrderLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _OrderLoaderState implements OrderLoaderState { + const factory _OrderLoaderState({ + required final List orders, + required final Option failureOptionOrder, + required final String status, + final String? search, + final String? outletId, + final bool isFetching, + final bool hasReachedMax, + final int page, + required final DateTime dateFrom, + required final DateTime dateTo, + }) = _$OrderLoaderStateImpl; + + @override + List get orders; + @override + Option get failureOptionOrder; + @override + String get status; + @override + String? get search; + @override + String? get outletId; + @override + bool get isFetching; + @override + bool get hasReachedMax; + @override + int get page; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + + /// Create a copy of OrderLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderLoaderStateImplCopyWith<_$OrderLoaderStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/order/order_loader/order_loader_event.dart b/lib/application/order/order_loader/order_loader_event.dart new file mode 100644 index 0000000..615c66f --- /dev/null +++ b/lib/application/order/order_loader/order_loader_event.dart @@ -0,0 +1,15 @@ +part of 'order_loader_bloc.dart'; + +@freezed +class OrderLoaderEvent with _$OrderLoaderEvent { + const factory OrderLoaderEvent.rangeDateChanged( + DateTime dateFrom, + DateTime dateTo, + ) = _RangeDateChanged; + const factory OrderLoaderEvent.statusChanged(String status) = _StatusChanged; + const factory OrderLoaderEvent.searchChanged(String search) = _SearchChanged; + const factory OrderLoaderEvent.outletChanged(String? outletId) = + _OutletChanged; + const factory OrderLoaderEvent.fetched({@Default(false) bool isRefresh}) = + _Fetched; +} diff --git a/lib/application/order/order_loader/order_loader_state.dart b/lib/application/order/order_loader/order_loader_state.dart new file mode 100644 index 0000000..fdce154 --- /dev/null +++ b/lib/application/order/order_loader/order_loader_state.dart @@ -0,0 +1,25 @@ +part of 'order_loader_bloc.dart'; + +@freezed +class OrderLoaderState with _$OrderLoaderState { + const factory OrderLoaderState({ + required List orders, + required Option failureOptionOrder, + required String status, + String? search, + String? outletId, + @Default(false) bool isFetching, + @Default(false) bool hasReachedMax, + @Default(1) int page, + required DateTime dateFrom, + required DateTime dateTo, + }) = _OrderLoaderState; + + factory OrderLoaderState.initial() => OrderLoaderState( + orders: [], + failureOptionOrder: none(), + dateFrom: DateTime.now(), + dateTo: DateTime.now(), + status: 'all', + ); +} diff --git a/lib/application/outlet/current_outlet_loader/current_outlet_loader_bloc.dart b/lib/application/outlet/current_outlet_loader/current_outlet_loader_bloc.dart new file mode 100644 index 0000000..943ed23 --- /dev/null +++ b/lib/application/outlet/current_outlet_loader/current_outlet_loader_bloc.dart @@ -0,0 +1,40 @@ +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/outlet/outlet.dart'; + +part 'current_outlet_loader_event.dart'; +part 'current_outlet_loader_state.dart'; +part 'current_outlet_loader_bloc.freezed.dart'; + +@injectable +class CurrentOutletLoaderBloc + extends Bloc { + final IOutletRepository _repository; + CurrentOutletLoaderBloc(this._repository) + : super(CurrentOutletLoaderState.initial()) { + on(_onCurrentOutletLoaderEvent); + } + + Future _onCurrentOutletLoaderEvent( + CurrentOutletLoaderEvent event, + Emitter emit, + ) { + return event.map( + fetched: (e) async { + emit(state.copyWith(isFetching: true, failureOptionOutlet: none())); + + final result = await _repository.currentOutlet(); + + var data = result.fold( + (f) => state.copyWith(failureOptionOutlet: optionOf(f)), + (currentOutlet) => state.copyWith(outlet: currentOutlet), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/outlet/current_outlet_loader/current_outlet_loader_bloc.freezed.dart b/lib/application/outlet/current_outlet_loader/current_outlet_loader_bloc.freezed.dart new file mode 100644 index 0000000..e78ce9f --- /dev/null +++ b/lib/application/outlet/current_outlet_loader/current_outlet_loader_bloc.freezed.dart @@ -0,0 +1,382 @@ +// 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 'current_outlet_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$CurrentOutletLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CurrentOutletLoaderEventCopyWith<$Res> { + factory $CurrentOutletLoaderEventCopyWith( + CurrentOutletLoaderEvent value, + $Res Function(CurrentOutletLoaderEvent) then, + ) = _$CurrentOutletLoaderEventCopyWithImpl<$Res, CurrentOutletLoaderEvent>; +} + +/// @nodoc +class _$CurrentOutletLoaderEventCopyWithImpl< + $Res, + $Val extends CurrentOutletLoaderEvent +> + implements $CurrentOutletLoaderEventCopyWith<$Res> { + _$CurrentOutletLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CurrentOutletLoaderEvent + /// 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>; +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$CurrentOutletLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CurrentOutletLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl(); + + @override + String toString() { + return 'CurrentOutletLoaderEvent.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({required TResult Function() fetched}) { + return fetched(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({TResult? Function()? fetched}) { + return fetched?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements CurrentOutletLoaderEvent { + const factory _Fetched() = _$FetchedImpl; +} + +/// @nodoc +mixin _$CurrentOutletLoaderState { + Outlet get outlet => throw _privateConstructorUsedError; + Option get failureOptionOutlet => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + + /// Create a copy of CurrentOutletLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CurrentOutletLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CurrentOutletLoaderStateCopyWith<$Res> { + factory $CurrentOutletLoaderStateCopyWith( + CurrentOutletLoaderState value, + $Res Function(CurrentOutletLoaderState) then, + ) = _$CurrentOutletLoaderStateCopyWithImpl<$Res, CurrentOutletLoaderState>; + @useResult + $Res call({ + Outlet outlet, + Option failureOptionOutlet, + bool isFetching, + }); + + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class _$CurrentOutletLoaderStateCopyWithImpl< + $Res, + $Val extends CurrentOutletLoaderState +> + implements $CurrentOutletLoaderStateCopyWith<$Res> { + _$CurrentOutletLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CurrentOutletLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? outlet = null, + Object? failureOptionOutlet = null, + Object? isFetching = null, + }) { + return _then( + _value.copyWith( + outlet: null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of CurrentOutletLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $OutletCopyWith<$Res> get outlet { + return $OutletCopyWith<$Res>(_value.outlet, (value) { + return _then(_value.copyWith(outlet: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$CurrentOutletLoaderStateImplCopyWith<$Res> + implements $CurrentOutletLoaderStateCopyWith<$Res> { + factory _$$CurrentOutletLoaderStateImplCopyWith( + _$CurrentOutletLoaderStateImpl value, + $Res Function(_$CurrentOutletLoaderStateImpl) then, + ) = __$$CurrentOutletLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + Outlet outlet, + Option failureOptionOutlet, + bool isFetching, + }); + + @override + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class __$$CurrentOutletLoaderStateImplCopyWithImpl<$Res> + extends + _$CurrentOutletLoaderStateCopyWithImpl< + $Res, + _$CurrentOutletLoaderStateImpl + > + implements _$$CurrentOutletLoaderStateImplCopyWith<$Res> { + __$$CurrentOutletLoaderStateImplCopyWithImpl( + _$CurrentOutletLoaderStateImpl _value, + $Res Function(_$CurrentOutletLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CurrentOutletLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? outlet = null, + Object? failureOptionOutlet = null, + Object? isFetching = null, + }) { + return _then( + _$CurrentOutletLoaderStateImpl( + outlet: null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$CurrentOutletLoaderStateImpl implements _CurrentOutletLoaderState { + const _$CurrentOutletLoaderStateImpl({ + required this.outlet, + required this.failureOptionOutlet, + this.isFetching = false, + }); + + @override + final Outlet outlet; + @override + final Option failureOptionOutlet; + @override + @JsonKey() + final bool isFetching; + + @override + String toString() { + return 'CurrentOutletLoaderState(outlet: $outlet, failureOptionOutlet: $failureOptionOutlet, isFetching: $isFetching)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CurrentOutletLoaderStateImpl && + (identical(other.outlet, outlet) || other.outlet == outlet) && + (identical(other.failureOptionOutlet, failureOptionOutlet) || + other.failureOptionOutlet == failureOptionOutlet) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching)); + } + + @override + int get hashCode => + Object.hash(runtimeType, outlet, failureOptionOutlet, isFetching); + + /// Create a copy of CurrentOutletLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CurrentOutletLoaderStateImplCopyWith<_$CurrentOutletLoaderStateImpl> + get copyWith => + __$$CurrentOutletLoaderStateImplCopyWithImpl< + _$CurrentOutletLoaderStateImpl + >(this, _$identity); +} + +abstract class _CurrentOutletLoaderState implements CurrentOutletLoaderState { + const factory _CurrentOutletLoaderState({ + required final Outlet outlet, + required final Option failureOptionOutlet, + final bool isFetching, + }) = _$CurrentOutletLoaderStateImpl; + + @override + Outlet get outlet; + @override + Option get failureOptionOutlet; + @override + bool get isFetching; + + /// Create a copy of CurrentOutletLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CurrentOutletLoaderStateImplCopyWith<_$CurrentOutletLoaderStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/outlet/current_outlet_loader/current_outlet_loader_event.dart b/lib/application/outlet/current_outlet_loader/current_outlet_loader_event.dart new file mode 100644 index 0000000..4a536c8 --- /dev/null +++ b/lib/application/outlet/current_outlet_loader/current_outlet_loader_event.dart @@ -0,0 +1,6 @@ +part of 'current_outlet_loader_bloc.dart'; + +@freezed +class CurrentOutletLoaderEvent with _$CurrentOutletLoaderEvent { + const factory CurrentOutletLoaderEvent.fetched() = _Fetched; +} diff --git a/lib/application/outlet/current_outlet_loader/current_outlet_loader_state.dart b/lib/application/outlet/current_outlet_loader/current_outlet_loader_state.dart new file mode 100644 index 0000000..658ef89 --- /dev/null +++ b/lib/application/outlet/current_outlet_loader/current_outlet_loader_state.dart @@ -0,0 +1,15 @@ +part of 'current_outlet_loader_bloc.dart'; + +@freezed +class CurrentOutletLoaderState with _$CurrentOutletLoaderState { + const factory CurrentOutletLoaderState({ + required Outlet outlet, + required Option failureOptionOutlet, + @Default(false) bool isFetching, + }) = _CurrentOutletLoaderState; + + factory CurrentOutletLoaderState.initial() => CurrentOutletLoaderState( + outlet: Outlet.empty(), + failureOptionOutlet: none(), + ); +} diff --git a/lib/application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart b/lib/application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart new file mode 100644 index 0000000..4b8ea49 --- /dev/null +++ b/lib/application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart @@ -0,0 +1,92 @@ +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/outlet/outlet.dart'; + +part 'outlet_list_loader_event.dart'; +part 'outlet_list_loader_state.dart'; +part 'outlet_list_loader_bloc.freezed.dart'; + +@injectable +class OutletListLoaderBloc + extends Bloc { + final IOutletRepository _outletRepository; + + OutletListLoaderBloc(this._outletRepository) + : super(OutletListLoaderState.initial()) { + on(_onOutletListLoaderEvent); + } + + Future _onOutletListLoaderEvent( + OutletListLoaderEvent event, + Emitter emit, + ) { + return event.map( + searchChanged: (e) async { + emit(state.copyWith(search: e.search)); + }, + isActiveChanged: (e) async { + emit(state.copyWith(isActive: e.isActive)); + }, + fetched: (e) async { + var newState = state; + + if (e.isRefresh) { + newState = state.copyWith(isFetching: true); + emit(newState); + } + + newState = await _mapFetchedToState(state, isRefresh: e.isRefresh); + + emit(newState); + }, + ); + } + + Future _mapFetchedToState( + OutletListLoaderState state, { + bool isRefresh = false, + }) async { + state = state.copyWith(isFetching: false); + + if (state.hasReachedMax && state.outlets.isNotEmpty && !isRefresh) { + return state; + } + + if (isRefresh) { + state = state.copyWith( + page: 1, + failureOptionOutlet: none(), + hasReachedMax: false, + outlets: [], + ); + } + + final failureOrOutlets = await _outletRepository.getList( + page: state.page, + search: state.search, + isActive: state.isActive, + ); + + state = failureOrOutlets.fold( + (f) { + if (state.outlets.isNotEmpty) { + return state.copyWith(hasReachedMax: true); + } + return state.copyWith(failureOptionOutlet: optionOf(f)); + }, + (outlets) { + return state.copyWith( + outlets: List.from(state.outlets)..addAll(outlets), + failureOptionOutlet: none(), + page: state.page + 1, + hasReachedMax: outlets.length < 10, + ); + }, + ); + + return state; + } +} diff --git a/lib/application/outlet/outlet_list_loader/outlet_list_loader_bloc.freezed.dart b/lib/application/outlet/outlet_list_loader/outlet_list_loader_bloc.freezed.dart new file mode 100644 index 0000000..65436de --- /dev/null +++ b/lib/application/outlet/outlet_list_loader/outlet_list_loader_bloc.freezed.dart @@ -0,0 +1,828 @@ +// 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 'outlet_list_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$OutletListLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String search) searchChanged, + required TResult Function(bool? isActive) isActiveChanged, + required TResult Function(bool isRefresh) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool? isActive)? isActiveChanged, + TResult? Function(bool isRefresh)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool? isActive)? isActiveChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_IsActiveChanged value) isActiveChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_IsActiveChanged value)? isActiveChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_IsActiveChanged value)? isActiveChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OutletListLoaderEventCopyWith<$Res> { + factory $OutletListLoaderEventCopyWith( + OutletListLoaderEvent value, + $Res Function(OutletListLoaderEvent) then, + ) = _$OutletListLoaderEventCopyWithImpl<$Res, OutletListLoaderEvent>; +} + +/// @nodoc +class _$OutletListLoaderEventCopyWithImpl< + $Res, + $Val extends OutletListLoaderEvent +> + implements $OutletListLoaderEventCopyWith<$Res> { + _$OutletListLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$SearchChangedImplCopyWith<$Res> { + factory _$$SearchChangedImplCopyWith( + _$SearchChangedImpl value, + $Res Function(_$SearchChangedImpl) then, + ) = __$$SearchChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String search}); +} + +/// @nodoc +class __$$SearchChangedImplCopyWithImpl<$Res> + extends _$OutletListLoaderEventCopyWithImpl<$Res, _$SearchChangedImpl> + implements _$$SearchChangedImplCopyWith<$Res> { + __$$SearchChangedImplCopyWithImpl( + _$SearchChangedImpl _value, + $Res Function(_$SearchChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? search = null}) { + return _then( + _$SearchChangedImpl( + null == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$SearchChangedImpl implements _SearchChanged { + const _$SearchChangedImpl(this.search); + + @override + final String search; + + @override + String toString() { + return 'OutletListLoaderEvent.searchChanged(search: $search)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SearchChangedImpl && + (identical(other.search, search) || other.search == search)); + } + + @override + int get hashCode => Object.hash(runtimeType, search); + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + __$$SearchChangedImplCopyWithImpl<_$SearchChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String search) searchChanged, + required TResult Function(bool? isActive) isActiveChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return searchChanged(search); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool? isActive)? isActiveChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return searchChanged?.call(search); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool? isActive)? isActiveChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(search); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_IsActiveChanged value) isActiveChanged, + required TResult Function(_Fetched value) fetched, + }) { + return searchChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_IsActiveChanged value)? isActiveChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return searchChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_IsActiveChanged value)? isActiveChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(this); + } + return orElse(); + } +} + +abstract class _SearchChanged implements OutletListLoaderEvent { + const factory _SearchChanged(final String search) = _$SearchChangedImpl; + + String get search; + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$IsActiveChangedImplCopyWith<$Res> { + factory _$$IsActiveChangedImplCopyWith( + _$IsActiveChangedImpl value, + $Res Function(_$IsActiveChangedImpl) then, + ) = __$$IsActiveChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({bool? isActive}); +} + +/// @nodoc +class __$$IsActiveChangedImplCopyWithImpl<$Res> + extends _$OutletListLoaderEventCopyWithImpl<$Res, _$IsActiveChangedImpl> + implements _$$IsActiveChangedImplCopyWith<$Res> { + __$$IsActiveChangedImplCopyWithImpl( + _$IsActiveChangedImpl _value, + $Res Function(_$IsActiveChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? isActive = freezed}) { + return _then( + _$IsActiveChangedImpl( + freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + ), + ); + } +} + +/// @nodoc + +class _$IsActiveChangedImpl implements _IsActiveChanged { + const _$IsActiveChangedImpl(this.isActive); + + @override + final bool? isActive; + + @override + String toString() { + return 'OutletListLoaderEvent.isActiveChanged(isActive: $isActive)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$IsActiveChangedImpl && + (identical(other.isActive, isActive) || + other.isActive == isActive)); + } + + @override + int get hashCode => Object.hash(runtimeType, isActive); + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$IsActiveChangedImplCopyWith<_$IsActiveChangedImpl> get copyWith => + __$$IsActiveChangedImplCopyWithImpl<_$IsActiveChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String search) searchChanged, + required TResult Function(bool? isActive) isActiveChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return isActiveChanged(isActive); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool? isActive)? isActiveChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return isActiveChanged?.call(isActive); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool? isActive)? isActiveChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (isActiveChanged != null) { + return isActiveChanged(isActive); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_IsActiveChanged value) isActiveChanged, + required TResult Function(_Fetched value) fetched, + }) { + return isActiveChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_IsActiveChanged value)? isActiveChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return isActiveChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_IsActiveChanged value)? isActiveChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (isActiveChanged != null) { + return isActiveChanged(this); + } + return orElse(); + } +} + +abstract class _IsActiveChanged implements OutletListLoaderEvent { + const factory _IsActiveChanged(final bool? isActive) = _$IsActiveChangedImpl; + + bool? get isActive; + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$IsActiveChangedImplCopyWith<_$IsActiveChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; + @useResult + $Res call({bool isRefresh}); +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$OutletListLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? isRefresh = null}) { + return _then( + _$FetchedImpl( + isRefresh: null == isRefresh + ? _value.isRefresh + : isRefresh // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl({this.isRefresh = false}); + + @override + @JsonKey() + final bool isRefresh; + + @override + String toString() { + return 'OutletListLoaderEvent.fetched(isRefresh: $isRefresh)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FetchedImpl && + (identical(other.isRefresh, isRefresh) || + other.isRefresh == isRefresh)); + } + + @override + int get hashCode => Object.hash(runtimeType, isRefresh); + + /// Create a copy of OutletListLoaderEvent + /// 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({ + required TResult Function(String search) searchChanged, + required TResult Function(bool? isActive) isActiveChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return fetched(isRefresh); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String search)? searchChanged, + TResult? Function(bool? isActive)? isActiveChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return fetched?.call(isRefresh); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String search)? searchChanged, + TResult Function(bool? isActive)? isActiveChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(isRefresh); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_IsActiveChanged value) isActiveChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_IsActiveChanged value)? isActiveChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_IsActiveChanged value)? isActiveChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements OutletListLoaderEvent { + const factory _Fetched({final bool isRefresh}) = _$FetchedImpl; + + bool get isRefresh; + + /// Create a copy of OutletListLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FetchedImplCopyWith<_$FetchedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$OutletListLoaderState { + List get outlets => throw _privateConstructorUsedError; + Option get failureOptionOutlet => + throw _privateConstructorUsedError; + String? get search => throw _privateConstructorUsedError; + bool? get isActive => throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + bool get hasReachedMax => throw _privateConstructorUsedError; + int get page => throw _privateConstructorUsedError; + + /// Create a copy of OutletListLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OutletListLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OutletListLoaderStateCopyWith<$Res> { + factory $OutletListLoaderStateCopyWith( + OutletListLoaderState value, + $Res Function(OutletListLoaderState) then, + ) = _$OutletListLoaderStateCopyWithImpl<$Res, OutletListLoaderState>; + @useResult + $Res call({ + List outlets, + Option failureOptionOutlet, + String? search, + bool? isActive, + bool isFetching, + bool hasReachedMax, + int page, + }); +} + +/// @nodoc +class _$OutletListLoaderStateCopyWithImpl< + $Res, + $Val extends OutletListLoaderState +> + implements $OutletListLoaderStateCopyWith<$Res> { + _$OutletListLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OutletListLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? outlets = null, + Object? failureOptionOutlet = null, + Object? search = freezed, + Object? isActive = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + }) { + return _then( + _value.copyWith( + outlets: null == outlets + ? _value.outlets + : outlets // ignore: cast_nullable_to_non_nullable + as List, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OutletListLoaderStateImplCopyWith<$Res> + implements $OutletListLoaderStateCopyWith<$Res> { + factory _$$OutletListLoaderStateImplCopyWith( + _$OutletListLoaderStateImpl value, + $Res Function(_$OutletListLoaderStateImpl) then, + ) = __$$OutletListLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + List outlets, + Option failureOptionOutlet, + String? search, + bool? isActive, + bool isFetching, + bool hasReachedMax, + int page, + }); +} + +/// @nodoc +class __$$OutletListLoaderStateImplCopyWithImpl<$Res> + extends + _$OutletListLoaderStateCopyWithImpl<$Res, _$OutletListLoaderStateImpl> + implements _$$OutletListLoaderStateImplCopyWith<$Res> { + __$$OutletListLoaderStateImplCopyWithImpl( + _$OutletListLoaderStateImpl _value, + $Res Function(_$OutletListLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletListLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? outlets = null, + Object? failureOptionOutlet = null, + Object? search = freezed, + Object? isActive = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + }) { + return _then( + _$OutletListLoaderStateImpl( + outlets: null == outlets + ? _value._outlets + : outlets // ignore: cast_nullable_to_non_nullable + as List, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$OutletListLoaderStateImpl implements _OutletListLoaderState { + const _$OutletListLoaderStateImpl({ + required final List outlets, + required this.failureOptionOutlet, + this.search, + this.isActive, + this.isFetching = false, + this.hasReachedMax = false, + this.page = 1, + }) : _outlets = outlets; + + final List _outlets; + @override + List get outlets { + if (_outlets is EqualUnmodifiableListView) return _outlets; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_outlets); + } + + @override + final Option failureOptionOutlet; + @override + final String? search; + @override + final bool? isActive; + @override + @JsonKey() + final bool isFetching; + @override + @JsonKey() + final bool hasReachedMax; + @override + @JsonKey() + final int page; + + @override + String toString() { + return 'OutletListLoaderState(outlets: $outlets, failureOptionOutlet: $failureOptionOutlet, search: $search, isActive: $isActive, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OutletListLoaderStateImpl && + const DeepCollectionEquality().equals(other._outlets, _outlets) && + (identical(other.failureOptionOutlet, failureOptionOutlet) || + other.failureOptionOutlet == failureOptionOutlet) && + (identical(other.search, search) || other.search == search) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.hasReachedMax, hasReachedMax) || + other.hasReachedMax == hasReachedMax) && + (identical(other.page, page) || other.page == page)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_outlets), + failureOptionOutlet, + search, + isActive, + isFetching, + hasReachedMax, + page, + ); + + /// Create a copy of OutletListLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OutletListLoaderStateImplCopyWith<_$OutletListLoaderStateImpl> + get copyWith => + __$$OutletListLoaderStateImplCopyWithImpl<_$OutletListLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _OutletListLoaderState implements OutletListLoaderState { + const factory _OutletListLoaderState({ + required final List outlets, + required final Option failureOptionOutlet, + final String? search, + final bool? isActive, + final bool isFetching, + final bool hasReachedMax, + final int page, + }) = _$OutletListLoaderStateImpl; + + @override + List get outlets; + @override + Option get failureOptionOutlet; + @override + String? get search; + @override + bool? get isActive; + @override + bool get isFetching; + @override + bool get hasReachedMax; + @override + int get page; + + /// Create a copy of OutletListLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OutletListLoaderStateImplCopyWith<_$OutletListLoaderStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/outlet/outlet_list_loader/outlet_list_loader_event.dart b/lib/application/outlet/outlet_list_loader/outlet_list_loader_event.dart new file mode 100644 index 0000000..4576c20 --- /dev/null +++ b/lib/application/outlet/outlet_list_loader/outlet_list_loader_event.dart @@ -0,0 +1,12 @@ +part of 'outlet_list_loader_bloc.dart'; + +@freezed +class OutletListLoaderEvent with _$OutletListLoaderEvent { + const factory OutletListLoaderEvent.searchChanged(String search) = + _SearchChanged; + const factory OutletListLoaderEvent.isActiveChanged(bool? isActive) = + _IsActiveChanged; + const factory OutletListLoaderEvent.fetched({ + @Default(false) bool isRefresh, + }) = _Fetched; +} diff --git a/lib/application/outlet/outlet_list_loader/outlet_list_loader_state.dart b/lib/application/outlet/outlet_list_loader/outlet_list_loader_state.dart new file mode 100644 index 0000000..9a699e1 --- /dev/null +++ b/lib/application/outlet/outlet_list_loader/outlet_list_loader_state.dart @@ -0,0 +1,17 @@ +part of 'outlet_list_loader_bloc.dart'; + +@freezed +class OutletListLoaderState with _$OutletListLoaderState { + const factory OutletListLoaderState({ + required List outlets, + required Option failureOptionOutlet, + String? search, + bool? isActive, + @Default(false) bool isFetching, + @Default(false) bool hasReachedMax, + @Default(1) int page, + }) = _OutletListLoaderState; + + factory OutletListLoaderState.initial() => + OutletListLoaderState(outlets: [], failureOptionOutlet: none()); +} diff --git a/lib/application/outlet/selected_outlet/selected_outlet_bloc.dart b/lib/application/outlet/selected_outlet/selected_outlet_bloc.dart new file mode 100644 index 0000000..77682f3 --- /dev/null +++ b/lib/application/outlet/selected_outlet/selected_outlet_bloc.dart @@ -0,0 +1,46 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/outlet/outlet.dart'; +import '../../../infrastructure/outlet/datasource/local_data_provider.dart'; + +part 'selected_outlet_event.dart'; +part 'selected_outlet_state.dart'; +part 'selected_outlet_bloc.freezed.dart'; + +@injectable +class SelectedOutletBloc + extends Bloc { + final OutletLocalDataProvider _localDataProvider; + + SelectedOutletBloc(this._localDataProvider) + : super(SelectedOutletState.initial()) { + on(_onSelectedOutletEvent); + } + + Future _onSelectedOutletEvent( + SelectedOutletEvent event, + Emitter emit, + ) { + return event.map( + loaded: (e) async { + final savedId = _localDataProvider.getSelectedOutletId(); + emit(state.copyWith(selectedOutletId: savedId)); + }, + selected: (e) async { + await _localDataProvider.saveSelectedOutletId(e.outlet.id); + emit( + state.copyWith( + selectedOutlet: e.outlet, + selectedOutletId: e.outlet.id, + ), + ); + }, + cleared: (e) async { + await _localDataProvider.deleteSelectedOutletId(); + emit(SelectedOutletState.initial()); + }, + ); + } +} diff --git a/lib/application/outlet/selected_outlet/selected_outlet_bloc.freezed.dart b/lib/application/outlet/selected_outlet/selected_outlet_bloc.freezed.dart new file mode 100644 index 0000000..634f59d --- /dev/null +++ b/lib/application/outlet/selected_outlet/selected_outlet_bloc.freezed.dart @@ -0,0 +1,649 @@ +// 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 'selected_outlet_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$SelectedOutletEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() loaded, + required TResult Function(Outlet outlet) selected, + required TResult Function() cleared, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loaded, + TResult? Function(Outlet outlet)? selected, + TResult? Function()? cleared, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loaded, + TResult Function(Outlet outlet)? selected, + TResult Function()? cleared, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_Loaded value) loaded, + required TResult Function(_Selected value) selected, + required TResult Function(_Cleared value) cleared, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Loaded value)? loaded, + TResult? Function(_Selected value)? selected, + TResult? Function(_Cleared value)? cleared, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Loaded value)? loaded, + TResult Function(_Selected value)? selected, + TResult Function(_Cleared value)? cleared, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SelectedOutletEventCopyWith<$Res> { + factory $SelectedOutletEventCopyWith( + SelectedOutletEvent value, + $Res Function(SelectedOutletEvent) then, + ) = _$SelectedOutletEventCopyWithImpl<$Res, SelectedOutletEvent>; +} + +/// @nodoc +class _$SelectedOutletEventCopyWithImpl<$Res, $Val extends SelectedOutletEvent> + implements $SelectedOutletEventCopyWith<$Res> { + _$SelectedOutletEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$LoadedImplCopyWith<$Res> { + factory _$$LoadedImplCopyWith( + _$LoadedImpl value, + $Res Function(_$LoadedImpl) then, + ) = __$$LoadedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$LoadedImplCopyWithImpl<$Res> + extends _$SelectedOutletEventCopyWithImpl<$Res, _$LoadedImpl> + implements _$$LoadedImplCopyWith<$Res> { + __$$LoadedImplCopyWithImpl( + _$LoadedImpl _value, + $Res Function(_$LoadedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$LoadedImpl implements _Loaded { + const _$LoadedImpl(); + + @override + String toString() { + return 'SelectedOutletEvent.loaded()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$LoadedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loaded, + required TResult Function(Outlet outlet) selected, + required TResult Function() cleared, + }) { + return loaded(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loaded, + TResult? Function(Outlet outlet)? selected, + TResult? Function()? cleared, + }) { + return loaded?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loaded, + TResult Function(Outlet outlet)? selected, + TResult Function()? cleared, + required TResult orElse(), + }) { + if (loaded != null) { + return loaded(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Loaded value) loaded, + required TResult Function(_Selected value) selected, + required TResult Function(_Cleared value) cleared, + }) { + return loaded(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Loaded value)? loaded, + TResult? Function(_Selected value)? selected, + TResult? Function(_Cleared value)? cleared, + }) { + return loaded?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Loaded value)? loaded, + TResult Function(_Selected value)? selected, + TResult Function(_Cleared value)? cleared, + required TResult orElse(), + }) { + if (loaded != null) { + return loaded(this); + } + return orElse(); + } +} + +abstract class _Loaded implements SelectedOutletEvent { + const factory _Loaded() = _$LoadedImpl; +} + +/// @nodoc +abstract class _$$SelectedImplCopyWith<$Res> { + factory _$$SelectedImplCopyWith( + _$SelectedImpl value, + $Res Function(_$SelectedImpl) then, + ) = __$$SelectedImplCopyWithImpl<$Res>; + @useResult + $Res call({Outlet outlet}); + + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class __$$SelectedImplCopyWithImpl<$Res> + extends _$SelectedOutletEventCopyWithImpl<$Res, _$SelectedImpl> + implements _$$SelectedImplCopyWith<$Res> { + __$$SelectedImplCopyWithImpl( + _$SelectedImpl _value, + $Res Function(_$SelectedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? outlet = null}) { + return _then( + _$SelectedImpl( + null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + ), + ); + } + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $OutletCopyWith<$Res> get outlet { + return $OutletCopyWith<$Res>(_value.outlet, (value) { + return _then(_value.copyWith(outlet: value)); + }); + } +} + +/// @nodoc + +class _$SelectedImpl implements _Selected { + const _$SelectedImpl(this.outlet); + + @override + final Outlet outlet; + + @override + String toString() { + return 'SelectedOutletEvent.selected(outlet: $outlet)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SelectedImpl && + (identical(other.outlet, outlet) || other.outlet == outlet)); + } + + @override + int get hashCode => Object.hash(runtimeType, outlet); + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SelectedImplCopyWith<_$SelectedImpl> get copyWith => + __$$SelectedImplCopyWithImpl<_$SelectedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loaded, + required TResult Function(Outlet outlet) selected, + required TResult Function() cleared, + }) { + return selected(outlet); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loaded, + TResult? Function(Outlet outlet)? selected, + TResult? Function()? cleared, + }) { + return selected?.call(outlet); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loaded, + TResult Function(Outlet outlet)? selected, + TResult Function()? cleared, + required TResult orElse(), + }) { + if (selected != null) { + return selected(outlet); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Loaded value) loaded, + required TResult Function(_Selected value) selected, + required TResult Function(_Cleared value) cleared, + }) { + return selected(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Loaded value)? loaded, + TResult? Function(_Selected value)? selected, + TResult? Function(_Cleared value)? cleared, + }) { + return selected?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Loaded value)? loaded, + TResult Function(_Selected value)? selected, + TResult Function(_Cleared value)? cleared, + required TResult orElse(), + }) { + if (selected != null) { + return selected(this); + } + return orElse(); + } +} + +abstract class _Selected implements SelectedOutletEvent { + const factory _Selected(final Outlet outlet) = _$SelectedImpl; + + Outlet get outlet; + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SelectedImplCopyWith<_$SelectedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ClearedImplCopyWith<$Res> { + factory _$$ClearedImplCopyWith( + _$ClearedImpl value, + $Res Function(_$ClearedImpl) then, + ) = __$$ClearedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$ClearedImplCopyWithImpl<$Res> + extends _$SelectedOutletEventCopyWithImpl<$Res, _$ClearedImpl> + implements _$$ClearedImplCopyWith<$Res> { + __$$ClearedImplCopyWithImpl( + _$ClearedImpl _value, + $Res Function(_$ClearedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SelectedOutletEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$ClearedImpl implements _Cleared { + const _$ClearedImpl(); + + @override + String toString() { + return 'SelectedOutletEvent.cleared()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$ClearedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loaded, + required TResult Function(Outlet outlet) selected, + required TResult Function() cleared, + }) { + return cleared(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loaded, + TResult? Function(Outlet outlet)? selected, + TResult? Function()? cleared, + }) { + return cleared?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loaded, + TResult Function(Outlet outlet)? selected, + TResult Function()? cleared, + required TResult orElse(), + }) { + if (cleared != null) { + return cleared(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_Loaded value) loaded, + required TResult Function(_Selected value) selected, + required TResult Function(_Cleared value) cleared, + }) { + return cleared(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_Loaded value)? loaded, + TResult? Function(_Selected value)? selected, + TResult? Function(_Cleared value)? cleared, + }) { + return cleared?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_Loaded value)? loaded, + TResult Function(_Selected value)? selected, + TResult Function(_Cleared value)? cleared, + required TResult orElse(), + }) { + if (cleared != null) { + return cleared(this); + } + return orElse(); + } +} + +abstract class _Cleared implements SelectedOutletEvent { + const factory _Cleared() = _$ClearedImpl; +} + +/// @nodoc +mixin _$SelectedOutletState { + /// null berarti "Semua Outlet" + Outlet? get selectedOutlet => throw _privateConstructorUsedError; + String? get selectedOutletId => throw _privateConstructorUsedError; + + /// Create a copy of SelectedOutletState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SelectedOutletStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SelectedOutletStateCopyWith<$Res> { + factory $SelectedOutletStateCopyWith( + SelectedOutletState value, + $Res Function(SelectedOutletState) then, + ) = _$SelectedOutletStateCopyWithImpl<$Res, SelectedOutletState>; + @useResult + $Res call({Outlet? selectedOutlet, String? selectedOutletId}); + + $OutletCopyWith<$Res>? get selectedOutlet; +} + +/// @nodoc +class _$SelectedOutletStateCopyWithImpl<$Res, $Val extends SelectedOutletState> + implements $SelectedOutletStateCopyWith<$Res> { + _$SelectedOutletStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SelectedOutletState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? selectedOutlet = freezed, + Object? selectedOutletId = freezed, + }) { + return _then( + _value.copyWith( + selectedOutlet: freezed == selectedOutlet + ? _value.selectedOutlet + : selectedOutlet // ignore: cast_nullable_to_non_nullable + as Outlet?, + selectedOutletId: freezed == selectedOutletId + ? _value.selectedOutletId + : selectedOutletId // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } + + /// Create a copy of SelectedOutletState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $OutletCopyWith<$Res>? get selectedOutlet { + if (_value.selectedOutlet == null) { + return null; + } + + return $OutletCopyWith<$Res>(_value.selectedOutlet!, (value) { + return _then(_value.copyWith(selectedOutlet: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SelectedOutletStateImplCopyWith<$Res> + implements $SelectedOutletStateCopyWith<$Res> { + factory _$$SelectedOutletStateImplCopyWith( + _$SelectedOutletStateImpl value, + $Res Function(_$SelectedOutletStateImpl) then, + ) = __$$SelectedOutletStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({Outlet? selectedOutlet, String? selectedOutletId}); + + @override + $OutletCopyWith<$Res>? get selectedOutlet; +} + +/// @nodoc +class __$$SelectedOutletStateImplCopyWithImpl<$Res> + extends _$SelectedOutletStateCopyWithImpl<$Res, _$SelectedOutletStateImpl> + implements _$$SelectedOutletStateImplCopyWith<$Res> { + __$$SelectedOutletStateImplCopyWithImpl( + _$SelectedOutletStateImpl _value, + $Res Function(_$SelectedOutletStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SelectedOutletState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? selectedOutlet = freezed, + Object? selectedOutletId = freezed, + }) { + return _then( + _$SelectedOutletStateImpl( + selectedOutlet: freezed == selectedOutlet + ? _value.selectedOutlet + : selectedOutlet // ignore: cast_nullable_to_non_nullable + as Outlet?, + selectedOutletId: freezed == selectedOutletId + ? _value.selectedOutletId + : selectedOutletId // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc + +class _$SelectedOutletStateImpl implements _SelectedOutletState { + const _$SelectedOutletStateImpl({this.selectedOutlet, this.selectedOutletId}); + + /// null berarti "Semua Outlet" + @override + final Outlet? selectedOutlet; + @override + final String? selectedOutletId; + + @override + String toString() { + return 'SelectedOutletState(selectedOutlet: $selectedOutlet, selectedOutletId: $selectedOutletId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SelectedOutletStateImpl && + (identical(other.selectedOutlet, selectedOutlet) || + other.selectedOutlet == selectedOutlet) && + (identical(other.selectedOutletId, selectedOutletId) || + other.selectedOutletId == selectedOutletId)); + } + + @override + int get hashCode => + Object.hash(runtimeType, selectedOutlet, selectedOutletId); + + /// Create a copy of SelectedOutletState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SelectedOutletStateImplCopyWith<_$SelectedOutletStateImpl> get copyWith => + __$$SelectedOutletStateImplCopyWithImpl<_$SelectedOutletStateImpl>( + this, + _$identity, + ); +} + +abstract class _SelectedOutletState implements SelectedOutletState { + const factory _SelectedOutletState({ + final Outlet? selectedOutlet, + final String? selectedOutletId, + }) = _$SelectedOutletStateImpl; + + /// null berarti "Semua Outlet" + @override + Outlet? get selectedOutlet; + @override + String? get selectedOutletId; + + /// Create a copy of SelectedOutletState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SelectedOutletStateImplCopyWith<_$SelectedOutletStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/outlet/selected_outlet/selected_outlet_event.dart b/lib/application/outlet/selected_outlet/selected_outlet_event.dart new file mode 100644 index 0000000..ddfd6b8 --- /dev/null +++ b/lib/application/outlet/selected_outlet/selected_outlet_event.dart @@ -0,0 +1,13 @@ +part of 'selected_outlet_bloc.dart'; + +@freezed +class SelectedOutletEvent with _$SelectedOutletEvent { + /// Load selected outlet id dari shared preferences + const factory SelectedOutletEvent.loaded() = _Loaded; + + /// User memilih outlet tertentu + const factory SelectedOutletEvent.selected(Outlet outlet) = _Selected; + + /// Reset ke "Semua Outlet" + const factory SelectedOutletEvent.cleared() = _Cleared; +} diff --git a/lib/application/outlet/selected_outlet/selected_outlet_state.dart b/lib/application/outlet/selected_outlet/selected_outlet_state.dart new file mode 100644 index 0000000..3cbf827 --- /dev/null +++ b/lib/application/outlet/selected_outlet/selected_outlet_state.dart @@ -0,0 +1,18 @@ +part of 'selected_outlet_bloc.dart'; + +@freezed +class SelectedOutletState with _$SelectedOutletState { + const factory SelectedOutletState({ + /// null berarti "Semua Outlet" + Outlet? selectedOutlet, + String? selectedOutletId, + }) = _SelectedOutletState; + + factory SelectedOutletState.initial() => const SelectedOutletState(); +} + +extension SelectedOutletStateX on SelectedOutletState { + bool get isAllOutlets => selectedOutletId == null; + + String get displayName => selectedOutlet?.name ?? 'Semua Outlet'; +} diff --git a/lib/application/product/product_loader/product_loader_bloc.dart b/lib/application/product/product_loader/product_loader_bloc.dart new file mode 100644 index 0000000..b08b29c --- /dev/null +++ b/lib/application/product/product_loader/product_loader_bloc.dart @@ -0,0 +1,92 @@ +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/product/product.dart'; + +part 'product_loader_event.dart'; +part 'product_loader_state.dart'; +part 'product_loader_bloc.freezed.dart'; + +@injectable +class ProductLoaderBloc extends Bloc { + final IProductRepository _productRepository; + + ProductLoaderBloc(this._productRepository) + : super(ProductLoaderState.initial()) { + on(_onProductLoaderEvent); + } + + Future _onProductLoaderEvent( + ProductLoaderEvent event, + Emitter emit, + ) { + return event.map( + categoryIdChanged: (e) async { + emit(state.copyWith(categoryId: e.categoryId)); + }, + searchChanged: (e) async { + emit(state.copyWith(search: e.search)); + }, + fetched: (e) async { + var newState = state; + + if (e.isRefresh) { + newState = state.copyWith(isFetching: true); + + emit(newState); + } + + newState = await _mapFetchedToState(state, isRefresh: e.isRefresh); + + emit(newState); + }, + ); + } + + Future _mapFetchedToState( + ProductLoaderState state, { + bool isRefresh = false, + }) async { + state = state.copyWith(isFetching: false); + + if (state.hasReachedMax && state.products.isNotEmpty && !isRefresh) { + return state; + } + + if (isRefresh) { + state = state.copyWith( + page: 1, + failureOptionProduct: none(), + hasReachedMax: false, + products: [], + ); + } + + final failureOrProduct = await _productRepository.get( + categoryId: state.categoryId, + page: state.page, + search: state.search, + ); + + state = failureOrProduct.fold( + (f) { + if (state.products.isNotEmpty) { + return state.copyWith(hasReachedMax: true); + } + return state.copyWith(failureOptionProduct: optionOf(f)); + }, + (products) { + return state.copyWith( + products: List.from(state.products)..addAll(products), + failureOptionProduct: none(), + page: state.page + 1, + hasReachedMax: products.length < 10, + ); + }, + ); + + return state; + } +} diff --git a/lib/application/product/product_loader/product_loader_bloc.freezed.dart b/lib/application/product/product_loader/product_loader_bloc.freezed.dart new file mode 100644 index 0000000..73ea5b2 --- /dev/null +++ b/lib/application/product/product_loader/product_loader_bloc.freezed.dart @@ -0,0 +1,821 @@ +// 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 'product_loader_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$ProductLoaderEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String categoryId) categoryIdChanged, + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String categoryId)? categoryIdChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String categoryId)? categoryIdChanged, + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_CategoryIdChanged value) categoryIdChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_CategoryIdChanged value)? categoryIdChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_CategoryIdChanged value)? categoryIdChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductLoaderEventCopyWith<$Res> { + factory $ProductLoaderEventCopyWith( + ProductLoaderEvent value, + $Res Function(ProductLoaderEvent) then, + ) = _$ProductLoaderEventCopyWithImpl<$Res, ProductLoaderEvent>; +} + +/// @nodoc +class _$ProductLoaderEventCopyWithImpl<$Res, $Val extends ProductLoaderEvent> + implements $ProductLoaderEventCopyWith<$Res> { + _$ProductLoaderEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$CategoryIdChangedImplCopyWith<$Res> { + factory _$$CategoryIdChangedImplCopyWith( + _$CategoryIdChangedImpl value, + $Res Function(_$CategoryIdChangedImpl) then, + ) = __$$CategoryIdChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String categoryId}); +} + +/// @nodoc +class __$$CategoryIdChangedImplCopyWithImpl<$Res> + extends _$ProductLoaderEventCopyWithImpl<$Res, _$CategoryIdChangedImpl> + implements _$$CategoryIdChangedImplCopyWith<$Res> { + __$$CategoryIdChangedImplCopyWithImpl( + _$CategoryIdChangedImpl _value, + $Res Function(_$CategoryIdChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? categoryId = null}) { + return _then( + _$CategoryIdChangedImpl( + null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$CategoryIdChangedImpl implements _CategoryIdChanged { + const _$CategoryIdChangedImpl(this.categoryId); + + @override + final String categoryId; + + @override + String toString() { + return 'ProductLoaderEvent.categoryIdChanged(categoryId: $categoryId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryIdChangedImpl && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId)); + } + + @override + int get hashCode => Object.hash(runtimeType, categoryId); + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryIdChangedImplCopyWith<_$CategoryIdChangedImpl> get copyWith => + __$$CategoryIdChangedImplCopyWithImpl<_$CategoryIdChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String categoryId) categoryIdChanged, + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return categoryIdChanged(categoryId); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String categoryId)? categoryIdChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return categoryIdChanged?.call(categoryId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String categoryId)? categoryIdChanged, + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (categoryIdChanged != null) { + return categoryIdChanged(categoryId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_CategoryIdChanged value) categoryIdChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) { + return categoryIdChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_CategoryIdChanged value)? categoryIdChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return categoryIdChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_CategoryIdChanged value)? categoryIdChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (categoryIdChanged != null) { + return categoryIdChanged(this); + } + return orElse(); + } +} + +abstract class _CategoryIdChanged implements ProductLoaderEvent { + const factory _CategoryIdChanged(final String categoryId) = + _$CategoryIdChangedImpl; + + String get categoryId; + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryIdChangedImplCopyWith<_$CategoryIdChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$SearchChangedImplCopyWith<$Res> { + factory _$$SearchChangedImplCopyWith( + _$SearchChangedImpl value, + $Res Function(_$SearchChangedImpl) then, + ) = __$$SearchChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String search}); +} + +/// @nodoc +class __$$SearchChangedImplCopyWithImpl<$Res> + extends _$ProductLoaderEventCopyWithImpl<$Res, _$SearchChangedImpl> + implements _$$SearchChangedImplCopyWith<$Res> { + __$$SearchChangedImplCopyWithImpl( + _$SearchChangedImpl _value, + $Res Function(_$SearchChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? search = null}) { + return _then( + _$SearchChangedImpl( + null == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$SearchChangedImpl implements _SearchChanged { + const _$SearchChangedImpl(this.search); + + @override + final String search; + + @override + String toString() { + return 'ProductLoaderEvent.searchChanged(search: $search)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SearchChangedImpl && + (identical(other.search, search) || other.search == search)); + } + + @override + int get hashCode => Object.hash(runtimeType, search); + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + __$$SearchChangedImplCopyWithImpl<_$SearchChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String categoryId) categoryIdChanged, + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return searchChanged(search); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String categoryId)? categoryIdChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return searchChanged?.call(search); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String categoryId)? categoryIdChanged, + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(search); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_CategoryIdChanged value) categoryIdChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) { + return searchChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_CategoryIdChanged value)? categoryIdChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return searchChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_CategoryIdChanged value)? categoryIdChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (searchChanged != null) { + return searchChanged(this); + } + return orElse(); + } +} + +abstract class _SearchChanged implements ProductLoaderEvent { + const factory _SearchChanged(final String search) = _$SearchChangedImpl; + + String get search; + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SearchChangedImplCopyWith<_$SearchChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$FetchedImplCopyWith<$Res> { + factory _$$FetchedImplCopyWith( + _$FetchedImpl value, + $Res Function(_$FetchedImpl) then, + ) = __$$FetchedImplCopyWithImpl<$Res>; + @useResult + $Res call({bool isRefresh}); +} + +/// @nodoc +class __$$FetchedImplCopyWithImpl<$Res> + extends _$ProductLoaderEventCopyWithImpl<$Res, _$FetchedImpl> + implements _$$FetchedImplCopyWith<$Res> { + __$$FetchedImplCopyWithImpl( + _$FetchedImpl _value, + $Res Function(_$FetchedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? isRefresh = null}) { + return _then( + _$FetchedImpl( + isRefresh: null == isRefresh + ? _value.isRefresh + : isRefresh // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$FetchedImpl implements _Fetched { + const _$FetchedImpl({this.isRefresh = false}); + + @override + @JsonKey() + final bool isRefresh; + + @override + String toString() { + return 'ProductLoaderEvent.fetched(isRefresh: $isRefresh)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FetchedImpl && + (identical(other.isRefresh, isRefresh) || + other.isRefresh == isRefresh)); + } + + @override + int get hashCode => Object.hash(runtimeType, isRefresh); + + /// Create a copy of ProductLoaderEvent + /// 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({ + required TResult Function(String categoryId) categoryIdChanged, + required TResult Function(String search) searchChanged, + required TResult Function(bool isRefresh) fetched, + }) { + return fetched(isRefresh); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String categoryId)? categoryIdChanged, + TResult? Function(String search)? searchChanged, + TResult? Function(bool isRefresh)? fetched, + }) { + return fetched?.call(isRefresh); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String categoryId)? categoryIdChanged, + TResult Function(String search)? searchChanged, + TResult Function(bool isRefresh)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(isRefresh); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_CategoryIdChanged value) categoryIdChanged, + required TResult Function(_SearchChanged value) searchChanged, + required TResult Function(_Fetched value) fetched, + }) { + return fetched(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_CategoryIdChanged value)? categoryIdChanged, + TResult? Function(_SearchChanged value)? searchChanged, + TResult? Function(_Fetched value)? fetched, + }) { + return fetched?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_CategoryIdChanged value)? categoryIdChanged, + TResult Function(_SearchChanged value)? searchChanged, + TResult Function(_Fetched value)? fetched, + required TResult orElse(), + }) { + if (fetched != null) { + return fetched(this); + } + return orElse(); + } +} + +abstract class _Fetched implements ProductLoaderEvent { + const factory _Fetched({final bool isRefresh}) = _$FetchedImpl; + + bool get isRefresh; + + /// Create a copy of ProductLoaderEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FetchedImplCopyWith<_$FetchedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProductLoaderState { + List get products => throw _privateConstructorUsedError; + Option get failureOptionProduct => + throw _privateConstructorUsedError; + String? get categoryId => throw _privateConstructorUsedError; + String? get search => throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + bool get hasReachedMax => throw _privateConstructorUsedError; + int get page => throw _privateConstructorUsedError; + + /// Create a copy of ProductLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductLoaderStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductLoaderStateCopyWith<$Res> { + factory $ProductLoaderStateCopyWith( + ProductLoaderState value, + $Res Function(ProductLoaderState) then, + ) = _$ProductLoaderStateCopyWithImpl<$Res, ProductLoaderState>; + @useResult + $Res call({ + List products, + Option failureOptionProduct, + String? categoryId, + String? search, + bool isFetching, + bool hasReachedMax, + int page, + }); +} + +/// @nodoc +class _$ProductLoaderStateCopyWithImpl<$Res, $Val extends ProductLoaderState> + implements $ProductLoaderStateCopyWith<$Res> { + _$ProductLoaderStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? products = null, + Object? failureOptionProduct = null, + Object? categoryId = freezed, + Object? search = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + }) { + return _then( + _value.copyWith( + products: null == products + ? _value.products + : products // ignore: cast_nullable_to_non_nullable + as List, + failureOptionProduct: null == failureOptionProduct + ? _value.failureOptionProduct + : failureOptionProduct // ignore: cast_nullable_to_non_nullable + as Option, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductLoaderStateImplCopyWith<$Res> + implements $ProductLoaderStateCopyWith<$Res> { + factory _$$ProductLoaderStateImplCopyWith( + _$ProductLoaderStateImpl value, + $Res Function(_$ProductLoaderStateImpl) then, + ) = __$$ProductLoaderStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + List products, + Option failureOptionProduct, + String? categoryId, + String? search, + bool isFetching, + bool hasReachedMax, + int page, + }); +} + +/// @nodoc +class __$$ProductLoaderStateImplCopyWithImpl<$Res> + extends _$ProductLoaderStateCopyWithImpl<$Res, _$ProductLoaderStateImpl> + implements _$$ProductLoaderStateImplCopyWith<$Res> { + __$$ProductLoaderStateImplCopyWithImpl( + _$ProductLoaderStateImpl _value, + $Res Function(_$ProductLoaderStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductLoaderState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? products = null, + Object? failureOptionProduct = null, + Object? categoryId = freezed, + Object? search = freezed, + Object? isFetching = null, + Object? hasReachedMax = null, + Object? page = null, + }) { + return _then( + _$ProductLoaderStateImpl( + products: null == products + ? _value._products + : products // ignore: cast_nullable_to_non_nullable + as List, + failureOptionProduct: null == failureOptionProduct + ? _value.failureOptionProduct + : failureOptionProduct // ignore: cast_nullable_to_non_nullable + as Option, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + search: freezed == search + ? _value.search + : search // ignore: cast_nullable_to_non_nullable + as String?, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + hasReachedMax: null == hasReachedMax + ? _value.hasReachedMax + : hasReachedMax // ignore: cast_nullable_to_non_nullable + as bool, + page: null == page + ? _value.page + : page // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$ProductLoaderStateImpl implements _ProductLoaderState { + const _$ProductLoaderStateImpl({ + required final List products, + required this.failureOptionProduct, + this.categoryId, + this.search, + this.isFetching = false, + this.hasReachedMax = false, + this.page = 1, + }) : _products = products; + + final List _products; + @override + List get products { + if (_products is EqualUnmodifiableListView) return _products; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_products); + } + + @override + final Option failureOptionProduct; + @override + final String? categoryId; + @override + final String? search; + @override + @JsonKey() + final bool isFetching; + @override + @JsonKey() + final bool hasReachedMax; + @override + @JsonKey() + final int page; + + @override + String toString() { + return 'ProductLoaderState(products: $products, failureOptionProduct: $failureOptionProduct, categoryId: $categoryId, search: $search, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductLoaderStateImpl && + const DeepCollectionEquality().equals(other._products, _products) && + (identical(other.failureOptionProduct, failureOptionProduct) || + other.failureOptionProduct == failureOptionProduct) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.search, search) || other.search == search) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.hasReachedMax, hasReachedMax) || + other.hasReachedMax == hasReachedMax) && + (identical(other.page, page) || other.page == page)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_products), + failureOptionProduct, + categoryId, + search, + isFetching, + hasReachedMax, + page, + ); + + /// Create a copy of ProductLoaderState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductLoaderStateImplCopyWith<_$ProductLoaderStateImpl> get copyWith => + __$$ProductLoaderStateImplCopyWithImpl<_$ProductLoaderStateImpl>( + this, + _$identity, + ); +} + +abstract class _ProductLoaderState implements ProductLoaderState { + const factory _ProductLoaderState({ + required final List products, + required final Option failureOptionProduct, + final String? categoryId, + final String? search, + final bool isFetching, + final bool hasReachedMax, + final int page, + }) = _$ProductLoaderStateImpl; + + @override + List get products; + @override + Option get failureOptionProduct; + @override + String? get categoryId; + @override + String? get search; + @override + bool get isFetching; + @override + bool get hasReachedMax; + @override + int get page; + + /// Create a copy of ProductLoaderState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductLoaderStateImplCopyWith<_$ProductLoaderStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/product/product_loader/product_loader_event.dart b/lib/application/product/product_loader/product_loader_event.dart new file mode 100644 index 0000000..1c6838c --- /dev/null +++ b/lib/application/product/product_loader/product_loader_event.dart @@ -0,0 +1,11 @@ +part of 'product_loader_bloc.dart'; + +@freezed +class ProductLoaderEvent with _$ProductLoaderEvent { + const factory ProductLoaderEvent.categoryIdChanged(String categoryId) = + _CategoryIdChanged; + const factory ProductLoaderEvent.searchChanged(String search) = + _SearchChanged; + const factory ProductLoaderEvent.fetched({@Default(false) bool isRefresh}) = + _Fetched; +} diff --git a/lib/application/product/product_loader/product_loader_state.dart b/lib/application/product/product_loader/product_loader_state.dart new file mode 100644 index 0000000..4d8856a --- /dev/null +++ b/lib/application/product/product_loader/product_loader_state.dart @@ -0,0 +1,17 @@ +part of 'product_loader_bloc.dart'; + +@freezed +class ProductLoaderState with _$ProductLoaderState { + const factory ProductLoaderState({ + required List products, + required Option failureOptionProduct, + String? categoryId, + String? search, + @Default(false) bool isFetching, + @Default(false) bool hasReachedMax, + @Default(1) int page, + }) = _ProductLoaderState; + + factory ProductLoaderState.initial() => + ProductLoaderState(products: [], failureOptionProduct: none()); +} diff --git a/lib/application/report/inventory_report/inventory_report_bloc.dart b/lib/application/report/inventory_report/inventory_report_bloc.dart new file mode 100644 index 0000000..f707d98 --- /dev/null +++ b/lib/application/report/inventory_report/inventory_report_bloc.dart @@ -0,0 +1,66 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.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'; +import '../../../domain/outlet/outlet.dart'; + +part 'inventory_report_event.dart'; +part 'inventory_report_state.dart'; +part 'inventory_report_bloc.freezed.dart'; + +@injectable +class InventoryReportBloc + extends Bloc { + final IAnalyticRepository _analyticRepository; + final IOutletRepository _outletRepository; + InventoryReportBloc(this._analyticRepository, this._outletRepository) + : super(InventoryReportState.initial()) { + on(_onInventoryReportEvent); + } + + Future _onInventoryReportEvent( + InventoryReportEvent event, + Emitter emit, + ) { + return event.map( + fetchedOutlet: (e) async { + emit( + state.copyWith(isFetchingOutlet: true, failureOptionOutlet: none()), + ); + + final result = await _outletRepository.currentOutlet(); + + var data = result.fold( + (f) => state.copyWith(failureOptionOutlet: optionOf(f)), + (currentOutlet) => state.copyWith(outlet: currentOutlet), + ); + + emit(data.copyWith(isFetchingOutlet: false)); + }, + fetchedInventory: (e) async { + emit( + state.copyWith( + isFetching: true, + failureOptionInventoryAnalytic: none(), + ), + ); + + final result = await _analyticRepository.getInventory( + dateFrom: e.dateFrom, + dateTo: e.dateTo, + ); + + var data = result.fold( + (f) => state.copyWith(failureOptionInventoryAnalytic: optionOf(f)), + (inventoryAnalytic) => + state.copyWith(inventoryAnalytic: inventoryAnalytic), + ); + + emit(data.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/report/inventory_report/inventory_report_bloc.freezed.dart b/lib/application/report/inventory_report/inventory_report_bloc.freezed.dart new file mode 100644 index 0000000..714993c --- /dev/null +++ b/lib/application/report/inventory_report/inventory_report_bloc.freezed.dart @@ -0,0 +1,645 @@ +// 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 'inventory_report_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$InventoryReportEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedOutlet, + required TResult Function(DateTime dateFrom, DateTime dateTo) + fetchedInventory, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedOutlet, + TResult? Function(DateTime dateFrom, DateTime dateTo)? fetchedInventory, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedOutlet, + TResult Function(DateTime dateFrom, DateTime dateTo)? fetchedInventory, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedOutlet value) fetchedOutlet, + required TResult Function(_FetchedInventory value) fetchedInventory, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedOutlet value)? fetchedOutlet, + TResult? Function(_FetchedInventory value)? fetchedInventory, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedOutlet value)? fetchedOutlet, + TResult Function(_FetchedInventory value)? fetchedInventory, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryReportEventCopyWith<$Res> { + factory $InventoryReportEventCopyWith( + InventoryReportEvent value, + $Res Function(InventoryReportEvent) then, + ) = _$InventoryReportEventCopyWithImpl<$Res, InventoryReportEvent>; +} + +/// @nodoc +class _$InventoryReportEventCopyWithImpl< + $Res, + $Val extends InventoryReportEvent +> + implements $InventoryReportEventCopyWith<$Res> { + _$InventoryReportEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryReportEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchedOutletImplCopyWith<$Res> { + factory _$$FetchedOutletImplCopyWith( + _$FetchedOutletImpl value, + $Res Function(_$FetchedOutletImpl) then, + ) = __$$FetchedOutletImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedOutletImplCopyWithImpl<$Res> + extends _$InventoryReportEventCopyWithImpl<$Res, _$FetchedOutletImpl> + implements _$$FetchedOutletImplCopyWith<$Res> { + __$$FetchedOutletImplCopyWithImpl( + _$FetchedOutletImpl _value, + $Res Function(_$FetchedOutletImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryReportEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedOutletImpl implements _FetchedOutlet { + const _$FetchedOutletImpl(); + + @override + String toString() { + return 'InventoryReportEvent.fetchedOutlet()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchedOutletImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedOutlet, + required TResult Function(DateTime dateFrom, DateTime dateTo) + fetchedInventory, + }) { + return fetchedOutlet(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedOutlet, + TResult? Function(DateTime dateFrom, DateTime dateTo)? fetchedInventory, + }) { + return fetchedOutlet?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedOutlet, + TResult Function(DateTime dateFrom, DateTime dateTo)? fetchedInventory, + required TResult orElse(), + }) { + if (fetchedOutlet != null) { + return fetchedOutlet(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedOutlet value) fetchedOutlet, + required TResult Function(_FetchedInventory value) fetchedInventory, + }) { + return fetchedOutlet(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedOutlet value)? fetchedOutlet, + TResult? Function(_FetchedInventory value)? fetchedInventory, + }) { + return fetchedOutlet?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedOutlet value)? fetchedOutlet, + TResult Function(_FetchedInventory value)? fetchedInventory, + required TResult orElse(), + }) { + if (fetchedOutlet != null) { + return fetchedOutlet(this); + } + return orElse(); + } +} + +abstract class _FetchedOutlet implements InventoryReportEvent { + const factory _FetchedOutlet() = _$FetchedOutletImpl; +} + +/// @nodoc +abstract class _$$FetchedInventoryImplCopyWith<$Res> { + factory _$$FetchedInventoryImplCopyWith( + _$FetchedInventoryImpl value, + $Res Function(_$FetchedInventoryImpl) then, + ) = __$$FetchedInventoryImplCopyWithImpl<$Res>; + @useResult + $Res call({DateTime dateFrom, DateTime dateTo}); +} + +/// @nodoc +class __$$FetchedInventoryImplCopyWithImpl<$Res> + extends _$InventoryReportEventCopyWithImpl<$Res, _$FetchedInventoryImpl> + implements _$$FetchedInventoryImplCopyWith<$Res> { + __$$FetchedInventoryImplCopyWithImpl( + _$FetchedInventoryImpl _value, + $Res Function(_$FetchedInventoryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryReportEvent + /// 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( + _$FetchedInventoryImpl( + 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 _$FetchedInventoryImpl implements _FetchedInventory { + const _$FetchedInventoryImpl(this.dateFrom, this.dateTo); + + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'InventoryReportEvent.fetchedInventory(dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FetchedInventoryImpl && + (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 InventoryReportEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$FetchedInventoryImplCopyWith<_$FetchedInventoryImpl> get copyWith => + __$$FetchedInventoryImplCopyWithImpl<_$FetchedInventoryImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedOutlet, + required TResult Function(DateTime dateFrom, DateTime dateTo) + fetchedInventory, + }) { + return fetchedInventory(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedOutlet, + TResult? Function(DateTime dateFrom, DateTime dateTo)? fetchedInventory, + }) { + return fetchedInventory?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedOutlet, + TResult Function(DateTime dateFrom, DateTime dateTo)? fetchedInventory, + required TResult orElse(), + }) { + if (fetchedInventory != null) { + return fetchedInventory(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedOutlet value) fetchedOutlet, + required TResult Function(_FetchedInventory value) fetchedInventory, + }) { + return fetchedInventory(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedOutlet value)? fetchedOutlet, + TResult? Function(_FetchedInventory value)? fetchedInventory, + }) { + return fetchedInventory?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedOutlet value)? fetchedOutlet, + TResult Function(_FetchedInventory value)? fetchedInventory, + required TResult orElse(), + }) { + if (fetchedInventory != null) { + return fetchedInventory(this); + } + return orElse(); + } +} + +abstract class _FetchedInventory implements InventoryReportEvent { + const factory _FetchedInventory( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$FetchedInventoryImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of InventoryReportEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FetchedInventoryImplCopyWith<_$FetchedInventoryImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventoryReportState { + InventoryAnalytic get inventoryAnalytic => throw _privateConstructorUsedError; + Option get failureOptionInventoryAnalytic => + throw _privateConstructorUsedError; + Outlet get outlet => throw _privateConstructorUsedError; + Option get failureOptionOutlet => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + bool get isFetchingOutlet => throw _privateConstructorUsedError; + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryReportStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryReportStateCopyWith<$Res> { + factory $InventoryReportStateCopyWith( + InventoryReportState value, + $Res Function(InventoryReportState) then, + ) = _$InventoryReportStateCopyWithImpl<$Res, InventoryReportState>; + @useResult + $Res call({ + InventoryAnalytic inventoryAnalytic, + Option failureOptionInventoryAnalytic, + Outlet outlet, + Option failureOptionOutlet, + bool isFetching, + bool isFetchingOutlet, + }); + + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic; + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class _$InventoryReportStateCopyWithImpl< + $Res, + $Val extends InventoryReportState +> + implements $InventoryReportStateCopyWith<$Res> { + _$InventoryReportStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inventoryAnalytic = null, + Object? failureOptionInventoryAnalytic = null, + Object? outlet = null, + Object? failureOptionOutlet = null, + Object? isFetching = null, + Object? isFetchingOutlet = null, + }) { + return _then( + _value.copyWith( + inventoryAnalytic: null == inventoryAnalytic + ? _value.inventoryAnalytic + : inventoryAnalytic // ignore: cast_nullable_to_non_nullable + as InventoryAnalytic, + failureOptionInventoryAnalytic: + null == failureOptionInventoryAnalytic + ? _value.failureOptionInventoryAnalytic + : failureOptionInventoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + outlet: null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + isFetchingOutlet: null == isFetchingOutlet + ? _value.isFetchingOutlet + : isFetchingOutlet // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic { + return $InventoryAnalyticCopyWith<$Res>(_value.inventoryAnalytic, (value) { + return _then(_value.copyWith(inventoryAnalytic: value) as $Val); + }); + } + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $OutletCopyWith<$Res> get outlet { + return $OutletCopyWith<$Res>(_value.outlet, (value) { + return _then(_value.copyWith(outlet: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryReportStateImplCopyWith<$Res> + implements $InventoryReportStateCopyWith<$Res> { + factory _$$InventoryReportStateImplCopyWith( + _$InventoryReportStateImpl value, + $Res Function(_$InventoryReportStateImpl) then, + ) = __$$InventoryReportStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + InventoryAnalytic inventoryAnalytic, + Option failureOptionInventoryAnalytic, + Outlet outlet, + Option failureOptionOutlet, + bool isFetching, + bool isFetchingOutlet, + }); + + @override + $InventoryAnalyticCopyWith<$Res> get inventoryAnalytic; + @override + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class __$$InventoryReportStateImplCopyWithImpl<$Res> + extends _$InventoryReportStateCopyWithImpl<$Res, _$InventoryReportStateImpl> + implements _$$InventoryReportStateImplCopyWith<$Res> { + __$$InventoryReportStateImplCopyWithImpl( + _$InventoryReportStateImpl _value, + $Res Function(_$InventoryReportStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? inventoryAnalytic = null, + Object? failureOptionInventoryAnalytic = null, + Object? outlet = null, + Object? failureOptionOutlet = null, + Object? isFetching = null, + Object? isFetchingOutlet = null, + }) { + return _then( + _$InventoryReportStateImpl( + inventoryAnalytic: null == inventoryAnalytic + ? _value.inventoryAnalytic + : inventoryAnalytic // ignore: cast_nullable_to_non_nullable + as InventoryAnalytic, + failureOptionInventoryAnalytic: null == failureOptionInventoryAnalytic + ? _value.failureOptionInventoryAnalytic + : failureOptionInventoryAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + outlet: null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + isFetchingOutlet: null == isFetchingOutlet + ? _value.isFetchingOutlet + : isFetchingOutlet // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$InventoryReportStateImpl implements _InventoryReportState { + const _$InventoryReportStateImpl({ + required this.inventoryAnalytic, + required this.failureOptionInventoryAnalytic, + required this.outlet, + required this.failureOptionOutlet, + this.isFetching = false, + this.isFetchingOutlet = false, + }); + + @override + final InventoryAnalytic inventoryAnalytic; + @override + final Option failureOptionInventoryAnalytic; + @override + final Outlet outlet; + @override + final Option failureOptionOutlet; + @override + @JsonKey() + final bool isFetching; + @override + @JsonKey() + final bool isFetchingOutlet; + + @override + String toString() { + return 'InventoryReportState(inventoryAnalytic: $inventoryAnalytic, failureOptionInventoryAnalytic: $failureOptionInventoryAnalytic, outlet: $outlet, failureOptionOutlet: $failureOptionOutlet, isFetching: $isFetching, isFetchingOutlet: $isFetchingOutlet)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryReportStateImpl && + (identical(other.inventoryAnalytic, inventoryAnalytic) || + other.inventoryAnalytic == inventoryAnalytic) && + (identical( + other.failureOptionInventoryAnalytic, + failureOptionInventoryAnalytic, + ) || + other.failureOptionInventoryAnalytic == + failureOptionInventoryAnalytic) && + (identical(other.outlet, outlet) || other.outlet == outlet) && + (identical(other.failureOptionOutlet, failureOptionOutlet) || + other.failureOptionOutlet == failureOptionOutlet) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.isFetchingOutlet, isFetchingOutlet) || + other.isFetchingOutlet == isFetchingOutlet)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + inventoryAnalytic, + failureOptionInventoryAnalytic, + outlet, + failureOptionOutlet, + isFetching, + isFetchingOutlet, + ); + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryReportStateImplCopyWith<_$InventoryReportStateImpl> + get copyWith => + __$$InventoryReportStateImplCopyWithImpl<_$InventoryReportStateImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryReportState implements InventoryReportState { + const factory _InventoryReportState({ + required final InventoryAnalytic inventoryAnalytic, + required final Option failureOptionInventoryAnalytic, + required final Outlet outlet, + required final Option failureOptionOutlet, + final bool isFetching, + final bool isFetchingOutlet, + }) = _$InventoryReportStateImpl; + + @override + InventoryAnalytic get inventoryAnalytic; + @override + Option get failureOptionInventoryAnalytic; + @override + Outlet get outlet; + @override + Option get failureOptionOutlet; + @override + bool get isFetching; + @override + bool get isFetchingOutlet; + + /// Create a copy of InventoryReportState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryReportStateImplCopyWith<_$InventoryReportStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/report/inventory_report/inventory_report_event.dart b/lib/application/report/inventory_report/inventory_report_event.dart new file mode 100644 index 0000000..713335f --- /dev/null +++ b/lib/application/report/inventory_report/inventory_report_event.dart @@ -0,0 +1,10 @@ +part of 'inventory_report_bloc.dart'; + +@freezed +class InventoryReportEvent with _$InventoryReportEvent { + const factory InventoryReportEvent.fetchedOutlet() = _FetchedOutlet; + const factory InventoryReportEvent.fetchedInventory( + DateTime dateFrom, + DateTime dateTo, + ) = _FetchedInventory; +} diff --git a/lib/application/report/inventory_report/inventory_report_state.dart b/lib/application/report/inventory_report/inventory_report_state.dart new file mode 100644 index 0000000..fb652ef --- /dev/null +++ b/lib/application/report/inventory_report/inventory_report_state.dart @@ -0,0 +1,20 @@ +part of 'inventory_report_bloc.dart'; + +@freezed +class InventoryReportState with _$InventoryReportState { + const factory InventoryReportState({ + required InventoryAnalytic inventoryAnalytic, + required Option failureOptionInventoryAnalytic, + required Outlet outlet, + required Option failureOptionOutlet, + @Default(false) bool isFetching, + @Default(false) bool isFetchingOutlet, + }) = _InventoryReportState; + + factory InventoryReportState.initial() => InventoryReportState( + inventoryAnalytic: InventoryAnalytic.empty(), + failureOptionInventoryAnalytic: none(), + outlet: Outlet.empty(), + failureOptionOutlet: none(), + ); +} diff --git a/lib/application/report/transaction_report/transaction_report_bloc.dart b/lib/application/report/transaction_report/transaction_report_bloc.dart new file mode 100644 index 0000000..b7b85d0 --- /dev/null +++ b/lib/application/report/transaction_report/transaction_report_bloc.dart @@ -0,0 +1,91 @@ +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'; +import '../../../domain/outlet/outlet.dart'; + +part 'transaction_report_event.dart'; +part 'transaction_report_state.dart'; +part 'transaction_report_bloc.freezed.dart'; + +@injectable +class TransactionReportBloc + extends Bloc { + final IAnalyticRepository _analyticRepository; + final IOutletRepository _outletRepository; + + TransactionReportBloc(this._analyticRepository, this._outletRepository) + : super(TransactionReportState.initial()) { + on(_onTransactionReportEvent); + } + + Future _onTransactionReportEvent( + TransactionReportEvent event, + Emitter emit, + ) { + return event.map( + fetchedOutlet: (e) async { + emit( + state.copyWith(isFetchingOutlet: true, failureOptionOutlet: none()), + ); + + final result = await _outletRepository.currentOutlet(); + + var data = result.fold( + (f) => state.copyWith(failureOptionOutlet: optionOf(f)), + (currentOutlet) => state.copyWith(outlet: currentOutlet), + ); + + emit(data.copyWith(isFetchingOutlet: false)); + }, + fetchedTransaction: (e) async { + emit(state.copyWith(isFetching: true, failureOptionAnalytic: none())); + + var newState = state; + + final category = await _analyticRepository.getCategory( + dateFrom: e.dateFrom, + dateTo: e.dateTo, + ); + final profitLoss = await _analyticRepository.getProfitLoss( + dateFrom: e.dateFrom, + dateTo: e.dateTo, + ); + final paymentMethod = await _analyticRepository.getPaymentMethod( + dateFrom: e.dateFrom, + dateTo: e.dateTo, + ); + final product = await _analyticRepository.getProduct( + dateFrom: e.dateFrom, + dateTo: e.dateTo, + ); + + newState = category.fold( + (f) => newState.copyWith(failureOptionAnalytic: optionOf(f)), + (categoryAnalytic) => + newState.copyWith(categoryAnalytic: categoryAnalytic), + ); + newState = profitLoss.fold( + (f) => newState.copyWith(failureOptionAnalytic: optionOf(f)), + (profitLossAnalytic) => + newState.copyWith(profitLossAnalytic: profitLossAnalytic), + ); + newState = paymentMethod.fold( + (f) => newState.copyWith(failureOptionAnalytic: optionOf(f)), + (paymentMethodAnalytic) => + newState.copyWith(paymentMethodAnalytic: paymentMethodAnalytic), + ); + newState = product.fold( + (f) => newState.copyWith(failureOptionAnalytic: optionOf(f)), + (productAnalytic) => + newState.copyWith(productAnalytic: productAnalytic), + ); + + emit(newState.copyWith(isFetching: false)); + }, + ); + } +} diff --git a/lib/application/report/transaction_report/transaction_report_bloc.freezed.dart b/lib/application/report/transaction_report/transaction_report_bloc.freezed.dart new file mode 100644 index 0000000..b60a09b --- /dev/null +++ b/lib/application/report/transaction_report/transaction_report_bloc.freezed.dart @@ -0,0 +1,752 @@ +// 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 'transaction_report_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$TransactionReportEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedOutlet, + required TResult Function(DateTime dateFrom, DateTime dateTo) + fetchedTransaction, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedOutlet, + TResult? Function(DateTime dateFrom, DateTime dateTo)? fetchedTransaction, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedOutlet, + TResult Function(DateTime dateFrom, DateTime dateTo)? fetchedTransaction, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedOutlet value) fetchedOutlet, + required TResult Function(_FetchedTransaction value) fetchedTransaction, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedOutlet value)? fetchedOutlet, + TResult? Function(_FetchedTransaction value)? fetchedTransaction, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedOutlet value)? fetchedOutlet, + TResult Function(_FetchedTransaction value)? fetchedTransaction, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TransactionReportEventCopyWith<$Res> { + factory $TransactionReportEventCopyWith( + TransactionReportEvent value, + $Res Function(TransactionReportEvent) then, + ) = _$TransactionReportEventCopyWithImpl<$Res, TransactionReportEvent>; +} + +/// @nodoc +class _$TransactionReportEventCopyWithImpl< + $Res, + $Val extends TransactionReportEvent +> + implements $TransactionReportEventCopyWith<$Res> { + _$TransactionReportEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of TransactionReportEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$FetchedOutletImplCopyWith<$Res> { + factory _$$FetchedOutletImplCopyWith( + _$FetchedOutletImpl value, + $Res Function(_$FetchedOutletImpl) then, + ) = __$$FetchedOutletImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$FetchedOutletImplCopyWithImpl<$Res> + extends _$TransactionReportEventCopyWithImpl<$Res, _$FetchedOutletImpl> + implements _$$FetchedOutletImplCopyWith<$Res> { + __$$FetchedOutletImplCopyWithImpl( + _$FetchedOutletImpl _value, + $Res Function(_$FetchedOutletImpl) _then, + ) : super(_value, _then); + + /// Create a copy of TransactionReportEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$FetchedOutletImpl implements _FetchedOutlet { + const _$FetchedOutletImpl(); + + @override + String toString() { + return 'TransactionReportEvent.fetchedOutlet()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$FetchedOutletImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedOutlet, + required TResult Function(DateTime dateFrom, DateTime dateTo) + fetchedTransaction, + }) { + return fetchedOutlet(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedOutlet, + TResult? Function(DateTime dateFrom, DateTime dateTo)? fetchedTransaction, + }) { + return fetchedOutlet?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedOutlet, + TResult Function(DateTime dateFrom, DateTime dateTo)? fetchedTransaction, + required TResult orElse(), + }) { + if (fetchedOutlet != null) { + return fetchedOutlet(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedOutlet value) fetchedOutlet, + required TResult Function(_FetchedTransaction value) fetchedTransaction, + }) { + return fetchedOutlet(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedOutlet value)? fetchedOutlet, + TResult? Function(_FetchedTransaction value)? fetchedTransaction, + }) { + return fetchedOutlet?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedOutlet value)? fetchedOutlet, + TResult Function(_FetchedTransaction value)? fetchedTransaction, + required TResult orElse(), + }) { + if (fetchedOutlet != null) { + return fetchedOutlet(this); + } + return orElse(); + } +} + +abstract class _FetchedOutlet implements TransactionReportEvent { + const factory _FetchedOutlet() = _$FetchedOutletImpl; +} + +/// @nodoc +abstract class _$$FetchedTransactionImplCopyWith<$Res> { + factory _$$FetchedTransactionImplCopyWith( + _$FetchedTransactionImpl value, + $Res Function(_$FetchedTransactionImpl) then, + ) = __$$FetchedTransactionImplCopyWithImpl<$Res>; + @useResult + $Res call({DateTime dateFrom, DateTime dateTo}); +} + +/// @nodoc +class __$$FetchedTransactionImplCopyWithImpl<$Res> + extends _$TransactionReportEventCopyWithImpl<$Res, _$FetchedTransactionImpl> + implements _$$FetchedTransactionImplCopyWith<$Res> { + __$$FetchedTransactionImplCopyWithImpl( + _$FetchedTransactionImpl _value, + $Res Function(_$FetchedTransactionImpl) _then, + ) : super(_value, _then); + + /// Create a copy of TransactionReportEvent + /// 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( + _$FetchedTransactionImpl( + 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 _$FetchedTransactionImpl implements _FetchedTransaction { + const _$FetchedTransactionImpl(this.dateFrom, this.dateTo); + + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + + @override + String toString() { + return 'TransactionReportEvent.fetchedTransaction(dateFrom: $dateFrom, dateTo: $dateTo)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$FetchedTransactionImpl && + (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 TransactionReportEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$FetchedTransactionImplCopyWith<_$FetchedTransactionImpl> get copyWith => + __$$FetchedTransactionImplCopyWithImpl<_$FetchedTransactionImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() fetchedOutlet, + required TResult Function(DateTime dateFrom, DateTime dateTo) + fetchedTransaction, + }) { + return fetchedTransaction(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? fetchedOutlet, + TResult? Function(DateTime dateFrom, DateTime dateTo)? fetchedTransaction, + }) { + return fetchedTransaction?.call(dateFrom, dateTo); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? fetchedOutlet, + TResult Function(DateTime dateFrom, DateTime dateTo)? fetchedTransaction, + required TResult orElse(), + }) { + if (fetchedTransaction != null) { + return fetchedTransaction(dateFrom, dateTo); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_FetchedOutlet value) fetchedOutlet, + required TResult Function(_FetchedTransaction value) fetchedTransaction, + }) { + return fetchedTransaction(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_FetchedOutlet value)? fetchedOutlet, + TResult? Function(_FetchedTransaction value)? fetchedTransaction, + }) { + return fetchedTransaction?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_FetchedOutlet value)? fetchedOutlet, + TResult Function(_FetchedTransaction value)? fetchedTransaction, + required TResult orElse(), + }) { + if (fetchedTransaction != null) { + return fetchedTransaction(this); + } + return orElse(); + } +} + +abstract class _FetchedTransaction implements TransactionReportEvent { + const factory _FetchedTransaction( + final DateTime dateFrom, + final DateTime dateTo, + ) = _$FetchedTransactionImpl; + + DateTime get dateFrom; + DateTime get dateTo; + + /// Create a copy of TransactionReportEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$FetchedTransactionImplCopyWith<_$FetchedTransactionImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$TransactionReportState { + CategoryAnalytic get categoryAnalytic => throw _privateConstructorUsedError; + ProfitLossAnalytic get profitLossAnalytic => + throw _privateConstructorUsedError; + PaymentMethodAnalytic get paymentMethodAnalytic => + throw _privateConstructorUsedError; + ProductAnalytic get productAnalytic => throw _privateConstructorUsedError; + Option get failureOptionAnalytic => + throw _privateConstructorUsedError; + Outlet get outlet => throw _privateConstructorUsedError; + Option get failureOptionOutlet => + throw _privateConstructorUsedError; + bool get isFetching => throw _privateConstructorUsedError; + bool get isFetchingOutlet => throw _privateConstructorUsedError; + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $TransactionReportStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TransactionReportStateCopyWith<$Res> { + factory $TransactionReportStateCopyWith( + TransactionReportState value, + $Res Function(TransactionReportState) then, + ) = _$TransactionReportStateCopyWithImpl<$Res, TransactionReportState>; + @useResult + $Res call({ + CategoryAnalytic categoryAnalytic, + ProfitLossAnalytic profitLossAnalytic, + PaymentMethodAnalytic paymentMethodAnalytic, + ProductAnalytic productAnalytic, + Option failureOptionAnalytic, + Outlet outlet, + Option failureOptionOutlet, + bool isFetching, + bool isFetchingOutlet, + }); + + $CategoryAnalyticCopyWith<$Res> get categoryAnalytic; + $ProfitLossAnalyticCopyWith<$Res> get profitLossAnalytic; + $PaymentMethodAnalyticCopyWith<$Res> get paymentMethodAnalytic; + $ProductAnalyticCopyWith<$Res> get productAnalytic; + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class _$TransactionReportStateCopyWithImpl< + $Res, + $Val extends TransactionReportState +> + implements $TransactionReportStateCopyWith<$Res> { + _$TransactionReportStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryAnalytic = null, + Object? profitLossAnalytic = null, + Object? paymentMethodAnalytic = null, + Object? productAnalytic = null, + Object? failureOptionAnalytic = null, + Object? outlet = null, + Object? failureOptionOutlet = null, + Object? isFetching = null, + Object? isFetchingOutlet = null, + }) { + return _then( + _value.copyWith( + categoryAnalytic: null == categoryAnalytic + ? _value.categoryAnalytic + : categoryAnalytic // ignore: cast_nullable_to_non_nullable + as CategoryAnalytic, + profitLossAnalytic: null == profitLossAnalytic + ? _value.profitLossAnalytic + : profitLossAnalytic // ignore: cast_nullable_to_non_nullable + as ProfitLossAnalytic, + paymentMethodAnalytic: null == paymentMethodAnalytic + ? _value.paymentMethodAnalytic + : paymentMethodAnalytic // ignore: cast_nullable_to_non_nullable + as PaymentMethodAnalytic, + productAnalytic: null == productAnalytic + ? _value.productAnalytic + : productAnalytic // ignore: cast_nullable_to_non_nullable + as ProductAnalytic, + failureOptionAnalytic: null == failureOptionAnalytic + ? _value.failureOptionAnalytic + : failureOptionAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + outlet: null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + isFetchingOutlet: null == isFetchingOutlet + ? _value.isFetchingOutlet + : isFetchingOutlet // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $CategoryAnalyticCopyWith<$Res> get categoryAnalytic { + return $CategoryAnalyticCopyWith<$Res>(_value.categoryAnalytic, (value) { + return _then(_value.copyWith(categoryAnalytic: value) as $Val); + }); + } + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossAnalyticCopyWith<$Res> get profitLossAnalytic { + return $ProfitLossAnalyticCopyWith<$Res>(_value.profitLossAnalytic, ( + value, + ) { + return _then(_value.copyWith(profitLossAnalytic: value) as $Val); + }); + } + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $PaymentMethodAnalyticCopyWith<$Res> get paymentMethodAnalytic { + return $PaymentMethodAnalyticCopyWith<$Res>(_value.paymentMethodAnalytic, ( + value, + ) { + return _then(_value.copyWith(paymentMethodAnalytic: value) as $Val); + }); + } + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProductAnalyticCopyWith<$Res> get productAnalytic { + return $ProductAnalyticCopyWith<$Res>(_value.productAnalytic, (value) { + return _then(_value.copyWith(productAnalytic: value) as $Val); + }); + } + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $OutletCopyWith<$Res> get outlet { + return $OutletCopyWith<$Res>(_value.outlet, (value) { + return _then(_value.copyWith(outlet: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$TransactionReportStateImplCopyWith<$Res> + implements $TransactionReportStateCopyWith<$Res> { + factory _$$TransactionReportStateImplCopyWith( + _$TransactionReportStateImpl value, + $Res Function(_$TransactionReportStateImpl) then, + ) = __$$TransactionReportStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + CategoryAnalytic categoryAnalytic, + ProfitLossAnalytic profitLossAnalytic, + PaymentMethodAnalytic paymentMethodAnalytic, + ProductAnalytic productAnalytic, + Option failureOptionAnalytic, + Outlet outlet, + Option failureOptionOutlet, + bool isFetching, + bool isFetchingOutlet, + }); + + @override + $CategoryAnalyticCopyWith<$Res> get categoryAnalytic; + @override + $ProfitLossAnalyticCopyWith<$Res> get profitLossAnalytic; + @override + $PaymentMethodAnalyticCopyWith<$Res> get paymentMethodAnalytic; + @override + $ProductAnalyticCopyWith<$Res> get productAnalytic; + @override + $OutletCopyWith<$Res> get outlet; +} + +/// @nodoc +class __$$TransactionReportStateImplCopyWithImpl<$Res> + extends + _$TransactionReportStateCopyWithImpl<$Res, _$TransactionReportStateImpl> + implements _$$TransactionReportStateImplCopyWith<$Res> { + __$$TransactionReportStateImplCopyWithImpl( + _$TransactionReportStateImpl _value, + $Res Function(_$TransactionReportStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryAnalytic = null, + Object? profitLossAnalytic = null, + Object? paymentMethodAnalytic = null, + Object? productAnalytic = null, + Object? failureOptionAnalytic = null, + Object? outlet = null, + Object? failureOptionOutlet = null, + Object? isFetching = null, + Object? isFetchingOutlet = null, + }) { + return _then( + _$TransactionReportStateImpl( + categoryAnalytic: null == categoryAnalytic + ? _value.categoryAnalytic + : categoryAnalytic // ignore: cast_nullable_to_non_nullable + as CategoryAnalytic, + profitLossAnalytic: null == profitLossAnalytic + ? _value.profitLossAnalytic + : profitLossAnalytic // ignore: cast_nullable_to_non_nullable + as ProfitLossAnalytic, + paymentMethodAnalytic: null == paymentMethodAnalytic + ? _value.paymentMethodAnalytic + : paymentMethodAnalytic // ignore: cast_nullable_to_non_nullable + as PaymentMethodAnalytic, + productAnalytic: null == productAnalytic + ? _value.productAnalytic + : productAnalytic // ignore: cast_nullable_to_non_nullable + as ProductAnalytic, + failureOptionAnalytic: null == failureOptionAnalytic + ? _value.failureOptionAnalytic + : failureOptionAnalytic // ignore: cast_nullable_to_non_nullable + as Option, + outlet: null == outlet + ? _value.outlet + : outlet // ignore: cast_nullable_to_non_nullable + as Outlet, + failureOptionOutlet: null == failureOptionOutlet + ? _value.failureOptionOutlet + : failureOptionOutlet // ignore: cast_nullable_to_non_nullable + as Option, + isFetching: null == isFetching + ? _value.isFetching + : isFetching // ignore: cast_nullable_to_non_nullable + as bool, + isFetchingOutlet: null == isFetchingOutlet + ? _value.isFetchingOutlet + : isFetchingOutlet // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$TransactionReportStateImpl implements _TransactionReportState { + const _$TransactionReportStateImpl({ + required this.categoryAnalytic, + required this.profitLossAnalytic, + required this.paymentMethodAnalytic, + required this.productAnalytic, + required this.failureOptionAnalytic, + required this.outlet, + required this.failureOptionOutlet, + this.isFetching = false, + this.isFetchingOutlet = false, + }); + + @override + final CategoryAnalytic categoryAnalytic; + @override + final ProfitLossAnalytic profitLossAnalytic; + @override + final PaymentMethodAnalytic paymentMethodAnalytic; + @override + final ProductAnalytic productAnalytic; + @override + final Option failureOptionAnalytic; + @override + final Outlet outlet; + @override + final Option failureOptionOutlet; + @override + @JsonKey() + final bool isFetching; + @override + @JsonKey() + final bool isFetchingOutlet; + + @override + String toString() { + return 'TransactionReportState(categoryAnalytic: $categoryAnalytic, profitLossAnalytic: $profitLossAnalytic, paymentMethodAnalytic: $paymentMethodAnalytic, productAnalytic: $productAnalytic, failureOptionAnalytic: $failureOptionAnalytic, outlet: $outlet, failureOptionOutlet: $failureOptionOutlet, isFetching: $isFetching, isFetchingOutlet: $isFetchingOutlet)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$TransactionReportStateImpl && + (identical(other.categoryAnalytic, categoryAnalytic) || + other.categoryAnalytic == categoryAnalytic) && + (identical(other.profitLossAnalytic, profitLossAnalytic) || + other.profitLossAnalytic == profitLossAnalytic) && + (identical(other.paymentMethodAnalytic, paymentMethodAnalytic) || + other.paymentMethodAnalytic == paymentMethodAnalytic) && + (identical(other.productAnalytic, productAnalytic) || + other.productAnalytic == productAnalytic) && + (identical(other.failureOptionAnalytic, failureOptionAnalytic) || + other.failureOptionAnalytic == failureOptionAnalytic) && + (identical(other.outlet, outlet) || other.outlet == outlet) && + (identical(other.failureOptionOutlet, failureOptionOutlet) || + other.failureOptionOutlet == failureOptionOutlet) && + (identical(other.isFetching, isFetching) || + other.isFetching == isFetching) && + (identical(other.isFetchingOutlet, isFetchingOutlet) || + other.isFetchingOutlet == isFetchingOutlet)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + categoryAnalytic, + profitLossAnalytic, + paymentMethodAnalytic, + productAnalytic, + failureOptionAnalytic, + outlet, + failureOptionOutlet, + isFetching, + isFetchingOutlet, + ); + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$TransactionReportStateImplCopyWith<_$TransactionReportStateImpl> + get copyWith => + __$$TransactionReportStateImplCopyWithImpl<_$TransactionReportStateImpl>( + this, + _$identity, + ); +} + +abstract class _TransactionReportState implements TransactionReportState { + const factory _TransactionReportState({ + required final CategoryAnalytic categoryAnalytic, + required final ProfitLossAnalytic profitLossAnalytic, + required final PaymentMethodAnalytic paymentMethodAnalytic, + required final ProductAnalytic productAnalytic, + required final Option failureOptionAnalytic, + required final Outlet outlet, + required final Option failureOptionOutlet, + final bool isFetching, + final bool isFetchingOutlet, + }) = _$TransactionReportStateImpl; + + @override + CategoryAnalytic get categoryAnalytic; + @override + ProfitLossAnalytic get profitLossAnalytic; + @override + PaymentMethodAnalytic get paymentMethodAnalytic; + @override + ProductAnalytic get productAnalytic; + @override + Option get failureOptionAnalytic; + @override + Outlet get outlet; + @override + Option get failureOptionOutlet; + @override + bool get isFetching; + @override + bool get isFetchingOutlet; + + /// Create a copy of TransactionReportState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$TransactionReportStateImplCopyWith<_$TransactionReportStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/report/transaction_report/transaction_report_event.dart b/lib/application/report/transaction_report/transaction_report_event.dart new file mode 100644 index 0000000..5b744e6 --- /dev/null +++ b/lib/application/report/transaction_report/transaction_report_event.dart @@ -0,0 +1,10 @@ +part of 'transaction_report_bloc.dart'; + +@freezed +class TransactionReportEvent with _$TransactionReportEvent { + const factory TransactionReportEvent.fetchedOutlet() = _FetchedOutlet; + const factory TransactionReportEvent.fetchedTransaction( + DateTime dateFrom, + DateTime dateTo, + ) = _FetchedTransaction; +} diff --git a/lib/application/report/transaction_report/transaction_report_state.dart b/lib/application/report/transaction_report/transaction_report_state.dart new file mode 100644 index 0000000..8a54c88 --- /dev/null +++ b/lib/application/report/transaction_report/transaction_report_state.dart @@ -0,0 +1,26 @@ +part of 'transaction_report_bloc.dart'; + +@freezed +class TransactionReportState with _$TransactionReportState { + const factory TransactionReportState({ + required CategoryAnalytic categoryAnalytic, + required ProfitLossAnalytic profitLossAnalytic, + required PaymentMethodAnalytic paymentMethodAnalytic, + required ProductAnalytic productAnalytic, + required Option failureOptionAnalytic, + required Outlet outlet, + required Option failureOptionOutlet, + @Default(false) bool isFetching, + @Default(false) bool isFetchingOutlet, + }) = _TransactionReportState; + + factory TransactionReportState.initial() => TransactionReportState( + failureOptionAnalytic: none(), + outlet: Outlet.empty(), + failureOptionOutlet: none(), + categoryAnalytic: CategoryAnalytic.empty(), + profitLossAnalytic: ProfitLossAnalytic.empty(), + paymentMethodAnalytic: PaymentMethodAnalytic.empty(), + productAnalytic: ProductAnalytic.empty(), + ); +} diff --git a/lib/application/user/change_password_form/change_password_form_bloc.dart b/lib/application/user/change_password_form/change_password_form_bloc.dart new file mode 100644 index 0000000..6a5378c --- /dev/null +++ b/lib/application/user/change_password_form/change_password_form_bloc.dart @@ -0,0 +1,70 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/user/user.dart'; + +part 'change_password_form_event.dart'; +part 'change_password_form_state.dart'; +part 'change_password_form_bloc.freezed.dart'; + +@injectable +class ChangePasswordFormBloc + extends Bloc { + final IUserRepository _repository; + ChangePasswordFormBloc(this._repository) + : super(ChangePasswordFormState.initial()) { + on(_onChangePasswordFormEvent); + } + + Future _onChangePasswordFormEvent( + ChangePasswordFormEvent event, + Emitter emit, + ) { + return event.map( + newPasswordChanged: (e) async { + emit( + state.copyWith( + newPassword: e.newPassword, + failureOrChangePasswordOption: none(), + ), + ); + }, + currentPasswordChanged: (e) async { + emit( + state.copyWith( + currentPassword: e.currentPassword, + failureOrChangePasswordOption: none(), + ), + ); + }, + submitted: (e) async { + Either? failureOrSuccess; + emit( + state.copyWith( + isSubmitting: true, + failureOrChangePasswordOption: none(), + ), + ); + + final oldPasswordValid = state.newPassword.isNotEmpty; + final currentPasswordValid = state.currentPassword.isNotEmpty; + + if (oldPasswordValid && currentPasswordValid) { + failureOrSuccess = await _repository.changePassword( + newPassword: state.newPassword, + currentPassword: state.currentPassword, + ); + emit( + state.copyWith( + isSubmitting: false, + failureOrChangePasswordOption: optionOf(failureOrSuccess), + ), + ); + } + emit(state.copyWith(showErrorMessages: true, isSubmitting: false)); + }, + ); + } +} diff --git a/lib/application/user/change_password_form/change_password_form_bloc.freezed.dart b/lib/application/user/change_password_form/change_password_form_bloc.freezed.dart new file mode 100644 index 0000000..55ee2a0 --- /dev/null +++ b/lib/application/user/change_password_form/change_password_form_bloc.freezed.dart @@ -0,0 +1,766 @@ +// 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 'change_password_form_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$ChangePasswordFormEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String newPassword) newPasswordChanged, + required TResult Function(String currentPassword) currentPasswordChanged, + required TResult Function() submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String newPassword)? newPasswordChanged, + TResult? Function(String currentPassword)? currentPasswordChanged, + TResult? Function()? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String newPassword)? newPasswordChanged, + TResult Function(String currentPassword)? currentPasswordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_NewPasswordChanged value) newPasswordChanged, + required TResult Function(_CurrentPasswordChanged value) + currentPasswordChanged, + required TResult Function(_Submitted value) submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NewPasswordChanged value)? newPasswordChanged, + TResult? Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult? Function(_Submitted value)? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NewPasswordChanged value)? newPasswordChanged, + TResult Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChangePasswordFormEventCopyWith<$Res> { + factory $ChangePasswordFormEventCopyWith( + ChangePasswordFormEvent value, + $Res Function(ChangePasswordFormEvent) then, + ) = _$ChangePasswordFormEventCopyWithImpl<$Res, ChangePasswordFormEvent>; +} + +/// @nodoc +class _$ChangePasswordFormEventCopyWithImpl< + $Res, + $Val extends ChangePasswordFormEvent +> + implements $ChangePasswordFormEventCopyWith<$Res> { + _$ChangePasswordFormEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$NewPasswordChangedImplCopyWith<$Res> { + factory _$$NewPasswordChangedImplCopyWith( + _$NewPasswordChangedImpl value, + $Res Function(_$NewPasswordChangedImpl) then, + ) = __$$NewPasswordChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String newPassword}); +} + +/// @nodoc +class __$$NewPasswordChangedImplCopyWithImpl<$Res> + extends + _$ChangePasswordFormEventCopyWithImpl<$Res, _$NewPasswordChangedImpl> + implements _$$NewPasswordChangedImplCopyWith<$Res> { + __$$NewPasswordChangedImplCopyWithImpl( + _$NewPasswordChangedImpl _value, + $Res Function(_$NewPasswordChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? newPassword = null}) { + return _then( + _$NewPasswordChangedImpl( + null == newPassword + ? _value.newPassword + : newPassword // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$NewPasswordChangedImpl implements _NewPasswordChanged { + const _$NewPasswordChangedImpl(this.newPassword); + + @override + final String newPassword; + + @override + String toString() { + return 'ChangePasswordFormEvent.newPasswordChanged(newPassword: $newPassword)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$NewPasswordChangedImpl && + (identical(other.newPassword, newPassword) || + other.newPassword == newPassword)); + } + + @override + int get hashCode => Object.hash(runtimeType, newPassword); + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$NewPasswordChangedImplCopyWith<_$NewPasswordChangedImpl> get copyWith => + __$$NewPasswordChangedImplCopyWithImpl<_$NewPasswordChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String newPassword) newPasswordChanged, + required TResult Function(String currentPassword) currentPasswordChanged, + required TResult Function() submitted, + }) { + return newPasswordChanged(newPassword); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String newPassword)? newPasswordChanged, + TResult? Function(String currentPassword)? currentPasswordChanged, + TResult? Function()? submitted, + }) { + return newPasswordChanged?.call(newPassword); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String newPassword)? newPasswordChanged, + TResult Function(String currentPassword)? currentPasswordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (newPasswordChanged != null) { + return newPasswordChanged(newPassword); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NewPasswordChanged value) newPasswordChanged, + required TResult Function(_CurrentPasswordChanged value) + currentPasswordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return newPasswordChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NewPasswordChanged value)? newPasswordChanged, + TResult? Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return newPasswordChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NewPasswordChanged value)? newPasswordChanged, + TResult Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (newPasswordChanged != null) { + return newPasswordChanged(this); + } + return orElse(); + } +} + +abstract class _NewPasswordChanged implements ChangePasswordFormEvent { + const factory _NewPasswordChanged(final String newPassword) = + _$NewPasswordChangedImpl; + + String get newPassword; + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$NewPasswordChangedImplCopyWith<_$NewPasswordChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$CurrentPasswordChangedImplCopyWith<$Res> { + factory _$$CurrentPasswordChangedImplCopyWith( + _$CurrentPasswordChangedImpl value, + $Res Function(_$CurrentPasswordChangedImpl) then, + ) = __$$CurrentPasswordChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String currentPassword}); +} + +/// @nodoc +class __$$CurrentPasswordChangedImplCopyWithImpl<$Res> + extends + _$ChangePasswordFormEventCopyWithImpl< + $Res, + _$CurrentPasswordChangedImpl + > + implements _$$CurrentPasswordChangedImplCopyWith<$Res> { + __$$CurrentPasswordChangedImplCopyWithImpl( + _$CurrentPasswordChangedImpl _value, + $Res Function(_$CurrentPasswordChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? currentPassword = null}) { + return _then( + _$CurrentPasswordChangedImpl( + null == currentPassword + ? _value.currentPassword + : currentPassword // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$CurrentPasswordChangedImpl implements _CurrentPasswordChanged { + const _$CurrentPasswordChangedImpl(this.currentPassword); + + @override + final String currentPassword; + + @override + String toString() { + return 'ChangePasswordFormEvent.currentPasswordChanged(currentPassword: $currentPassword)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CurrentPasswordChangedImpl && + (identical(other.currentPassword, currentPassword) || + other.currentPassword == currentPassword)); + } + + @override + int get hashCode => Object.hash(runtimeType, currentPassword); + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CurrentPasswordChangedImplCopyWith<_$CurrentPasswordChangedImpl> + get copyWith => + __$$CurrentPasswordChangedImplCopyWithImpl<_$CurrentPasswordChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String newPassword) newPasswordChanged, + required TResult Function(String currentPassword) currentPasswordChanged, + required TResult Function() submitted, + }) { + return currentPasswordChanged(currentPassword); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String newPassword)? newPasswordChanged, + TResult? Function(String currentPassword)? currentPasswordChanged, + TResult? Function()? submitted, + }) { + return currentPasswordChanged?.call(currentPassword); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String newPassword)? newPasswordChanged, + TResult Function(String currentPassword)? currentPasswordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (currentPasswordChanged != null) { + return currentPasswordChanged(currentPassword); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NewPasswordChanged value) newPasswordChanged, + required TResult Function(_CurrentPasswordChanged value) + currentPasswordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return currentPasswordChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NewPasswordChanged value)? newPasswordChanged, + TResult? Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return currentPasswordChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NewPasswordChanged value)? newPasswordChanged, + TResult Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (currentPasswordChanged != null) { + return currentPasswordChanged(this); + } + return orElse(); + } +} + +abstract class _CurrentPasswordChanged implements ChangePasswordFormEvent { + const factory _CurrentPasswordChanged(final String currentPassword) = + _$CurrentPasswordChangedImpl; + + String get currentPassword; + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CurrentPasswordChangedImplCopyWith<_$CurrentPasswordChangedImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$SubmittedImplCopyWith<$Res> { + factory _$$SubmittedImplCopyWith( + _$SubmittedImpl value, + $Res Function(_$SubmittedImpl) then, + ) = __$$SubmittedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SubmittedImplCopyWithImpl<$Res> + extends _$ChangePasswordFormEventCopyWithImpl<$Res, _$SubmittedImpl> + implements _$$SubmittedImplCopyWith<$Res> { + __$$SubmittedImplCopyWithImpl( + _$SubmittedImpl _value, + $Res Function(_$SubmittedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ChangePasswordFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SubmittedImpl implements _Submitted { + const _$SubmittedImpl(); + + @override + String toString() { + return 'ChangePasswordFormEvent.submitted()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SubmittedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String newPassword) newPasswordChanged, + required TResult Function(String currentPassword) currentPasswordChanged, + required TResult Function() submitted, + }) { + return submitted(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String newPassword)? newPasswordChanged, + TResult? Function(String currentPassword)? currentPasswordChanged, + TResult? Function()? submitted, + }) { + return submitted?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String newPassword)? newPasswordChanged, + TResult Function(String currentPassword)? currentPasswordChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NewPasswordChanged value) newPasswordChanged, + required TResult Function(_CurrentPasswordChanged value) + currentPasswordChanged, + required TResult Function(_Submitted value) submitted, + }) { + return submitted(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NewPasswordChanged value)? newPasswordChanged, + TResult? Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return submitted?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NewPasswordChanged value)? newPasswordChanged, + TResult Function(_CurrentPasswordChanged value)? currentPasswordChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(this); + } + return orElse(); + } +} + +abstract class _Submitted implements ChangePasswordFormEvent { + const factory _Submitted() = _$SubmittedImpl; +} + +/// @nodoc +mixin _$ChangePasswordFormState { + String get newPassword => throw _privateConstructorUsedError; + String get currentPassword => throw _privateConstructorUsedError; + Option> get failureOrChangePasswordOption => + throw _privateConstructorUsedError; + bool get isSubmitting => throw _privateConstructorUsedError; + bool get showErrorMessages => throw _privateConstructorUsedError; + + /// Create a copy of ChangePasswordFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ChangePasswordFormStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChangePasswordFormStateCopyWith<$Res> { + factory $ChangePasswordFormStateCopyWith( + ChangePasswordFormState value, + $Res Function(ChangePasswordFormState) then, + ) = _$ChangePasswordFormStateCopyWithImpl<$Res, ChangePasswordFormState>; + @useResult + $Res call({ + String newPassword, + String currentPassword, + Option> failureOrChangePasswordOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class _$ChangePasswordFormStateCopyWithImpl< + $Res, + $Val extends ChangePasswordFormState +> + implements $ChangePasswordFormStateCopyWith<$Res> { + _$ChangePasswordFormStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ChangePasswordFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? newPassword = null, + Object? currentPassword = null, + Object? failureOrChangePasswordOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _value.copyWith( + newPassword: null == newPassword + ? _value.newPassword + : newPassword // ignore: cast_nullable_to_non_nullable + as String, + currentPassword: null == currentPassword + ? _value.currentPassword + : currentPassword // ignore: cast_nullable_to_non_nullable + as String, + failureOrChangePasswordOption: null == failureOrChangePasswordOption + ? _value.failureOrChangePasswordOption + : failureOrChangePasswordOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ChangePasswordFormStateImplCopyWith<$Res> + implements $ChangePasswordFormStateCopyWith<$Res> { + factory _$$ChangePasswordFormStateImplCopyWith( + _$ChangePasswordFormStateImpl value, + $Res Function(_$ChangePasswordFormStateImpl) then, + ) = __$$ChangePasswordFormStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String newPassword, + String currentPassword, + Option> failureOrChangePasswordOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class __$$ChangePasswordFormStateImplCopyWithImpl<$Res> + extends + _$ChangePasswordFormStateCopyWithImpl< + $Res, + _$ChangePasswordFormStateImpl + > + implements _$$ChangePasswordFormStateImplCopyWith<$Res> { + __$$ChangePasswordFormStateImplCopyWithImpl( + _$ChangePasswordFormStateImpl _value, + $Res Function(_$ChangePasswordFormStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ChangePasswordFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? newPassword = null, + Object? currentPassword = null, + Object? failureOrChangePasswordOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _$ChangePasswordFormStateImpl( + newPassword: null == newPassword + ? _value.newPassword + : newPassword // ignore: cast_nullable_to_non_nullable + as String, + currentPassword: null == currentPassword + ? _value.currentPassword + : currentPassword // ignore: cast_nullable_to_non_nullable + as String, + failureOrChangePasswordOption: null == failureOrChangePasswordOption + ? _value.failureOrChangePasswordOption + : failureOrChangePasswordOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$ChangePasswordFormStateImpl implements _ChangePasswordFormState { + const _$ChangePasswordFormStateImpl({ + required this.newPassword, + required this.currentPassword, + required this.failureOrChangePasswordOption, + this.isSubmitting = false, + this.showErrorMessages = false, + }); + + @override + final String newPassword; + @override + final String currentPassword; + @override + final Option> failureOrChangePasswordOption; + @override + @JsonKey() + final bool isSubmitting; + @override + @JsonKey() + final bool showErrorMessages; + + @override + String toString() { + return 'ChangePasswordFormState(newPassword: $newPassword, currentPassword: $currentPassword, failureOrChangePasswordOption: $failureOrChangePasswordOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChangePasswordFormStateImpl && + (identical(other.newPassword, newPassword) || + other.newPassword == newPassword) && + (identical(other.currentPassword, currentPassword) || + other.currentPassword == currentPassword) && + (identical( + other.failureOrChangePasswordOption, + failureOrChangePasswordOption, + ) || + other.failureOrChangePasswordOption == + failureOrChangePasswordOption) && + (identical(other.isSubmitting, isSubmitting) || + other.isSubmitting == isSubmitting) && + (identical(other.showErrorMessages, showErrorMessages) || + other.showErrorMessages == showErrorMessages)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + newPassword, + currentPassword, + failureOrChangePasswordOption, + isSubmitting, + showErrorMessages, + ); + + /// Create a copy of ChangePasswordFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ChangePasswordFormStateImplCopyWith<_$ChangePasswordFormStateImpl> + get copyWith => + __$$ChangePasswordFormStateImplCopyWithImpl< + _$ChangePasswordFormStateImpl + >(this, _$identity); +} + +abstract class _ChangePasswordFormState implements ChangePasswordFormState { + const factory _ChangePasswordFormState({ + required final String newPassword, + required final String currentPassword, + required final Option> + failureOrChangePasswordOption, + final bool isSubmitting, + final bool showErrorMessages, + }) = _$ChangePasswordFormStateImpl; + + @override + String get newPassword; + @override + String get currentPassword; + @override + Option> get failureOrChangePasswordOption; + @override + bool get isSubmitting; + @override + bool get showErrorMessages; + + /// Create a copy of ChangePasswordFormState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ChangePasswordFormStateImplCopyWith<_$ChangePasswordFormStateImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/application/user/change_password_form/change_password_form_event.dart b/lib/application/user/change_password_form/change_password_form_event.dart new file mode 100644 index 0000000..41b9342 --- /dev/null +++ b/lib/application/user/change_password_form/change_password_form_event.dart @@ -0,0 +1,11 @@ +part of 'change_password_form_bloc.dart'; + +@freezed +class ChangePasswordFormEvent with _$ChangePasswordFormEvent { + const factory ChangePasswordFormEvent.newPasswordChanged(String newPassword) = + _NewPasswordChanged; + const factory ChangePasswordFormEvent.currentPasswordChanged( + String currentPassword, + ) = _CurrentPasswordChanged; + const factory ChangePasswordFormEvent.submitted() = _Submitted; +} diff --git a/lib/application/user/change_password_form/change_password_form_state.dart b/lib/application/user/change_password_form/change_password_form_state.dart new file mode 100644 index 0000000..d735ef9 --- /dev/null +++ b/lib/application/user/change_password_form/change_password_form_state.dart @@ -0,0 +1,18 @@ +part of 'change_password_form_bloc.dart'; + +@freezed +class ChangePasswordFormState with _$ChangePasswordFormState { + const factory ChangePasswordFormState({ + required String newPassword, + required String currentPassword, + required Option> failureOrChangePasswordOption, + @Default(false) bool isSubmitting, + @Default(false) bool showErrorMessages, + }) = _ChangePasswordFormState; + + factory ChangePasswordFormState.initial() => ChangePasswordFormState( + currentPassword: '', + newPassword: '', + failureOrChangePasswordOption: none(), + ); +} diff --git a/lib/application/user/user_edit_form/user_edit_form_bloc.dart b/lib/application/user/user_edit_form/user_edit_form_bloc.dart new file mode 100644 index 0000000..b62f52d --- /dev/null +++ b/lib/application/user/user_edit_form/user_edit_form_bloc.dart @@ -0,0 +1,46 @@ +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/user/user.dart'; + +part 'user_edit_form_event.dart'; +part 'user_edit_form_state.dart'; +part 'user_edit_form_bloc.freezed.dart'; + +@injectable +class UserEditFormBloc extends Bloc { + final IUserRepository _repository; + UserEditFormBloc(this._repository) : super(UserEditFormState.initial()) { + on(_onUserEditFormEvent); + } + + Future _onUserEditFormEvent( + UserEditFormEvent event, + Emitter emit, + ) { + return event.map( + nameChanged: (e) async { + emit(state.copyWith(name: e.name, failureOrUserOption: none())); + }, + submitted: (e) async { + Either? failureOrUser; + emit(state.copyWith(isSubmitting: true, failureOrUserOption: none())); + + final nameValid = state.name.isNotEmpty; + + if (nameValid) { + failureOrUser = await _repository.editUser(name: state.name); + emit( + state.copyWith( + isSubmitting: false, + failureOrUserOption: optionOf(failureOrUser), + ), + ); + } + emit(state.copyWith(showErrorMessages: true, isSubmitting: false)); + }, + ); + } +} diff --git a/lib/application/user/user_edit_form/user_edit_form_bloc.freezed.dart b/lib/application/user/user_edit_form/user_edit_form_bloc.freezed.dart new file mode 100644 index 0000000..99fb54a --- /dev/null +++ b/lib/application/user/user_edit_form/user_edit_form_bloc.freezed.dart @@ -0,0 +1,542 @@ +// 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 'user_edit_form_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$UserEditFormEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function() submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function()? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function()? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_Submitted value) submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_Submitted value)? submitted, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $UserEditFormEventCopyWith<$Res> { + factory $UserEditFormEventCopyWith( + UserEditFormEvent value, + $Res Function(UserEditFormEvent) then, + ) = _$UserEditFormEventCopyWithImpl<$Res, UserEditFormEvent>; +} + +/// @nodoc +class _$UserEditFormEventCopyWithImpl<$Res, $Val extends UserEditFormEvent> + implements $UserEditFormEventCopyWith<$Res> { + _$UserEditFormEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of UserEditFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$NameChangedImplCopyWith<$Res> { + factory _$$NameChangedImplCopyWith( + _$NameChangedImpl value, + $Res Function(_$NameChangedImpl) then, + ) = __$$NameChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String name}); +} + +/// @nodoc +class __$$NameChangedImplCopyWithImpl<$Res> + extends _$UserEditFormEventCopyWithImpl<$Res, _$NameChangedImpl> + implements _$$NameChangedImplCopyWith<$Res> { + __$$NameChangedImplCopyWithImpl( + _$NameChangedImpl _value, + $Res Function(_$NameChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserEditFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? name = null}) { + return _then( + _$NameChangedImpl( + null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$NameChangedImpl implements _NameChanged { + const _$NameChangedImpl(this.name); + + @override + final String name; + + @override + String toString() { + return 'UserEditFormEvent.nameChanged(name: $name)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$NameChangedImpl && + (identical(other.name, name) || other.name == name)); + } + + @override + int get hashCode => Object.hash(runtimeType, name); + + /// Create a copy of UserEditFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$NameChangedImplCopyWith<_$NameChangedImpl> get copyWith => + __$$NameChangedImplCopyWithImpl<_$NameChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function() submitted, + }) { + return nameChanged(name); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function()? submitted, + }) { + return nameChanged?.call(name); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (nameChanged != null) { + return nameChanged(name); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_Submitted value) submitted, + }) { + return nameChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return nameChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (nameChanged != null) { + return nameChanged(this); + } + return orElse(); + } +} + +abstract class _NameChanged implements UserEditFormEvent { + const factory _NameChanged(final String name) = _$NameChangedImpl; + + String get name; + + /// Create a copy of UserEditFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$NameChangedImplCopyWith<_$NameChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$SubmittedImplCopyWith<$Res> { + factory _$$SubmittedImplCopyWith( + _$SubmittedImpl value, + $Res Function(_$SubmittedImpl) then, + ) = __$$SubmittedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SubmittedImplCopyWithImpl<$Res> + extends _$UserEditFormEventCopyWithImpl<$Res, _$SubmittedImpl> + implements _$$SubmittedImplCopyWith<$Res> { + __$$SubmittedImplCopyWithImpl( + _$SubmittedImpl _value, + $Res Function(_$SubmittedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserEditFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SubmittedImpl implements _Submitted { + const _$SubmittedImpl(); + + @override + String toString() { + return 'UserEditFormEvent.submitted()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SubmittedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function() submitted, + }) { + return submitted(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function()? submitted, + }) { + return submitted?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function()? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_Submitted value) submitted, + }) { + return submitted(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_Submitted value)? submitted, + }) { + return submitted?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_Submitted value)? submitted, + required TResult orElse(), + }) { + if (submitted != null) { + return submitted(this); + } + return orElse(); + } +} + +abstract class _Submitted implements UserEditFormEvent { + const factory _Submitted() = _$SubmittedImpl; +} + +/// @nodoc +mixin _$UserEditFormState { + String get name => throw _privateConstructorUsedError; + Option> get failureOrUserOption => + throw _privateConstructorUsedError; + bool get isSubmitting => throw _privateConstructorUsedError; + bool get showErrorMessages => throw _privateConstructorUsedError; + + /// Create a copy of UserEditFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $UserEditFormStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $UserEditFormStateCopyWith<$Res> { + factory $UserEditFormStateCopyWith( + UserEditFormState value, + $Res Function(UserEditFormState) then, + ) = _$UserEditFormStateCopyWithImpl<$Res, UserEditFormState>; + @useResult + $Res call({ + String name, + Option> failureOrUserOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class _$UserEditFormStateCopyWithImpl<$Res, $Val extends UserEditFormState> + implements $UserEditFormStateCopyWith<$Res> { + _$UserEditFormStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of UserEditFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? failureOrUserOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + failureOrUserOption: null == failureOrUserOption + ? _value.failureOrUserOption + : failureOrUserOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$UserEditFormStateImplCopyWith<$Res> + implements $UserEditFormStateCopyWith<$Res> { + factory _$$UserEditFormStateImplCopyWith( + _$UserEditFormStateImpl value, + $Res Function(_$UserEditFormStateImpl) then, + ) = __$$UserEditFormStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String name, + Option> failureOrUserOption, + bool isSubmitting, + bool showErrorMessages, + }); +} + +/// @nodoc +class __$$UserEditFormStateImplCopyWithImpl<$Res> + extends _$UserEditFormStateCopyWithImpl<$Res, _$UserEditFormStateImpl> + implements _$$UserEditFormStateImplCopyWith<$Res> { + __$$UserEditFormStateImplCopyWithImpl( + _$UserEditFormStateImpl _value, + $Res Function(_$UserEditFormStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserEditFormState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? failureOrUserOption = null, + Object? isSubmitting = null, + Object? showErrorMessages = null, + }) { + return _then( + _$UserEditFormStateImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + failureOrUserOption: null == failureOrUserOption + ? _value.failureOrUserOption + : failureOrUserOption // ignore: cast_nullable_to_non_nullable + as Option>, + isSubmitting: null == isSubmitting + ? _value.isSubmitting + : isSubmitting // ignore: cast_nullable_to_non_nullable + as bool, + showErrorMessages: null == showErrorMessages + ? _value.showErrorMessages + : showErrorMessages // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$UserEditFormStateImpl implements _UserEditFormState { + const _$UserEditFormStateImpl({ + required this.name, + required this.failureOrUserOption, + this.isSubmitting = false, + this.showErrorMessages = false, + }); + + @override + final String name; + @override + final Option> failureOrUserOption; + @override + @JsonKey() + final bool isSubmitting; + @override + @JsonKey() + final bool showErrorMessages; + + @override + String toString() { + return 'UserEditFormState(name: $name, failureOrUserOption: $failureOrUserOption, isSubmitting: $isSubmitting, showErrorMessages: $showErrorMessages)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$UserEditFormStateImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.failureOrUserOption, failureOrUserOption) || + other.failureOrUserOption == failureOrUserOption) && + (identical(other.isSubmitting, isSubmitting) || + other.isSubmitting == isSubmitting) && + (identical(other.showErrorMessages, showErrorMessages) || + other.showErrorMessages == showErrorMessages)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + name, + failureOrUserOption, + isSubmitting, + showErrorMessages, + ); + + /// Create a copy of UserEditFormState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$UserEditFormStateImplCopyWith<_$UserEditFormStateImpl> get copyWith => + __$$UserEditFormStateImplCopyWithImpl<_$UserEditFormStateImpl>( + this, + _$identity, + ); +} + +abstract class _UserEditFormState implements UserEditFormState { + const factory _UserEditFormState({ + required final String name, + required final Option> failureOrUserOption, + final bool isSubmitting, + final bool showErrorMessages, + }) = _$UserEditFormStateImpl; + + @override + String get name; + @override + Option> get failureOrUserOption; + @override + bool get isSubmitting; + @override + bool get showErrorMessages; + + /// Create a copy of UserEditFormState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$UserEditFormStateImplCopyWith<_$UserEditFormStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/user/user_edit_form/user_edit_form_event.dart b/lib/application/user/user_edit_form/user_edit_form_event.dart new file mode 100644 index 0000000..6162825 --- /dev/null +++ b/lib/application/user/user_edit_form/user_edit_form_event.dart @@ -0,0 +1,7 @@ +part of 'user_edit_form_bloc.dart'; + +@freezed +class UserEditFormEvent with _$UserEditFormEvent { + const factory UserEditFormEvent.nameChanged(String name) = _NameChanged; + const factory UserEditFormEvent.submitted() = _Submitted; +} diff --git a/lib/application/user/user_edit_form/user_edit_form_state.dart b/lib/application/user/user_edit_form/user_edit_form_state.dart new file mode 100644 index 0000000..8b848c5 --- /dev/null +++ b/lib/application/user/user_edit_form/user_edit_form_state.dart @@ -0,0 +1,14 @@ +part of 'user_edit_form_bloc.dart'; + +@freezed +class UserEditFormState with _$UserEditFormState { + const factory UserEditFormState({ + required String name, + required Option> failureOrUserOption, + @Default(false) bool isSubmitting, + @Default(false) bool showErrorMessages, + }) = _UserEditFormState; + + factory UserEditFormState.initial() => + UserEditFormState(name: '', failureOrUserOption: none()); +} diff --git a/lib/common/api/api_client.dart b/lib/common/api/api_client.dart index ca71634..95ab220 100644 --- a/lib/common/api/api_client.dart +++ b/lib/common/api/api_client.dart @@ -25,6 +25,7 @@ class ApiClient { ApiClient(this._dio, this._env) { _dio.options.baseUrl = _env.baseUrl; + _dio.options.validateStatus = (status) => status! < 500; _dio.options.connectTimeout = const Duration(seconds: 20); _dio.interceptors.add(BadNetworkErrorInterceptor()); _dio.interceptors.add(BadRequestErrorInterceptor()); diff --git a/lib/common/constant/app_constant.dart b/lib/common/constant/app_constant.dart index b0dbc06..26db70f 100644 --- a/lib/common/constant/app_constant.dart +++ b/lib/common/constant/app_constant.dart @@ -1,3 +1,3 @@ class AppConstant { - static const String appName = ""; + static const String appName = "Enaklo Owner"; } diff --git a/lib/common/constant/local_storage_key.dart b/lib/common/constant/local_storage_key.dart new file mode 100644 index 0000000..06f4f98 --- /dev/null +++ b/lib/common/constant/local_storage_key.dart @@ -0,0 +1,6 @@ +class LocalStorageKey { + static const String lang = 'lang'; + static const String token = 'token'; + static const String user = 'user'; + static const String selectedOutletId = 'selected_outlet_id'; +} diff --git a/lib/common/di/di_firebase.dart b/lib/common/di/di_firebase.dart new file mode 100644 index 0000000..8ab3f0d --- /dev/null +++ b/lib/common/di/di_firebase.dart @@ -0,0 +1,8 @@ +import 'package:firebase_core/firebase_core.dart'; +import 'package:injectable/injectable.dart'; + +@module +abstract class FirebaseDi { + @preResolve + Future get firebaseApp => Firebase.initializeApp(); +} diff --git a/lib/common/di/di_package_info.dart b/lib/common/di/di_package_info.dart new file mode 100644 index 0000000..cbc71c7 --- /dev/null +++ b/lib/common/di/di_package_info.dart @@ -0,0 +1,9 @@ +import 'package:injectable/injectable.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +@module +abstract class PackageInfoDi { + @preResolve // karena butuh async init + @lazySingleton + Future get packageInfo => PackageInfo.fromPlatform(); +} diff --git a/lib/common/extension/build_context_extension.dart b/lib/common/extension/build_context_extension.dart new file mode 100644 index 0000000..6b8ed04 --- /dev/null +++ b/lib/common/extension/build_context_extension.dart @@ -0,0 +1,5 @@ +part of 'extension.dart'; + +extension BuildContextX on BuildContext { + AppLocalizations get lang => AppLocalizations.of(this)!; +} diff --git a/lib/common/extension/date_extension.dart b/lib/common/extension/date_extension.dart new file mode 100644 index 0000000..65e60a1 --- /dev/null +++ b/lib/common/extension/date_extension.dart @@ -0,0 +1,38 @@ +part of 'extension.dart'; + +extension DateTimeIndonesia on DateTime { + /// Format: 13 Agustus 2025 + String get toDate { + return DateFormat('d MMMM yyyy', 'id_ID').format(this); + } + + /// Format: 13 Agustus 2025 20:00 + String get toDatetime { + return DateFormat('d MMMM yyyy HH:mm', 'id_ID').format(this); + } + + /// Format: Rabu, 13 Agustus 2025 + String get toDayDate { + return DateFormat('EEEE, d MMMM yyyy', 'id_ID').format(this); + } + + /// Format: 13/08/2025 + String get toShortDate { + return DateFormat('dd/MM/yyyy', 'id_ID').format(this); + } + + /// Format: 13-08-2025 + String get toServerDate { + return DateFormat('dd-MM-yyyy', 'id_ID').format(this); + } + + /// Format jam: 14:30 + String get toHourMinute { + return DateFormat('HH:mm', 'id_ID').format(this); + } + + /// Format jam + detik: 14:30:05 + String get toHourMinuteSecond { + return DateFormat('HH:mm:ss', 'id_ID').format(this); + } +} diff --git a/lib/common/extension/extension.dart b/lib/common/extension/extension.dart index 7199fdd..64bd608 100644 --- a/lib/common/extension/extension.dart +++ b/lib/common/extension/extension.dart @@ -1 +1,9 @@ - // TODO: define your code +import 'package:flutter/widgets.dart'; +import 'package:intl/intl.dart'; + +import '../../l10n/app_localizations.dart'; + +part 'int_extension.dart'; +part 'date_extension.dart'; +part 'string_extension.dart'; +part 'build_context_extension.dart'; diff --git a/lib/common/extension/int_extension.dart b/lib/common/extension/int_extension.dart new file mode 100644 index 0000000..b9f4180 --- /dev/null +++ b/lib/common/extension/int_extension.dart @@ -0,0 +1,9 @@ +part of 'extension.dart'; + +extension IntegerExt on int { + String get currencyFormatRp => NumberFormat.currency( + locale: 'id', + symbol: 'Rp. ', + decimalDigits: 0, + ).format(this); +} diff --git a/lib/common/extension/string_extension.dart b/lib/common/extension/string_extension.dart new file mode 100644 index 0000000..23687e9 --- /dev/null +++ b/lib/common/extension/string_extension.dart @@ -0,0 +1,28 @@ +part of 'extension.dart'; + +extension StringExt on String { + int get toIntegerFromText { + final cleanedText = replaceAll(RegExp(r'[^0-9]'), ''); + final parsedValue = int.tryParse(cleanedText) ?? 0; + return parsedValue; + } + + String get currencyFormatRpV2 { + final parsedValue = int.tryParse(this) ?? 0; + return NumberFormat.currency( + locale: 'id', + symbol: 'Rp. ', + decimalDigits: 0, + ).format(parsedValue); + } + + String get toTitleCase { + if (isEmpty) return ''; + return split(' ') + .map((word) { + if (word.isEmpty) return ''; + return word[0].toUpperCase() + word.substring(1).toLowerCase(); + }) + .join(' '); + } +} diff --git a/lib/common/function/app_function.dart b/lib/common/function/app_function.dart index ddffdda..617d7bf 100644 --- a/lib/common/function/app_function.dart +++ b/lib/common/function/app_function.dart @@ -1,4 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../injection.dart'; +import '../constant/local_storage_key.dart'; void dismissKeyboard(BuildContext context) { final currentFocus = FocusScope.of(context); @@ -6,3 +10,10 @@ void dismissKeyboard(BuildContext context) { FocusManager.instance.primaryFocus?.unfocus(); } } + +Map getAuthorizationHeader() { + return { + 'Authorization': + 'Bearer ${getIt().getString(LocalStorageKey.token)}', + }; +} diff --git a/lib/common/painter/wave_painter.dart b/lib/common/painter/wave_painter.dart new file mode 100644 index 0000000..750a7f5 --- /dev/null +++ b/lib/common/painter/wave_painter.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'dart:math' as math; + +class WavePainter extends CustomPainter { + final double animation; + final Color color; + + WavePainter({required this.animation, required this.color}); + + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = color + ..strokeWidth = 1.5 + ..style = PaintingStyle.stroke; + + final path = Path(); + + // Create simplified wave patterns (reduced from 3 to 2 waves) + for (int i = 0; i < 2; i++) { + path.reset(); + final double waveHeight = 15 + (i * 8); + final double frequency = 0.015 + (i * 0.008); + final double phase = animation + (i * math.pi / 2); + + path.moveTo(0, size.height * 0.4 + (i * 40)); + + for (double x = 0; x <= size.width; x += 8) { + final y = + size.height * 0.4 + + (i * 40) + + math.sin((x * frequency) + phase) * waveHeight; + path.lineTo(x, y); + } + + canvas.drawPath(path, paint..color = color.withOpacity(0.2 - (i * 0.05))); + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => true; +} diff --git a/lib/common/theme/app_color.dart b/lib/common/theme/app_color.dart index 63dd90f..5485daa 100644 --- a/lib/common/theme/app_color.dart +++ b/lib/common/theme/app_color.dart @@ -1,5 +1,65 @@ part of 'theme.dart'; class AppColor { - // TODO: define color + // Primary Colors + static const Color primary = Color.fromARGB(255, 196, 2, 2); // #d90000 + static const Color primaryLight = Color(0xFFFF4D4D); // merah terang + static const Color primaryDark = Color(0xFF990000); // merah gelap + + // Secondary Colors + static const Color secondary = Color(0xFF4CAF50); + static const Color secondaryLight = Color(0xFF81C784); + static const Color secondaryDark = Color(0xFF388E3C); + + // Background Colors + static const Color background = Color(0xFFF8F9FA); + static const Color backgroundLight = Color(0xFFFFFFFF); + static const Color backgroundDark = Color(0xFF1A1A1A); + static const Color surface = Color(0xFFFFFFFF); + static const Color surfaceDark = Color(0xFF2D2D2D); + + // Text Colors + static const Color textPrimary = Color(0xFF212121); + static const Color textSecondary = Color(0xFF757575); + static const Color textLight = Color(0xFFBDBDBD); + static const Color textWhite = Color(0xFFFFFFFF); + + // Status Colors + static const Color success = Color(0xFF4CAF50); + static const Color error = Color(0xFFE53E3E); + static const Color warning = Color(0xFFFF9800); + static const Color info = Color(0xFF2196F3); + + // Border Colors + static const Color border = Color(0xFFE0E0E0); + static const Color borderLight = Color(0xFFF0F0F0); + static const Color borderDark = Color(0xFFBDBDBD); + + // Basic Color + static const Color white = Color(0xFFFFFFFF); + static const Color black = Color(0xFF000000); + + // Gradient Colors + static const List primaryGradient = [ + Color(0xFFD90000), // primary + Color(0xFF990000), // dark red + ]; + static const List successGradient = [ + Color(0xFF4CAF50), + Color(0xFF81C784), + ]; + + static const List backgroundGradient = [ + Color(0xFFF5F5F5), + Color(0xFFE8E8E8), + ]; + + // Opacity Variations + static Color primaryWithOpacity(double opacity) => + primary.withOpacity(opacity); + static Color successWithOpacity(double opacity) => + success.withOpacity(opacity); + static Color errorWithOpacity(double opacity) => error.withOpacity(opacity); + static Color warningWithOpacity(double opacity) => + warning.withOpacity(opacity); } diff --git a/lib/common/theme/app_style.dart b/lib/common/theme/app_style.dart index 5c422cc..246e087 100644 --- a/lib/common/theme/app_style.dart +++ b/lib/common/theme/app_style.dart @@ -1,5 +1,27 @@ part of 'theme.dart'; class AppStyle { - // TODO: define style + static TextStyle xs = TextStyle(color: AppColor.textPrimary, fontSize: 11); + + static TextStyle sm = TextStyle(color: AppColor.textPrimary, fontSize: 12); + + static TextStyle md = TextStyle(color: AppColor.textPrimary, fontSize: 14); + + static TextStyle lg = TextStyle(color: AppColor.textPrimary, fontSize: 16); + + static TextStyle xl = TextStyle(color: AppColor.textPrimary, fontSize: 18); + + static TextStyle xxl = TextStyle(color: AppColor.textPrimary, fontSize: 20); + + static TextStyle h6 = TextStyle(color: AppColor.textPrimary, fontSize: 22); + + static TextStyle h5 = TextStyle(color: AppColor.textPrimary, fontSize: 24); + + static TextStyle h4 = TextStyle(color: AppColor.textPrimary, fontSize: 26); + + static TextStyle h3 = TextStyle(color: AppColor.textPrimary, fontSize: 28); + + static TextStyle h2 = TextStyle(color: AppColor.textPrimary, fontSize: 30); + + static TextStyle h1 = TextStyle(color: AppColor.textPrimary, fontSize: 32); } diff --git a/lib/common/theme/app_value.dart b/lib/common/theme/app_value.dart index d76dbcc..327463c 100644 --- a/lib/common/theme/app_value.dart +++ b/lib/common/theme/app_value.dart @@ -1,5 +1,7 @@ part of 'theme.dart'; class AppValue { - // TODO: define value + static const double padding = 20.0; + static const double margin = 20.0; + static const double radius = 16.0; } diff --git a/lib/common/theme/theme.dart b/lib/common/theme/theme.dart index 4d69f35..844f0d6 100644 --- a/lib/common/theme/theme.dart +++ b/lib/common/theme/theme.dart @@ -1,11 +1,69 @@ import 'package:flutter/material.dart'; +import '../../presentation/components/assets/fonts.gen.dart'; + part 'app_color.dart'; part 'app_style.dart'; part 'app_value.dart'; class ThemeApp { static ThemeData get theme => ThemeData( - useMaterial3: true, - ); + useMaterial3: true, + scaffoldBackgroundColor: AppColor.background, + fontFamily: FontFamily.quicksand, + inputDecorationTheme: InputDecorationTheme( + hintStyle: AppStyle.md.copyWith(color: AppColor.textSecondary), + contentPadding: const EdgeInsets.symmetric(horizontal: AppValue.padding), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppValue.radius), + borderSide: const BorderSide(color: AppColor.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppValue.radius), + borderSide: const BorderSide(color: AppColor.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppValue.radius), + borderSide: const BorderSide(color: AppColor.primary, width: 2), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(AppValue.radius), + borderSide: const BorderSide(color: AppColor.error), + ), + filled: true, + fillColor: AppColor.backgroundLight, + ), + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppValue.radius), + ), + ), + ), + bottomNavigationBarTheme: BottomNavigationBarThemeData( + backgroundColor: AppColor.white, + selectedItemColor: AppColor.primary, + unselectedItemColor: AppColor.textSecondary, + selectedLabelStyle: AppStyle.md.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w600, + ), + unselectedLabelStyle: AppStyle.md.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + appBarTheme: AppBarTheme( + backgroundColor: AppColor.primary, + elevation: 1, + titleTextStyle: AppStyle.xl.copyWith( + fontWeight: FontWeight.w700, + letterSpacing: -0.5, + color: AppColor.white, + ), + iconTheme: const IconThemeData(color: AppColor.white), + ), + ); } diff --git a/lib/common/url/api_path.dart b/lib/common/url/api_path.dart new file mode 100644 index 0000000..cdccbd3 --- /dev/null +++ b/lib/common/url/api_path.dart @@ -0,0 +1,36 @@ +class ApiPath { + // Auth + static const String login = '/api/v1/auth/login'; + static const String logout = '/api/v1/auth/logout'; + + // Analytic + static const String salesAnalytic = '/api/v1/analytics/sales'; + static const String profitLossAnalytic = '/api/v1/analytics/profit-loss'; + static const String categoryAnalytic = '/api/v1/analytics/categories'; + static const String dashboardAnalytic = '/api/v1/analytics/dashboard'; + static const String productAnalytic = '/api/v1/analytics/products'; + static const String paymentMethodAnalytic = + '/api/v1/analytics/paymentMethods'; + + // Inventory + static const String inventoryReportDetail = + '/api/v1/inventory/report/details'; + + // Category + static const String category = '/api/v1/categories'; + + // Product + static const String product = '/api/v1/products'; + + // Customer + static const String customer = '/api/v1/customers'; + + // Order + static const String order = '/api/v1/orders'; + + // Outlet + static const String outlet = '/api/v1/outlets'; + + // User + static const String user = '/api/v1/users'; +} diff --git a/lib/common/utils/device_info_service.dart b/lib/common/utils/device_info_service.dart new file mode 100644 index 0000000..0791a03 --- /dev/null +++ b/lib/common/utils/device_info_service.dart @@ -0,0 +1,82 @@ +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:injectable/injectable.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +class DeviceInfo { + final String deviceId; + final String deviceName; + final String deviceType; + final String platform; + final String osVersion; + final String appVersion; + + const DeviceInfo({ + required this.deviceId, + required this.deviceName, + required this.deviceType, + required this.platform, + required this.osVersion, + required this.appVersion, + }); + + Map toJson() => { + 'device_id': deviceId, + 'device_name': deviceName, + 'device_type': deviceType, + 'platform': platform, + 'os_version': osVersion, + 'app_version': appVersion, + }; +} + +@lazySingleton +class DeviceInfoService { + final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin(); + + Future getDeviceInfo() async { + final packageInfo = await PackageInfo.fromPlatform(); + final appVersion = packageInfo.version; + + if (Platform.isAndroid) { + final info = await _deviceInfo.androidInfo; + return DeviceInfo( + deviceId: info.id, + deviceName: '${info.manufacturer} ${info.model}', + deviceType: _resolveDeviceType(info.model), + platform: 'android', + osVersion: 'Android ${info.version.release}', + appVersion: appVersion, + ); + } else if (Platform.isIOS) { + final info = await _deviceInfo.iosInfo; + return DeviceInfo( + deviceId: info.identifierForVendor ?? '', + deviceName: info.name, + deviceType: _resolveDeviceType(info.model), + platform: 'ios', + osVersion: '${info.systemName} ${info.systemVersion}', + appVersion: appVersion, + ); + } + + // Fallback (web/desktop — tidak dipakai tapi aman) + return DeviceInfo( + deviceId: 'unknown', + deviceName: 'unknown', + deviceType: 'desktop', + platform: 'web', + osVersion: 'unknown', + appVersion: appVersion, + ); + } + + /// Tentukan device_type berdasarkan model name. + /// Nilai valid: 'mobile' | 'tablet' | 'desktop' + String _resolveDeviceType(String model) { + final lower = model.toLowerCase(); + if (lower.contains('ipad') || lower.contains('tablet')) return 'tablet'; + return 'mobile'; + } +} diff --git a/lib/common/utils/fcm_service.dart b/lib/common/utils/fcm_service.dart new file mode 100644 index 0000000..de2dff5 --- /dev/null +++ b/lib/common/utils/fcm_service.dart @@ -0,0 +1,200 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:injectable/injectable.dart'; + +/// Background message handler — must be a top-level function. +/// Firebase must be initialized here for background isolate. +@pragma('vm:entry-point') +Future firebaseMessagingBackgroundHandler(RemoteMessage message) async { + await Firebase.initializeApp(); + debugPrint('[FCM] Background message: ${message.messageId}'); + // Show local notification for data-only messages in background + await _showBackgroundNotification(message); +} + +/// Standalone local notifications plugin for background isolate use. +final _backgroundLocalNotifications = FlutterLocalNotificationsPlugin(); + +Future _showBackgroundNotification(RemoteMessage message) async { + const androidInit = AndroidInitializationSettings('@drawable/ic_notification'); + await _backgroundLocalNotifications.initialize( + const InitializationSettings(android: androidInit), + ); + + final notification = message.notification; + // Only show manually for data-only messages (FCM auto-shows notification messages) + if (notification != null) return; + + final title = message.data['title'] as String?; + final body = message.data['body'] as String?; + if (title == null && body == null) return; + + await _backgroundLocalNotifications.show( + message.hashCode, + title, + body, + const NotificationDetails( + android: AndroidNotificationDetails( + 'high_importance_channel', + 'High Importance Notifications', + importance: Importance.high, + priority: Priority.high, + icon: '@drawable/ic_notification', + ), + ), + payload: jsonEncode(message.data), + ); +} + +@lazySingleton +class FcmService { + final FirebaseMessaging _messaging = FirebaseMessaging.instance; + + final FlutterLocalNotificationsPlugin _localNotifications = + FlutterLocalNotificationsPlugin(); + + static const _androidChannel = AndroidNotificationChannel( + 'high_importance_channel', + 'High Importance Notifications', + description: 'This channel is used for important notifications.', + importance: Importance.max, // max agar banner (heads-up) muncul + playSound: true, + enableVibration: true, + enableLights: true, + ); + + /// Call this once during app startup (after Firebase.initializeApp). + Future initialize({ + void Function(RemoteMessage message)? onMessageTap, + }) async { + // 1. Request permission (iOS + Android 13+) + await _requestPermission(); + + // 2. Setup local notifications (needed to show heads-up on Android) + await _setupLocalNotifications(); + + // 3. Register background handler + FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler); + + // 4. Foreground message handler + FirebaseMessaging.onMessage.listen((message) { + debugPrint('[FCM] Foreground message: ${message.messageId}'); + _showLocalNotification(message); + }); + + // 5. App opened from notification (background → foreground) + FirebaseMessaging.onMessageOpenedApp.listen((message) { + debugPrint('[FCM] Notification tapped (background): ${message.messageId}'); + onMessageTap?.call(message); + }); + + // 6. App launched from terminated state via notification + final initialMessage = await _messaging.getInitialMessage(); + if (initialMessage != null) { + debugPrint('[FCM] App launched from notification: ${initialMessage.messageId}'); + onMessageTap?.call(initialMessage); + } + + // 7. Print FCM token for debugging + final token = await getToken(); + debugPrint('[FCM] Token: $token'); + } + + Future _requestPermission() async { + final settings = await _messaging.requestPermission( + alert: true, + badge: true, + sound: true, + ); + debugPrint('[FCM] Permission status: ${settings.authorizationStatus}'); + } + + Future _setupLocalNotifications() async { + // Android init + const androidInit = AndroidInitializationSettings('@mipmap/launcher_icon'); + + // iOS init + const iosInit = DarwinInitializationSettings( + requestAlertPermission: false, + requestBadgePermission: false, + requestSoundPermission: false, + ); + + const initSettings = InitializationSettings( + android: androidInit, + iOS: iosInit, + ); + + await _localNotifications.initialize( + initSettings, + onDidReceiveNotificationResponse: (details) { + debugPrint('[FCM] Local notification tapped: ${details.payload}'); + }, + ); + + // Create Android notification channel + if (Platform.isAndroid) { + await _localNotifications + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel(_androidChannel); + } + + // iOS: show notification even when app is in foreground + await _messaging.setForegroundNotificationPresentationOptions( + alert: true, + badge: true, + sound: true, + ); + } + + void _showLocalNotification(RemoteMessage message) { + final notification = message.notification; + if (notification == null) return; + + _localNotifications.show( + notification.hashCode, + notification.title, + notification.body, + NotificationDetails( + android: AndroidNotificationDetails( + _androidChannel.id, + _androidChannel.name, + channelDescription: _androidChannel.description, + icon: '@drawable/ic_notification', + importance: Importance.max, + priority: Priority.high, + playSound: true, + enableVibration: true, + // Heads-up notification (banner) + fullScreenIntent: false, + ), + iOS: const DarwinNotificationDetails( + presentAlert: true, + presentBadge: true, + presentSound: true, + ), + ), + payload: jsonEncode(message.data), + ); + } + + /// Returns the FCM registration token for this device. + Future getToken() => _messaging.getToken(); + + /// Subscribe to a topic (e.g. 'all', 'promo'). + Future subscribeToTopic(String topic) => + _messaging.subscribeToTopic(topic); + + /// Unsubscribe from a topic. + Future unsubscribeFromTopic(String topic) => + _messaging.unsubscribeFromTopic(topic); + + /// Listen for token refresh. + Stream get onTokenRefresh => _messaging.onTokenRefresh; +} diff --git a/lib/common/utils/pdf_service.dart b/lib/common/utils/pdf_service.dart new file mode 100644 index 0000000..a7222a7 --- /dev/null +++ b/lib/common/utils/pdf_service.dart @@ -0,0 +1,79 @@ +import 'dart:developer'; +import 'dart:io'; + +import 'package:open_file/open_file.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pdf/widgets.dart'; + +class HelperPdfService { + static Future saveDocument({ + required String name, + required Document pdf, + }) async { + try { + log("Starting PDF save process for: $name"); + log("PDF document object: $pdf"); + + final bytes = await pdf.save(); + log("PDF bytes generated successfully, size: ${bytes.length} bytes"); + + if (bytes.isEmpty) { + log("WARNING: PDF bytes are empty!"); + return Future.error("PDF bytes are empty"); + } + + final dir = await getApplicationDocumentsDirectory(); + log("Documents directory: ${dir.path}"); + + final file = File('${dir.path}/$name'); + log("Saving PDF to: ${file.path}"); + + await file.writeAsBytes(bytes); + log("PDF saved successfully to: ${file.path}"); + + // Verify file was created + if (await file.exists()) { + final fileSize = await file.length(); + log("File exists and size is: $fileSize bytes"); + } else { + log("ERROR: File was not created!"); + return Future.error("File was not created"); + } + + return file; + } catch (e) { + log("Failed to save document: $e"); + log("Error stack trace: ${StackTrace.current}"); + return Future.error("Failed to save document: $e"); + } + } + + static Future openFile(File file) async { + try { + final url = file.path; + log("Attempting to open file: $url"); + + if (!await file.exists()) { + log("ERROR: File does not exist: $url"); + return; + } + + final fileSize = await file.length(); + log("File exists and size is: $fileSize bytes"); + + log("Calling OpenFile.open..."); + final result = await OpenFile.open(url, type: "application/pdf"); + log("OpenFile result: $result"); + + if (result.type == ResultType.done) { + log("File opened successfully"); + } else { + log("File opening failed with result: ${result.type}"); + log("Error message: ${result.message}"); + } + } catch (e) { + log("Failed to open file: $e"); + log("Error stack trace: ${StackTrace.current}"); + } + } +} diff --git a/lib/common/utils/permission.dart b/lib/common/utils/permission.dart new file mode 100644 index 0000000..b2cb177 --- /dev/null +++ b/lib/common/utils/permission.dart @@ -0,0 +1,72 @@ +import 'dart:developer'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class PermessionHelper { + Future checkPermission() async { + final deviceInfo = await DeviceInfoPlugin().androidInfo; + bool permissionStatus; + if (deviceInfo.version.sdkInt > 32) { + permissionStatus = await Permission.photos.request().isGranted; + } else { + permissionStatus = await Permission.storage.request().isGranted; + } + + if (permissionStatus) { + log('Izin penyimpanan sudah diberikan.'); + } else { + if (deviceInfo.version.sdkInt > 32) { + log('deviceInfo.version.sdkInt > 32.'); + permissionStatus = await Permission.photos.request().isGranted; + } else { + permissionStatus = await Permission.storage.request().isGranted; + } + // } else { + // openAppSettings(); + // } + } + log('permissionStatus: $permissionStatus'); + return permissionStatus; + } + + void permessionPrinter() async { + Map statuses = await [ + Permission.bluetooth, + Permission.bluetoothScan, + Permission.bluetoothAdvertise, + Permission.bluetoothConnect, + ].request(); + + log("statuses: $statuses"); + } +} + + // try { + // final status = + // await PermessionHelper().checkPermission(); + // if (status) { + // final pdfFile = await InventoryReport.previewPdf( + // searchDateFormatted: widget.searchDateFormatted, + // inventory: widget.inventory, + // ); + // log("pdfFile: $pdfFile"); + // await HelperPdfService.openFile(pdfFile); + // } else { + // ScaffoldMessenger.of(context).showSnackBar( + // const SnackBar( + // content: Text( + // 'Storage permission is required to save PDF'), + // backgroundColor: Colors.red, + // ), + // ); + // } + // } catch (e) { + // log("Error generating PDF: $e"); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text('Failed to generate PDF: $e'), + // backgroundColor: Colors.red, + // ), + // ); + // } \ No newline at end of file diff --git a/lib/common/validator/validator.dart b/lib/common/validator/validator.dart new file mode 100644 index 0000000..63589f0 --- /dev/null +++ b/lib/common/validator/validator.dart @@ -0,0 +1,28 @@ +class AppValidator { + static String? validateEmail(String? value) { + if (value == null || value.isEmpty) { + return 'Email wajib diisi'; + } + final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'); + if (!emailRegex.hasMatch(value)) { + return 'Format email tidak valid'; + } + return null; + } + + static String? validatePassword(String? value) { + if (value == null || value.isEmpty) { + return 'Password wajib diisi'; + } + if (value.length < 8) { + return 'Password minimal 8 karakter'; + } + // if (!RegExp(r'[A-Z]').hasMatch(value)) { + // return 'Password harus mengandung huruf besar'; + // } + // if (!RegExp(r'[0-9]').hasMatch(value)) { + // return 'Password harus mengandung angka'; + // } + return null; + } +} diff --git a/lib/domain/analytic/analytic.dart b/lib/domain/analytic/analytic.dart new file mode 100644 index 0000000..f51eb5a --- /dev/null +++ b/lib/domain/analytic/analytic.dart @@ -0,0 +1,14 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'analytic.freezed.dart'; + +part 'entities/sales_analytic_entity.dart'; +part 'entities/profit_loss_analytic_entity.dart'; +part 'entities/category_analytic_entity.dart'; +part 'entities/inventory_analytic_entity.dart'; +part 'entities/dashboard_analytic_entity.dart'; +part 'entities/product_analytic_entity.dart'; +part 'entities/payment_method_analytic_entity.dart'; +part 'failures/analytic_failure.dart'; diff --git a/lib/domain/analytic/analytic.freezed.dart b/lib/domain/analytic/analytic.freezed.dart new file mode 100644 index 0000000..5cd5ff1 --- /dev/null +++ b/lib/domain/analytic/analytic.freezed.dart @@ -0,0 +1,7711 @@ +// 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 'analytic.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$SalesAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + DateTime get dateFrom => throw _privateConstructorUsedError; + DateTime get dateTo => throw _privateConstructorUsedError; + String get groupBy => throw _privateConstructorUsedError; + SalesAnalyticSummary get summary => throw _privateConstructorUsedError; + List get data => throw _privateConstructorUsedError; + + /// Create a copy of SalesAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesAnalyticCopyWith<$Res> { + factory $SalesAnalyticCopyWith( + SalesAnalytic value, + $Res Function(SalesAnalytic) then, + ) = _$SalesAnalyticCopyWithImpl<$Res, SalesAnalytic>; + @useResult + $Res call({ + String organizationId, + String outletId, + DateTime dateFrom, + DateTime dateTo, + String groupBy, + SalesAnalyticSummary summary, + List data, + }); + + $SalesAnalyticSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$SalesAnalyticCopyWithImpl<$Res, $Val extends SalesAnalytic> + implements $SalesAnalyticCopyWith<$Res> { + _$SalesAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // 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, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as SalesAnalyticSummary, + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of SalesAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SalesAnalyticSummaryCopyWith<$Res> get summary { + return $SalesAnalyticSummaryCopyWith<$Res>(_value.summary, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SalesAnalyticImplCopyWith<$Res> + implements $SalesAnalyticCopyWith<$Res> { + factory _$$SalesAnalyticImplCopyWith( + _$SalesAnalyticImpl value, + $Res Function(_$SalesAnalyticImpl) then, + ) = __$$SalesAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String outletId, + DateTime dateFrom, + DateTime dateTo, + String groupBy, + SalesAnalyticSummary summary, + List data, + }); + + @override + $SalesAnalyticSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$$SalesAnalyticImplCopyWithImpl<$Res> + extends _$SalesAnalyticCopyWithImpl<$Res, _$SalesAnalyticImpl> + implements _$$SalesAnalyticImplCopyWith<$Res> { + __$$SalesAnalyticImplCopyWithImpl( + _$SalesAnalyticImpl _value, + $Res Function(_$SalesAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + }) { + return _then( + _$SalesAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // 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, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as SalesAnalyticSummary, + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$SalesAnalyticImpl implements _SalesAnalytic { + const _$SalesAnalyticImpl({ + required this.organizationId, + required this.outletId, + required this.dateFrom, + required this.dateTo, + required this.groupBy, + required this.summary, + required final List data, + }) : _data = data; + + @override + final String organizationId; + @override + final String outletId; + @override + final DateTime dateFrom; + @override + final DateTime dateTo; + @override + final String groupBy; + @override + final SalesAnalyticSummary summary; + final List _data; + @override + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + @override + String toString() { + return 'SalesAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of SalesAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesAnalyticImplCopyWith<_$SalesAnalyticImpl> get copyWith => + __$$SalesAnalyticImplCopyWithImpl<_$SalesAnalyticImpl>(this, _$identity); +} + +abstract class _SalesAnalytic implements SalesAnalytic { + const factory _SalesAnalytic({ + required final String organizationId, + required final String outletId, + required final DateTime dateFrom, + required final DateTime dateTo, + required final String groupBy, + required final SalesAnalyticSummary summary, + required final List data, + }) = _$SalesAnalyticImpl; + + @override + String get organizationId; + @override + String get outletId; + @override + DateTime get dateFrom; + @override + DateTime get dateTo; + @override + String get groupBy; + @override + SalesAnalyticSummary get summary; + @override + List get data; + + /// Create a copy of SalesAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesAnalyticImplCopyWith<_$SalesAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$SalesAnalyticSummary { + int get totalSales => throw _privateConstructorUsedError; + int get totalOrders => throw _privateConstructorUsedError; + int get totalItems => throw _privateConstructorUsedError; + double get averageOrderValue => throw _privateConstructorUsedError; + int get totalTax => throw _privateConstructorUsedError; + int get totalDiscount => throw _privateConstructorUsedError; + int get netSales => throw _privateConstructorUsedError; + + /// Create a copy of SalesAnalyticSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesAnalyticSummaryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesAnalyticSummaryCopyWith<$Res> { + factory $SalesAnalyticSummaryCopyWith( + SalesAnalyticSummary value, + $Res Function(SalesAnalyticSummary) then, + ) = _$SalesAnalyticSummaryCopyWithImpl<$Res, SalesAnalyticSummary>; + @useResult + $Res call({ + int totalSales, + int totalOrders, + int totalItems, + double averageOrderValue, + int totalTax, + int totalDiscount, + int netSales, + }); +} + +/// @nodoc +class _$SalesAnalyticSummaryCopyWithImpl< + $Res, + $Val extends SalesAnalyticSummary +> + implements $SalesAnalyticSummaryCopyWith<$Res> { + _$SalesAnalyticSummaryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesAnalyticSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = null, + Object? totalOrders = null, + Object? totalItems = null, + Object? averageOrderValue = null, + Object? totalTax = null, + Object? totalDiscount = null, + Object? netSales = null, + }) { + return _then( + _value.copyWith( + totalSales: null == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + totalItems: null == totalItems + ? _value.totalItems + : totalItems // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + totalTax: null == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int, + totalDiscount: null == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$SalesAnalyticSummaryImplCopyWith<$Res> + implements $SalesAnalyticSummaryCopyWith<$Res> { + factory _$$SalesAnalyticSummaryImplCopyWith( + _$SalesAnalyticSummaryImpl value, + $Res Function(_$SalesAnalyticSummaryImpl) then, + ) = __$$SalesAnalyticSummaryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalSales, + int totalOrders, + int totalItems, + double averageOrderValue, + int totalTax, + int totalDiscount, + int netSales, + }); +} + +/// @nodoc +class __$$SalesAnalyticSummaryImplCopyWithImpl<$Res> + extends _$SalesAnalyticSummaryCopyWithImpl<$Res, _$SalesAnalyticSummaryImpl> + implements _$$SalesAnalyticSummaryImplCopyWith<$Res> { + __$$SalesAnalyticSummaryImplCopyWithImpl( + _$SalesAnalyticSummaryImpl _value, + $Res Function(_$SalesAnalyticSummaryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesAnalyticSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = null, + Object? totalOrders = null, + Object? totalItems = null, + Object? averageOrderValue = null, + Object? totalTax = null, + Object? totalDiscount = null, + Object? netSales = null, + }) { + return _then( + _$SalesAnalyticSummaryImpl( + totalSales: null == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + totalItems: null == totalItems + ? _value.totalItems + : totalItems // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + totalTax: null == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int, + totalDiscount: null == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$SalesAnalyticSummaryImpl implements _SalesAnalyticSummary { + const _$SalesAnalyticSummaryImpl({ + required this.totalSales, + required this.totalOrders, + required this.totalItems, + required this.averageOrderValue, + required this.totalTax, + required this.totalDiscount, + required this.netSales, + }); + + @override + final int totalSales; + @override + final int totalOrders; + @override + final int totalItems; + @override + final double averageOrderValue; + @override + final int totalTax; + @override + final int totalDiscount; + @override + final int netSales; + + @override + String toString() { + return 'SalesAnalyticSummary(totalSales: $totalSales, totalOrders: $totalOrders, totalItems: $totalItems, averageOrderValue: $averageOrderValue, totalTax: $totalTax, totalDiscount: $totalDiscount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesAnalyticSummaryImpl && + (identical(other.totalSales, totalSales) || + other.totalSales == totalSales) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.totalItems, totalItems) || + other.totalItems == totalItems) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue) && + (identical(other.totalTax, totalTax) || + other.totalTax == totalTax) && + (identical(other.totalDiscount, totalDiscount) || + other.totalDiscount == totalDiscount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalSales, + totalOrders, + totalItems, + averageOrderValue, + totalTax, + totalDiscount, + netSales, + ); + + /// Create a copy of SalesAnalyticSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesAnalyticSummaryImplCopyWith<_$SalesAnalyticSummaryImpl> + get copyWith => + __$$SalesAnalyticSummaryImplCopyWithImpl<_$SalesAnalyticSummaryImpl>( + this, + _$identity, + ); +} + +abstract class _SalesAnalyticSummary implements SalesAnalyticSummary { + const factory _SalesAnalyticSummary({ + required final int totalSales, + required final int totalOrders, + required final int totalItems, + required final double averageOrderValue, + required final int totalTax, + required final int totalDiscount, + required final int netSales, + }) = _$SalesAnalyticSummaryImpl; + + @override + int get totalSales; + @override + int get totalOrders; + @override + int get totalItems; + @override + double get averageOrderValue; + @override + int get totalTax; + @override + int get totalDiscount; + @override + int get netSales; + + /// Create a copy of SalesAnalyticSummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesAnalyticSummaryImplCopyWith<_$SalesAnalyticSummaryImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$SalesAnalyticData { + DateTime get date => throw _privateConstructorUsedError; + int get sales => throw _privateConstructorUsedError; + int get orders => throw _privateConstructorUsedError; + int get items => throw _privateConstructorUsedError; + int get tax => throw _privateConstructorUsedError; + int get discount => throw _privateConstructorUsedError; + int get netSales => throw _privateConstructorUsedError; + + /// Create a copy of SalesAnalyticData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesAnalyticDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesAnalyticDataCopyWith<$Res> { + factory $SalesAnalyticDataCopyWith( + SalesAnalyticData value, + $Res Function(SalesAnalyticData) then, + ) = _$SalesAnalyticDataCopyWithImpl<$Res, SalesAnalyticData>; + @useResult + $Res call({ + DateTime date, + int sales, + int orders, + int items, + int tax, + int discount, + int netSales, + }); +} + +/// @nodoc +class _$SalesAnalyticDataCopyWithImpl<$Res, $Val extends SalesAnalyticData> + implements $SalesAnalyticDataCopyWith<$Res> { + _$SalesAnalyticDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesAnalyticData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? sales = null, + Object? orders = null, + Object? items = null, + Object? tax = null, + Object? discount = null, + Object? netSales = null, + }) { + return _then( + _value.copyWith( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime, + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + items: null == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$SalesAnalyticDataImplCopyWith<$Res> + implements $SalesAnalyticDataCopyWith<$Res> { + factory _$$SalesAnalyticDataImplCopyWith( + _$SalesAnalyticDataImpl value, + $Res Function(_$SalesAnalyticDataImpl) then, + ) = __$$SalesAnalyticDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + DateTime date, + int sales, + int orders, + int items, + int tax, + int discount, + int netSales, + }); +} + +/// @nodoc +class __$$SalesAnalyticDataImplCopyWithImpl<$Res> + extends _$SalesAnalyticDataCopyWithImpl<$Res, _$SalesAnalyticDataImpl> + implements _$$SalesAnalyticDataImplCopyWith<$Res> { + __$$SalesAnalyticDataImplCopyWithImpl( + _$SalesAnalyticDataImpl _value, + $Res Function(_$SalesAnalyticDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesAnalyticData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? sales = null, + Object? orders = null, + Object? items = null, + Object? tax = null, + Object? discount = null, + Object? netSales = null, + }) { + return _then( + _$SalesAnalyticDataImpl( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime, + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + items: null == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$SalesAnalyticDataImpl implements _SalesAnalyticData { + const _$SalesAnalyticDataImpl({ + required this.date, + required this.sales, + required this.orders, + required this.items, + required this.tax, + required this.discount, + required this.netSales, + }); + + @override + final DateTime date; + @override + final int sales; + @override + final int orders; + @override + final int items; + @override + final int tax; + @override + final int discount; + @override + final int netSales; + + @override + String toString() { + return 'SalesAnalyticData(date: $date, sales: $sales, orders: $orders, items: $items, tax: $tax, discount: $discount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesAnalyticDataImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.orders, orders) || other.orders == orders) && + (identical(other.items, items) || other.items == items) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + date, + sales, + orders, + items, + tax, + discount, + netSales, + ); + + /// Create a copy of SalesAnalyticData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesAnalyticDataImplCopyWith<_$SalesAnalyticDataImpl> get copyWith => + __$$SalesAnalyticDataImplCopyWithImpl<_$SalesAnalyticDataImpl>( + this, + _$identity, + ); +} + +abstract class _SalesAnalyticData implements SalesAnalyticData { + const factory _SalesAnalyticData({ + required final DateTime date, + required final int sales, + required final int orders, + required final int items, + required final int tax, + required final int discount, + required final int netSales, + }) = _$SalesAnalyticDataImpl; + + @override + DateTime get date; + @override + int get sales; + @override + int get orders; + @override + int get items; + @override + int get tax; + @override + int get discount; + @override + int get netSales; + + /// Create a copy of SalesAnalyticData + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesAnalyticDataImplCopyWith<_$SalesAnalyticDataImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + String get groupBy => throw _privateConstructorUsedError; + ProfitLossSummary get summary => throw _privateConstructorUsedError; + List get data => throw _privateConstructorUsedError; + List get productData => + throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossAnalyticCopyWith<$Res> { + factory $ProfitLossAnalyticCopyWith( + ProfitLossAnalytic value, + $Res Function(ProfitLossAnalytic) then, + ) = _$ProfitLossAnalyticCopyWithImpl<$Res, ProfitLossAnalytic>; + @useResult + $Res call({ + String organizationId, + String dateFrom, + String dateTo, + String groupBy, + ProfitLossSummary summary, + List data, + List productData, + }); + + $ProfitLossSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$ProfitLossAnalyticCopyWithImpl<$Res, $Val extends ProfitLossAnalytic> + implements $ProfitLossAnalyticCopyWith<$Res> { + _$ProfitLossAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + Object? productData = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummary, + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + productData: null == productData + ? _value.productData + : productData // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossSummaryCopyWith<$Res> get summary { + return $ProfitLossSummaryCopyWith<$Res>(_value.summary, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProfitLossAnalyticImplCopyWith<$Res> + implements $ProfitLossAnalyticCopyWith<$Res> { + factory _$$ProfitLossAnalyticImplCopyWith( + _$ProfitLossAnalyticImpl value, + $Res Function(_$ProfitLossAnalyticImpl) then, + ) = __$$ProfitLossAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String dateFrom, + String dateTo, + String groupBy, + ProfitLossSummary summary, + List data, + List productData, + }); + + @override + $ProfitLossSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$$ProfitLossAnalyticImplCopyWithImpl<$Res> + extends _$ProfitLossAnalyticCopyWithImpl<$Res, _$ProfitLossAnalyticImpl> + implements _$$ProfitLossAnalyticImplCopyWith<$Res> { + __$$ProfitLossAnalyticImplCopyWithImpl( + _$ProfitLossAnalyticImpl _value, + $Res Function(_$ProfitLossAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + Object? productData = null, + }) { + return _then( + _$ProfitLossAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummary, + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + productData: null == productData + ? _value._productData + : productData // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossAnalyticImpl implements _ProfitLossAnalytic { + const _$ProfitLossAnalyticImpl({ + required this.organizationId, + required this.dateFrom, + required this.dateTo, + required this.groupBy, + required this.summary, + required final List data, + required final List productData, + }) : _data = data, + _productData = productData; + + @override + final String organizationId; + @override + final String dateFrom; + @override + final String dateTo; + @override + final String groupBy; + @override + final ProfitLossSummary summary; + final List _data; + @override + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + final List _productData; + @override + List get productData { + if (_productData is EqualUnmodifiableListView) return _productData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_productData); + } + + @override + String toString() { + return 'ProfitLossAnalytic(organizationId: $organizationId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data, productData: $productData)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data) && + const DeepCollectionEquality().equals( + other._productData, + _productData, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + const DeepCollectionEquality().hash(_productData), + ); + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossAnalyticImplCopyWith<_$ProfitLossAnalyticImpl> get copyWith => + __$$ProfitLossAnalyticImplCopyWithImpl<_$ProfitLossAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossAnalytic implements ProfitLossAnalytic { + const factory _ProfitLossAnalytic({ + required final String organizationId, + required final String dateFrom, + required final String dateTo, + required final String groupBy, + required final ProfitLossSummary summary, + required final List data, + required final List productData, + }) = _$ProfitLossAnalyticImpl; + + @override + String get organizationId; + @override + String get dateFrom; + @override + String get dateTo; + @override + String get groupBy; + @override + ProfitLossSummary get summary; + @override + List get data; + @override + List get productData; + + /// Create a copy of ProfitLossAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossAnalyticImplCopyWith<_$ProfitLossAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossSummary { + int get totalRevenue => throw _privateConstructorUsedError; + int get totalCost => throw _privateConstructorUsedError; + int get grossProfit => throw _privateConstructorUsedError; + double get grossProfitMargin => throw _privateConstructorUsedError; + int get totalTax => throw _privateConstructorUsedError; + int get totalDiscount => throw _privateConstructorUsedError; + int get netProfit => throw _privateConstructorUsedError; + double get netProfitMargin => throw _privateConstructorUsedError; + int get totalOrders => throw _privateConstructorUsedError; + double get averageProfit => throw _privateConstructorUsedError; + double get profitabilityRatio => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossSummaryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossSummaryCopyWith<$Res> { + factory $ProfitLossSummaryCopyWith( + ProfitLossSummary value, + $Res Function(ProfitLossSummary) then, + ) = _$ProfitLossSummaryCopyWithImpl<$Res, ProfitLossSummary>; + @useResult + $Res call({ + int totalRevenue, + int totalCost, + int grossProfit, + double grossProfitMargin, + int totalTax, + int totalDiscount, + int netProfit, + double netProfitMargin, + int totalOrders, + double averageProfit, + double profitabilityRatio, + }); +} + +/// @nodoc +class _$ProfitLossSummaryCopyWithImpl<$Res, $Val extends ProfitLossSummary> + implements $ProfitLossSummaryCopyWith<$Res> { + _$ProfitLossSummaryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = null, + Object? totalCost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? totalTax = null, + Object? totalDiscount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? totalOrders = null, + Object? averageProfit = null, + Object? profitabilityRatio = null, + }) { + return _then( + _value.copyWith( + totalRevenue: null == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int, + totalCost: null == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalTax: null == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int, + totalDiscount: null == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageProfit: null == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double, + profitabilityRatio: null == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossSummaryImplCopyWith<$Res> + implements $ProfitLossSummaryCopyWith<$Res> { + factory _$$ProfitLossSummaryImplCopyWith( + _$ProfitLossSummaryImpl value, + $Res Function(_$ProfitLossSummaryImpl) then, + ) = __$$ProfitLossSummaryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalRevenue, + int totalCost, + int grossProfit, + double grossProfitMargin, + int totalTax, + int totalDiscount, + int netProfit, + double netProfitMargin, + int totalOrders, + double averageProfit, + double profitabilityRatio, + }); +} + +/// @nodoc +class __$$ProfitLossSummaryImplCopyWithImpl<$Res> + extends _$ProfitLossSummaryCopyWithImpl<$Res, _$ProfitLossSummaryImpl> + implements _$$ProfitLossSummaryImplCopyWith<$Res> { + __$$ProfitLossSummaryImplCopyWithImpl( + _$ProfitLossSummaryImpl _value, + $Res Function(_$ProfitLossSummaryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = null, + Object? totalCost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? totalTax = null, + Object? totalDiscount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? totalOrders = null, + Object? averageProfit = null, + Object? profitabilityRatio = null, + }) { + return _then( + _$ProfitLossSummaryImpl( + totalRevenue: null == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int, + totalCost: null == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalTax: null == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int, + totalDiscount: null == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageProfit: null == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double, + profitabilityRatio: null == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossSummaryImpl implements _ProfitLossSummary { + const _$ProfitLossSummaryImpl({ + required this.totalRevenue, + required this.totalCost, + required this.grossProfit, + required this.grossProfitMargin, + required this.totalTax, + required this.totalDiscount, + required this.netProfit, + required this.netProfitMargin, + required this.totalOrders, + required this.averageProfit, + required this.profitabilityRatio, + }); + + @override + final int totalRevenue; + @override + final int totalCost; + @override + final int grossProfit; + @override + final double grossProfitMargin; + @override + final int totalTax; + @override + final int totalDiscount; + @override + final int netProfit; + @override + final double netProfitMargin; + @override + final int totalOrders; + @override + final double averageProfit; + @override + final double profitabilityRatio; + + @override + String toString() { + return 'ProfitLossSummary(totalRevenue: $totalRevenue, totalCost: $totalCost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, totalTax: $totalTax, totalDiscount: $totalDiscount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, totalOrders: $totalOrders, averageProfit: $averageProfit, profitabilityRatio: $profitabilityRatio)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossSummaryImpl && + (identical(other.totalRevenue, totalRevenue) || + other.totalRevenue == totalRevenue) && + (identical(other.totalCost, totalCost) || + other.totalCost == totalCost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.totalTax, totalTax) || + other.totalTax == totalTax) && + (identical(other.totalDiscount, totalDiscount) || + other.totalDiscount == totalDiscount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageProfit, averageProfit) || + other.averageProfit == averageProfit) && + (identical(other.profitabilityRatio, profitabilityRatio) || + other.profitabilityRatio == profitabilityRatio)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalRevenue, + totalCost, + grossProfit, + grossProfitMargin, + totalTax, + totalDiscount, + netProfit, + netProfitMargin, + totalOrders, + averageProfit, + profitabilityRatio, + ); + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossSummaryImplCopyWith<_$ProfitLossSummaryImpl> get copyWith => + __$$ProfitLossSummaryImplCopyWithImpl<_$ProfitLossSummaryImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossSummary implements ProfitLossSummary { + const factory _ProfitLossSummary({ + required final int totalRevenue, + required final int totalCost, + required final int grossProfit, + required final double grossProfitMargin, + required final int totalTax, + required final int totalDiscount, + required final int netProfit, + required final double netProfitMargin, + required final int totalOrders, + required final double averageProfit, + required final double profitabilityRatio, + }) = _$ProfitLossSummaryImpl; + + @override + int get totalRevenue; + @override + int get totalCost; + @override + int get grossProfit; + @override + double get grossProfitMargin; + @override + int get totalTax; + @override + int get totalDiscount; + @override + int get netProfit; + @override + double get netProfitMargin; + @override + int get totalOrders; + @override + double get averageProfit; + @override + double get profitabilityRatio; + + /// Create a copy of ProfitLossSummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossSummaryImplCopyWith<_$ProfitLossSummaryImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossDailyData { + String get date => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + int get grossProfit => throw _privateConstructorUsedError; + double get grossProfitMargin => throw _privateConstructorUsedError; + int get tax => throw _privateConstructorUsedError; + int get discount => throw _privateConstructorUsedError; + int get netProfit => throw _privateConstructorUsedError; + double get netProfitMargin => throw _privateConstructorUsedError; + int get orders => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossDailyDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossDailyDataCopyWith<$Res> { + factory $ProfitLossDailyDataCopyWith( + ProfitLossDailyData value, + $Res Function(ProfitLossDailyData) then, + ) = _$ProfitLossDailyDataCopyWithImpl<$Res, ProfitLossDailyData>; + @useResult + $Res call({ + String date, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int tax, + int discount, + int netProfit, + double netProfitMargin, + int orders, + }); +} + +/// @nodoc +class _$ProfitLossDailyDataCopyWithImpl<$Res, $Val extends ProfitLossDailyData> + implements $ProfitLossDailyDataCopyWith<$Res> { + _$ProfitLossDailyDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? tax = null, + Object? discount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? orders = null, + }) { + return _then( + _value.copyWith( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossDailyDataImplCopyWith<$Res> + implements $ProfitLossDailyDataCopyWith<$Res> { + factory _$$ProfitLossDailyDataImplCopyWith( + _$ProfitLossDailyDataImpl value, + $Res Function(_$ProfitLossDailyDataImpl) then, + ) = __$$ProfitLossDailyDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String date, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int tax, + int discount, + int netProfit, + double netProfitMargin, + int orders, + }); +} + +/// @nodoc +class __$$ProfitLossDailyDataImplCopyWithImpl<$Res> + extends _$ProfitLossDailyDataCopyWithImpl<$Res, _$ProfitLossDailyDataImpl> + implements _$$ProfitLossDailyDataImplCopyWith<$Res> { + __$$ProfitLossDailyDataImplCopyWithImpl( + _$ProfitLossDailyDataImpl _value, + $Res Function(_$ProfitLossDailyDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? tax = null, + Object? discount = null, + Object? netProfit = null, + Object? netProfitMargin = null, + Object? orders = null, + }) { + return _then( + _$ProfitLossDailyDataImpl( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netProfit: null == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int, + netProfitMargin: null == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossDailyDataImpl implements _ProfitLossDailyData { + const _$ProfitLossDailyDataImpl({ + required this.date, + required this.revenue, + required this.cost, + required this.grossProfit, + required this.grossProfitMargin, + required this.tax, + required this.discount, + required this.netProfit, + required this.netProfitMargin, + required this.orders, + }); + + @override + final String date; + @override + final int revenue; + @override + final int cost; + @override + final int grossProfit; + @override + final double grossProfitMargin; + @override + final int tax; + @override + final int discount; + @override + final int netProfit; + @override + final double netProfitMargin; + @override + final int orders; + + @override + String toString() { + return 'ProfitLossDailyData(date: $date, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, tax: $tax, discount: $discount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, orders: $orders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossDailyDataImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.orders, orders) || other.orders == orders)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + date, + revenue, + cost, + grossProfit, + grossProfitMargin, + tax, + discount, + netProfit, + netProfitMargin, + orders, + ); + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossDailyDataImplCopyWith<_$ProfitLossDailyDataImpl> get copyWith => + __$$ProfitLossDailyDataImplCopyWithImpl<_$ProfitLossDailyDataImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossDailyData implements ProfitLossDailyData { + const factory _ProfitLossDailyData({ + required final String date, + required final int revenue, + required final int cost, + required final int grossProfit, + required final double grossProfitMargin, + required final int tax, + required final int discount, + required final int netProfit, + required final double netProfitMargin, + required final int orders, + }) = _$ProfitLossDailyDataImpl; + + @override + String get date; + @override + int get revenue; + @override + int get cost; + @override + int get grossProfit; + @override + double get grossProfitMargin; + @override + int get tax; + @override + int get discount; + @override + int get netProfit; + @override + double get netProfitMargin; + @override + int get orders; + + /// Create a copy of ProfitLossDailyData + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossDailyDataImplCopyWith<_$ProfitLossDailyDataImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProfitLossProductData { + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryId => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantitySold => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + int get grossProfit => throw _privateConstructorUsedError; + double get grossProfitMargin => throw _privateConstructorUsedError; + int get averagePrice => throw _privateConstructorUsedError; + int get averageCost => throw _privateConstructorUsedError; + int get profitPerUnit => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossProductDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossProductDataCopyWith<$Res> { + factory $ProfitLossProductDataCopyWith( + ProfitLossProductData value, + $Res Function(ProfitLossProductData) then, + ) = _$ProfitLossProductDataCopyWithImpl<$Res, ProfitLossProductData>; + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int averagePrice, + int averageCost, + int profitPerUnit, + }); +} + +/// @nodoc +class _$ProfitLossProductDataCopyWithImpl< + $Res, + $Val extends ProfitLossProductData +> + implements $ProfitLossProductDataCopyWith<$Res> { + _$ProfitLossProductDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? averagePrice = null, + Object? averageCost = null, + Object? profitPerUnit = null, + }) { + return _then( + _value.copyWith( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int, + averageCost: null == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int, + profitPerUnit: null == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossProductDataImplCopyWith<$Res> + implements $ProfitLossProductDataCopyWith<$Res> { + factory _$$ProfitLossProductDataImplCopyWith( + _$ProfitLossProductDataImpl value, + $Res Function(_$ProfitLossProductDataImpl) then, + ) = __$$ProfitLossProductDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + int cost, + int grossProfit, + double grossProfitMargin, + int averagePrice, + int averageCost, + int profitPerUnit, + }); +} + +/// @nodoc +class __$$ProfitLossProductDataImplCopyWithImpl<$Res> + extends + _$ProfitLossProductDataCopyWithImpl<$Res, _$ProfitLossProductDataImpl> + implements _$$ProfitLossProductDataImplCopyWith<$Res> { + __$$ProfitLossProductDataImplCopyWithImpl( + _$ProfitLossProductDataImpl _value, + $Res Function(_$ProfitLossProductDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? cost = null, + Object? grossProfit = null, + Object? grossProfitMargin = null, + Object? averagePrice = null, + Object? averageCost = null, + Object? profitPerUnit = null, + }) { + return _then( + _$ProfitLossProductDataImpl( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + grossProfit: null == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int, + grossProfitMargin: null == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int, + averageCost: null == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int, + profitPerUnit: null == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$ProfitLossProductDataImpl implements _ProfitLossProductData { + const _$ProfitLossProductDataImpl({ + required this.productId, + required this.productName, + required this.categoryId, + required this.categoryName, + required this.quantitySold, + required this.revenue, + required this.cost, + required this.grossProfit, + required this.grossProfitMargin, + required this.averagePrice, + required this.averageCost, + required this.profitPerUnit, + }); + + @override + final String productId; + @override + final String productName; + @override + final String categoryId; + @override + final String categoryName; + @override + final int quantitySold; + @override + final int revenue; + @override + final int cost; + @override + final int grossProfit; + @override + final double grossProfitMargin; + @override + final int averagePrice; + @override + final int averageCost; + @override + final int profitPerUnit; + + @override + String toString() { + return 'ProfitLossProductData(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, averagePrice: $averagePrice, averageCost: $averageCost, profitPerUnit: $profitPerUnit)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossProductDataImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.averageCost, averageCost) || + other.averageCost == averageCost) && + (identical(other.profitPerUnit, profitPerUnit) || + other.profitPerUnit == profitPerUnit)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + cost, + grossProfit, + grossProfitMargin, + averagePrice, + averageCost, + profitPerUnit, + ); + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossProductDataImplCopyWith<_$ProfitLossProductDataImpl> + get copyWith => + __$$ProfitLossProductDataImplCopyWithImpl<_$ProfitLossProductDataImpl>( + this, + _$identity, + ); +} + +abstract class _ProfitLossProductData implements ProfitLossProductData { + const factory _ProfitLossProductData({ + required final String productId, + required final String productName, + required final String categoryId, + required final String categoryName, + required final int quantitySold, + required final int revenue, + required final int cost, + required final int grossProfit, + required final double grossProfitMargin, + required final int averagePrice, + required final int averageCost, + required final int profitPerUnit, + }) = _$ProfitLossProductDataImpl; + + @override + String get productId; + @override + String get productName; + @override + String get categoryId; + @override + String get categoryName; + @override + int get quantitySold; + @override + int get revenue; + @override + int get cost; + @override + int get grossProfit; + @override + double get grossProfitMargin; + @override + int get averagePrice; + @override + int get averageCost; + @override + int get profitPerUnit; + + /// Create a copy of ProfitLossProductData + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossProductDataImplCopyWith<_$ProfitLossProductDataImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$CategoryAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + List get data => throw _privateConstructorUsedError; + + /// Create a copy of CategoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryAnalyticCopyWith<$Res> { + factory $CategoryAnalyticCopyWith( + CategoryAnalytic value, + $Res Function(CategoryAnalytic) then, + ) = _$CategoryAnalyticCopyWithImpl<$Res, CategoryAnalytic>; + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + List data, + }); +} + +/// @nodoc +class _$CategoryAnalyticCopyWithImpl<$Res, $Val extends CategoryAnalytic> + implements $CategoryAnalyticCopyWith<$Res> { + _$CategoryAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? data = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryAnalyticImplCopyWith<$Res> + implements $CategoryAnalyticCopyWith<$Res> { + factory _$$CategoryAnalyticImplCopyWith( + _$CategoryAnalyticImpl value, + $Res Function(_$CategoryAnalyticImpl) then, + ) = __$$CategoryAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + List data, + }); +} + +/// @nodoc +class __$$CategoryAnalyticImplCopyWithImpl<$Res> + extends _$CategoryAnalyticCopyWithImpl<$Res, _$CategoryAnalyticImpl> + implements _$$CategoryAnalyticImplCopyWith<$Res> { + __$$CategoryAnalyticImplCopyWithImpl( + _$CategoryAnalyticImpl _value, + $Res Function(_$CategoryAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? data = null, + }) { + return _then( + _$CategoryAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$CategoryAnalyticImpl implements _CategoryAnalytic { + const _$CategoryAnalyticImpl({ + required this.organizationId, + required this.outletId, + required this.dateFrom, + required this.dateTo, + required final List data, + }) : _data = data; + + @override + final String organizationId; + @override + final String outletId; + @override + final String dateFrom; + @override + final String dateTo; + final List _data; + @override + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + @override + String toString() { + return 'CategoryAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of CategoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryAnalyticImplCopyWith<_$CategoryAnalyticImpl> get copyWith => + __$$CategoryAnalyticImplCopyWithImpl<_$CategoryAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _CategoryAnalytic implements CategoryAnalytic { + const factory _CategoryAnalytic({ + required final String organizationId, + required final String outletId, + required final String dateFrom, + required final String dateTo, + required final List data, + }) = _$CategoryAnalyticImpl; + + @override + String get organizationId; + @override + String get outletId; + @override + String get dateFrom; + @override + String get dateTo; + @override + List get data; + + /// Create a copy of CategoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryAnalyticImplCopyWith<_$CategoryAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$CategoryAnalyticItem { + String get categoryId => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get totalRevenue => throw _privateConstructorUsedError; + int get totalQuantity => throw _privateConstructorUsedError; + int get productCount => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + + /// Create a copy of CategoryAnalyticItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryAnalyticItemCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryAnalyticItemCopyWith<$Res> { + factory $CategoryAnalyticItemCopyWith( + CategoryAnalyticItem value, + $Res Function(CategoryAnalyticItem) then, + ) = _$CategoryAnalyticItemCopyWithImpl<$Res, CategoryAnalyticItem>; + @useResult + $Res call({ + String categoryId, + String categoryName, + int totalRevenue, + int totalQuantity, + int productCount, + int orderCount, + }); +} + +/// @nodoc +class _$CategoryAnalyticItemCopyWithImpl< + $Res, + $Val extends CategoryAnalyticItem +> + implements $CategoryAnalyticItemCopyWith<$Res> { + _$CategoryAnalyticItemCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryAnalyticItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryId = null, + Object? categoryName = null, + Object? totalRevenue = null, + Object? totalQuantity = null, + Object? productCount = null, + Object? orderCount = null, + }) { + return _then( + _value.copyWith( + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + totalRevenue: null == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int, + totalQuantity: null == totalQuantity + ? _value.totalQuantity + : totalQuantity // ignore: cast_nullable_to_non_nullable + as int, + productCount: null == productCount + ? _value.productCount + : productCount // ignore: cast_nullable_to_non_nullable + as int, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryAnalyticItemImplCopyWith<$Res> + implements $CategoryAnalyticItemCopyWith<$Res> { + factory _$$CategoryAnalyticItemImplCopyWith( + _$CategoryAnalyticItemImpl value, + $Res Function(_$CategoryAnalyticItemImpl) then, + ) = __$$CategoryAnalyticItemImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String categoryId, + String categoryName, + int totalRevenue, + int totalQuantity, + int productCount, + int orderCount, + }); +} + +/// @nodoc +class __$$CategoryAnalyticItemImplCopyWithImpl<$Res> + extends _$CategoryAnalyticItemCopyWithImpl<$Res, _$CategoryAnalyticItemImpl> + implements _$$CategoryAnalyticItemImplCopyWith<$Res> { + __$$CategoryAnalyticItemImplCopyWithImpl( + _$CategoryAnalyticItemImpl _value, + $Res Function(_$CategoryAnalyticItemImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryAnalyticItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryId = null, + Object? categoryName = null, + Object? totalRevenue = null, + Object? totalQuantity = null, + Object? productCount = null, + Object? orderCount = null, + }) { + return _then( + _$CategoryAnalyticItemImpl( + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + totalRevenue: null == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int, + totalQuantity: null == totalQuantity + ? _value.totalQuantity + : totalQuantity // ignore: cast_nullable_to_non_nullable + as int, + productCount: null == productCount + ? _value.productCount + : productCount // ignore: cast_nullable_to_non_nullable + as int, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$CategoryAnalyticItemImpl implements _CategoryAnalyticItem { + const _$CategoryAnalyticItemImpl({ + required this.categoryId, + required this.categoryName, + required this.totalRevenue, + required this.totalQuantity, + required this.productCount, + required this.orderCount, + }); + + @override + final String categoryId; + @override + final String categoryName; + @override + final int totalRevenue; + @override + final int totalQuantity; + @override + final int productCount; + @override + final int orderCount; + + @override + String toString() { + return 'CategoryAnalyticItem(categoryId: $categoryId, categoryName: $categoryName, totalRevenue: $totalRevenue, totalQuantity: $totalQuantity, productCount: $productCount, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryAnalyticItemImpl && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.totalRevenue, totalRevenue) || + other.totalRevenue == totalRevenue) && + (identical(other.totalQuantity, totalQuantity) || + other.totalQuantity == totalQuantity) && + (identical(other.productCount, productCount) || + other.productCount == productCount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + categoryId, + categoryName, + totalRevenue, + totalQuantity, + productCount, + orderCount, + ); + + /// Create a copy of CategoryAnalyticItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryAnalyticItemImplCopyWith<_$CategoryAnalyticItemImpl> + get copyWith => + __$$CategoryAnalyticItemImplCopyWithImpl<_$CategoryAnalyticItemImpl>( + this, + _$identity, + ); +} + +abstract class _CategoryAnalyticItem implements CategoryAnalyticItem { + const factory _CategoryAnalyticItem({ + required final String categoryId, + required final String categoryName, + required final int totalRevenue, + required final int totalQuantity, + required final int productCount, + required final int orderCount, + }) = _$CategoryAnalyticItemImpl; + + @override + String get categoryId; + @override + String get categoryName; + @override + int get totalRevenue; + @override + int get totalQuantity; + @override + int get productCount; + @override + int get orderCount; + + /// Create a copy of CategoryAnalyticItem + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryAnalyticItemImplCopyWith<_$CategoryAnalyticItemImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventoryAnalytic { + InventorySummary get summary => throw _privateConstructorUsedError; + List get products => throw _privateConstructorUsedError; + List get ingredients => + throw _privateConstructorUsedError; + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticCopyWith<$Res> { + factory $InventoryAnalyticCopyWith( + InventoryAnalytic value, + $Res Function(InventoryAnalytic) then, + ) = _$InventoryAnalyticCopyWithImpl<$Res, InventoryAnalytic>; + @useResult + $Res call({ + InventorySummary summary, + List products, + List ingredients, + }); + + $InventorySummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$InventoryAnalyticCopyWithImpl<$Res, $Val extends InventoryAnalytic> + implements $InventoryAnalyticCopyWith<$Res> { + _$InventoryAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = null, + Object? products = null, + Object? ingredients = null, + }) { + return _then( + _value.copyWith( + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummary, + products: null == products + ? _value.products + : products // ignore: cast_nullable_to_non_nullable + as List, + ingredients: null == ingredients + ? _value.ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventorySummaryCopyWith<$Res> get summary { + return $InventorySummaryCopyWith<$Res>(_value.summary, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryAnalyticImplCopyWith<$Res> + implements $InventoryAnalyticCopyWith<$Res> { + factory _$$InventoryAnalyticImplCopyWith( + _$InventoryAnalyticImpl value, + $Res Function(_$InventoryAnalyticImpl) then, + ) = __$$InventoryAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + InventorySummary summary, + List products, + List ingredients, + }); + + @override + $InventorySummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$$InventoryAnalyticImplCopyWithImpl<$Res> + extends _$InventoryAnalyticCopyWithImpl<$Res, _$InventoryAnalyticImpl> + implements _$$InventoryAnalyticImplCopyWith<$Res> { + __$$InventoryAnalyticImplCopyWithImpl( + _$InventoryAnalyticImpl _value, + $Res Function(_$InventoryAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = null, + Object? products = null, + Object? ingredients = null, + }) { + return _then( + _$InventoryAnalyticImpl( + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummary, + products: null == products + ? _value._products + : products // ignore: cast_nullable_to_non_nullable + as List, + ingredients: null == ingredients + ? _value._ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$InventoryAnalyticImpl implements _InventoryAnalytic { + const _$InventoryAnalyticImpl({ + required this.summary, + required final List products, + required final List ingredients, + }) : _products = products, + _ingredients = ingredients; + + @override + final InventorySummary summary; + final List _products; + @override + List get products { + if (_products is EqualUnmodifiableListView) return _products; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_products); + } + + final List _ingredients; + @override + List get ingredients { + if (_ingredients is EqualUnmodifiableListView) return _ingredients; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_ingredients); + } + + @override + String toString() { + return 'InventoryAnalytic(summary: $summary, products: $products, ingredients: $ingredients)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryAnalyticImpl && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._products, _products) && + const DeepCollectionEquality().equals( + other._ingredients, + _ingredients, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + summary, + const DeepCollectionEquality().hash(_products), + const DeepCollectionEquality().hash(_ingredients), + ); + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryAnalyticImplCopyWith<_$InventoryAnalyticImpl> get copyWith => + __$$InventoryAnalyticImplCopyWithImpl<_$InventoryAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryAnalytic implements InventoryAnalytic { + const factory _InventoryAnalytic({ + required final InventorySummary summary, + required final List products, + required final List ingredients, + }) = _$InventoryAnalyticImpl; + + @override + InventorySummary get summary; + @override + List get products; + @override + List get ingredients; + + /// Create a copy of InventoryAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryAnalyticImplCopyWith<_$InventoryAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventorySummary { + int get totalProducts => throw _privateConstructorUsedError; + int get totalIngredients => throw _privateConstructorUsedError; + int get totalValue => throw _privateConstructorUsedError; + int get lowStockProducts => throw _privateConstructorUsedError; + int get lowStockIngredients => throw _privateConstructorUsedError; + int get zeroStockProducts => throw _privateConstructorUsedError; + int get zeroStockIngredients => throw _privateConstructorUsedError; + int get totalSoldProducts => throw _privateConstructorUsedError; + int get totalSoldIngredients => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get outletName => throw _privateConstructorUsedError; + String get generatedAt => throw _privateConstructorUsedError; + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventorySummaryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventorySummaryCopyWith<$Res> { + factory $InventorySummaryCopyWith( + InventorySummary value, + $Res Function(InventorySummary) then, + ) = _$InventorySummaryCopyWithImpl<$Res, InventorySummary>; + @useResult + $Res call({ + int totalProducts, + int totalIngredients, + int totalValue, + int lowStockProducts, + int lowStockIngredients, + int zeroStockProducts, + int zeroStockIngredients, + int totalSoldProducts, + int totalSoldIngredients, + String outletId, + String outletName, + String generatedAt, + }); +} + +/// @nodoc +class _$InventorySummaryCopyWithImpl<$Res, $Val extends InventorySummary> + implements $InventorySummaryCopyWith<$Res> { + _$InventorySummaryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = null, + Object? totalIngredients = null, + Object? totalValue = null, + Object? lowStockProducts = null, + Object? lowStockIngredients = null, + Object? zeroStockProducts = null, + Object? zeroStockIngredients = null, + Object? totalSoldProducts = null, + Object? totalSoldIngredients = null, + Object? outletId = null, + Object? outletName = null, + Object? generatedAt = null, + }) { + return _then( + _value.copyWith( + totalProducts: null == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int, + totalIngredients: null == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + lowStockProducts: null == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int, + lowStockIngredients: null == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + zeroStockProducts: null == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int, + zeroStockIngredients: null == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalSoldProducts: null == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int, + totalSoldIngredients: null == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + outletName: null == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String, + generatedAt: null == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventorySummaryImplCopyWith<$Res> + implements $InventorySummaryCopyWith<$Res> { + factory _$$InventorySummaryImplCopyWith( + _$InventorySummaryImpl value, + $Res Function(_$InventorySummaryImpl) then, + ) = __$$InventorySummaryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalProducts, + int totalIngredients, + int totalValue, + int lowStockProducts, + int lowStockIngredients, + int zeroStockProducts, + int zeroStockIngredients, + int totalSoldProducts, + int totalSoldIngredients, + String outletId, + String outletName, + String generatedAt, + }); +} + +/// @nodoc +class __$$InventorySummaryImplCopyWithImpl<$Res> + extends _$InventorySummaryCopyWithImpl<$Res, _$InventorySummaryImpl> + implements _$$InventorySummaryImplCopyWith<$Res> { + __$$InventorySummaryImplCopyWithImpl( + _$InventorySummaryImpl _value, + $Res Function(_$InventorySummaryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = null, + Object? totalIngredients = null, + Object? totalValue = null, + Object? lowStockProducts = null, + Object? lowStockIngredients = null, + Object? zeroStockProducts = null, + Object? zeroStockIngredients = null, + Object? totalSoldProducts = null, + Object? totalSoldIngredients = null, + Object? outletId = null, + Object? outletName = null, + Object? generatedAt = null, + }) { + return _then( + _$InventorySummaryImpl( + totalProducts: null == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int, + totalIngredients: null == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + lowStockProducts: null == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int, + lowStockIngredients: null == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + zeroStockProducts: null == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int, + zeroStockIngredients: null == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int, + totalSoldProducts: null == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int, + totalSoldIngredients: null == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + outletName: null == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String, + generatedAt: null == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$InventorySummaryImpl implements _InventorySummary { + const _$InventorySummaryImpl({ + required this.totalProducts, + required this.totalIngredients, + required this.totalValue, + required this.lowStockProducts, + required this.lowStockIngredients, + required this.zeroStockProducts, + required this.zeroStockIngredients, + required this.totalSoldProducts, + required this.totalSoldIngredients, + required this.outletId, + required this.outletName, + required this.generatedAt, + }); + + @override + final int totalProducts; + @override + final int totalIngredients; + @override + final int totalValue; + @override + final int lowStockProducts; + @override + final int lowStockIngredients; + @override + final int zeroStockProducts; + @override + final int zeroStockIngredients; + @override + final int totalSoldProducts; + @override + final int totalSoldIngredients; + @override + final String outletId; + @override + final String outletName; + @override + final String generatedAt; + + @override + String toString() { + return 'InventorySummary(totalProducts: $totalProducts, totalIngredients: $totalIngredients, totalValue: $totalValue, lowStockProducts: $lowStockProducts, lowStockIngredients: $lowStockIngredients, zeroStockProducts: $zeroStockProducts, zeroStockIngredients: $zeroStockIngredients, totalSoldProducts: $totalSoldProducts, totalSoldIngredients: $totalSoldIngredients, outletId: $outletId, outletName: $outletName, generatedAt: $generatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventorySummaryImpl && + (identical(other.totalProducts, totalProducts) || + other.totalProducts == totalProducts) && + (identical(other.totalIngredients, totalIngredients) || + other.totalIngredients == totalIngredients) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.lowStockProducts, lowStockProducts) || + other.lowStockProducts == lowStockProducts) && + (identical(other.lowStockIngredients, lowStockIngredients) || + other.lowStockIngredients == lowStockIngredients) && + (identical(other.zeroStockProducts, zeroStockProducts) || + other.zeroStockProducts == zeroStockProducts) && + (identical(other.zeroStockIngredients, zeroStockIngredients) || + other.zeroStockIngredients == zeroStockIngredients) && + (identical(other.totalSoldProducts, totalSoldProducts) || + other.totalSoldProducts == totalSoldProducts) && + (identical(other.totalSoldIngredients, totalSoldIngredients) || + other.totalSoldIngredients == totalSoldIngredients) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.outletName, outletName) || + other.outletName == outletName) && + (identical(other.generatedAt, generatedAt) || + other.generatedAt == generatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalProducts, + totalIngredients, + totalValue, + lowStockProducts, + lowStockIngredients, + zeroStockProducts, + zeroStockIngredients, + totalSoldProducts, + totalSoldIngredients, + outletId, + outletName, + generatedAt, + ); + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventorySummaryImplCopyWith<_$InventorySummaryImpl> get copyWith => + __$$InventorySummaryImplCopyWithImpl<_$InventorySummaryImpl>( + this, + _$identity, + ); +} + +abstract class _InventorySummary implements InventorySummary { + const factory _InventorySummary({ + required final int totalProducts, + required final int totalIngredients, + required final int totalValue, + required final int lowStockProducts, + required final int lowStockIngredients, + required final int zeroStockProducts, + required final int zeroStockIngredients, + required final int totalSoldProducts, + required final int totalSoldIngredients, + required final String outletId, + required final String outletName, + required final String generatedAt, + }) = _$InventorySummaryImpl; + + @override + int get totalProducts; + @override + int get totalIngredients; + @override + int get totalValue; + @override + int get lowStockProducts; + @override + int get lowStockIngredients; + @override + int get zeroStockProducts; + @override + int get zeroStockIngredients; + @override + int get totalSoldProducts; + @override + int get totalSoldIngredients; + @override + String get outletId; + @override + String get outletName; + @override + String get generatedAt; + + /// Create a copy of InventorySummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventorySummaryImplCopyWith<_$InventorySummaryImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventoryProduct { + String get id => throw _privateConstructorUsedError; + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantity => throw _privateConstructorUsedError; + int get reorderLevel => throw _privateConstructorUsedError; + int get unitCost => throw _privateConstructorUsedError; + int get totalValue => throw _privateConstructorUsedError; + int get totalIn => throw _privateConstructorUsedError; + int get totalOut => throw _privateConstructorUsedError; + bool get isLowStock => throw _privateConstructorUsedError; + bool get isZeroStock => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryProductCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryProductCopyWith<$Res> { + factory $InventoryProductCopyWith( + InventoryProduct value, + $Res Function(InventoryProduct) then, + ) = _$InventoryProductCopyWithImpl<$Res, InventoryProduct>; + @useResult + $Res call({ + String id, + String productId, + String productName, + String categoryName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class _$InventoryProductCopyWithImpl<$Res, $Val extends InventoryProduct> + implements $InventoryProductCopyWith<$Res> { + _$InventoryProductCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? productId = null, + Object? productName = null, + Object? categoryName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryProductImplCopyWith<$Res> + implements $InventoryProductCopyWith<$Res> { + factory _$$InventoryProductImplCopyWith( + _$InventoryProductImpl value, + $Res Function(_$InventoryProductImpl) then, + ) = __$$InventoryProductImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String productId, + String productName, + String categoryName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class __$$InventoryProductImplCopyWithImpl<$Res> + extends _$InventoryProductCopyWithImpl<$Res, _$InventoryProductImpl> + implements _$$InventoryProductImplCopyWith<$Res> { + __$$InventoryProductImplCopyWithImpl( + _$InventoryProductImpl _value, + $Res Function(_$InventoryProductImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? productId = null, + Object? productName = null, + Object? categoryName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _$InventoryProductImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$InventoryProductImpl implements _InventoryProduct { + const _$InventoryProductImpl({ + required this.id, + required this.productId, + required this.productName, + required this.categoryName, + required this.quantity, + required this.reorderLevel, + required this.unitCost, + required this.totalValue, + required this.totalIn, + required this.totalOut, + required this.isLowStock, + required this.isZeroStock, + required this.updatedAt, + }); + + @override + final String id; + @override + final String productId; + @override + final String productName; + @override + final String categoryName; + @override + final int quantity; + @override + final int reorderLevel; + @override + final int unitCost; + @override + final int totalValue; + @override + final int totalIn; + @override + final int totalOut; + @override + final bool isLowStock; + @override + final bool isZeroStock; + @override + final String updatedAt; + + @override + String toString() { + return 'InventoryProduct(id: $id, productId: $productId, productName: $productName, categoryName: $categoryName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryProductImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + productId, + productName, + categoryName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryProductImplCopyWith<_$InventoryProductImpl> get copyWith => + __$$InventoryProductImplCopyWithImpl<_$InventoryProductImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryProduct implements InventoryProduct { + const factory _InventoryProduct({ + required final String id, + required final String productId, + required final String productName, + required final String categoryName, + required final int quantity, + required final int reorderLevel, + required final int unitCost, + required final int totalValue, + required final int totalIn, + required final int totalOut, + required final bool isLowStock, + required final bool isZeroStock, + required final String updatedAt, + }) = _$InventoryProductImpl; + + @override + String get id; + @override + String get productId; + @override + String get productName; + @override + String get categoryName; + @override + int get quantity; + @override + int get reorderLevel; + @override + int get unitCost; + @override + int get totalValue; + @override + int get totalIn; + @override + int get totalOut; + @override + bool get isLowStock; + @override + bool get isZeroStock; + @override + String get updatedAt; + + /// Create a copy of InventoryProduct + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryProductImplCopyWith<_$InventoryProductImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$InventoryIngredient { + String get id => throw _privateConstructorUsedError; + String get ingredientId => throw _privateConstructorUsedError; + String get ingredientName => throw _privateConstructorUsedError; + String get unitName => throw _privateConstructorUsedError; + int get quantity => throw _privateConstructorUsedError; + int get reorderLevel => throw _privateConstructorUsedError; + int get unitCost => throw _privateConstructorUsedError; + int get totalValue => throw _privateConstructorUsedError; + int get totalIn => throw _privateConstructorUsedError; + int get totalOut => throw _privateConstructorUsedError; + bool get isLowStock => throw _privateConstructorUsedError; + bool get isZeroStock => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryIngredientCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryIngredientCopyWith<$Res> { + factory $InventoryIngredientCopyWith( + InventoryIngredient value, + $Res Function(InventoryIngredient) then, + ) = _$InventoryIngredientCopyWithImpl<$Res, InventoryIngredient>; + @useResult + $Res call({ + String id, + String ingredientId, + String ingredientName, + String unitName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class _$InventoryIngredientCopyWithImpl<$Res, $Val extends InventoryIngredient> + implements $InventoryIngredientCopyWith<$Res> { + _$InventoryIngredientCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? ingredientId = null, + Object? ingredientName = null, + Object? unitName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + ingredientId: null == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String, + ingredientName: null == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String, + unitName: null == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryIngredientImplCopyWith<$Res> + implements $InventoryIngredientCopyWith<$Res> { + factory _$$InventoryIngredientImplCopyWith( + _$InventoryIngredientImpl value, + $Res Function(_$InventoryIngredientImpl) then, + ) = __$$InventoryIngredientImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String ingredientId, + String ingredientName, + String unitName, + int quantity, + int reorderLevel, + int unitCost, + int totalValue, + int totalIn, + int totalOut, + bool isLowStock, + bool isZeroStock, + String updatedAt, + }); +} + +/// @nodoc +class __$$InventoryIngredientImplCopyWithImpl<$Res> + extends _$InventoryIngredientCopyWithImpl<$Res, _$InventoryIngredientImpl> + implements _$$InventoryIngredientImplCopyWith<$Res> { + __$$InventoryIngredientImplCopyWithImpl( + _$InventoryIngredientImpl _value, + $Res Function(_$InventoryIngredientImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? ingredientId = null, + Object? ingredientName = null, + Object? unitName = null, + Object? quantity = null, + Object? reorderLevel = null, + Object? unitCost = null, + Object? totalValue = null, + Object? totalIn = null, + Object? totalOut = null, + Object? isLowStock = null, + Object? isZeroStock = null, + Object? updatedAt = null, + }) { + return _then( + _$InventoryIngredientImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + ingredientId: null == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String, + ingredientName: null == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String, + unitName: null == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + reorderLevel: null == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int, + unitCost: null == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int, + totalValue: null == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int, + totalIn: null == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int, + totalOut: null == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int, + isLowStock: null == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool, + isZeroStock: null == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$InventoryIngredientImpl implements _InventoryIngredient { + const _$InventoryIngredientImpl({ + required this.id, + required this.ingredientId, + required this.ingredientName, + required this.unitName, + required this.quantity, + required this.reorderLevel, + required this.unitCost, + required this.totalValue, + required this.totalIn, + required this.totalOut, + required this.isLowStock, + required this.isZeroStock, + required this.updatedAt, + }); + + @override + final String id; + @override + final String ingredientId; + @override + final String ingredientName; + @override + final String unitName; + @override + final int quantity; + @override + final int reorderLevel; + @override + final int unitCost; + @override + final int totalValue; + @override + final int totalIn; + @override + final int totalOut; + @override + final bool isLowStock; + @override + final bool isZeroStock; + @override + final String updatedAt; + + @override + String toString() { + return 'InventoryIngredient(id: $id, ingredientId: $ingredientId, ingredientName: $ingredientName, unitName: $unitName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryIngredientImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.ingredientId, ingredientId) || + other.ingredientId == ingredientId) && + (identical(other.ingredientName, ingredientName) || + other.ingredientName == ingredientName) && + (identical(other.unitName, unitName) || + other.unitName == unitName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + ingredientId, + ingredientName, + unitName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryIngredientImplCopyWith<_$InventoryIngredientImpl> get copyWith => + __$$InventoryIngredientImplCopyWithImpl<_$InventoryIngredientImpl>( + this, + _$identity, + ); +} + +abstract class _InventoryIngredient implements InventoryIngredient { + const factory _InventoryIngredient({ + required final String id, + required final String ingredientId, + required final String ingredientName, + required final String unitName, + required final int quantity, + required final int reorderLevel, + required final int unitCost, + required final int totalValue, + required final int totalIn, + required final int totalOut, + required final bool isLowStock, + required final bool isZeroStock, + required final String updatedAt, + }) = _$InventoryIngredientImpl; + + @override + String get id; + @override + String get ingredientId; + @override + String get ingredientName; + @override + String get unitName; + @override + int get quantity; + @override + int get reorderLevel; + @override + int get unitCost; + @override + int get totalValue; + @override + int get totalIn; + @override + int get totalOut; + @override + bool get isLowStock; + @override + bool get isZeroStock; + @override + String get updatedAt; + + /// Create a copy of InventoryIngredient + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryIngredientImplCopyWith<_$InventoryIngredientImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + DashboardOverview get overview => throw _privateConstructorUsedError; + List get topProducts => + throw _privateConstructorUsedError; + List get paymentMethods => + throw _privateConstructorUsedError; + List get recentSales => + throw _privateConstructorUsedError; + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticCopyWith<$Res> { + factory $DashboardAnalyticCopyWith( + DashboardAnalytic value, + $Res Function(DashboardAnalytic) then, + ) = _$DashboardAnalyticCopyWithImpl<$Res, DashboardAnalytic>; + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + DashboardOverview overview, + List topProducts, + List paymentMethods, + List recentSales, + }); + + $DashboardOverviewCopyWith<$Res> get overview; +} + +/// @nodoc +class _$DashboardAnalyticCopyWithImpl<$Res, $Val extends DashboardAnalytic> + implements $DashboardAnalyticCopyWith<$Res> { + _$DashboardAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? overview = null, + Object? topProducts = null, + Object? paymentMethods = null, + Object? recentSales = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + overview: null == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverview, + topProducts: null == topProducts + ? _value.topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List, + paymentMethods: null == paymentMethods + ? _value.paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List, + recentSales: null == recentSales + ? _value.recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardOverviewCopyWith<$Res> get overview { + return $DashboardOverviewCopyWith<$Res>(_value.overview, (value) { + return _then(_value.copyWith(overview: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$DashboardAnalyticImplCopyWith<$Res> + implements $DashboardAnalyticCopyWith<$Res> { + factory _$$DashboardAnalyticImplCopyWith( + _$DashboardAnalyticImpl value, + $Res Function(_$DashboardAnalyticImpl) then, + ) = __$$DashboardAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + DashboardOverview overview, + List topProducts, + List paymentMethods, + List recentSales, + }); + + @override + $DashboardOverviewCopyWith<$Res> get overview; +} + +/// @nodoc +class __$$DashboardAnalyticImplCopyWithImpl<$Res> + extends _$DashboardAnalyticCopyWithImpl<$Res, _$DashboardAnalyticImpl> + implements _$$DashboardAnalyticImplCopyWith<$Res> { + __$$DashboardAnalyticImplCopyWithImpl( + _$DashboardAnalyticImpl _value, + $Res Function(_$DashboardAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? overview = null, + Object? topProducts = null, + Object? paymentMethods = null, + Object? recentSales = null, + }) { + return _then( + _$DashboardAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + overview: null == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverview, + topProducts: null == topProducts + ? _value._topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List, + paymentMethods: null == paymentMethods + ? _value._paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List, + recentSales: null == recentSales + ? _value._recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$DashboardAnalyticImpl implements _DashboardAnalytic { + const _$DashboardAnalyticImpl({ + required this.organizationId, + required this.outletId, + required this.dateFrom, + required this.dateTo, + required this.overview, + required final List topProducts, + required final List paymentMethods, + required final List recentSales, + }) : _topProducts = topProducts, + _paymentMethods = paymentMethods, + _recentSales = recentSales; + + @override + final String organizationId; + @override + final String outletId; + @override + final String dateFrom; + @override + final String dateTo; + @override + final DashboardOverview overview; + final List _topProducts; + @override + List get topProducts { + if (_topProducts is EqualUnmodifiableListView) return _topProducts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_topProducts); + } + + final List _paymentMethods; + @override + List get paymentMethods { + if (_paymentMethods is EqualUnmodifiableListView) return _paymentMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_paymentMethods); + } + + final List _recentSales; + @override + List get recentSales { + if (_recentSales is EqualUnmodifiableListView) return _recentSales; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_recentSales); + } + + @override + String toString() { + return 'DashboardAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, overview: $overview, topProducts: $topProducts, paymentMethods: $paymentMethods, recentSales: $recentSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.overview, overview) || + other.overview == overview) && + const DeepCollectionEquality().equals( + other._topProducts, + _topProducts, + ) && + const DeepCollectionEquality().equals( + other._paymentMethods, + _paymentMethods, + ) && + const DeepCollectionEquality().equals( + other._recentSales, + _recentSales, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + overview, + const DeepCollectionEquality().hash(_topProducts), + const DeepCollectionEquality().hash(_paymentMethods), + const DeepCollectionEquality().hash(_recentSales), + ); + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardAnalyticImplCopyWith<_$DashboardAnalyticImpl> get copyWith => + __$$DashboardAnalyticImplCopyWithImpl<_$DashboardAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardAnalytic implements DashboardAnalytic { + const factory _DashboardAnalytic({ + required final String organizationId, + required final String outletId, + required final String dateFrom, + required final String dateTo, + required final DashboardOverview overview, + required final List topProducts, + required final List paymentMethods, + required final List recentSales, + }) = _$DashboardAnalyticImpl; + + @override + String get organizationId; + @override + String get outletId; + @override + String get dateFrom; + @override + String get dateTo; + @override + DashboardOverview get overview; + @override + List get topProducts; + @override + List get paymentMethods; + @override + List get recentSales; + + /// Create a copy of DashboardAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardAnalyticImplCopyWith<_$DashboardAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardOverview { + int get totalSales => throw _privateConstructorUsedError; + int get totalOrders => throw _privateConstructorUsedError; + double get averageOrderValue => throw _privateConstructorUsedError; + int get totalCustomers => throw _privateConstructorUsedError; + int get voidedOrders => throw _privateConstructorUsedError; + int get refundedOrders => throw _privateConstructorUsedError; + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardOverviewCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardOverviewCopyWith<$Res> { + factory $DashboardOverviewCopyWith( + DashboardOverview value, + $Res Function(DashboardOverview) then, + ) = _$DashboardOverviewCopyWithImpl<$Res, DashboardOverview>; + @useResult + $Res call({ + int totalSales, + int totalOrders, + double averageOrderValue, + int totalCustomers, + int voidedOrders, + int refundedOrders, + }); +} + +/// @nodoc +class _$DashboardOverviewCopyWithImpl<$Res, $Val extends DashboardOverview> + implements $DashboardOverviewCopyWith<$Res> { + _$DashboardOverviewCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = null, + Object? totalOrders = null, + Object? averageOrderValue = null, + Object? totalCustomers = null, + Object? voidedOrders = null, + Object? refundedOrders = null, + }) { + return _then( + _value.copyWith( + totalSales: null == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + totalCustomers: null == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int, + voidedOrders: null == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int, + refundedOrders: null == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardOverviewImplCopyWith<$Res> + implements $DashboardOverviewCopyWith<$Res> { + factory _$$DashboardOverviewImplCopyWith( + _$DashboardOverviewImpl value, + $Res Function(_$DashboardOverviewImpl) then, + ) = __$$DashboardOverviewImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + int totalSales, + int totalOrders, + double averageOrderValue, + int totalCustomers, + int voidedOrders, + int refundedOrders, + }); +} + +/// @nodoc +class __$$DashboardOverviewImplCopyWithImpl<$Res> + extends _$DashboardOverviewCopyWithImpl<$Res, _$DashboardOverviewImpl> + implements _$$DashboardOverviewImplCopyWith<$Res> { + __$$DashboardOverviewImplCopyWithImpl( + _$DashboardOverviewImpl _value, + $Res Function(_$DashboardOverviewImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = null, + Object? totalOrders = null, + Object? averageOrderValue = null, + Object? totalCustomers = null, + Object? voidedOrders = null, + Object? refundedOrders = null, + }) { + return _then( + _$DashboardOverviewImpl( + totalSales: null == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + totalCustomers: null == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int, + voidedOrders: null == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int, + refundedOrders: null == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$DashboardOverviewImpl implements _DashboardOverview { + const _$DashboardOverviewImpl({ + required this.totalSales, + required this.totalOrders, + required this.averageOrderValue, + required this.totalCustomers, + required this.voidedOrders, + required this.refundedOrders, + }); + + @override + final int totalSales; + @override + final int totalOrders; + @override + final double averageOrderValue; + @override + final int totalCustomers; + @override + final int voidedOrders; + @override + final int refundedOrders; + + @override + String toString() { + return 'DashboardOverview(totalSales: $totalSales, totalOrders: $totalOrders, averageOrderValue: $averageOrderValue, totalCustomers: $totalCustomers, voidedOrders: $voidedOrders, refundedOrders: $refundedOrders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardOverviewImpl && + (identical(other.totalSales, totalSales) || + other.totalSales == totalSales) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue) && + (identical(other.totalCustomers, totalCustomers) || + other.totalCustomers == totalCustomers) && + (identical(other.voidedOrders, voidedOrders) || + other.voidedOrders == voidedOrders) && + (identical(other.refundedOrders, refundedOrders) || + other.refundedOrders == refundedOrders)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalSales, + totalOrders, + averageOrderValue, + totalCustomers, + voidedOrders, + refundedOrders, + ); + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardOverviewImplCopyWith<_$DashboardOverviewImpl> get copyWith => + __$$DashboardOverviewImplCopyWithImpl<_$DashboardOverviewImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardOverview implements DashboardOverview { + const factory _DashboardOverview({ + required final int totalSales, + required final int totalOrders, + required final double averageOrderValue, + required final int totalCustomers, + required final int voidedOrders, + required final int refundedOrders, + }) = _$DashboardOverviewImpl; + + @override + int get totalSales; + @override + int get totalOrders; + @override + double get averageOrderValue; + @override + int get totalCustomers; + @override + int get voidedOrders; + @override + int get refundedOrders; + + /// Create a copy of DashboardOverview + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardOverviewImplCopyWith<_$DashboardOverviewImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardTopProduct { + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryId => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantitySold => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + double get averagePrice => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardTopProductCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardTopProductCopyWith<$Res> { + factory $DashboardTopProductCopyWith( + DashboardTopProduct value, + $Res Function(DashboardTopProduct) then, + ) = _$DashboardTopProductCopyWithImpl<$Res, DashboardTopProduct>; + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + double averagePrice, + int orderCount, + }); +} + +/// @nodoc +class _$DashboardTopProductCopyWithImpl<$Res, $Val extends DashboardTopProduct> + implements $DashboardTopProductCopyWith<$Res> { + _$DashboardTopProductCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? averagePrice = null, + Object? orderCount = null, + }) { + return _then( + _value.copyWith( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardTopProductImplCopyWith<$Res> + implements $DashboardTopProductCopyWith<$Res> { + factory _$$DashboardTopProductImplCopyWith( + _$DashboardTopProductImpl value, + $Res Function(_$DashboardTopProductImpl) then, + ) = __$$DashboardTopProductImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + double averagePrice, + int orderCount, + }); +} + +/// @nodoc +class __$$DashboardTopProductImplCopyWithImpl<$Res> + extends _$DashboardTopProductCopyWithImpl<$Res, _$DashboardTopProductImpl> + implements _$$DashboardTopProductImplCopyWith<$Res> { + __$$DashboardTopProductImplCopyWithImpl( + _$DashboardTopProductImpl _value, + $Res Function(_$DashboardTopProductImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? averagePrice = null, + Object? orderCount = null, + }) { + return _then( + _$DashboardTopProductImpl( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$DashboardTopProductImpl implements _DashboardTopProduct { + const _$DashboardTopProductImpl({ + required this.productId, + required this.productName, + required this.categoryId, + required this.categoryName, + required this.quantitySold, + required this.revenue, + required this.averagePrice, + required this.orderCount, + }); + + @override + final String productId; + @override + final String productName; + @override + final String categoryId; + @override + final String categoryName; + @override + final int quantitySold; + @override + final int revenue; + @override + final double averagePrice; + @override + final int orderCount; + + @override + String toString() { + return 'DashboardTopProduct(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, averagePrice: $averagePrice, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardTopProductImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + averagePrice, + orderCount, + ); + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardTopProductImplCopyWith<_$DashboardTopProductImpl> get copyWith => + __$$DashboardTopProductImplCopyWithImpl<_$DashboardTopProductImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardTopProduct implements DashboardTopProduct { + const factory _DashboardTopProduct({ + required final String productId, + required final String productName, + required final String categoryId, + required final String categoryName, + required final int quantitySold, + required final int revenue, + required final double averagePrice, + required final int orderCount, + }) = _$DashboardTopProductImpl; + + @override + String get productId; + @override + String get productName; + @override + String get categoryId; + @override + String get categoryName; + @override + int get quantitySold; + @override + int get revenue; + @override + double get averagePrice; + @override + int get orderCount; + + /// Create a copy of DashboardTopProduct + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardTopProductImplCopyWith<_$DashboardTopProductImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardPaymentMethod { + String get paymentMethodId => throw _privateConstructorUsedError; + String get paymentMethodName => throw _privateConstructorUsedError; + String get paymentMethodType => throw _privateConstructorUsedError; + int get totalAmount => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + int get paymentCount => throw _privateConstructorUsedError; + double get percentage => throw _privateConstructorUsedError; + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardPaymentMethodCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardPaymentMethodCopyWith<$Res> { + factory $DashboardPaymentMethodCopyWith( + DashboardPaymentMethod value, + $Res Function(DashboardPaymentMethod) then, + ) = _$DashboardPaymentMethodCopyWithImpl<$Res, DashboardPaymentMethod>; + @useResult + $Res call({ + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + int totalAmount, + int orderCount, + int paymentCount, + double percentage, + }); +} + +/// @nodoc +class _$DashboardPaymentMethodCopyWithImpl< + $Res, + $Val extends DashboardPaymentMethod +> + implements $DashboardPaymentMethodCopyWith<$Res> { + _$DashboardPaymentMethodCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? totalAmount = null, + Object? orderCount = null, + Object? paymentCount = null, + Object? percentage = null, + }) { + return _then( + _value.copyWith( + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + percentage: null == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardPaymentMethodImplCopyWith<$Res> + implements $DashboardPaymentMethodCopyWith<$Res> { + factory _$$DashboardPaymentMethodImplCopyWith( + _$DashboardPaymentMethodImpl value, + $Res Function(_$DashboardPaymentMethodImpl) then, + ) = __$$DashboardPaymentMethodImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + int totalAmount, + int orderCount, + int paymentCount, + double percentage, + }); +} + +/// @nodoc +class __$$DashboardPaymentMethodImplCopyWithImpl<$Res> + extends + _$DashboardPaymentMethodCopyWithImpl<$Res, _$DashboardPaymentMethodImpl> + implements _$$DashboardPaymentMethodImplCopyWith<$Res> { + __$$DashboardPaymentMethodImplCopyWithImpl( + _$DashboardPaymentMethodImpl _value, + $Res Function(_$DashboardPaymentMethodImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? totalAmount = null, + Object? orderCount = null, + Object? paymentCount = null, + Object? percentage = null, + }) { + return _then( + _$DashboardPaymentMethodImpl( + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + percentage: null == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double, + ), + ); + } +} + +/// @nodoc + +class _$DashboardPaymentMethodImpl implements _DashboardPaymentMethod { + const _$DashboardPaymentMethodImpl({ + required this.paymentMethodId, + required this.paymentMethodName, + required this.paymentMethodType, + required this.totalAmount, + required this.orderCount, + required this.paymentCount, + required this.percentage, + }); + + @override + final String paymentMethodId; + @override + final String paymentMethodName; + @override + final String paymentMethodType; + @override + final int totalAmount; + @override + final int orderCount; + @override + final int paymentCount; + @override + final double percentage; + + @override + String toString() { + return 'DashboardPaymentMethod(paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, totalAmount: $totalAmount, orderCount: $orderCount, paymentCount: $paymentCount, percentage: $percentage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardPaymentMethodImpl && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.percentage, percentage) || + other.percentage == percentage)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodId, + paymentMethodName, + paymentMethodType, + totalAmount, + orderCount, + paymentCount, + percentage, + ); + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardPaymentMethodImplCopyWith<_$DashboardPaymentMethodImpl> + get copyWith => + __$$DashboardPaymentMethodImplCopyWithImpl<_$DashboardPaymentMethodImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardPaymentMethod implements DashboardPaymentMethod { + const factory _DashboardPaymentMethod({ + required final String paymentMethodId, + required final String paymentMethodName, + required final String paymentMethodType, + required final int totalAmount, + required final int orderCount, + required final int paymentCount, + required final double percentage, + }) = _$DashboardPaymentMethodImpl; + + @override + String get paymentMethodId; + @override + String get paymentMethodName; + @override + String get paymentMethodType; + @override + int get totalAmount; + @override + int get orderCount; + @override + int get paymentCount; + @override + double get percentage; + + /// Create a copy of DashboardPaymentMethod + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardPaymentMethodImplCopyWith<_$DashboardPaymentMethodImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$DashboardRecentSale { + String get date => throw _privateConstructorUsedError; + int get sales => throw _privateConstructorUsedError; + int get orders => throw _privateConstructorUsedError; + int get items => throw _privateConstructorUsedError; + int get tax => throw _privateConstructorUsedError; + int get discount => throw _privateConstructorUsedError; + int get netSales => throw _privateConstructorUsedError; + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardRecentSaleCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardRecentSaleCopyWith<$Res> { + factory $DashboardRecentSaleCopyWith( + DashboardRecentSale value, + $Res Function(DashboardRecentSale) then, + ) = _$DashboardRecentSaleCopyWithImpl<$Res, DashboardRecentSale>; + @useResult + $Res call({ + String date, + int sales, + int orders, + int items, + int tax, + int discount, + int netSales, + }); +} + +/// @nodoc +class _$DashboardRecentSaleCopyWithImpl<$Res, $Val extends DashboardRecentSale> + implements $DashboardRecentSaleCopyWith<$Res> { + _$DashboardRecentSaleCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? sales = null, + Object? orders = null, + Object? items = null, + Object? tax = null, + Object? discount = null, + Object? netSales = null, + }) { + return _then( + _value.copyWith( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + items: null == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardRecentSaleImplCopyWith<$Res> + implements $DashboardRecentSaleCopyWith<$Res> { + factory _$$DashboardRecentSaleImplCopyWith( + _$DashboardRecentSaleImpl value, + $Res Function(_$DashboardRecentSaleImpl) then, + ) = __$$DashboardRecentSaleImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String date, + int sales, + int orders, + int items, + int tax, + int discount, + int netSales, + }); +} + +/// @nodoc +class __$$DashboardRecentSaleImplCopyWithImpl<$Res> + extends _$DashboardRecentSaleCopyWithImpl<$Res, _$DashboardRecentSaleImpl> + implements _$$DashboardRecentSaleImplCopyWith<$Res> { + __$$DashboardRecentSaleImplCopyWithImpl( + _$DashboardRecentSaleImpl _value, + $Res Function(_$DashboardRecentSaleImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = null, + Object? sales = null, + Object? orders = null, + Object? items = null, + Object? tax = null, + Object? discount = null, + Object? netSales = null, + }) { + return _then( + _$DashboardRecentSaleImpl( + date: null == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String, + sales: null == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int, + orders: null == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int, + items: null == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int, + tax: null == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int, + discount: null == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int, + netSales: null == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$DashboardRecentSaleImpl implements _DashboardRecentSale { + const _$DashboardRecentSaleImpl({ + required this.date, + required this.sales, + required this.orders, + required this.items, + required this.tax, + required this.discount, + required this.netSales, + }); + + @override + final String date; + @override + final int sales; + @override + final int orders; + @override + final int items; + @override + final int tax; + @override + final int discount; + @override + final int netSales; + + @override + String toString() { + return 'DashboardRecentSale(date: $date, sales: $sales, orders: $orders, items: $items, tax: $tax, discount: $discount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardRecentSaleImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.orders, orders) || other.orders == orders) && + (identical(other.items, items) || other.items == items) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + date, + sales, + orders, + items, + tax, + discount, + netSales, + ); + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardRecentSaleImplCopyWith<_$DashboardRecentSaleImpl> get copyWith => + __$$DashboardRecentSaleImplCopyWithImpl<_$DashboardRecentSaleImpl>( + this, + _$identity, + ); +} + +abstract class _DashboardRecentSale implements DashboardRecentSale { + const factory _DashboardRecentSale({ + required final String date, + required final int sales, + required final int orders, + required final int items, + required final int tax, + required final int discount, + required final int netSales, + }) = _$DashboardRecentSaleImpl; + + @override + String get date; + @override + int get sales; + @override + int get orders; + @override + int get items; + @override + int get tax; + @override + int get discount; + @override + int get netSales; + + /// Create a copy of DashboardRecentSale + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardRecentSaleImplCopyWith<_$DashboardRecentSaleImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProductAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + List get data => throw _privateConstructorUsedError; + + /// Create a copy of ProductAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductAnalyticCopyWith<$Res> { + factory $ProductAnalyticCopyWith( + ProductAnalytic value, + $Res Function(ProductAnalytic) then, + ) = _$ProductAnalyticCopyWithImpl<$Res, ProductAnalytic>; + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + List data, + }); +} + +/// @nodoc +class _$ProductAnalyticCopyWithImpl<$Res, $Val extends ProductAnalytic> + implements $ProductAnalyticCopyWith<$Res> { + _$ProductAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? data = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductAnalyticImplCopyWith<$Res> + implements $ProductAnalyticCopyWith<$Res> { + factory _$$ProductAnalyticImplCopyWith( + _$ProductAnalyticImpl value, + $Res Function(_$ProductAnalyticImpl) then, + ) = __$$ProductAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + List data, + }); +} + +/// @nodoc +class __$$ProductAnalyticImplCopyWithImpl<$Res> + extends _$ProductAnalyticCopyWithImpl<$Res, _$ProductAnalyticImpl> + implements _$$ProductAnalyticImplCopyWith<$Res> { + __$$ProductAnalyticImplCopyWithImpl( + _$ProductAnalyticImpl _value, + $Res Function(_$ProductAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? data = null, + }) { + return _then( + _$ProductAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$ProductAnalyticImpl implements _ProductAnalytic { + const _$ProductAnalyticImpl({ + required this.organizationId, + required this.outletId, + required this.dateFrom, + required this.dateTo, + required final List data, + }) : _data = data; + + @override + final String organizationId; + @override + final String outletId; + @override + final String dateFrom; + @override + final String dateTo; + final List _data; + @override + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + @override + String toString() { + return 'ProductAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of ProductAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductAnalyticImplCopyWith<_$ProductAnalyticImpl> get copyWith => + __$$ProductAnalyticImplCopyWithImpl<_$ProductAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _ProductAnalytic implements ProductAnalytic { + const factory _ProductAnalytic({ + required final String organizationId, + required final String outletId, + required final String dateFrom, + required final String dateTo, + required final List data, + }) = _$ProductAnalyticImpl; + + @override + String get organizationId; + @override + String get outletId; + @override + String get dateFrom; + @override + String get dateTo; + @override + List get data; + + /// Create a copy of ProductAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductAnalyticImplCopyWith<_$ProductAnalyticImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProductAnalyticData { + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + String get categoryId => throw _privateConstructorUsedError; + String get categoryName => throw _privateConstructorUsedError; + int get quantitySold => throw _privateConstructorUsedError; + int get revenue => throw _privateConstructorUsedError; + double get averagePrice => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + + /// Create a copy of ProductAnalyticData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductAnalyticDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductAnalyticDataCopyWith<$Res> { + factory $ProductAnalyticDataCopyWith( + ProductAnalyticData value, + $Res Function(ProductAnalyticData) then, + ) = _$ProductAnalyticDataCopyWithImpl<$Res, ProductAnalyticData>; + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + double averagePrice, + int orderCount, + }); +} + +/// @nodoc +class _$ProductAnalyticDataCopyWithImpl<$Res, $Val extends ProductAnalyticData> + implements $ProductAnalyticDataCopyWith<$Res> { + _$ProductAnalyticDataCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductAnalyticData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? averagePrice = null, + Object? orderCount = null, + }) { + return _then( + _value.copyWith( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductAnalyticDataImplCopyWith<$Res> + implements $ProductAnalyticDataCopyWith<$Res> { + factory _$$ProductAnalyticDataImplCopyWith( + _$ProductAnalyticDataImpl value, + $Res Function(_$ProductAnalyticDataImpl) then, + ) = __$$ProductAnalyticDataImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String productId, + String productName, + String categoryId, + String categoryName, + int quantitySold, + int revenue, + double averagePrice, + int orderCount, + }); +} + +/// @nodoc +class __$$ProductAnalyticDataImplCopyWithImpl<$Res> + extends _$ProductAnalyticDataCopyWithImpl<$Res, _$ProductAnalyticDataImpl> + implements _$$ProductAnalyticDataImplCopyWith<$Res> { + __$$ProductAnalyticDataImplCopyWithImpl( + _$ProductAnalyticDataImpl _value, + $Res Function(_$ProductAnalyticDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalyticData + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = null, + Object? productName = null, + Object? categoryId = null, + Object? categoryName = null, + Object? quantitySold = null, + Object? revenue = null, + Object? averagePrice = null, + Object? orderCount = null, + }) { + return _then( + _$ProductAnalyticDataImpl( + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + categoryName: null == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String, + quantitySold: null == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int, + revenue: null == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int, + averagePrice: null == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + ), + ); + } +} + +/// @nodoc + +class _$ProductAnalyticDataImpl implements _ProductAnalyticData { + const _$ProductAnalyticDataImpl({ + required this.productId, + required this.productName, + required this.categoryId, + required this.categoryName, + required this.quantitySold, + required this.revenue, + required this.averagePrice, + required this.orderCount, + }); + + @override + final String productId; + @override + final String productName; + @override + final String categoryId; + @override + final String categoryName; + @override + final int quantitySold; + @override + final int revenue; + @override + final double averagePrice; + @override + final int orderCount; + + @override + String toString() { + return 'ProductAnalyticData(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, averagePrice: $averagePrice, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductAnalyticDataImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + averagePrice, + orderCount, + ); + + /// Create a copy of ProductAnalyticData + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductAnalyticDataImplCopyWith<_$ProductAnalyticDataImpl> get copyWith => + __$$ProductAnalyticDataImplCopyWithImpl<_$ProductAnalyticDataImpl>( + this, + _$identity, + ); +} + +abstract class _ProductAnalyticData implements ProductAnalyticData { + const factory _ProductAnalyticData({ + required final String productId, + required final String productName, + required final String categoryId, + required final String categoryName, + required final int quantitySold, + required final int revenue, + required final double averagePrice, + required final int orderCount, + }) = _$ProductAnalyticDataImpl; + + @override + String get productId; + @override + String get productName; + @override + String get categoryId; + @override + String get categoryName; + @override + int get quantitySold; + @override + int get revenue; + @override + double get averagePrice; + @override + int get orderCount; + + /// Create a copy of ProductAnalyticData + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductAnalyticDataImplCopyWith<_$ProductAnalyticDataImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$PaymentMethodAnalytic { + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get dateFrom => throw _privateConstructorUsedError; + String get dateTo => throw _privateConstructorUsedError; + String get groupBy => throw _privateConstructorUsedError; + PaymentMethodSummary get summary => throw _privateConstructorUsedError; + List get data => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodAnalyticCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodAnalyticCopyWith<$Res> { + factory $PaymentMethodAnalyticCopyWith( + PaymentMethodAnalytic value, + $Res Function(PaymentMethodAnalytic) then, + ) = _$PaymentMethodAnalyticCopyWithImpl<$Res, PaymentMethodAnalytic>; + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + String groupBy, + PaymentMethodSummary summary, + List data, + }); + + $PaymentMethodSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class _$PaymentMethodAnalyticCopyWithImpl< + $Res, + $Val extends PaymentMethodAnalytic +> + implements $PaymentMethodAnalyticCopyWith<$Res> { + _$PaymentMethodAnalyticCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + }) { + return _then( + _value.copyWith( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as PaymentMethodSummary, + data: null == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } + + /// Create a copy of PaymentMethodAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $PaymentMethodSummaryCopyWith<$Res> get summary { + return $PaymentMethodSummaryCopyWith<$Res>(_value.summary, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$PaymentMethodAnalyticImplCopyWith<$Res> + implements $PaymentMethodAnalyticCopyWith<$Res> { + factory _$$PaymentMethodAnalyticImplCopyWith( + _$PaymentMethodAnalyticImpl value, + $Res Function(_$PaymentMethodAnalyticImpl) then, + ) = __$$PaymentMethodAnalyticImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String organizationId, + String outletId, + String dateFrom, + String dateTo, + String groupBy, + PaymentMethodSummary summary, + List data, + }); + + @override + $PaymentMethodSummaryCopyWith<$Res> get summary; +} + +/// @nodoc +class __$$PaymentMethodAnalyticImplCopyWithImpl<$Res> + extends + _$PaymentMethodAnalyticCopyWithImpl<$Res, _$PaymentMethodAnalyticImpl> + implements _$$PaymentMethodAnalyticImplCopyWith<$Res> { + __$$PaymentMethodAnalyticImplCopyWithImpl( + _$PaymentMethodAnalyticImpl _value, + $Res Function(_$PaymentMethodAnalyticImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodAnalytic + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = null, + Object? outletId = null, + Object? dateFrom = null, + Object? dateTo = null, + Object? groupBy = null, + Object? summary = null, + Object? data = null, + }) { + return _then( + _$PaymentMethodAnalyticImpl( + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + dateFrom: null == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String, + dateTo: null == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String, + groupBy: null == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String, + summary: null == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as PaymentMethodSummary, + data: null == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$PaymentMethodAnalyticImpl implements _PaymentMethodAnalytic { + const _$PaymentMethodAnalyticImpl({ + required this.organizationId, + required this.outletId, + required this.dateFrom, + required this.dateTo, + required this.groupBy, + required this.summary, + required final List data, + }) : _data = data; + + @override + final String organizationId; + @override + final String outletId; + @override + final String dateFrom; + @override + final String dateTo; + @override + final String groupBy; + @override + final PaymentMethodSummary summary; + final List _data; + @override + List get data { + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_data); + } + + @override + String toString() { + return 'PaymentMethodAnalytic(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodAnalyticImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of PaymentMethodAnalytic + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodAnalyticImplCopyWith<_$PaymentMethodAnalyticImpl> + get copyWith => + __$$PaymentMethodAnalyticImplCopyWithImpl<_$PaymentMethodAnalyticImpl>( + this, + _$identity, + ); +} + +abstract class _PaymentMethodAnalytic implements PaymentMethodAnalytic { + const factory _PaymentMethodAnalytic({ + required final String organizationId, + required final String outletId, + required final String dateFrom, + required final String dateTo, + required final String groupBy, + required final PaymentMethodSummary summary, + required final List data, + }) = _$PaymentMethodAnalyticImpl; + + @override + String get organizationId; + @override + String get outletId; + @override + String get dateFrom; + @override + String get dateTo; + @override + String get groupBy; + @override + PaymentMethodSummary get summary; + @override + List get data; + + /// Create a copy of PaymentMethodAnalytic + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodAnalyticImplCopyWith<_$PaymentMethodAnalyticImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$PaymentMethodItem { + String get paymentMethodId => throw _privateConstructorUsedError; + String get paymentMethodName => throw _privateConstructorUsedError; + String get paymentMethodType => throw _privateConstructorUsedError; + num get totalAmount => throw _privateConstructorUsedError; + int get orderCount => throw _privateConstructorUsedError; + int get paymentCount => throw _privateConstructorUsedError; + double get percentage => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodItemCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodItemCopyWith<$Res> { + factory $PaymentMethodItemCopyWith( + PaymentMethodItem value, + $Res Function(PaymentMethodItem) then, + ) = _$PaymentMethodItemCopyWithImpl<$Res, PaymentMethodItem>; + @useResult + $Res call({ + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + num totalAmount, + int orderCount, + int paymentCount, + double percentage, + }); +} + +/// @nodoc +class _$PaymentMethodItemCopyWithImpl<$Res, $Val extends PaymentMethodItem> + implements $PaymentMethodItemCopyWith<$Res> { + _$PaymentMethodItemCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? totalAmount = null, + Object? orderCount = null, + Object? paymentCount = null, + Object? percentage = null, + }) { + return _then( + _value.copyWith( + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + percentage: null == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$PaymentMethodItemImplCopyWith<$Res> + implements $PaymentMethodItemCopyWith<$Res> { + factory _$$PaymentMethodItemImplCopyWith( + _$PaymentMethodItemImpl value, + $Res Function(_$PaymentMethodItemImpl) then, + ) = __$$PaymentMethodItemImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + num totalAmount, + int orderCount, + int paymentCount, + double percentage, + }); +} + +/// @nodoc +class __$$PaymentMethodItemImplCopyWithImpl<$Res> + extends _$PaymentMethodItemCopyWithImpl<$Res, _$PaymentMethodItemImpl> + implements _$$PaymentMethodItemImplCopyWith<$Res> { + __$$PaymentMethodItemImplCopyWithImpl( + _$PaymentMethodItemImpl _value, + $Res Function(_$PaymentMethodItemImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? totalAmount = null, + Object? orderCount = null, + Object? paymentCount = null, + Object? percentage = null, + }) { + return _then( + _$PaymentMethodItemImpl( + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num, + orderCount: null == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + percentage: null == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double, + ), + ); + } +} + +/// @nodoc + +class _$PaymentMethodItemImpl implements _PaymentMethodItem { + const _$PaymentMethodItemImpl({ + required this.paymentMethodId, + required this.paymentMethodName, + required this.paymentMethodType, + required this.totalAmount, + required this.orderCount, + required this.paymentCount, + required this.percentage, + }); + + @override + final String paymentMethodId; + @override + final String paymentMethodName; + @override + final String paymentMethodType; + @override + final num totalAmount; + @override + final int orderCount; + @override + final int paymentCount; + @override + final double percentage; + + @override + String toString() { + return 'PaymentMethodItem(paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, totalAmount: $totalAmount, orderCount: $orderCount, paymentCount: $paymentCount, percentage: $percentage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodItemImpl && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.percentage, percentage) || + other.percentage == percentage)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodId, + paymentMethodName, + paymentMethodType, + totalAmount, + orderCount, + paymentCount, + percentage, + ); + + /// Create a copy of PaymentMethodItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodItemImplCopyWith<_$PaymentMethodItemImpl> get copyWith => + __$$PaymentMethodItemImplCopyWithImpl<_$PaymentMethodItemImpl>( + this, + _$identity, + ); +} + +abstract class _PaymentMethodItem implements PaymentMethodItem { + const factory _PaymentMethodItem({ + required final String paymentMethodId, + required final String paymentMethodName, + required final String paymentMethodType, + required final num totalAmount, + required final int orderCount, + required final int paymentCount, + required final double percentage, + }) = _$PaymentMethodItemImpl; + + @override + String get paymentMethodId; + @override + String get paymentMethodName; + @override + String get paymentMethodType; + @override + num get totalAmount; + @override + int get orderCount; + @override + int get paymentCount; + @override + double get percentage; + + /// Create a copy of PaymentMethodItem + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodItemImplCopyWith<_$PaymentMethodItemImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$PaymentMethodSummary { + num get totalAmount => throw _privateConstructorUsedError; + int get totalOrders => throw _privateConstructorUsedError; + int get totalPayments => throw _privateConstructorUsedError; + double get averageOrderValue => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodSummaryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodSummaryCopyWith<$Res> { + factory $PaymentMethodSummaryCopyWith( + PaymentMethodSummary value, + $Res Function(PaymentMethodSummary) then, + ) = _$PaymentMethodSummaryCopyWithImpl<$Res, PaymentMethodSummary>; + @useResult + $Res call({ + num totalAmount, + int totalOrders, + int totalPayments, + double averageOrderValue, + }); +} + +/// @nodoc +class _$PaymentMethodSummaryCopyWithImpl< + $Res, + $Val extends PaymentMethodSummary +> + implements $PaymentMethodSummaryCopyWith<$Res> { + _$PaymentMethodSummaryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalAmount = null, + Object? totalOrders = null, + Object? totalPayments = null, + Object? averageOrderValue = null, + }) { + return _then( + _value.copyWith( + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + totalPayments: null == totalPayments + ? _value.totalPayments + : totalPayments // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$PaymentMethodSummaryImplCopyWith<$Res> + implements $PaymentMethodSummaryCopyWith<$Res> { + factory _$$PaymentMethodSummaryImplCopyWith( + _$PaymentMethodSummaryImpl value, + $Res Function(_$PaymentMethodSummaryImpl) then, + ) = __$$PaymentMethodSummaryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + num totalAmount, + int totalOrders, + int totalPayments, + double averageOrderValue, + }); +} + +/// @nodoc +class __$$PaymentMethodSummaryImplCopyWithImpl<$Res> + extends _$PaymentMethodSummaryCopyWithImpl<$Res, _$PaymentMethodSummaryImpl> + implements _$$PaymentMethodSummaryImplCopyWith<$Res> { + __$$PaymentMethodSummaryImplCopyWithImpl( + _$PaymentMethodSummaryImpl _value, + $Res Function(_$PaymentMethodSummaryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodSummary + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalAmount = null, + Object? totalOrders = null, + Object? totalPayments = null, + Object? averageOrderValue = null, + }) { + return _then( + _$PaymentMethodSummaryImpl( + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num, + totalOrders: null == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int, + totalPayments: null == totalPayments + ? _value.totalPayments + : totalPayments // ignore: cast_nullable_to_non_nullable + as int, + averageOrderValue: null == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double, + ), + ); + } +} + +/// @nodoc + +class _$PaymentMethodSummaryImpl implements _PaymentMethodSummary { + const _$PaymentMethodSummaryImpl({ + required this.totalAmount, + required this.totalOrders, + required this.totalPayments, + required this.averageOrderValue, + }); + + @override + final num totalAmount; + @override + final int totalOrders; + @override + final int totalPayments; + @override + final double averageOrderValue; + + @override + String toString() { + return 'PaymentMethodSummary(totalAmount: $totalAmount, totalOrders: $totalOrders, totalPayments: $totalPayments, averageOrderValue: $averageOrderValue)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodSummaryImpl && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.totalPayments, totalPayments) || + other.totalPayments == totalPayments) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + totalAmount, + totalOrders, + totalPayments, + averageOrderValue, + ); + + /// Create a copy of PaymentMethodSummary + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodSummaryImplCopyWith<_$PaymentMethodSummaryImpl> + get copyWith => + __$$PaymentMethodSummaryImplCopyWithImpl<_$PaymentMethodSummaryImpl>( + this, + _$identity, + ); +} + +abstract class _PaymentMethodSummary implements PaymentMethodSummary { + const factory _PaymentMethodSummary({ + required final num totalAmount, + required final int totalOrders, + required final int totalPayments, + required final double averageOrderValue, + }) = _$PaymentMethodSummaryImpl; + + @override + num get totalAmount; + @override + int get totalOrders; + @override + int get totalPayments; + @override + double get averageOrderValue; + + /// Create a copy of PaymentMethodSummary + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodSummaryImplCopyWith<_$PaymentMethodSummaryImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$AnalyticFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AnalyticFailureCopyWith<$Res> { + factory $AnalyticFailureCopyWith( + AnalyticFailure value, + $Res Function(AnalyticFailure) then, + ) = _$AnalyticFailureCopyWithImpl<$Res, AnalyticFailure>; +} + +/// @nodoc +class _$AnalyticFailureCopyWithImpl<$Res, $Val extends AnalyticFailure> + implements $AnalyticFailureCopyWith<$Res> { + _$AnalyticFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$AnalyticFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'AnalyticFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements AnalyticFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$AnalyticFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'AnalyticFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements AnalyticFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$AnalyticFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'AnalyticFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements AnalyticFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$AnalyticFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'AnalyticFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements AnalyticFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of AnalyticFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/analytic/entities/category_analytic_entity.dart b/lib/domain/analytic/entities/category_analytic_entity.dart new file mode 100644 index 0000000..56d8f29 --- /dev/null +++ b/lib/domain/analytic/entities/category_analytic_entity.dart @@ -0,0 +1,41 @@ +part of '../analytic.dart'; + +@freezed +class CategoryAnalytic with _$CategoryAnalytic { + const factory CategoryAnalytic({ + required String organizationId, + required String outletId, + required String dateFrom, + required String dateTo, + required List data, + }) = _CategoryAnalytic; + + factory CategoryAnalytic.empty() => const CategoryAnalytic( + organizationId: "", + outletId: "", + dateFrom: "", + dateTo: "", + data: [], + ); +} + +@freezed +class CategoryAnalyticItem with _$CategoryAnalyticItem { + const factory CategoryAnalyticItem({ + required String categoryId, + required String categoryName, + required int totalRevenue, + required int totalQuantity, + required int productCount, + required int orderCount, + }) = _CategoryAnalyticItem; + + factory CategoryAnalyticItem.empty() => const CategoryAnalyticItem( + categoryId: "", + categoryName: "", + totalRevenue: 0, + totalQuantity: 0, + productCount: 0, + orderCount: 0, + ); +} diff --git a/lib/domain/analytic/entities/dashboard_analytic_entity.dart b/lib/domain/analytic/entities/dashboard_analytic_entity.dart new file mode 100644 index 0000000..204c85b --- /dev/null +++ b/lib/domain/analytic/entities/dashboard_analytic_entity.dart @@ -0,0 +1,118 @@ +part of '../analytic.dart'; + +@freezed +class DashboardAnalytic with _$DashboardAnalytic { + const factory DashboardAnalytic({ + required String organizationId, + required String outletId, + required String dateFrom, + required String dateTo, + required DashboardOverview overview, + required List topProducts, + required List paymentMethods, + required List recentSales, + }) = _DashboardAnalytic; + + factory DashboardAnalytic.empty() => DashboardAnalytic( + organizationId: '', + outletId: '', + dateFrom: '', + dateTo: '', + overview: DashboardOverview.empty(), + topProducts: const [], + paymentMethods: const [], + recentSales: const [], + ); +} + +@freezed +class DashboardOverview with _$DashboardOverview { + const factory DashboardOverview({ + required int totalSales, + required int totalOrders, + required double averageOrderValue, + required int totalCustomers, + required int voidedOrders, + required int refundedOrders, + }) = _DashboardOverview; + + factory DashboardOverview.empty() => const DashboardOverview( + totalSales: 0, + totalOrders: 0, + averageOrderValue: 0.0, + totalCustomers: 0, + voidedOrders: 0, + refundedOrders: 0, + ); +} + +@freezed +class DashboardTopProduct with _$DashboardTopProduct { + const factory DashboardTopProduct({ + required String productId, + required String productName, + required String categoryId, + required String categoryName, + required int quantitySold, + required int revenue, + required double averagePrice, + required int orderCount, + }) = _DashboardTopProduct; + + factory DashboardTopProduct.empty() => const DashboardTopProduct( + productId: '', + productName: '', + categoryId: '', + categoryName: '', + quantitySold: 0, + revenue: 0, + averagePrice: 0.0, + orderCount: 0, + ); +} + +@freezed +class DashboardPaymentMethod with _$DashboardPaymentMethod { + const factory DashboardPaymentMethod({ + required String paymentMethodId, + required String paymentMethodName, + required String paymentMethodType, + required int totalAmount, + required int orderCount, + required int paymentCount, + required double percentage, + }) = _DashboardPaymentMethod; + + factory DashboardPaymentMethod.empty() => const DashboardPaymentMethod( + paymentMethodId: '', + paymentMethodName: '', + paymentMethodType: '', + totalAmount: 0, + orderCount: 0, + paymentCount: 0, + percentage: 0.0, + ); +} + +@freezed +class DashboardRecentSale with _$DashboardRecentSale { + const factory DashboardRecentSale({ + required String date, + required int sales, + required int orders, + required int items, + required int tax, + required int discount, + required int netSales, + }) = _DashboardRecentSale; + + factory DashboardRecentSale.empty() => const DashboardRecentSale( + date: '', + sales: 0, + orders: 0, + items: 0, + tax: 0, + discount: 0, + netSales: 0, + ); +} diff --git a/lib/domain/analytic/entities/inventory_analytic_entity.dart b/lib/domain/analytic/entities/inventory_analytic_entity.dart new file mode 100644 index 0000000..00d373c --- /dev/null +++ b/lib/domain/analytic/entities/inventory_analytic_entity.dart @@ -0,0 +1,119 @@ +part of '../analytic.dart'; + +@freezed +class InventoryAnalytic with _$InventoryAnalytic { + const factory InventoryAnalytic({ + required InventorySummary summary, + required List products, + required List ingredients, + }) = _InventoryAnalytic; + + factory InventoryAnalytic.empty() => InventoryAnalytic( + summary: InventorySummary.empty(), + products: [], + ingredients: [], + ); +} + +@freezed +class InventorySummary with _$InventorySummary { + const factory InventorySummary({ + required int totalProducts, + required int totalIngredients, + required int totalValue, + required int lowStockProducts, + required int lowStockIngredients, + required int zeroStockProducts, + required int zeroStockIngredients, + required int totalSoldProducts, + required int totalSoldIngredients, + required String outletId, + required String outletName, + required String generatedAt, + }) = _InventorySummary; + + factory InventorySummary.empty() => const InventorySummary( + totalProducts: 0, + totalIngredients: 0, + totalValue: 0, + lowStockProducts: 0, + lowStockIngredients: 0, + zeroStockProducts: 0, + zeroStockIngredients: 0, + totalSoldProducts: 0, + totalSoldIngredients: 0, + outletId: "", + outletName: "", + generatedAt: "", + ); +} + +@freezed +class InventoryProduct with _$InventoryProduct { + const factory InventoryProduct({ + required String id, + required String productId, + required String productName, + required String categoryName, + required int quantity, + required int reorderLevel, + required int unitCost, + required int totalValue, + required int totalIn, + required int totalOut, + required bool isLowStock, + required bool isZeroStock, + required String updatedAt, + }) = _InventoryProduct; + + factory InventoryProduct.empty() => const InventoryProduct( + id: "", + productId: "", + productName: "", + categoryName: "", + quantity: 0, + reorderLevel: 0, + unitCost: 0, + totalValue: 0, + totalIn: 0, + totalOut: 0, + isLowStock: false, + isZeroStock: false, + updatedAt: "", + ); +} + +@freezed +class InventoryIngredient with _$InventoryIngredient { + const factory InventoryIngredient({ + required String id, + required String ingredientId, + required String ingredientName, + required String unitName, + required int quantity, + required int reorderLevel, + required int unitCost, + required int totalValue, + required int totalIn, + required int totalOut, + required bool isLowStock, + required bool isZeroStock, + required String updatedAt, + }) = _InventoryIngredient; + + factory InventoryIngredient.empty() => const InventoryIngredient( + id: "", + ingredientId: "", + ingredientName: "", + unitName: "", + quantity: 0, + reorderLevel: 0, + unitCost: 0, + totalValue: 0, + totalIn: 0, + totalOut: 0, + isLowStock: false, + isZeroStock: false, + updatedAt: "", + ); +} diff --git a/lib/domain/analytic/entities/payment_method_analytic_entity.dart b/lib/domain/analytic/entities/payment_method_analytic_entity.dart new file mode 100644 index 0000000..859e06d --- /dev/null +++ b/lib/domain/analytic/entities/payment_method_analytic_entity.dart @@ -0,0 +1,64 @@ +part of '../analytic.dart'; + +@freezed +class PaymentMethodAnalytic with _$PaymentMethodAnalytic { + const factory PaymentMethodAnalytic({ + required String organizationId, + required String outletId, + required String dateFrom, + required String dateTo, + required String groupBy, + required PaymentMethodSummary summary, + required List data, + }) = _PaymentMethodAnalytic; + + factory PaymentMethodAnalytic.empty() => PaymentMethodAnalytic( + organizationId: '', + outletId: '', + dateFrom: '', + dateTo: '', + groupBy: '', + summary: PaymentMethodSummary.empty(), + data: [], + ); +} + +@freezed +class PaymentMethodItem with _$PaymentMethodItem { + const factory PaymentMethodItem({ + required String paymentMethodId, + required String paymentMethodName, + required String paymentMethodType, + required num totalAmount, + required int orderCount, + required int paymentCount, + required double percentage, + }) = _PaymentMethodItem; + + factory PaymentMethodItem.empty() => const PaymentMethodItem( + paymentMethodId: '', + paymentMethodName: '', + paymentMethodType: '', + totalAmount: 0, + orderCount: 0, + paymentCount: 0, + percentage: 0.0, + ); +} + +@freezed +class PaymentMethodSummary with _$PaymentMethodSummary { + const factory PaymentMethodSummary({ + required num totalAmount, + required int totalOrders, + required int totalPayments, + required double averageOrderValue, + }) = _PaymentMethodSummary; + + factory PaymentMethodSummary.empty() => const PaymentMethodSummary( + totalAmount: 0, + totalOrders: 0, + totalPayments: 0, + averageOrderValue: 0.0, + ); +} diff --git a/lib/domain/analytic/entities/product_analytic_entity.dart b/lib/domain/analytic/entities/product_analytic_entity.dart new file mode 100644 index 0000000..33b8c3a --- /dev/null +++ b/lib/domain/analytic/entities/product_analytic_entity.dart @@ -0,0 +1,45 @@ +part of '../analytic.dart'; + +@freezed +class ProductAnalytic with _$ProductAnalytic { + const factory ProductAnalytic({ + required String organizationId, + required String outletId, + required String dateFrom, + required String dateTo, + required List data, + }) = _ProductAnalytic; + + factory ProductAnalytic.empty() => const ProductAnalytic( + organizationId: '', + outletId: '', + dateFrom: '', + dateTo: '', + data: [], + ); +} + +@freezed +class ProductAnalyticData with _$ProductAnalyticData { + const factory ProductAnalyticData({ + required String productId, + required String productName, + required String categoryId, + required String categoryName, + required int quantitySold, + required int revenue, + required double averagePrice, + required int orderCount, + }) = _ProductAnalyticData; + + factory ProductAnalyticData.empty() => const ProductAnalyticData( + productId: '', + productName: '', + categoryId: '', + categoryName: '', + quantitySold: 0, + revenue: 0, + averagePrice: 0.0, + orderCount: 0, + ); +} diff --git a/lib/domain/analytic/entities/profit_loss_analytic_entity.dart b/lib/domain/analytic/entities/profit_loss_analytic_entity.dart new file mode 100644 index 0000000..3828307 --- /dev/null +++ b/lib/domain/analytic/entities/profit_loss_analytic_entity.dart @@ -0,0 +1,117 @@ +part of '../analytic.dart'; + +@freezed +class ProfitLossAnalytic with _$ProfitLossAnalytic { + const factory ProfitLossAnalytic({ + required String organizationId, + required String dateFrom, + required String dateTo, + required String groupBy, + required ProfitLossSummary summary, + required List data, + required List productData, + }) = _ProfitLossAnalytic; + + factory ProfitLossAnalytic.empty() => ProfitLossAnalytic( + organizationId: '', + dateFrom: '', + dateTo: '', + groupBy: '', + summary: ProfitLossSummary.empty(), + data: [], + productData: [], + ); +} + +@freezed +class ProfitLossSummary with _$ProfitLossSummary { + const factory ProfitLossSummary({ + required int totalRevenue, + required int totalCost, + required int grossProfit, + required double grossProfitMargin, + required int totalTax, + required int totalDiscount, + required int netProfit, + required double netProfitMargin, + required int totalOrders, + required double averageProfit, + required double profitabilityRatio, + }) = _ProfitLossSummary; + + factory ProfitLossSummary.empty() => ProfitLossSummary( + totalRevenue: 0, + totalCost: 0, + grossProfit: 0, + grossProfitMargin: 0, + totalTax: 0, + totalDiscount: 0, + netProfit: 0, + netProfitMargin: 0, + totalOrders: 0, + averageProfit: 0, + profitabilityRatio: 0, + ); +} + +@freezed +class ProfitLossDailyData with _$ProfitLossDailyData { + const factory ProfitLossDailyData({ + required String date, + required int revenue, + required int cost, + required int grossProfit, + required double grossProfitMargin, + required int tax, + required int discount, + required int netProfit, + required double netProfitMargin, + required int orders, + }) = _ProfitLossDailyData; + + factory ProfitLossDailyData.empty() => ProfitLossDailyData( + date: '', + revenue: 0, + cost: 0, + grossProfit: 0, + grossProfitMargin: 0, + tax: 0, + discount: 0, + netProfit: 0, + netProfitMargin: 0, + orders: 0, + ); +} + +@freezed +class ProfitLossProductData with _$ProfitLossProductData { + const factory ProfitLossProductData({ + required String productId, + required String productName, + required String categoryId, + required String categoryName, + required int quantitySold, + required int revenue, + required int cost, + required int grossProfit, + required double grossProfitMargin, + required int averagePrice, + required int averageCost, + required int profitPerUnit, + }) = _ProfitLossProductData; + + factory ProfitLossProductData.empty() => ProfitLossProductData( + productId: '', + productName: '', + categoryId: '', + categoryName: '', + quantitySold: 0, + revenue: 0, + cost: 0, + grossProfit: 0, + grossProfitMargin: 0, + averagePrice: 0, + averageCost: 0, + profitPerUnit: 0, + ); +} diff --git a/lib/domain/analytic/entities/sales_analytic_entity.dart b/lib/domain/analytic/entities/sales_analytic_entity.dart new file mode 100644 index 0000000..e53d57f --- /dev/null +++ b/lib/domain/analytic/entities/sales_analytic_entity.dart @@ -0,0 +1,70 @@ +part of '../analytic.dart'; + +@freezed +class SalesAnalytic with _$SalesAnalytic { + const factory SalesAnalytic({ + required String organizationId, + required String outletId, + required DateTime dateFrom, + required DateTime dateTo, + required String groupBy, + required SalesAnalyticSummary summary, + required List data, + }) = _SalesAnalytic; + + factory SalesAnalytic.empty() => SalesAnalytic( + organizationId: '', + outletId: '', + dateFrom: DateTime.fromMillisecondsSinceEpoch(0), + dateTo: DateTime.fromMillisecondsSinceEpoch(0), + groupBy: '', + summary: SalesAnalyticSummary.empty(), + data: [], + ); +} + +@freezed +class SalesAnalyticSummary with _$SalesAnalyticSummary { + const factory SalesAnalyticSummary({ + required int totalSales, + required int totalOrders, + required int totalItems, + required double averageOrderValue, + required int totalTax, + required int totalDiscount, + required int netSales, + }) = _SalesAnalyticSummary; + + factory SalesAnalyticSummary.empty() => const SalesAnalyticSummary( + totalSales: 0, + totalOrders: 0, + totalItems: 0, + averageOrderValue: 0, + totalTax: 0, + totalDiscount: 0, + netSales: 0, + ); +} + +@freezed +class SalesAnalyticData with _$SalesAnalyticData { + const factory SalesAnalyticData({ + required DateTime date, + required int sales, + required int orders, + required int items, + required int tax, + required int discount, + required int netSales, + }) = _SalesAnalyticData; + + factory SalesAnalyticData.empty() => SalesAnalyticData( + date: DateTime.fromMillisecondsSinceEpoch(0), + sales: 0, + orders: 0, + items: 0, + tax: 0, + discount: 0, + netSales: 0, + ); +} diff --git a/lib/domain/analytic/failures/analytic_failure.dart b/lib/domain/analytic/failures/analytic_failure.dart new file mode 100644 index 0000000..d0b1a54 --- /dev/null +++ b/lib/domain/analytic/failures/analytic_failure.dart @@ -0,0 +1,10 @@ +part of '../analytic.dart'; + +@freezed +sealed class AnalyticFailure with _$AnalyticFailure { + const factory AnalyticFailure.serverError(ApiFailure failure) = _ServerError; + const factory AnalyticFailure.unexpectedError() = _UnexpectedError; + const factory AnalyticFailure.empty() = _Empty; + const factory AnalyticFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/analytic/repositories/i_analytic_repository.dart b/lib/domain/analytic/repositories/i_analytic_repository.dart new file mode 100644 index 0000000..dbaf131 --- /dev/null +++ b/lib/domain/analytic/repositories/i_analytic_repository.dart @@ -0,0 +1,47 @@ +import 'package:dartz/dartz.dart'; + +import '../analytic.dart'; + +abstract class IAnalyticRepository { + Future> getSales({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); + + Future> getProfitLoss({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); + + Future> getCategory({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); + + Future> getInventory({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); + + Future> getDashboard({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); + + Future> getProduct({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); + + Future> getPaymentMethod({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }); +} diff --git a/lib/domain/auth/auth.dart b/lib/domain/auth/auth.dart new file mode 100644 index 0000000..20c5d07 --- /dev/null +++ b/lib/domain/auth/auth.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:dartz/dartz.dart'; + +import '../../common/api/api_failure.dart'; +import '../user/user.dart'; + +part 'failures/auth_failure.dart'; +part 'repositories/i_auth_repository.dart'; +part 'entities/auth_entity.dart'; + +part 'auth.freezed.dart'; diff --git a/lib/domain/auth/auth.freezed.dart b/lib/domain/auth/auth.freezed.dart new file mode 100644 index 0000000..405a0c7 --- /dev/null +++ b/lib/domain/auth/auth.freezed.dart @@ -0,0 +1,693 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'auth.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$AuthFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthFailureCopyWith<$Res> { + factory $AuthFailureCopyWith( + AuthFailure value, + $Res Function(AuthFailure) then, + ) = _$AuthFailureCopyWithImpl<$Res, AuthFailure>; +} + +/// @nodoc +class _$AuthFailureCopyWithImpl<$Res, $Val extends AuthFailure> + implements $AuthFailureCopyWith<$Res> { + _$AuthFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$AuthFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'AuthFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements AuthFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$AuthFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'AuthFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements AuthFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$AuthFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'AuthFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements AuthFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of AuthFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$Auth { + String get token => throw _privateConstructorUsedError; + DateTime get expiresAt => throw _privateConstructorUsedError; + User get user => throw _privateConstructorUsedError; + + /// Create a copy of Auth + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AuthCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthCopyWith<$Res> { + factory $AuthCopyWith(Auth value, $Res Function(Auth) then) = + _$AuthCopyWithImpl<$Res, Auth>; + @useResult + $Res call({String token, DateTime expiresAt, User user}); + + $UserCopyWith<$Res> get user; +} + +/// @nodoc +class _$AuthCopyWithImpl<$Res, $Val extends Auth> + implements $AuthCopyWith<$Res> { + _$AuthCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Auth + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + Object? expiresAt = null, + Object? user = null, + }) { + return _then( + _value.copyWith( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + expiresAt: null == expiresAt + ? _value.expiresAt + : expiresAt // ignore: cast_nullable_to_non_nullable + as DateTime, + user: null == user + ? _value.user + : user // ignore: cast_nullable_to_non_nullable + as User, + ) + as $Val, + ); + } + + /// Create a copy of Auth + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $UserCopyWith<$Res> get user { + return $UserCopyWith<$Res>(_value.user, (value) { + return _then(_value.copyWith(user: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$AuthImplCopyWith<$Res> implements $AuthCopyWith<$Res> { + factory _$$AuthImplCopyWith( + _$AuthImpl value, + $Res Function(_$AuthImpl) then, + ) = __$$AuthImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String token, DateTime expiresAt, User user}); + + @override + $UserCopyWith<$Res> get user; +} + +/// @nodoc +class __$$AuthImplCopyWithImpl<$Res> + extends _$AuthCopyWithImpl<$Res, _$AuthImpl> + implements _$$AuthImplCopyWith<$Res> { + __$$AuthImplCopyWithImpl(_$AuthImpl _value, $Res Function(_$AuthImpl) _then) + : super(_value, _then); + + /// Create a copy of Auth + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = null, + Object? expiresAt = null, + Object? user = null, + }) { + return _then( + _$AuthImpl( + token: null == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String, + expiresAt: null == expiresAt + ? _value.expiresAt + : expiresAt // ignore: cast_nullable_to_non_nullable + as DateTime, + user: null == user + ? _value.user + : user // ignore: cast_nullable_to_non_nullable + as User, + ), + ); + } +} + +/// @nodoc + +class _$AuthImpl extends _Auth { + const _$AuthImpl({ + required this.token, + required this.expiresAt, + required this.user, + }) : super._(); + + @override + final String token; + @override + final DateTime expiresAt; + @override + final User user; + + @override + String toString() { + return 'Auth(token: $token, expiresAt: $expiresAt, user: $user)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AuthImpl && + (identical(other.token, token) || other.token == token) && + (identical(other.expiresAt, expiresAt) || + other.expiresAt == expiresAt) && + (identical(other.user, user) || other.user == user)); + } + + @override + int get hashCode => Object.hash(runtimeType, token, expiresAt, user); + + /// Create a copy of Auth + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AuthImplCopyWith<_$AuthImpl> get copyWith => + __$$AuthImplCopyWithImpl<_$AuthImpl>(this, _$identity); +} + +abstract class _Auth extends Auth { + const factory _Auth({ + required final String token, + required final DateTime expiresAt, + required final User user, + }) = _$AuthImpl; + const _Auth._() : super._(); + + @override + String get token; + @override + DateTime get expiresAt; + @override + User get user; + + /// Create a copy of Auth + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AuthImplCopyWith<_$AuthImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/auth/entities/auth_entity.dart b/lib/domain/auth/entities/auth_entity.dart new file mode 100644 index 0000000..fdce15a --- /dev/null +++ b/lib/domain/auth/entities/auth_entity.dart @@ -0,0 +1,18 @@ +part of '../auth.dart'; + +@freezed +class Auth with _$Auth { + const Auth._(); + const factory Auth({ + required String token, + required DateTime expiresAt, + required User user, + }) = _Auth; + + /// State kosong (misalnya untuk initial state di Bloc) + factory Auth.empty() => Auth( + token: '', + expiresAt: DateTime.fromMillisecondsSinceEpoch(0), + user: User.empty(), + ); +} diff --git a/lib/domain/auth/failures/auth_failure.dart b/lib/domain/auth/failures/auth_failure.dart new file mode 100644 index 0000000..bf304fd --- /dev/null +++ b/lib/domain/auth/failures/auth_failure.dart @@ -0,0 +1,9 @@ +part of '../auth.dart'; + +@freezed +sealed class AuthFailure with _$AuthFailure { + const factory AuthFailure.serverError(ApiFailure failure) = _ServerError; + const factory AuthFailure.unexpectedError() = _UnexpectedError; + const factory AuthFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/auth/repositories/i_auth_repository.dart b/lib/domain/auth/repositories/i_auth_repository.dart new file mode 100644 index 0000000..5cfce76 --- /dev/null +++ b/lib/domain/auth/repositories/i_auth_repository.dart @@ -0,0 +1,18 @@ +part of '../auth.dart'; + +abstract class IAuthRepository { + Future> login({ + required String email, + required String password, + required String deviceId, + required String deviceName, + required String deviceType, + required String platform, + required String osVersion, + required String appVersion, + String? fcmToken, + }); + Future hasToken(); + Future> currentUser(); + Future> logout(); +} diff --git a/lib/domain/category/category.dart b/lib/domain/category/category.dart new file mode 100644 index 0000000..0e50ce0 --- /dev/null +++ b/lib/domain/category/category.dart @@ -0,0 +1,10 @@ +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'category.freezed.dart'; + +part 'entities/category_entity.dart'; +part 'failures/category_failure.dart'; +part 'repositories/i_auth_repository.dart'; diff --git a/lib/domain/category/category.freezed.dart b/lib/domain/category/category.freezed.dart new file mode 100644 index 0000000..204a55c --- /dev/null +++ b/lib/domain/category/category.freezed.dart @@ -0,0 +1,952 @@ +// 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 'category.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$Category { + String get id => throw _privateConstructorUsedError; + String get organizationId => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + String get businessType => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + DateTime? get createdAt => throw _privateConstructorUsedError; + DateTime? get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of Category + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryCopyWith<$Res> { + factory $CategoryCopyWith(Category value, $Res Function(Category) then) = + _$CategoryCopyWithImpl<$Res, Category>; + @useResult + $Res call({ + String id, + String organizationId, + String name, + String description, + String businessType, + Map metadata, + DateTime? createdAt, + DateTime? updatedAt, + }); +} + +/// @nodoc +class _$CategoryCopyWithImpl<$Res, $Val extends Category> + implements $CategoryCopyWith<$Res> { + _$CategoryCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Category + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? name = null, + Object? description = null, + Object? businessType = null, + Object? metadata = null, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + businessType: null == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryImplCopyWith<$Res> + implements $CategoryCopyWith<$Res> { + factory _$$CategoryImplCopyWith( + _$CategoryImpl value, + $Res Function(_$CategoryImpl) then, + ) = __$$CategoryImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String organizationId, + String name, + String description, + String businessType, + Map metadata, + DateTime? createdAt, + DateTime? updatedAt, + }); +} + +/// @nodoc +class __$$CategoryImplCopyWithImpl<$Res> + extends _$CategoryCopyWithImpl<$Res, _$CategoryImpl> + implements _$$CategoryImplCopyWith<$Res> { + __$$CategoryImplCopyWithImpl( + _$CategoryImpl _value, + $Res Function(_$CategoryImpl) _then, + ) : super(_value, _then); + + /// Create a copy of Category + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? name = null, + Object? description = null, + Object? businessType = null, + Object? metadata = null, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$CategoryImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + businessType: null == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ), + ); + } +} + +/// @nodoc + +class _$CategoryImpl implements _Category { + const _$CategoryImpl({ + required this.id, + required this.organizationId, + required this.name, + required this.description, + required this.businessType, + required final Map metadata, + this.createdAt, + this.updatedAt, + }) : _metadata = metadata; + + @override + final String id; + @override + final String organizationId; + @override + final String name; + @override + final String description; + @override + final String businessType; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final DateTime? createdAt; + @override + final DateTime? updatedAt; + + @override + String toString() { + return 'Category(id: $id, organizationId: $organizationId, name: $name, description: $description, businessType: $businessType, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.name, name) || other.name == name) && + (identical(other.description, description) || + other.description == description) && + (identical(other.businessType, businessType) || + other.businessType == businessType) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + name, + description, + businessType, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of Category + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryImplCopyWith<_$CategoryImpl> get copyWith => + __$$CategoryImplCopyWithImpl<_$CategoryImpl>(this, _$identity); +} + +abstract class _Category implements Category { + const factory _Category({ + required final String id, + required final String organizationId, + required final String name, + required final String description, + required final String businessType, + required final Map metadata, + final DateTime? createdAt, + final DateTime? updatedAt, + }) = _$CategoryImpl; + + @override + String get id; + @override + String get organizationId; + @override + String get name; + @override + String get description; + @override + String get businessType; + @override + Map get metadata; + @override + DateTime? get createdAt; + @override + DateTime? get updatedAt; + + /// Create a copy of Category + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryImplCopyWith<_$CategoryImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$CategoryFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryFailureCopyWith<$Res> { + factory $CategoryFailureCopyWith( + CategoryFailure value, + $Res Function(CategoryFailure) then, + ) = _$CategoryFailureCopyWithImpl<$Res, CategoryFailure>; +} + +/// @nodoc +class _$CategoryFailureCopyWithImpl<$Res, $Val extends CategoryFailure> + implements $CategoryFailureCopyWith<$Res> { + _$CategoryFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$CategoryFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'CategoryFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements CategoryFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$CategoryFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'CategoryFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements CategoryFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$CategoryFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'CategoryFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements CategoryFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$CategoryFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'CategoryFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements CategoryFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of CategoryFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/category/entities/category_entity.dart b/lib/domain/category/entities/category_entity.dart new file mode 100644 index 0000000..a6d351a --- /dev/null +++ b/lib/domain/category/entities/category_entity.dart @@ -0,0 +1,33 @@ +part of '../category.dart'; + +@freezed +class Category with _$Category { + const factory Category({ + required String id, + required String organizationId, + required String name, + required String description, + required String businessType, + required Map metadata, + DateTime? createdAt, + DateTime? updatedAt, + }) = _Category; + + factory Category.empty() => const Category( + id: '', + organizationId: '', + name: '', + description: '', + businessType: '', + metadata: {}, + ); + + factory Category.addAllData() => Category( + id: 'all', + organizationId: '', + name: 'Semua', + description: '', + businessType: '', + metadata: {}, + ); +} diff --git a/lib/domain/category/failures/category_failure.dart b/lib/domain/category/failures/category_failure.dart new file mode 100644 index 0000000..0df9feb --- /dev/null +++ b/lib/domain/category/failures/category_failure.dart @@ -0,0 +1,10 @@ +part of '../category.dart'; + +@freezed +sealed class CategoryFailure with _$CategoryFailure { + const factory CategoryFailure.serverError(ApiFailure failure) = _ServerError; + const factory CategoryFailure.unexpectedError() = _UnexpectedError; + const factory CategoryFailure.empty() = _Empty; + const factory CategoryFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/category/repositories/i_auth_repository.dart b/lib/domain/category/repositories/i_auth_repository.dart new file mode 100644 index 0000000..c41a494 --- /dev/null +++ b/lib/domain/category/repositories/i_auth_repository.dart @@ -0,0 +1,9 @@ +part of '../category.dart'; + +abstract class ICategoryRepository { + Future>> get({ + int page = 1, + int limit = 20, + bool isActive = true, + }); +} diff --git a/lib/domain/customer/customer.dart b/lib/domain/customer/customer.dart new file mode 100644 index 0000000..d81a9f0 --- /dev/null +++ b/lib/domain/customer/customer.dart @@ -0,0 +1,9 @@ +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'customer.freezed.dart'; +part 'entities/customer_entity.dart'; +part 'failures/customer_failure.dart'; +part 'repositories/i_customer_repository.dart'; diff --git a/lib/domain/customer/customer.freezed.dart b/lib/domain/customer/customer.freezed.dart new file mode 100644 index 0000000..d970276 --- /dev/null +++ b/lib/domain/customer/customer.freezed.dart @@ -0,0 +1,1015 @@ +// 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 'customer.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$Customer { + String get id => throw _privateConstructorUsedError; + String get organizationId => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get email => throw _privateConstructorUsedError; + String get phone => throw _privateConstructorUsedError; + String get address => throw _privateConstructorUsedError; + bool get isDefault => throw _privateConstructorUsedError; + bool get isActive => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + String get createdAt => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of Customer + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CustomerCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CustomerCopyWith<$Res> { + factory $CustomerCopyWith(Customer value, $Res Function(Customer) then) = + _$CustomerCopyWithImpl<$Res, Customer>; + @useResult + $Res call({ + String id, + String organizationId, + String name, + String email, + String phone, + String address, + bool isDefault, + bool isActive, + Map metadata, + String createdAt, + String updatedAt, + }); +} + +/// @nodoc +class _$CustomerCopyWithImpl<$Res, $Val extends Customer> + implements $CustomerCopyWith<$Res> { + _$CustomerCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Customer + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? name = null, + Object? email = null, + Object? phone = null, + Object? address = null, + Object? isDefault = null, + Object? isActive = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + phone: null == phone + ? _value.phone + : phone // ignore: cast_nullable_to_non_nullable + as String, + address: null == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String, + isDefault: null == isDefault + ? _value.isDefault + : isDefault // ignore: cast_nullable_to_non_nullable + as bool, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CustomerImplCopyWith<$Res> + implements $CustomerCopyWith<$Res> { + factory _$$CustomerImplCopyWith( + _$CustomerImpl value, + $Res Function(_$CustomerImpl) then, + ) = __$$CustomerImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String organizationId, + String name, + String email, + String phone, + String address, + bool isDefault, + bool isActive, + Map metadata, + String createdAt, + String updatedAt, + }); +} + +/// @nodoc +class __$$CustomerImplCopyWithImpl<$Res> + extends _$CustomerCopyWithImpl<$Res, _$CustomerImpl> + implements _$$CustomerImplCopyWith<$Res> { + __$$CustomerImplCopyWithImpl( + _$CustomerImpl _value, + $Res Function(_$CustomerImpl) _then, + ) : super(_value, _then); + + /// Create a copy of Customer + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? name = null, + Object? email = null, + Object? phone = null, + Object? address = null, + Object? isDefault = null, + Object? isActive = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _$CustomerImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + phone: null == phone + ? _value.phone + : phone // ignore: cast_nullable_to_non_nullable + as String, + address: null == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String, + isDefault: null == isDefault + ? _value.isDefault + : isDefault // ignore: cast_nullable_to_non_nullable + as bool, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$CustomerImpl implements _Customer { + const _$CustomerImpl({ + required this.id, + required this.organizationId, + required this.name, + required this.email, + required this.phone, + required this.address, + required this.isDefault, + required this.isActive, + required final Map metadata, + required this.createdAt, + required this.updatedAt, + }) : _metadata = metadata; + + @override + final String id; + @override + final String organizationId; + @override + final String name; + @override + final String email; + @override + final String phone; + @override + final String address; + @override + final bool isDefault; + @override + final bool isActive; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final String createdAt; + @override + final String updatedAt; + + @override + String toString() { + return 'Customer(id: $id, organizationId: $organizationId, name: $name, email: $email, phone: $phone, address: $address, isDefault: $isDefault, isActive: $isActive, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CustomerImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.name, name) || other.name == name) && + (identical(other.email, email) || other.email == email) && + (identical(other.phone, phone) || other.phone == phone) && + (identical(other.address, address) || other.address == address) && + (identical(other.isDefault, isDefault) || + other.isDefault == isDefault) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + name, + email, + phone, + address, + isDefault, + isActive, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of Customer + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CustomerImplCopyWith<_$CustomerImpl> get copyWith => + __$$CustomerImplCopyWithImpl<_$CustomerImpl>(this, _$identity); +} + +abstract class _Customer implements Customer { + const factory _Customer({ + required final String id, + required final String organizationId, + required final String name, + required final String email, + required final String phone, + required final String address, + required final bool isDefault, + required final bool isActive, + required final Map metadata, + required final String createdAt, + required final String updatedAt, + }) = _$CustomerImpl; + + @override + String get id; + @override + String get organizationId; + @override + String get name; + @override + String get email; + @override + String get phone; + @override + String get address; + @override + bool get isDefault; + @override + bool get isActive; + @override + Map get metadata; + @override + String get createdAt; + @override + String get updatedAt; + + /// Create a copy of Customer + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CustomerImplCopyWith<_$CustomerImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$CustomerFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CustomerFailureCopyWith<$Res> { + factory $CustomerFailureCopyWith( + CustomerFailure value, + $Res Function(CustomerFailure) then, + ) = _$CustomerFailureCopyWithImpl<$Res, CustomerFailure>; +} + +/// @nodoc +class _$CustomerFailureCopyWithImpl<$Res, $Val extends CustomerFailure> + implements $CustomerFailureCopyWith<$Res> { + _$CustomerFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$CustomerFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'CustomerFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements CustomerFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$CustomerFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'CustomerFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements CustomerFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$CustomerFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'CustomerFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements CustomerFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$CustomerFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'CustomerFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements CustomerFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of CustomerFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/customer/entities/customer_entity.dart b/lib/domain/customer/entities/customer_entity.dart new file mode 100644 index 0000000..5d1632c --- /dev/null +++ b/lib/domain/customer/entities/customer_entity.dart @@ -0,0 +1,32 @@ +part of '../customer.dart'; + +@freezed +class Customer with _$Customer { + const factory Customer({ + required String id, + required String organizationId, + required String name, + required String email, + required String phone, + required String address, + required bool isDefault, + required bool isActive, + required Map metadata, + required String createdAt, + required String updatedAt, + }) = _Customer; + + factory Customer.empty() => Customer( + id: '', + organizationId: '', + name: '', + email: '', + phone: '', + address: '', + isDefault: false, + isActive: false, + metadata: const {}, + createdAt: '', + updatedAt: '', + ); +} diff --git a/lib/domain/customer/failures/customer_failure.dart b/lib/domain/customer/failures/customer_failure.dart new file mode 100644 index 0000000..48d0f86 --- /dev/null +++ b/lib/domain/customer/failures/customer_failure.dart @@ -0,0 +1,10 @@ +part of '../customer.dart'; + +@freezed +sealed class CustomerFailure with _$CustomerFailure { + const factory CustomerFailure.serverError(ApiFailure failure) = _ServerError; + const factory CustomerFailure.unexpectedError() = _UnexpectedError; + const factory CustomerFailure.empty() = _Empty; + const factory CustomerFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/customer/repositories/i_customer_repository.dart b/lib/domain/customer/repositories/i_customer_repository.dart new file mode 100644 index 0000000..6efbac2 --- /dev/null +++ b/lib/domain/customer/repositories/i_customer_repository.dart @@ -0,0 +1,9 @@ +part of '../customer.dart'; + +abstract class ICustomerRepository { + Future>> get({ + int page = 1, + int limit = 20, + String? search, + }); +} diff --git a/lib/domain/language/language.dart b/lib/domain/language/language.dart new file mode 100644 index 0000000..d87a4d7 --- /dev/null +++ b/lib/domain/language/language.dart @@ -0,0 +1,37 @@ +import 'package:flutter/widgets.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'language.freezed.dart'; + +@freezed +abstract class Language with _$Language { + factory Language({ + required Locale locale, + required String name, + required String nativeName, + required String path, + }) = _Language; + + const Language._(); + + factory Language.empty() => Language( + locale: const Locale('id', 'ID'), + name: '', + path: '', + nativeName: '', + ); + + factory Language.indonesian() => Language( + locale: const Locale('id', 'ID'), + name: 'Indonesian', + nativeName: 'Bahasa Indonesia', + path: '🇮🇩', + ); + + factory Language.english() => Language( + locale: const Locale('en', 'US'), + name: 'English', + path: '🇺🇸', + nativeName: 'English', + ); +} diff --git a/lib/domain/language/language.freezed.dart b/lib/domain/language/language.freezed.dart new file mode 100644 index 0000000..c8f89a4 --- /dev/null +++ b/lib/domain/language/language.freezed.dart @@ -0,0 +1,210 @@ +// 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 'language.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$Language { + Locale get locale => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get nativeName => throw _privateConstructorUsedError; + String get path => throw _privateConstructorUsedError; + + /// Create a copy of Language + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LanguageCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LanguageCopyWith<$Res> { + factory $LanguageCopyWith(Language value, $Res Function(Language) then) = + _$LanguageCopyWithImpl<$Res, Language>; + @useResult + $Res call({Locale locale, String name, String nativeName, String path}); +} + +/// @nodoc +class _$LanguageCopyWithImpl<$Res, $Val extends Language> + implements $LanguageCopyWith<$Res> { + _$LanguageCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Language + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? locale = null, + Object? name = null, + Object? nativeName = null, + Object? path = null, + }) { + return _then( + _value.copyWith( + locale: null == locale + ? _value.locale + : locale // ignore: cast_nullable_to_non_nullable + as Locale, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + nativeName: null == nativeName + ? _value.nativeName + : nativeName // ignore: cast_nullable_to_non_nullable + as String, + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$LanguageImplCopyWith<$Res> + implements $LanguageCopyWith<$Res> { + factory _$$LanguageImplCopyWith( + _$LanguageImpl value, + $Res Function(_$LanguageImpl) then, + ) = __$$LanguageImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({Locale locale, String name, String nativeName, String path}); +} + +/// @nodoc +class __$$LanguageImplCopyWithImpl<$Res> + extends _$LanguageCopyWithImpl<$Res, _$LanguageImpl> + implements _$$LanguageImplCopyWith<$Res> { + __$$LanguageImplCopyWithImpl( + _$LanguageImpl _value, + $Res Function(_$LanguageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of Language + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? locale = null, + Object? name = null, + Object? nativeName = null, + Object? path = null, + }) { + return _then( + _$LanguageImpl( + locale: null == locale + ? _value.locale + : locale // ignore: cast_nullable_to_non_nullable + as Locale, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + nativeName: null == nativeName + ? _value.nativeName + : nativeName // ignore: cast_nullable_to_non_nullable + as String, + path: null == path + ? _value.path + : path // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$LanguageImpl extends _Language { + _$LanguageImpl({ + required this.locale, + required this.name, + required this.nativeName, + required this.path, + }) : super._(); + + @override + final Locale locale; + @override + final String name; + @override + final String nativeName; + @override + final String path; + + @override + String toString() { + return 'Language(locale: $locale, name: $name, nativeName: $nativeName, path: $path)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LanguageImpl && + (identical(other.locale, locale) || other.locale == locale) && + (identical(other.name, name) || other.name == name) && + (identical(other.nativeName, nativeName) || + other.nativeName == nativeName) && + (identical(other.path, path) || other.path == path)); + } + + @override + int get hashCode => Object.hash(runtimeType, locale, name, nativeName, path); + + /// Create a copy of Language + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LanguageImplCopyWith<_$LanguageImpl> get copyWith => + __$$LanguageImplCopyWithImpl<_$LanguageImpl>(this, _$identity); +} + +abstract class _Language extends Language { + factory _Language({ + required final Locale locale, + required final String name, + required final String nativeName, + required final String path, + }) = _$LanguageImpl; + _Language._() : super._(); + + @override + Locale get locale; + @override + String get name; + @override + String get nativeName; + @override + String get path; + + /// Create a copy of Language + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LanguageImplCopyWith<_$LanguageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/order/entities/order_entity.dart b/lib/domain/order/entities/order_entity.dart new file mode 100644 index 0000000..f921570 --- /dev/null +++ b/lib/domain/order/entities/order_entity.dart @@ -0,0 +1,161 @@ +part of '../order.dart'; + +@freezed +class Order with _$Order { + const factory Order({ + required String id, + required String orderNumber, + required String outletId, + required String userId, + required String tableNumber, + required String orderType, + required String status, + required int subtotal, + required int taxAmount, + required int discountAmount, + required int totalAmount, + required int totalCost, + required int remainingAmount, + required String paymentStatus, + required int refundAmount, + required bool isVoid, + required bool isRefund, + required String notes, + required Map metadata, + required String createdAt, + required String updatedAt, + required List orderItems, + required List payments, + required int totalPaid, + required int paymentCount, + required String splitType, + }) = _Order; + + factory Order.empty() => Order( + id: '', + orderNumber: '', + outletId: '', + userId: '', + tableNumber: '', + orderType: '', + status: '', + subtotal: 0, + taxAmount: 0, + discountAmount: 0, + totalAmount: 0, + totalCost: 0, + remainingAmount: 0, + paymentStatus: '', + refundAmount: 0, + isVoid: false, + isRefund: false, + notes: '', + metadata: {}, + createdAt: '', + updatedAt: '', + orderItems: [], + payments: [], + totalPaid: 0, + paymentCount: 0, + splitType: '', + ); +} + +@freezed +class OrderItem with _$OrderItem { + const factory OrderItem({ + required String id, + required String orderId, + required String productId, + required String productName, + required int quantity, + required int price, + required int subtotal, + required int discountAmount, + required int total, + required int cost, + required Map metadata, + required String createdAt, + required String updatedAt, + }) = _OrderItem; + + factory OrderItem.empty() => OrderItem( + id: '', + orderId: '', + productId: '', + productName: '', + quantity: 0, + price: 0, + subtotal: 0, + discountAmount: 0, + total: 0, + cost: 0, + metadata: {}, + createdAt: '', + updatedAt: '', + ); +} + +@freezed +class OrderPayment with _$OrderPayment { + const factory OrderPayment({ + required String id, + required String orderId, + required String paymentMethodId, + required String paymentMethodName, + required String paymentMethodType, + required int amount, + required String status, + required int splitNumber, + required int splitTotal, + required String splitType, + required String splitDescription, + required int refundAmount, + required Map metadata, + required String createdAt, + required String updatedAt, + required List paymentOrderItems, + }) = _OrderPayment; + + factory OrderPayment.empty() => OrderPayment( + id: '', + orderId: '', + paymentMethodId: '', + paymentMethodName: '', + paymentMethodType: '', + amount: 0, + status: '', + splitNumber: 0, + splitTotal: 0, + splitType: '', + splitDescription: '', + refundAmount: 0, + metadata: {}, + createdAt: '', + updatedAt: '', + paymentOrderItems: [], + ); +} + +@freezed +class PaymentOrderItem with _$PaymentOrderItem { + const factory PaymentOrderItem({ + required String id, + required String orderPaymentId, + required String orderItemId, + required int amount, + required int refundAmount, + required String createdAt, + required String updatedAt, + }) = _PaymentOrderItem; + + factory PaymentOrderItem.empty() => PaymentOrderItem( + id: '', + orderPaymentId: '', + orderItemId: '', + amount: 0, + refundAmount: 0, + createdAt: '', + updatedAt: '', + ); +} diff --git a/lib/domain/order/failures/order_failure.dart b/lib/domain/order/failures/order_failure.dart new file mode 100644 index 0000000..ed26fe4 --- /dev/null +++ b/lib/domain/order/failures/order_failure.dart @@ -0,0 +1,10 @@ +part of '../order.dart'; + +@freezed +sealed class OrderFailure with _$OrderFailure { + const factory OrderFailure.serverError(ApiFailure failure) = _ServerError; + const factory OrderFailure.unexpectedError() = _UnexpectedError; + const factory OrderFailure.empty() = _Empty; + const factory OrderFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/order/order.dart b/lib/domain/order/order.dart new file mode 100644 index 0000000..73e8ed4 --- /dev/null +++ b/lib/domain/order/order.dart @@ -0,0 +1,10 @@ +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'order.freezed.dart'; + +part 'entities/order_entity.dart'; +part 'failures/order_failure.dart'; +part 'repositories/i_order_repository.dart'; diff --git a/lib/domain/order/order.freezed.dart b/lib/domain/order/order.freezed.dart new file mode 100644 index 0000000..3c8f628 --- /dev/null +++ b/lib/domain/order/order.freezed.dart @@ -0,0 +1,2538 @@ +// 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 'order.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$Order { + String get id => throw _privateConstructorUsedError; + String get orderNumber => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get userId => throw _privateConstructorUsedError; + String get tableNumber => throw _privateConstructorUsedError; + String get orderType => throw _privateConstructorUsedError; + String get status => throw _privateConstructorUsedError; + int get subtotal => throw _privateConstructorUsedError; + int get taxAmount => throw _privateConstructorUsedError; + int get discountAmount => throw _privateConstructorUsedError; + int get totalAmount => throw _privateConstructorUsedError; + int get totalCost => throw _privateConstructorUsedError; + int get remainingAmount => throw _privateConstructorUsedError; + String get paymentStatus => throw _privateConstructorUsedError; + int get refundAmount => throw _privateConstructorUsedError; + bool get isVoid => throw _privateConstructorUsedError; + bool get isRefund => throw _privateConstructorUsedError; + String get notes => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + String get createdAt => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + List get orderItems => throw _privateConstructorUsedError; + List get payments => throw _privateConstructorUsedError; + int get totalPaid => throw _privateConstructorUsedError; + int get paymentCount => throw _privateConstructorUsedError; + String get splitType => throw _privateConstructorUsedError; + + /// Create a copy of Order + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderCopyWith<$Res> { + factory $OrderCopyWith(Order value, $Res Function(Order) then) = + _$OrderCopyWithImpl<$Res, Order>; + @useResult + $Res call({ + String id, + String orderNumber, + String outletId, + String userId, + String tableNumber, + String orderType, + String status, + int subtotal, + int taxAmount, + int discountAmount, + int totalAmount, + int totalCost, + int remainingAmount, + String paymentStatus, + int refundAmount, + bool isVoid, + bool isRefund, + String notes, + Map metadata, + String createdAt, + String updatedAt, + List orderItems, + List payments, + int totalPaid, + int paymentCount, + String splitType, + }); +} + +/// @nodoc +class _$OrderCopyWithImpl<$Res, $Val extends Order> + implements $OrderCopyWith<$Res> { + _$OrderCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Order + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderNumber = null, + Object? outletId = null, + Object? userId = null, + Object? tableNumber = null, + Object? orderType = null, + Object? status = null, + Object? subtotal = null, + Object? taxAmount = null, + Object? discountAmount = null, + Object? totalAmount = null, + Object? totalCost = null, + Object? remainingAmount = null, + Object? paymentStatus = null, + Object? refundAmount = null, + Object? isVoid = null, + Object? isRefund = null, + Object? notes = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? orderItems = null, + Object? payments = null, + Object? totalPaid = null, + Object? paymentCount = null, + Object? splitType = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderNumber: null == orderNumber + ? _value.orderNumber + : orderNumber // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + userId: null == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String, + tableNumber: null == tableNumber + ? _value.tableNumber + : tableNumber // ignore: cast_nullable_to_non_nullable + as String, + orderType: null == orderType + ? _value.orderType + : orderType // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + subtotal: null == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int, + taxAmount: null == taxAmount + ? _value.taxAmount + : taxAmount // ignore: cast_nullable_to_non_nullable + as int, + discountAmount: null == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int, + totalCost: null == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int, + remainingAmount: null == remainingAmount + ? _value.remainingAmount + : remainingAmount // ignore: cast_nullable_to_non_nullable + as int, + paymentStatus: null == paymentStatus + ? _value.paymentStatus + : paymentStatus // ignore: cast_nullable_to_non_nullable + as String, + refundAmount: null == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int, + isVoid: null == isVoid + ? _value.isVoid + : isVoid // ignore: cast_nullable_to_non_nullable + as bool, + isRefund: null == isRefund + ? _value.isRefund + : isRefund // ignore: cast_nullable_to_non_nullable + as bool, + notes: null == notes + ? _value.notes + : notes // ignore: cast_nullable_to_non_nullable + as String, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + orderItems: null == orderItems + ? _value.orderItems + : orderItems // ignore: cast_nullable_to_non_nullable + as List, + payments: null == payments + ? _value.payments + : payments // ignore: cast_nullable_to_non_nullable + as List, + totalPaid: null == totalPaid + ? _value.totalPaid + : totalPaid // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + splitType: null == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OrderImplCopyWith<$Res> implements $OrderCopyWith<$Res> { + factory _$$OrderImplCopyWith( + _$OrderImpl value, + $Res Function(_$OrderImpl) then, + ) = __$$OrderImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String orderNumber, + String outletId, + String userId, + String tableNumber, + String orderType, + String status, + int subtotal, + int taxAmount, + int discountAmount, + int totalAmount, + int totalCost, + int remainingAmount, + String paymentStatus, + int refundAmount, + bool isVoid, + bool isRefund, + String notes, + Map metadata, + String createdAt, + String updatedAt, + List orderItems, + List payments, + int totalPaid, + int paymentCount, + String splitType, + }); +} + +/// @nodoc +class __$$OrderImplCopyWithImpl<$Res> + extends _$OrderCopyWithImpl<$Res, _$OrderImpl> + implements _$$OrderImplCopyWith<$Res> { + __$$OrderImplCopyWithImpl( + _$OrderImpl _value, + $Res Function(_$OrderImpl) _then, + ) : super(_value, _then); + + /// Create a copy of Order + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderNumber = null, + Object? outletId = null, + Object? userId = null, + Object? tableNumber = null, + Object? orderType = null, + Object? status = null, + Object? subtotal = null, + Object? taxAmount = null, + Object? discountAmount = null, + Object? totalAmount = null, + Object? totalCost = null, + Object? remainingAmount = null, + Object? paymentStatus = null, + Object? refundAmount = null, + Object? isVoid = null, + Object? isRefund = null, + Object? notes = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? orderItems = null, + Object? payments = null, + Object? totalPaid = null, + Object? paymentCount = null, + Object? splitType = null, + }) { + return _then( + _$OrderImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderNumber: null == orderNumber + ? _value.orderNumber + : orderNumber // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + userId: null == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String, + tableNumber: null == tableNumber + ? _value.tableNumber + : tableNumber // ignore: cast_nullable_to_non_nullable + as String, + orderType: null == orderType + ? _value.orderType + : orderType // ignore: cast_nullable_to_non_nullable + as String, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + subtotal: null == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int, + taxAmount: null == taxAmount + ? _value.taxAmount + : taxAmount // ignore: cast_nullable_to_non_nullable + as int, + discountAmount: null == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int, + totalAmount: null == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int, + totalCost: null == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int, + remainingAmount: null == remainingAmount + ? _value.remainingAmount + : remainingAmount // ignore: cast_nullable_to_non_nullable + as int, + paymentStatus: null == paymentStatus + ? _value.paymentStatus + : paymentStatus // ignore: cast_nullable_to_non_nullable + as String, + refundAmount: null == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int, + isVoid: null == isVoid + ? _value.isVoid + : isVoid // ignore: cast_nullable_to_non_nullable + as bool, + isRefund: null == isRefund + ? _value.isRefund + : isRefund // ignore: cast_nullable_to_non_nullable + as bool, + notes: null == notes + ? _value.notes + : notes // ignore: cast_nullable_to_non_nullable + as String, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + orderItems: null == orderItems + ? _value._orderItems + : orderItems // ignore: cast_nullable_to_non_nullable + as List, + payments: null == payments + ? _value._payments + : payments // ignore: cast_nullable_to_non_nullable + as List, + totalPaid: null == totalPaid + ? _value.totalPaid + : totalPaid // ignore: cast_nullable_to_non_nullable + as int, + paymentCount: null == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int, + splitType: null == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$OrderImpl implements _Order { + const _$OrderImpl({ + required this.id, + required this.orderNumber, + required this.outletId, + required this.userId, + required this.tableNumber, + required this.orderType, + required this.status, + required this.subtotal, + required this.taxAmount, + required this.discountAmount, + required this.totalAmount, + required this.totalCost, + required this.remainingAmount, + required this.paymentStatus, + required this.refundAmount, + required this.isVoid, + required this.isRefund, + required this.notes, + required final Map metadata, + required this.createdAt, + required this.updatedAt, + required final List orderItems, + required final List payments, + required this.totalPaid, + required this.paymentCount, + required this.splitType, + }) : _metadata = metadata, + _orderItems = orderItems, + _payments = payments; + + @override + final String id; + @override + final String orderNumber; + @override + final String outletId; + @override + final String userId; + @override + final String tableNumber; + @override + final String orderType; + @override + final String status; + @override + final int subtotal; + @override + final int taxAmount; + @override + final int discountAmount; + @override + final int totalAmount; + @override + final int totalCost; + @override + final int remainingAmount; + @override + final String paymentStatus; + @override + final int refundAmount; + @override + final bool isVoid; + @override + final bool isRefund; + @override + final String notes; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final String createdAt; + @override + final String updatedAt; + final List _orderItems; + @override + List get orderItems { + if (_orderItems is EqualUnmodifiableListView) return _orderItems; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_orderItems); + } + + final List _payments; + @override + List get payments { + if (_payments is EqualUnmodifiableListView) return _payments; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_payments); + } + + @override + final int totalPaid; + @override + final int paymentCount; + @override + final String splitType; + + @override + String toString() { + return 'Order(id: $id, orderNumber: $orderNumber, outletId: $outletId, userId: $userId, tableNumber: $tableNumber, orderType: $orderType, status: $status, subtotal: $subtotal, taxAmount: $taxAmount, discountAmount: $discountAmount, totalAmount: $totalAmount, totalCost: $totalCost, remainingAmount: $remainingAmount, paymentStatus: $paymentStatus, refundAmount: $refundAmount, isVoid: $isVoid, isRefund: $isRefund, notes: $notes, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt, orderItems: $orderItems, payments: $payments, totalPaid: $totalPaid, paymentCount: $paymentCount, splitType: $splitType)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderNumber, orderNumber) || + other.orderNumber == orderNumber) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.userId, userId) || other.userId == userId) && + (identical(other.tableNumber, tableNumber) || + other.tableNumber == tableNumber) && + (identical(other.orderType, orderType) || + other.orderType == orderType) && + (identical(other.status, status) || other.status == status) && + (identical(other.subtotal, subtotal) || + other.subtotal == subtotal) && + (identical(other.taxAmount, taxAmount) || + other.taxAmount == taxAmount) && + (identical(other.discountAmount, discountAmount) || + other.discountAmount == discountAmount) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.totalCost, totalCost) || + other.totalCost == totalCost) && + (identical(other.remainingAmount, remainingAmount) || + other.remainingAmount == remainingAmount) && + (identical(other.paymentStatus, paymentStatus) || + other.paymentStatus == paymentStatus) && + (identical(other.refundAmount, refundAmount) || + other.refundAmount == refundAmount) && + (identical(other.isVoid, isVoid) || other.isVoid == isVoid) && + (identical(other.isRefund, isRefund) || + other.isRefund == isRefund) && + (identical(other.notes, notes) || other.notes == notes) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals( + other._orderItems, + _orderItems, + ) && + const DeepCollectionEquality().equals(other._payments, _payments) && + (identical(other.totalPaid, totalPaid) || + other.totalPaid == totalPaid) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.splitType, splitType) || + other.splitType == splitType)); + } + + @override + int get hashCode => Object.hashAll([ + runtimeType, + id, + orderNumber, + outletId, + userId, + tableNumber, + orderType, + status, + subtotal, + taxAmount, + discountAmount, + totalAmount, + totalCost, + remainingAmount, + paymentStatus, + refundAmount, + isVoid, + isRefund, + notes, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + const DeepCollectionEquality().hash(_orderItems), + const DeepCollectionEquality().hash(_payments), + totalPaid, + paymentCount, + splitType, + ]); + + /// Create a copy of Order + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderImplCopyWith<_$OrderImpl> get copyWith => + __$$OrderImplCopyWithImpl<_$OrderImpl>(this, _$identity); +} + +abstract class _Order implements Order { + const factory _Order({ + required final String id, + required final String orderNumber, + required final String outletId, + required final String userId, + required final String tableNumber, + required final String orderType, + required final String status, + required final int subtotal, + required final int taxAmount, + required final int discountAmount, + required final int totalAmount, + required final int totalCost, + required final int remainingAmount, + required final String paymentStatus, + required final int refundAmount, + required final bool isVoid, + required final bool isRefund, + required final String notes, + required final Map metadata, + required final String createdAt, + required final String updatedAt, + required final List orderItems, + required final List payments, + required final int totalPaid, + required final int paymentCount, + required final String splitType, + }) = _$OrderImpl; + + @override + String get id; + @override + String get orderNumber; + @override + String get outletId; + @override + String get userId; + @override + String get tableNumber; + @override + String get orderType; + @override + String get status; + @override + int get subtotal; + @override + int get taxAmount; + @override + int get discountAmount; + @override + int get totalAmount; + @override + int get totalCost; + @override + int get remainingAmount; + @override + String get paymentStatus; + @override + int get refundAmount; + @override + bool get isVoid; + @override + bool get isRefund; + @override + String get notes; + @override + Map get metadata; + @override + String get createdAt; + @override + String get updatedAt; + @override + List get orderItems; + @override + List get payments; + @override + int get totalPaid; + @override + int get paymentCount; + @override + String get splitType; + + /// Create a copy of Order + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderImplCopyWith<_$OrderImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$OrderItem { + String get id => throw _privateConstructorUsedError; + String get orderId => throw _privateConstructorUsedError; + String get productId => throw _privateConstructorUsedError; + String get productName => throw _privateConstructorUsedError; + int get quantity => throw _privateConstructorUsedError; + int get price => throw _privateConstructorUsedError; + int get subtotal => throw _privateConstructorUsedError; + int get discountAmount => throw _privateConstructorUsedError; + int get total => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + String get createdAt => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of OrderItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderItemCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderItemCopyWith<$Res> { + factory $OrderItemCopyWith(OrderItem value, $Res Function(OrderItem) then) = + _$OrderItemCopyWithImpl<$Res, OrderItem>; + @useResult + $Res call({ + String id, + String orderId, + String productId, + String productName, + int quantity, + int price, + int subtotal, + int discountAmount, + int total, + int cost, + Map metadata, + String createdAt, + String updatedAt, + }); +} + +/// @nodoc +class _$OrderItemCopyWithImpl<$Res, $Val extends OrderItem> + implements $OrderItemCopyWith<$Res> { + _$OrderItemCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderId = null, + Object? productId = null, + Object? productName = null, + Object? quantity = null, + Object? price = null, + Object? subtotal = null, + Object? discountAmount = null, + Object? total = null, + Object? cost = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderId: null == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + price: null == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int, + subtotal: null == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int, + discountAmount: null == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int, + total: null == total + ? _value.total + : total // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OrderItemImplCopyWith<$Res> + implements $OrderItemCopyWith<$Res> { + factory _$$OrderItemImplCopyWith( + _$OrderItemImpl value, + $Res Function(_$OrderItemImpl) then, + ) = __$$OrderItemImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String orderId, + String productId, + String productName, + int quantity, + int price, + int subtotal, + int discountAmount, + int total, + int cost, + Map metadata, + String createdAt, + String updatedAt, + }); +} + +/// @nodoc +class __$$OrderItemImplCopyWithImpl<$Res> + extends _$OrderItemCopyWithImpl<$Res, _$OrderItemImpl> + implements _$$OrderItemImplCopyWith<$Res> { + __$$OrderItemImplCopyWithImpl( + _$OrderItemImpl _value, + $Res Function(_$OrderItemImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderId = null, + Object? productId = null, + Object? productName = null, + Object? quantity = null, + Object? price = null, + Object? subtotal = null, + Object? discountAmount = null, + Object? total = null, + Object? cost = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _$OrderItemImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderId: null == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + productName: null == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String, + quantity: null == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int, + price: null == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int, + subtotal: null == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int, + discountAmount: null == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int, + total: null == total + ? _value.total + : total // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$OrderItemImpl implements _OrderItem { + const _$OrderItemImpl({ + required this.id, + required this.orderId, + required this.productId, + required this.productName, + required this.quantity, + required this.price, + required this.subtotal, + required this.discountAmount, + required this.total, + required this.cost, + required final Map metadata, + required this.createdAt, + required this.updatedAt, + }) : _metadata = metadata; + + @override + final String id; + @override + final String orderId; + @override + final String productId; + @override + final String productName; + @override + final int quantity; + @override + final int price; + @override + final int subtotal; + @override + final int discountAmount; + @override + final int total; + @override + final int cost; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final String createdAt; + @override + final String updatedAt; + + @override + String toString() { + return 'OrderItem(id: $id, orderId: $orderId, productId: $productId, productName: $productName, quantity: $quantity, price: $price, subtotal: $subtotal, discountAmount: $discountAmount, total: $total, cost: $cost, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderItemImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderId, orderId) || other.orderId == orderId) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.price, price) || other.price == price) && + (identical(other.subtotal, subtotal) || + other.subtotal == subtotal) && + (identical(other.discountAmount, discountAmount) || + other.discountAmount == discountAmount) && + (identical(other.total, total) || other.total == total) && + (identical(other.cost, cost) || other.cost == cost) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + orderId, + productId, + productName, + quantity, + price, + subtotal, + discountAmount, + total, + cost, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of OrderItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderItemImplCopyWith<_$OrderItemImpl> get copyWith => + __$$OrderItemImplCopyWithImpl<_$OrderItemImpl>(this, _$identity); +} + +abstract class _OrderItem implements OrderItem { + const factory _OrderItem({ + required final String id, + required final String orderId, + required final String productId, + required final String productName, + required final int quantity, + required final int price, + required final int subtotal, + required final int discountAmount, + required final int total, + required final int cost, + required final Map metadata, + required final String createdAt, + required final String updatedAt, + }) = _$OrderItemImpl; + + @override + String get id; + @override + String get orderId; + @override + String get productId; + @override + String get productName; + @override + int get quantity; + @override + int get price; + @override + int get subtotal; + @override + int get discountAmount; + @override + int get total; + @override + int get cost; + @override + Map get metadata; + @override + String get createdAt; + @override + String get updatedAt; + + /// Create a copy of OrderItem + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderItemImplCopyWith<_$OrderItemImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$OrderPayment { + String get id => throw _privateConstructorUsedError; + String get orderId => throw _privateConstructorUsedError; + String get paymentMethodId => throw _privateConstructorUsedError; + String get paymentMethodName => throw _privateConstructorUsedError; + String get paymentMethodType => throw _privateConstructorUsedError; + int get amount => throw _privateConstructorUsedError; + String get status => throw _privateConstructorUsedError; + int get splitNumber => throw _privateConstructorUsedError; + int get splitTotal => throw _privateConstructorUsedError; + String get splitType => throw _privateConstructorUsedError; + String get splitDescription => throw _privateConstructorUsedError; + int get refundAmount => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + String get createdAt => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + List get paymentOrderItems => + throw _privateConstructorUsedError; + + /// Create a copy of OrderPayment + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderPaymentCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderPaymentCopyWith<$Res> { + factory $OrderPaymentCopyWith( + OrderPayment value, + $Res Function(OrderPayment) then, + ) = _$OrderPaymentCopyWithImpl<$Res, OrderPayment>; + @useResult + $Res call({ + String id, + String orderId, + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + int amount, + String status, + int splitNumber, + int splitTotal, + String splitType, + String splitDescription, + int refundAmount, + Map metadata, + String createdAt, + String updatedAt, + List paymentOrderItems, + }); +} + +/// @nodoc +class _$OrderPaymentCopyWithImpl<$Res, $Val extends OrderPayment> + implements $OrderPaymentCopyWith<$Res> { + _$OrderPaymentCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderPayment + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderId = null, + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? amount = null, + Object? status = null, + Object? splitNumber = null, + Object? splitTotal = null, + Object? splitType = null, + Object? splitDescription = null, + Object? refundAmount = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? paymentOrderItems = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderId: null == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + amount: null == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + splitNumber: null == splitNumber + ? _value.splitNumber + : splitNumber // ignore: cast_nullable_to_non_nullable + as int, + splitTotal: null == splitTotal + ? _value.splitTotal + : splitTotal // ignore: cast_nullable_to_non_nullable + as int, + splitType: null == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String, + splitDescription: null == splitDescription + ? _value.splitDescription + : splitDescription // ignore: cast_nullable_to_non_nullable + as String, + refundAmount: null == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + paymentOrderItems: null == paymentOrderItems + ? _value.paymentOrderItems + : paymentOrderItems // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OrderPaymentImplCopyWith<$Res> + implements $OrderPaymentCopyWith<$Res> { + factory _$$OrderPaymentImplCopyWith( + _$OrderPaymentImpl value, + $Res Function(_$OrderPaymentImpl) then, + ) = __$$OrderPaymentImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String orderId, + String paymentMethodId, + String paymentMethodName, + String paymentMethodType, + int amount, + String status, + int splitNumber, + int splitTotal, + String splitType, + String splitDescription, + int refundAmount, + Map metadata, + String createdAt, + String updatedAt, + List paymentOrderItems, + }); +} + +/// @nodoc +class __$$OrderPaymentImplCopyWithImpl<$Res> + extends _$OrderPaymentCopyWithImpl<$Res, _$OrderPaymentImpl> + implements _$$OrderPaymentImplCopyWith<$Res> { + __$$OrderPaymentImplCopyWithImpl( + _$OrderPaymentImpl _value, + $Res Function(_$OrderPaymentImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderPayment + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderId = null, + Object? paymentMethodId = null, + Object? paymentMethodName = null, + Object? paymentMethodType = null, + Object? amount = null, + Object? status = null, + Object? splitNumber = null, + Object? splitTotal = null, + Object? splitType = null, + Object? splitDescription = null, + Object? refundAmount = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? paymentOrderItems = null, + }) { + return _then( + _$OrderPaymentImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderId: null == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodId: null == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodName: null == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String, + paymentMethodType: null == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String, + amount: null == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + splitNumber: null == splitNumber + ? _value.splitNumber + : splitNumber // ignore: cast_nullable_to_non_nullable + as int, + splitTotal: null == splitTotal + ? _value.splitTotal + : splitTotal // ignore: cast_nullable_to_non_nullable + as int, + splitType: null == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String, + splitDescription: null == splitDescription + ? _value.splitDescription + : splitDescription // ignore: cast_nullable_to_non_nullable + as String, + refundAmount: null == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + paymentOrderItems: null == paymentOrderItems + ? _value._paymentOrderItems + : paymentOrderItems // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$OrderPaymentImpl implements _OrderPayment { + const _$OrderPaymentImpl({ + required this.id, + required this.orderId, + required this.paymentMethodId, + required this.paymentMethodName, + required this.paymentMethodType, + required this.amount, + required this.status, + required this.splitNumber, + required this.splitTotal, + required this.splitType, + required this.splitDescription, + required this.refundAmount, + required final Map metadata, + required this.createdAt, + required this.updatedAt, + required final List paymentOrderItems, + }) : _metadata = metadata, + _paymentOrderItems = paymentOrderItems; + + @override + final String id; + @override + final String orderId; + @override + final String paymentMethodId; + @override + final String paymentMethodName; + @override + final String paymentMethodType; + @override + final int amount; + @override + final String status; + @override + final int splitNumber; + @override + final int splitTotal; + @override + final String splitType; + @override + final String splitDescription; + @override + final int refundAmount; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final String createdAt; + @override + final String updatedAt; + final List _paymentOrderItems; + @override + List get paymentOrderItems { + if (_paymentOrderItems is EqualUnmodifiableListView) + return _paymentOrderItems; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_paymentOrderItems); + } + + @override + String toString() { + return 'OrderPayment(id: $id, orderId: $orderId, paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, amount: $amount, status: $status, splitNumber: $splitNumber, splitTotal: $splitTotal, splitType: $splitType, splitDescription: $splitDescription, refundAmount: $refundAmount, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt, paymentOrderItems: $paymentOrderItems)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderPaymentImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderId, orderId) || other.orderId == orderId) && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.amount, amount) || other.amount == amount) && + (identical(other.status, status) || other.status == status) && + (identical(other.splitNumber, splitNumber) || + other.splitNumber == splitNumber) && + (identical(other.splitTotal, splitTotal) || + other.splitTotal == splitTotal) && + (identical(other.splitType, splitType) || + other.splitType == splitType) && + (identical(other.splitDescription, splitDescription) || + other.splitDescription == splitDescription) && + (identical(other.refundAmount, refundAmount) || + other.refundAmount == refundAmount) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals( + other._paymentOrderItems, + _paymentOrderItems, + )); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + orderId, + paymentMethodId, + paymentMethodName, + paymentMethodType, + amount, + status, + splitNumber, + splitTotal, + splitType, + splitDescription, + refundAmount, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + const DeepCollectionEquality().hash(_paymentOrderItems), + ); + + /// Create a copy of OrderPayment + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderPaymentImplCopyWith<_$OrderPaymentImpl> get copyWith => + __$$OrderPaymentImplCopyWithImpl<_$OrderPaymentImpl>(this, _$identity); +} + +abstract class _OrderPayment implements OrderPayment { + const factory _OrderPayment({ + required final String id, + required final String orderId, + required final String paymentMethodId, + required final String paymentMethodName, + required final String paymentMethodType, + required final int amount, + required final String status, + required final int splitNumber, + required final int splitTotal, + required final String splitType, + required final String splitDescription, + required final int refundAmount, + required final Map metadata, + required final String createdAt, + required final String updatedAt, + required final List paymentOrderItems, + }) = _$OrderPaymentImpl; + + @override + String get id; + @override + String get orderId; + @override + String get paymentMethodId; + @override + String get paymentMethodName; + @override + String get paymentMethodType; + @override + int get amount; + @override + String get status; + @override + int get splitNumber; + @override + int get splitTotal; + @override + String get splitType; + @override + String get splitDescription; + @override + int get refundAmount; + @override + Map get metadata; + @override + String get createdAt; + @override + String get updatedAt; + @override + List get paymentOrderItems; + + /// Create a copy of OrderPayment + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderPaymentImplCopyWith<_$OrderPaymentImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$PaymentOrderItem { + String get id => throw _privateConstructorUsedError; + String get orderPaymentId => throw _privateConstructorUsedError; + String get orderItemId => throw _privateConstructorUsedError; + int get amount => throw _privateConstructorUsedError; + int get refundAmount => throw _privateConstructorUsedError; + String get createdAt => throw _privateConstructorUsedError; + String get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of PaymentOrderItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentOrderItemCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentOrderItemCopyWith<$Res> { + factory $PaymentOrderItemCopyWith( + PaymentOrderItem value, + $Res Function(PaymentOrderItem) then, + ) = _$PaymentOrderItemCopyWithImpl<$Res, PaymentOrderItem>; + @useResult + $Res call({ + String id, + String orderPaymentId, + String orderItemId, + int amount, + int refundAmount, + String createdAt, + String updatedAt, + }); +} + +/// @nodoc +class _$PaymentOrderItemCopyWithImpl<$Res, $Val extends PaymentOrderItem> + implements $PaymentOrderItemCopyWith<$Res> { + _$PaymentOrderItemCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentOrderItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderPaymentId = null, + Object? orderItemId = null, + Object? amount = null, + Object? refundAmount = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderPaymentId: null == orderPaymentId + ? _value.orderPaymentId + : orderPaymentId // ignore: cast_nullable_to_non_nullable + as String, + orderItemId: null == orderItemId + ? _value.orderItemId + : orderItemId // ignore: cast_nullable_to_non_nullable + as String, + amount: null == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int, + refundAmount: null == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$PaymentOrderItemImplCopyWith<$Res> + implements $PaymentOrderItemCopyWith<$Res> { + factory _$$PaymentOrderItemImplCopyWith( + _$PaymentOrderItemImpl value, + $Res Function(_$PaymentOrderItemImpl) then, + ) = __$$PaymentOrderItemImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String orderPaymentId, + String orderItemId, + int amount, + int refundAmount, + String createdAt, + String updatedAt, + }); +} + +/// @nodoc +class __$$PaymentOrderItemImplCopyWithImpl<$Res> + extends _$PaymentOrderItemCopyWithImpl<$Res, _$PaymentOrderItemImpl> + implements _$$PaymentOrderItemImplCopyWith<$Res> { + __$$PaymentOrderItemImplCopyWithImpl( + _$PaymentOrderItemImpl _value, + $Res Function(_$PaymentOrderItemImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentOrderItem + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? orderPaymentId = null, + Object? orderItemId = null, + Object? amount = null, + Object? refundAmount = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _$PaymentOrderItemImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + orderPaymentId: null == orderPaymentId + ? _value.orderPaymentId + : orderPaymentId // ignore: cast_nullable_to_non_nullable + as String, + orderItemId: null == orderItemId + ? _value.orderItemId + : orderItemId // ignore: cast_nullable_to_non_nullable + as String, + amount: null == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int, + refundAmount: null == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$PaymentOrderItemImpl implements _PaymentOrderItem { + const _$PaymentOrderItemImpl({ + required this.id, + required this.orderPaymentId, + required this.orderItemId, + required this.amount, + required this.refundAmount, + required this.createdAt, + required this.updatedAt, + }); + + @override + final String id; + @override + final String orderPaymentId; + @override + final String orderItemId; + @override + final int amount; + @override + final int refundAmount; + @override + final String createdAt; + @override + final String updatedAt; + + @override + String toString() { + return 'PaymentOrderItem(id: $id, orderPaymentId: $orderPaymentId, orderItemId: $orderItemId, amount: $amount, refundAmount: $refundAmount, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentOrderItemImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderPaymentId, orderPaymentId) || + other.orderPaymentId == orderPaymentId) && + (identical(other.orderItemId, orderItemId) || + other.orderItemId == orderItemId) && + (identical(other.amount, amount) || other.amount == amount) && + (identical(other.refundAmount, refundAmount) || + other.refundAmount == refundAmount) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + orderPaymentId, + orderItemId, + amount, + refundAmount, + createdAt, + updatedAt, + ); + + /// Create a copy of PaymentOrderItem + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentOrderItemImplCopyWith<_$PaymentOrderItemImpl> get copyWith => + __$$PaymentOrderItemImplCopyWithImpl<_$PaymentOrderItemImpl>( + this, + _$identity, + ); +} + +abstract class _PaymentOrderItem implements PaymentOrderItem { + const factory _PaymentOrderItem({ + required final String id, + required final String orderPaymentId, + required final String orderItemId, + required final int amount, + required final int refundAmount, + required final String createdAt, + required final String updatedAt, + }) = _$PaymentOrderItemImpl; + + @override + String get id; + @override + String get orderPaymentId; + @override + String get orderItemId; + @override + int get amount; + @override + int get refundAmount; + @override + String get createdAt; + @override + String get updatedAt; + + /// Create a copy of PaymentOrderItem + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentOrderItemImplCopyWith<_$PaymentOrderItemImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$OrderFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderFailureCopyWith<$Res> { + factory $OrderFailureCopyWith( + OrderFailure value, + $Res Function(OrderFailure) then, + ) = _$OrderFailureCopyWithImpl<$Res, OrderFailure>; +} + +/// @nodoc +class _$OrderFailureCopyWithImpl<$Res, $Val extends OrderFailure> + implements $OrderFailureCopyWith<$Res> { + _$OrderFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$OrderFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'OrderFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements OrderFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$OrderFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'OrderFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements OrderFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$OrderFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'OrderFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements OrderFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$OrderFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'OrderFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements OrderFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of OrderFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/order/repositories/i_order_repository.dart b/lib/domain/order/repositories/i_order_repository.dart new file mode 100644 index 0000000..7f13301 --- /dev/null +++ b/lib/domain/order/repositories/i_order_repository.dart @@ -0,0 +1,13 @@ +part of '../order.dart'; + +abstract class IOrderRepository { + Future>> get({ + int page = 1, + int limit = 10, + String? status, + String? search, + String? outletId, + required DateTime dateFrom, + required DateTime dateTo, + }); +} diff --git a/lib/domain/outlet/entities/outlet_entity.dart b/lib/domain/outlet/entities/outlet_entity.dart new file mode 100644 index 0000000..fcca16c --- /dev/null +++ b/lib/domain/outlet/entities/outlet_entity.dart @@ -0,0 +1,32 @@ +part of '../outlet.dart'; + +@freezed +class Outlet with _$Outlet { + const factory Outlet({ + required String id, + required String organizationId, + required String name, + required String address, + required String phoneNumber, + required String businessType, + required String currency, + required int taxRate, + required bool isActive, + required DateTime createdAt, + required DateTime updatedAt, + }) = _Outlet; + + factory Outlet.empty() => Outlet( + id: '', + organizationId: '', + name: '', + address: '', + phoneNumber: '', + businessType: '', + currency: '', + taxRate: 0, + isActive: false, + createdAt: DateTime(1970), + updatedAt: DateTime(1970), + ); +} diff --git a/lib/domain/outlet/failures/outlet_failure.dart b/lib/domain/outlet/failures/outlet_failure.dart new file mode 100644 index 0000000..1f53408 --- /dev/null +++ b/lib/domain/outlet/failures/outlet_failure.dart @@ -0,0 +1,10 @@ +part of '../outlet.dart'; + +@freezed +sealed class OutletFailure with _$OutletFailure { + const factory OutletFailure.serverError(ApiFailure failure) = _ServerError; + const factory OutletFailure.unexpectedError() = _UnexpectedError; + const factory OutletFailure.empty() = _Empty; + const factory OutletFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/outlet/outlet.dart b/lib/domain/outlet/outlet.dart new file mode 100644 index 0000000..32c2ff4 --- /dev/null +++ b/lib/domain/outlet/outlet.dart @@ -0,0 +1,10 @@ +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'outlet.freezed.dart'; + +part 'entities/outlet_entity.dart'; +part 'failures/outlet_failure.dart'; +part 'repositories/i_outlet_repository.dart'; diff --git a/lib/domain/outlet/outlet.freezed.dart b/lib/domain/outlet/outlet.freezed.dart new file mode 100644 index 0000000..d8d857e --- /dev/null +++ b/lib/domain/outlet/outlet.freezed.dart @@ -0,0 +1,1009 @@ +// 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 'outlet.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$Outlet { + String get id => throw _privateConstructorUsedError; + String get organizationId => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get address => throw _privateConstructorUsedError; + String get phoneNumber => throw _privateConstructorUsedError; + String get businessType => throw _privateConstructorUsedError; + String get currency => throw _privateConstructorUsedError; + int get taxRate => throw _privateConstructorUsedError; + bool get isActive => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of Outlet + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OutletCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OutletCopyWith<$Res> { + factory $OutletCopyWith(Outlet value, $Res Function(Outlet) then) = + _$OutletCopyWithImpl<$Res, Outlet>; + @useResult + $Res call({ + String id, + String organizationId, + String name, + String address, + String phoneNumber, + String businessType, + String currency, + int taxRate, + bool isActive, + DateTime createdAt, + DateTime updatedAt, + }); +} + +/// @nodoc +class _$OutletCopyWithImpl<$Res, $Val extends Outlet> + implements $OutletCopyWith<$Res> { + _$OutletCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Outlet + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? name = null, + Object? address = null, + Object? phoneNumber = null, + Object? businessType = null, + Object? currency = null, + Object? taxRate = null, + Object? isActive = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + address: null == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String, + phoneNumber: null == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String, + businessType: null == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String, + currency: null == currency + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String, + taxRate: null == taxRate + ? _value.taxRate + : taxRate // ignore: cast_nullable_to_non_nullable + as int, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OutletImplCopyWith<$Res> implements $OutletCopyWith<$Res> { + factory _$$OutletImplCopyWith( + _$OutletImpl value, + $Res Function(_$OutletImpl) then, + ) = __$$OutletImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String organizationId, + String name, + String address, + String phoneNumber, + String businessType, + String currency, + int taxRate, + bool isActive, + DateTime createdAt, + DateTime updatedAt, + }); +} + +/// @nodoc +class __$$OutletImplCopyWithImpl<$Res> + extends _$OutletCopyWithImpl<$Res, _$OutletImpl> + implements _$$OutletImplCopyWith<$Res> { + __$$OutletImplCopyWithImpl( + _$OutletImpl _value, + $Res Function(_$OutletImpl) _then, + ) : super(_value, _then); + + /// Create a copy of Outlet + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? name = null, + Object? address = null, + Object? phoneNumber = null, + Object? businessType = null, + Object? currency = null, + Object? taxRate = null, + Object? isActive = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _$OutletImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + address: null == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String, + phoneNumber: null == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String, + businessType: null == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String, + currency: null == currency + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String, + taxRate: null == taxRate + ? _value.taxRate + : taxRate // ignore: cast_nullable_to_non_nullable + as int, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ), + ); + } +} + +/// @nodoc + +class _$OutletImpl implements _Outlet { + const _$OutletImpl({ + required this.id, + required this.organizationId, + required this.name, + required this.address, + required this.phoneNumber, + required this.businessType, + required this.currency, + required this.taxRate, + required this.isActive, + required this.createdAt, + required this.updatedAt, + }); + + @override + final String id; + @override + final String organizationId; + @override + final String name; + @override + final String address; + @override + final String phoneNumber; + @override + final String businessType; + @override + final String currency; + @override + final int taxRate; + @override + final bool isActive; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + + @override + String toString() { + return 'Outlet(id: $id, organizationId: $organizationId, name: $name, address: $address, phoneNumber: $phoneNumber, businessType: $businessType, currency: $currency, taxRate: $taxRate, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OutletImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.name, name) || other.name == name) && + (identical(other.address, address) || other.address == address) && + (identical(other.phoneNumber, phoneNumber) || + other.phoneNumber == phoneNumber) && + (identical(other.businessType, businessType) || + other.businessType == businessType) && + (identical(other.currency, currency) || + other.currency == currency) && + (identical(other.taxRate, taxRate) || other.taxRate == taxRate) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + name, + address, + phoneNumber, + businessType, + currency, + taxRate, + isActive, + createdAt, + updatedAt, + ); + + /// Create a copy of Outlet + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OutletImplCopyWith<_$OutletImpl> get copyWith => + __$$OutletImplCopyWithImpl<_$OutletImpl>(this, _$identity); +} + +abstract class _Outlet implements Outlet { + const factory _Outlet({ + required final String id, + required final String organizationId, + required final String name, + required final String address, + required final String phoneNumber, + required final String businessType, + required final String currency, + required final int taxRate, + required final bool isActive, + required final DateTime createdAt, + required final DateTime updatedAt, + }) = _$OutletImpl; + + @override + String get id; + @override + String get organizationId; + @override + String get name; + @override + String get address; + @override + String get phoneNumber; + @override + String get businessType; + @override + String get currency; + @override + int get taxRate; + @override + bool get isActive; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + + /// Create a copy of Outlet + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OutletImplCopyWith<_$OutletImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$OutletFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OutletFailureCopyWith<$Res> { + factory $OutletFailureCopyWith( + OutletFailure value, + $Res Function(OutletFailure) then, + ) = _$OutletFailureCopyWithImpl<$Res, OutletFailure>; +} + +/// @nodoc +class _$OutletFailureCopyWithImpl<$Res, $Val extends OutletFailure> + implements $OutletFailureCopyWith<$Res> { + _$OutletFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$OutletFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'OutletFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements OutletFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$OutletFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'OutletFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements OutletFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$OutletFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'OutletFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements OutletFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$OutletFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'OutletFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements OutletFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of OutletFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/outlet/repositories/i_outlet_repository.dart b/lib/domain/outlet/repositories/i_outlet_repository.dart new file mode 100644 index 0000000..4f12e5c --- /dev/null +++ b/lib/domain/outlet/repositories/i_outlet_repository.dart @@ -0,0 +1,12 @@ +part of '../outlet.dart'; + +abstract class IOutletRepository { + Future> currentOutlet(); + + Future>> getList({ + int page = 1, + int limit = 10, + String? search, + bool? isActive, + }); +} diff --git a/lib/domain/product/entities/product_entity.dart b/lib/domain/product/entities/product_entity.dart new file mode 100644 index 0000000..c461e5e --- /dev/null +++ b/lib/domain/product/entities/product_entity.dart @@ -0,0 +1,43 @@ +part of '../product.dart'; + +@freezed +class Product with _$Product { + const factory Product({ + required String id, + required String organizationId, + required String categoryId, + required String sku, + required String name, + required String description, + required int price, + required int cost, + required String businessType, + required String imageUrl, + required String printerType, + required Map metadata, + required bool isActive, + required DateTime createdAt, + required DateTime updatedAt, + required List variants, + }) = _Product; + + /// ✅ factory kosong untuk default state + factory Product.empty() => Product( + id: '', + organizationId: '', + categoryId: '', + sku: '', + name: '', + description: '', + price: 0, + cost: 0, + businessType: '', + imageUrl: '', + printerType: '', + metadata: {}, + isActive: false, + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + variants: [], + ); +} diff --git a/lib/domain/product/entities/product_variant_entity.dart b/lib/domain/product/entities/product_variant_entity.dart new file mode 100644 index 0000000..d8cb985 --- /dev/null +++ b/lib/domain/product/entities/product_variant_entity.dart @@ -0,0 +1,26 @@ +part of '../product.dart'; + +@freezed +class ProductVariant with _$ProductVariant { + const factory ProductVariant({ + required String id, + required String productId, + required String name, + required int priceModifier, + required int cost, + required Map metadata, + required DateTime createdAt, + required DateTime updatedAt, + }) = _ProductVariant; + + factory ProductVariant.empty() => ProductVariant( + id: '', + productId: '', + name: '', + priceModifier: 0, + cost: 0, + metadata: {}, + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ); +} diff --git a/lib/domain/product/failures/product_failure.dart b/lib/domain/product/failures/product_failure.dart new file mode 100644 index 0000000..97612c1 --- /dev/null +++ b/lib/domain/product/failures/product_failure.dart @@ -0,0 +1,10 @@ +part of '../product.dart'; + +@freezed +sealed class ProductFailure with _$ProductFailure { + const factory ProductFailure.serverError(ApiFailure failure) = _ServerError; + const factory ProductFailure.unexpectedError() = _UnexpectedError; + const factory ProductFailure.empty() = _Empty; + const factory ProductFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/product/product.dart b/lib/domain/product/product.dart new file mode 100644 index 0000000..97aa7ee --- /dev/null +++ b/lib/domain/product/product.dart @@ -0,0 +1,11 @@ +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'product.freezed.dart'; + +part 'entities/product_entity.dart'; +part 'entities/product_variant_entity.dart'; +part 'failures/product_failure.dart'; +part 'repositories/i_product_repository.dart'; diff --git a/lib/domain/product/product.freezed.dart b/lib/domain/product/product.freezed.dart new file mode 100644 index 0000000..75b42f9 --- /dev/null +++ b/lib/domain/product/product.freezed.dart @@ -0,0 +1,1435 @@ +// 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 'product.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$Product { + String get id => throw _privateConstructorUsedError; + String get organizationId => throw _privateConstructorUsedError; + String get categoryId => throw _privateConstructorUsedError; + String get sku => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + int get price => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + String get businessType => throw _privateConstructorUsedError; + String get imageUrl => throw _privateConstructorUsedError; + String get printerType => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + bool get isActive => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + List get variants => throw _privateConstructorUsedError; + + /// Create a copy of Product + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductCopyWith<$Res> { + factory $ProductCopyWith(Product value, $Res Function(Product) then) = + _$ProductCopyWithImpl<$Res, Product>; + @useResult + $Res call({ + String id, + String organizationId, + String categoryId, + String sku, + String name, + String description, + int price, + int cost, + String businessType, + String imageUrl, + String printerType, + Map metadata, + bool isActive, + DateTime createdAt, + DateTime updatedAt, + List variants, + }); +} + +/// @nodoc +class _$ProductCopyWithImpl<$Res, $Val extends Product> + implements $ProductCopyWith<$Res> { + _$ProductCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of Product + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? categoryId = null, + Object? sku = null, + Object? name = null, + Object? description = null, + Object? price = null, + Object? cost = null, + Object? businessType = null, + Object? imageUrl = null, + Object? printerType = null, + Object? metadata = null, + Object? isActive = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? variants = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + sku: null == sku + ? _value.sku + : sku // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + price: null == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + businessType: null == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String, + imageUrl: null == imageUrl + ? _value.imageUrl + : imageUrl // ignore: cast_nullable_to_non_nullable + as String, + printerType: null == printerType + ? _value.printerType + : printerType // ignore: cast_nullable_to_non_nullable + as String, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + variants: null == variants + ? _value.variants + : variants // ignore: cast_nullable_to_non_nullable + as List, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductImplCopyWith<$Res> implements $ProductCopyWith<$Res> { + factory _$$ProductImplCopyWith( + _$ProductImpl value, + $Res Function(_$ProductImpl) then, + ) = __$$ProductImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String organizationId, + String categoryId, + String sku, + String name, + String description, + int price, + int cost, + String businessType, + String imageUrl, + String printerType, + Map metadata, + bool isActive, + DateTime createdAt, + DateTime updatedAt, + List variants, + }); +} + +/// @nodoc +class __$$ProductImplCopyWithImpl<$Res> + extends _$ProductCopyWithImpl<$Res, _$ProductImpl> + implements _$$ProductImplCopyWith<$Res> { + __$$ProductImplCopyWithImpl( + _$ProductImpl _value, + $Res Function(_$ProductImpl) _then, + ) : super(_value, _then); + + /// Create a copy of Product + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? categoryId = null, + Object? sku = null, + Object? name = null, + Object? description = null, + Object? price = null, + Object? cost = null, + Object? businessType = null, + Object? imageUrl = null, + Object? printerType = null, + Object? metadata = null, + Object? isActive = null, + Object? createdAt = null, + Object? updatedAt = null, + Object? variants = null, + }) { + return _then( + _$ProductImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + categoryId: null == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String, + sku: null == sku + ? _value.sku + : sku // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + price: null == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + businessType: null == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String, + imageUrl: null == imageUrl + ? _value.imageUrl + : imageUrl // ignore: cast_nullable_to_non_nullable + as String, + printerType: null == printerType + ? _value.printerType + : printerType // ignore: cast_nullable_to_non_nullable + as String, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + variants: null == variants + ? _value._variants + : variants // ignore: cast_nullable_to_non_nullable + as List, + ), + ); + } +} + +/// @nodoc + +class _$ProductImpl implements _Product { + const _$ProductImpl({ + required this.id, + required this.organizationId, + required this.categoryId, + required this.sku, + required this.name, + required this.description, + required this.price, + required this.cost, + required this.businessType, + required this.imageUrl, + required this.printerType, + required final Map metadata, + required this.isActive, + required this.createdAt, + required this.updatedAt, + required final List variants, + }) : _metadata = metadata, + _variants = variants; + + @override + final String id; + @override + final String organizationId; + @override + final String categoryId; + @override + final String sku; + @override + final String name; + @override + final String description; + @override + final int price; + @override + final int cost; + @override + final String businessType; + @override + final String imageUrl; + @override + final String printerType; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final bool isActive; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + final List _variants; + @override + List get variants { + if (_variants is EqualUnmodifiableListView) return _variants; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_variants); + } + + @override + String toString() { + return 'Product(id: $id, organizationId: $organizationId, categoryId: $categoryId, sku: $sku, name: $name, description: $description, price: $price, cost: $cost, businessType: $businessType, imageUrl: $imageUrl, printerType: $printerType, metadata: $metadata, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt, variants: $variants)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.sku, sku) || other.sku == sku) && + (identical(other.name, name) || other.name == name) && + (identical(other.description, description) || + other.description == description) && + (identical(other.price, price) || other.price == price) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.businessType, businessType) || + other.businessType == businessType) && + (identical(other.imageUrl, imageUrl) || + other.imageUrl == imageUrl) && + (identical(other.printerType, printerType) || + other.printerType == printerType) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals(other._variants, _variants)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + categoryId, + sku, + name, + description, + price, + cost, + businessType, + imageUrl, + printerType, + const DeepCollectionEquality().hash(_metadata), + isActive, + createdAt, + updatedAt, + const DeepCollectionEquality().hash(_variants), + ); + + /// Create a copy of Product + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductImplCopyWith<_$ProductImpl> get copyWith => + __$$ProductImplCopyWithImpl<_$ProductImpl>(this, _$identity); +} + +abstract class _Product implements Product { + const factory _Product({ + required final String id, + required final String organizationId, + required final String categoryId, + required final String sku, + required final String name, + required final String description, + required final int price, + required final int cost, + required final String businessType, + required final String imageUrl, + required final String printerType, + required final Map metadata, + required final bool isActive, + required final DateTime createdAt, + required final DateTime updatedAt, + required final List variants, + }) = _$ProductImpl; + + @override + String get id; + @override + String get organizationId; + @override + String get categoryId; + @override + String get sku; + @override + String get name; + @override + String get description; + @override + int get price; + @override + int get cost; + @override + String get businessType; + @override + String get imageUrl; + @override + String get printerType; + @override + Map get metadata; + @override + bool get isActive; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + @override + List get variants; + + /// Create a copy of Product + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductImplCopyWith<_$ProductImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProductVariant { + String get id => throw _privateConstructorUsedError; + String get productId => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + int get priceModifier => throw _privateConstructorUsedError; + int get cost => throw _privateConstructorUsedError; + Map get metadata => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of ProductVariant + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductVariantCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductVariantCopyWith<$Res> { + factory $ProductVariantCopyWith( + ProductVariant value, + $Res Function(ProductVariant) then, + ) = _$ProductVariantCopyWithImpl<$Res, ProductVariant>; + @useResult + $Res call({ + String id, + String productId, + String name, + int priceModifier, + int cost, + Map metadata, + DateTime createdAt, + DateTime updatedAt, + }); +} + +/// @nodoc +class _$ProductVariantCopyWithImpl<$Res, $Val extends ProductVariant> + implements $ProductVariantCopyWith<$Res> { + _$ProductVariantCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductVariant + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? productId = null, + Object? name = null, + Object? priceModifier = null, + Object? cost = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + priceModifier: null == priceModifier + ? _value.priceModifier + : priceModifier // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductVariantImplCopyWith<$Res> + implements $ProductVariantCopyWith<$Res> { + factory _$$ProductVariantImplCopyWith( + _$ProductVariantImpl value, + $Res Function(_$ProductVariantImpl) then, + ) = __$$ProductVariantImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String productId, + String name, + int priceModifier, + int cost, + Map metadata, + DateTime createdAt, + DateTime updatedAt, + }); +} + +/// @nodoc +class __$$ProductVariantImplCopyWithImpl<$Res> + extends _$ProductVariantCopyWithImpl<$Res, _$ProductVariantImpl> + implements _$$ProductVariantImplCopyWith<$Res> { + __$$ProductVariantImplCopyWithImpl( + _$ProductVariantImpl _value, + $Res Function(_$ProductVariantImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductVariant + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? productId = null, + Object? name = null, + Object? priceModifier = null, + Object? cost = null, + Object? metadata = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _$ProductVariantImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + productId: null == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + priceModifier: null == priceModifier + ? _value.priceModifier + : priceModifier // ignore: cast_nullable_to_non_nullable + as int, + cost: null == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int, + metadata: null == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ), + ); + } +} + +/// @nodoc + +class _$ProductVariantImpl implements _ProductVariant { + const _$ProductVariantImpl({ + required this.id, + required this.productId, + required this.name, + required this.priceModifier, + required this.cost, + required final Map metadata, + required this.createdAt, + required this.updatedAt, + }) : _metadata = metadata; + + @override + final String id; + @override + final String productId; + @override + final String name; + @override + final int priceModifier; + @override + final int cost; + final Map _metadata; + @override + Map get metadata { + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_metadata); + } + + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + + @override + String toString() { + return 'ProductVariant(id: $id, productId: $productId, name: $name, priceModifier: $priceModifier, cost: $cost, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductVariantImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.name, name) || other.name == name) && + (identical(other.priceModifier, priceModifier) || + other.priceModifier == priceModifier) && + (identical(other.cost, cost) || other.cost == cost) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + productId, + name, + priceModifier, + cost, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of ProductVariant + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductVariantImplCopyWith<_$ProductVariantImpl> get copyWith => + __$$ProductVariantImplCopyWithImpl<_$ProductVariantImpl>( + this, + _$identity, + ); +} + +abstract class _ProductVariant implements ProductVariant { + const factory _ProductVariant({ + required final String id, + required final String productId, + required final String name, + required final int priceModifier, + required final int cost, + required final Map metadata, + required final DateTime createdAt, + required final DateTime updatedAt, + }) = _$ProductVariantImpl; + + @override + String get id; + @override + String get productId; + @override + String get name; + @override + int get priceModifier; + @override + int get cost; + @override + Map get metadata; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + + /// Create a copy of ProductVariant + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductVariantImplCopyWith<_$ProductVariantImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$ProductFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductFailureCopyWith<$Res> { + factory $ProductFailureCopyWith( + ProductFailure value, + $Res Function(ProductFailure) then, + ) = _$ProductFailureCopyWithImpl<$Res, ProductFailure>; +} + +/// @nodoc +class _$ProductFailureCopyWithImpl<$Res, $Val extends ProductFailure> + implements $ProductFailureCopyWith<$Res> { + _$ProductFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$ProductFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'ProductFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements ProductFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$ProductFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'ProductFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements ProductFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$ProductFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'ProductFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements ProductFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$ProductFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'ProductFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements ProductFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of ProductFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/domain/product/repositories/i_product_repository.dart b/lib/domain/product/repositories/i_product_repository.dart new file mode 100644 index 0000000..e357866 --- /dev/null +++ b/lib/domain/product/repositories/i_product_repository.dart @@ -0,0 +1,10 @@ +part of '../product.dart'; + +abstract class IProductRepository { + Future>> get({ + int page = 1, + int limit = 10, + String? categoryId, + String? search, + }); +} diff --git a/lib/domain/user/entities/user_entity.dart b/lib/domain/user/entities/user_entity.dart new file mode 100644 index 0000000..ddc9c02 --- /dev/null +++ b/lib/domain/user/entities/user_entity.dart @@ -0,0 +1,32 @@ +part of '../user.dart'; + +@freezed +class User with _$User { + const User._(); + + const factory User({ + required String id, + required String organizationId, + required String outletId, + required String name, + required String email, + required String role, + required Map permissions, + required bool isActive, + required DateTime createdAt, + required DateTime updatedAt, + }) = _User; + + factory User.empty() => User( + id: '', + organizationId: '', + outletId: '', + name: '', + email: '', + role: '', + permissions: {}, + isActive: false, + createdAt: DateTime.now(), + updatedAt: DateTime.now(), + ); +} diff --git a/lib/domain/user/failures/user_failure.dart b/lib/domain/user/failures/user_failure.dart new file mode 100644 index 0000000..43edeac --- /dev/null +++ b/lib/domain/user/failures/user_failure.dart @@ -0,0 +1,10 @@ +part of '../user.dart'; + +@freezed +sealed class UserFailure with _$UserFailure { + const factory UserFailure.serverError(ApiFailure failure) = _ServerError; + const factory UserFailure.unexpectedError() = _UnexpectedError; + const factory UserFailure.empty() = _Empty; + const factory UserFailure.dynamicErrorMessage(String erroMessage) = + _DynamicErrorMessage; +} diff --git a/lib/domain/user/repositories/i_user_repository.dart b/lib/domain/user/repositories/i_user_repository.dart new file mode 100644 index 0000000..3adfa4f --- /dev/null +++ b/lib/domain/user/repositories/i_user_repository.dart @@ -0,0 +1,9 @@ +part of '../user.dart'; + +abstract class IUserRepository { + Future> editUser({required String name}); + Future> changePassword({ + required String newPassword, + required String currentPassword, + }); +} diff --git a/lib/domain/user/user.dart b/lib/domain/user/user.dart new file mode 100644 index 0000000..4165584 --- /dev/null +++ b/lib/domain/user/user.dart @@ -0,0 +1,10 @@ +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../common/api/api_failure.dart'; + +part 'user.freezed.dart'; + +part 'entities/user_entity.dart'; +part 'failures/user_failure.dart'; +part 'repositories/i_user_repository.dart'; diff --git a/lib/domain/user/user.freezed.dart b/lib/domain/user/user.freezed.dart new file mode 100644 index 0000000..e5e7720 --- /dev/null +++ b/lib/domain/user/user.freezed.dart @@ -0,0 +1,995 @@ +// 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 'user.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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 _$User { + String get id => throw _privateConstructorUsedError; + String get organizationId => throw _privateConstructorUsedError; + String get outletId => throw _privateConstructorUsedError; + String get name => throw _privateConstructorUsedError; + String get email => throw _privateConstructorUsedError; + String get role => throw _privateConstructorUsedError; + Map get permissions => throw _privateConstructorUsedError; + bool get isActive => throw _privateConstructorUsedError; + DateTime get createdAt => throw _privateConstructorUsedError; + DateTime get updatedAt => throw _privateConstructorUsedError; + + /// Create a copy of User + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $UserCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $UserCopyWith<$Res> { + factory $UserCopyWith(User value, $Res Function(User) then) = + _$UserCopyWithImpl<$Res, User>; + @useResult + $Res call({ + String id, + String organizationId, + String outletId, + String name, + String email, + String role, + Map permissions, + bool isActive, + DateTime createdAt, + DateTime updatedAt, + }); +} + +/// @nodoc +class _$UserCopyWithImpl<$Res, $Val extends User> + implements $UserCopyWith<$Res> { + _$UserCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of User + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? outletId = null, + Object? name = null, + Object? email = null, + Object? role = null, + Object? permissions = null, + Object? isActive = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + role: null == role + ? _value.role + : role // ignore: cast_nullable_to_non_nullable + as String, + permissions: null == permissions + ? _value.permissions + : permissions // ignore: cast_nullable_to_non_nullable + as Map, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$UserImplCopyWith<$Res> implements $UserCopyWith<$Res> { + factory _$$UserImplCopyWith( + _$UserImpl value, + $Res Function(_$UserImpl) then, + ) = __$$UserImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + String id, + String organizationId, + String outletId, + String name, + String email, + String role, + Map permissions, + bool isActive, + DateTime createdAt, + DateTime updatedAt, + }); +} + +/// @nodoc +class __$$UserImplCopyWithImpl<$Res> + extends _$UserCopyWithImpl<$Res, _$UserImpl> + implements _$$UserImplCopyWith<$Res> { + __$$UserImplCopyWithImpl(_$UserImpl _value, $Res Function(_$UserImpl) _then) + : super(_value, _then); + + /// Create a copy of User + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? organizationId = null, + Object? outletId = null, + Object? name = null, + Object? email = null, + Object? role = null, + Object? permissions = null, + Object? isActive = null, + Object? createdAt = null, + Object? updatedAt = null, + }) { + return _then( + _$UserImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + organizationId: null == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String, + outletId: null == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String, + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + email: null == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String, + role: null == role + ? _value.role + : role // ignore: cast_nullable_to_non_nullable + as String, + permissions: null == permissions + ? _value._permissions + : permissions // ignore: cast_nullable_to_non_nullable + as Map, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, + createdAt: null == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime, + updatedAt: null == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime, + ), + ); + } +} + +/// @nodoc + +class _$UserImpl extends _User { + const _$UserImpl({ + required this.id, + required this.organizationId, + required this.outletId, + required this.name, + required this.email, + required this.role, + required final Map permissions, + required this.isActive, + required this.createdAt, + required this.updatedAt, + }) : _permissions = permissions, + super._(); + + @override + final String id; + @override + final String organizationId; + @override + final String outletId; + @override + final String name; + @override + final String email; + @override + final String role; + final Map _permissions; + @override + Map get permissions { + if (_permissions is EqualUnmodifiableMapView) return _permissions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_permissions); + } + + @override + final bool isActive; + @override + final DateTime createdAt; + @override + final DateTime updatedAt; + + @override + String toString() { + return 'User(id: $id, organizationId: $organizationId, outletId: $outletId, name: $name, email: $email, role: $role, permissions: $permissions, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$UserImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.name, name) || other.name == name) && + (identical(other.email, email) || other.email == email) && + (identical(other.role, role) || other.role == role) && + const DeepCollectionEquality().equals( + other._permissions, + _permissions, + ) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + outletId, + name, + email, + role, + const DeepCollectionEquality().hash(_permissions), + isActive, + createdAt, + updatedAt, + ); + + /// Create a copy of User + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$UserImplCopyWith<_$UserImpl> get copyWith => + __$$UserImplCopyWithImpl<_$UserImpl>(this, _$identity); +} + +abstract class _User extends User { + const factory _User({ + required final String id, + required final String organizationId, + required final String outletId, + required final String name, + required final String email, + required final String role, + required final Map permissions, + required final bool isActive, + required final DateTime createdAt, + required final DateTime updatedAt, + }) = _$UserImpl; + const _User._() : super._(); + + @override + String get id; + @override + String get organizationId; + @override + String get outletId; + @override + String get name; + @override + String get email; + @override + String get role; + @override + Map get permissions; + @override + bool get isActive; + @override + DateTime get createdAt; + @override + DateTime get updatedAt; + + /// Create a copy of User + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$UserImplCopyWith<_$UserImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$UserFailure { + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $UserFailureCopyWith<$Res> { + factory $UserFailureCopyWith( + UserFailure value, + $Res Function(UserFailure) then, + ) = _$UserFailureCopyWithImpl<$Res, UserFailure>; +} + +/// @nodoc +class _$UserFailureCopyWithImpl<$Res, $Val extends UserFailure> + implements $UserFailureCopyWith<$Res> { + _$UserFailureCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$ServerErrorImplCopyWith<$Res> { + factory _$$ServerErrorImplCopyWith( + _$ServerErrorImpl value, + $Res Function(_$ServerErrorImpl) then, + ) = __$$ServerErrorImplCopyWithImpl<$Res>; + @useResult + $Res call({ApiFailure failure}); + + $ApiFailureCopyWith<$Res> get failure; +} + +/// @nodoc +class __$$ServerErrorImplCopyWithImpl<$Res> + extends _$UserFailureCopyWithImpl<$Res, _$ServerErrorImpl> + implements _$$ServerErrorImplCopyWith<$Res> { + __$$ServerErrorImplCopyWithImpl( + _$ServerErrorImpl _value, + $Res Function(_$ServerErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? failure = null}) { + return _then( + _$ServerErrorImpl( + null == failure + ? _value.failure + : failure // ignore: cast_nullable_to_non_nullable + as ApiFailure, + ), + ); + } + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ApiFailureCopyWith<$Res> get failure { + return $ApiFailureCopyWith<$Res>(_value.failure, (value) { + return _then(_value.copyWith(failure: value)); + }); + } +} + +/// @nodoc + +class _$ServerErrorImpl implements _ServerError { + const _$ServerErrorImpl(this.failure); + + @override + final ApiFailure failure; + + @override + String toString() { + return 'UserFailure.serverError(failure: $failure)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServerErrorImpl && + (identical(other.failure, failure) || other.failure == failure)); + } + + @override + int get hashCode => Object.hash(runtimeType, failure); + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + __$$ServerErrorImplCopyWithImpl<_$ServerErrorImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return serverError(failure); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return serverError?.call(failure); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(failure); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return serverError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return serverError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (serverError != null) { + return serverError(this); + } + return orElse(); + } +} + +abstract class _ServerError implements UserFailure { + const factory _ServerError(final ApiFailure failure) = _$ServerErrorImpl; + + ApiFailure get failure; + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServerErrorImplCopyWith<_$ServerErrorImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$UnexpectedErrorImplCopyWith<$Res> { + factory _$$UnexpectedErrorImplCopyWith( + _$UnexpectedErrorImpl value, + $Res Function(_$UnexpectedErrorImpl) then, + ) = __$$UnexpectedErrorImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$UnexpectedErrorImplCopyWithImpl<$Res> + extends _$UserFailureCopyWithImpl<$Res, _$UnexpectedErrorImpl> + implements _$$UnexpectedErrorImplCopyWith<$Res> { + __$$UnexpectedErrorImplCopyWithImpl( + _$UnexpectedErrorImpl _value, + $Res Function(_$UnexpectedErrorImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$UnexpectedErrorImpl implements _UnexpectedError { + const _$UnexpectedErrorImpl(); + + @override + String toString() { + return 'UserFailure.unexpectedError()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$UnexpectedErrorImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return unexpectedError(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return unexpectedError?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return unexpectedError(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return unexpectedError?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (unexpectedError != null) { + return unexpectedError(this); + } + return orElse(); + } +} + +abstract class _UnexpectedError implements UserFailure { + const factory _UnexpectedError() = _$UnexpectedErrorImpl; +} + +/// @nodoc +abstract class _$$EmptyImplCopyWith<$Res> { + factory _$$EmptyImplCopyWith( + _$EmptyImpl value, + $Res Function(_$EmptyImpl) then, + ) = __$$EmptyImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$EmptyImplCopyWithImpl<$Res> + extends _$UserFailureCopyWithImpl<$Res, _$EmptyImpl> + implements _$$EmptyImplCopyWith<$Res> { + __$$EmptyImplCopyWithImpl( + _$EmptyImpl _value, + $Res Function(_$EmptyImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$EmptyImpl implements _Empty { + const _$EmptyImpl(); + + @override + String toString() { + return 'UserFailure.empty()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$EmptyImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return empty(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return empty?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return empty(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return empty?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (empty != null) { + return empty(this); + } + return orElse(); + } +} + +abstract class _Empty implements UserFailure { + const factory _Empty() = _$EmptyImpl; +} + +/// @nodoc +abstract class _$$DynamicErrorMessageImplCopyWith<$Res> { + factory _$$DynamicErrorMessageImplCopyWith( + _$DynamicErrorMessageImpl value, + $Res Function(_$DynamicErrorMessageImpl) then, + ) = __$$DynamicErrorMessageImplCopyWithImpl<$Res>; + @useResult + $Res call({String erroMessage}); +} + +/// @nodoc +class __$$DynamicErrorMessageImplCopyWithImpl<$Res> + extends _$UserFailureCopyWithImpl<$Res, _$DynamicErrorMessageImpl> + implements _$$DynamicErrorMessageImplCopyWith<$Res> { + __$$DynamicErrorMessageImplCopyWithImpl( + _$DynamicErrorMessageImpl _value, + $Res Function(_$DynamicErrorMessageImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? erroMessage = null}) { + return _then( + _$DynamicErrorMessageImpl( + null == erroMessage + ? _value.erroMessage + : erroMessage // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$DynamicErrorMessageImpl implements _DynamicErrorMessage { + const _$DynamicErrorMessageImpl(this.erroMessage); + + @override + final String erroMessage; + + @override + String toString() { + return 'UserFailure.dynamicErrorMessage(erroMessage: $erroMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DynamicErrorMessageImpl && + (identical(other.erroMessage, erroMessage) || + other.erroMessage == erroMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, erroMessage); + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + __$$DynamicErrorMessageImplCopyWithImpl<_$DynamicErrorMessageImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(ApiFailure failure) serverError, + required TResult Function() unexpectedError, + required TResult Function() empty, + required TResult Function(String erroMessage) dynamicErrorMessage, + }) { + return dynamicErrorMessage(erroMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(ApiFailure failure)? serverError, + TResult? Function()? unexpectedError, + TResult? Function()? empty, + TResult? Function(String erroMessage)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(erroMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(ApiFailure failure)? serverError, + TResult Function()? unexpectedError, + TResult Function()? empty, + TResult Function(String erroMessage)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(erroMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_ServerError value) serverError, + required TResult Function(_UnexpectedError value) unexpectedError, + required TResult Function(_Empty value) empty, + required TResult Function(_DynamicErrorMessage value) dynamicErrorMessage, + }) { + return dynamicErrorMessage(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_ServerError value)? serverError, + TResult? Function(_UnexpectedError value)? unexpectedError, + TResult? Function(_Empty value)? empty, + TResult? Function(_DynamicErrorMessage value)? dynamicErrorMessage, + }) { + return dynamicErrorMessage?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_ServerError value)? serverError, + TResult Function(_UnexpectedError value)? unexpectedError, + TResult Function(_Empty value)? empty, + TResult Function(_DynamicErrorMessage value)? dynamicErrorMessage, + required TResult orElse(), + }) { + if (dynamicErrorMessage != null) { + return dynamicErrorMessage(this); + } + return orElse(); + } +} + +abstract class _DynamicErrorMessage implements UserFailure { + const factory _DynamicErrorMessage(final String erroMessage) = + _$DynamicErrorMessageImpl; + + String get erroMessage; + + /// Create a copy of UserFailure + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DynamicErrorMessageImplCopyWith<_$DynamicErrorMessageImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/env.dart b/lib/env.dart index de21eb6..ddc3051 100644 --- a/lib/env.dart +++ b/lib/env.dart @@ -9,12 +9,12 @@ abstract class Env { @dev class DevEnv implements Env { @override - String get baseUrl => ''; // example value + String get baseUrl => 'https://api-pos.apskel.id'; // example value } @Injectable(as: Env) @prod class ProdEnv implements Env { @override - String get baseUrl => ''; + String get baseUrl => 'https://api-pos.apskel.id'; } diff --git a/lib/infrastructure/analytic/analytic_dtos.dart b/lib/infrastructure/analytic/analytic_dtos.dart new file mode 100644 index 0000000..abdb439 --- /dev/null +++ b/lib/infrastructure/analytic/analytic_dtos.dart @@ -0,0 +1,14 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/analytic/analytic.dart'; + +part 'analytic_dtos.freezed.dart'; +part 'analytic_dtos.g.dart'; + +part 'dto/sales_analytic_dto.dart'; +part 'dto/profit_loss_analytic_dto.dart'; +part 'dto/category_analytic_dto.dart'; +part 'dto/inventory_analytic_dto.dart'; +part 'dto/dashboard_analytic_dto.dart'; +part 'dto/product_analytic_dto.dart'; +part 'dto/payment_method_analytic_dto.dart'; diff --git a/lib/infrastructure/analytic/analytic_dtos.freezed.dart b/lib/infrastructure/analytic/analytic_dtos.freezed.dart new file mode 100644 index 0000000..f5f56fd --- /dev/null +++ b/lib/infrastructure/analytic/analytic_dtos.freezed.dart @@ -0,0 +1,8232 @@ +// 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 'analytic_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +SalesAnalyticDto _$SalesAnalyticDtoFromJson(Map json) { + return _SalesAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$SalesAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + DateTime? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + DateTime? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'group_by') + String? get groupBy => throw _privateConstructorUsedError; + @JsonKey(name: 'summary') + SalesAnalyticSummaryDto? get summary => throw _privateConstructorUsedError; + @JsonKey(name: 'data') + List? get data => throw _privateConstructorUsedError; + + /// Serializes this SalesAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SalesAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesAnalyticDtoCopyWith<$Res> { + factory $SalesAnalyticDtoCopyWith( + SalesAnalyticDto value, + $Res Function(SalesAnalyticDto) then, + ) = _$SalesAnalyticDtoCopyWithImpl<$Res, SalesAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') DateTime? dateFrom, + @JsonKey(name: 'date_to') DateTime? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') SalesAnalyticSummaryDto? summary, + @JsonKey(name: 'data') List? data, + }); + + $SalesAnalyticSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class _$SalesAnalyticDtoCopyWithImpl<$Res, $Val extends SalesAnalyticDto> + implements $SalesAnalyticDtoCopyWith<$Res> { + _$SalesAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as DateTime?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as DateTime?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as SalesAnalyticSummaryDto?, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of SalesAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $SalesAnalyticSummaryDtoCopyWith<$Res>? get summary { + if (_value.summary == null) { + return null; + } + + return $SalesAnalyticSummaryDtoCopyWith<$Res>(_value.summary!, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$SalesAnalyticDtoImplCopyWith<$Res> + implements $SalesAnalyticDtoCopyWith<$Res> { + factory _$$SalesAnalyticDtoImplCopyWith( + _$SalesAnalyticDtoImpl value, + $Res Function(_$SalesAnalyticDtoImpl) then, + ) = __$$SalesAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') DateTime? dateFrom, + @JsonKey(name: 'date_to') DateTime? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') SalesAnalyticSummaryDto? summary, + @JsonKey(name: 'data') List? data, + }); + + @override + $SalesAnalyticSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class __$$SalesAnalyticDtoImplCopyWithImpl<$Res> + extends _$SalesAnalyticDtoCopyWithImpl<$Res, _$SalesAnalyticDtoImpl> + implements _$$SalesAnalyticDtoImplCopyWith<$Res> { + __$$SalesAnalyticDtoImplCopyWithImpl( + _$SalesAnalyticDtoImpl _value, + $Res Function(_$SalesAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + }) { + return _then( + _$SalesAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as DateTime?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as DateTime?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as SalesAnalyticSummaryDto?, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$SalesAnalyticDtoImpl extends _SalesAnalyticDto { + const _$SalesAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'group_by') this.groupBy, + @JsonKey(name: 'summary') this.summary, + @JsonKey(name: 'data') final List? data, + }) : _data = data, + super._(); + + factory _$SalesAnalyticDtoImpl.fromJson(Map json) => + _$$SalesAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'date_from') + final DateTime? dateFrom; + @override + @JsonKey(name: 'date_to') + final DateTime? dateTo; + @override + @JsonKey(name: 'group_by') + final String? groupBy; + @override + @JsonKey(name: 'summary') + final SalesAnalyticSummaryDto? summary; + final List? _data; + @override + @JsonKey(name: 'data') + List? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'SalesAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of SalesAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesAnalyticDtoImplCopyWith<_$SalesAnalyticDtoImpl> get copyWith => + __$$SalesAnalyticDtoImplCopyWithImpl<_$SalesAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$SalesAnalyticDtoImplToJson(this); + } +} + +abstract class _SalesAnalyticDto extends SalesAnalyticDto { + const factory _SalesAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'date_from') final DateTime? dateFrom, + @JsonKey(name: 'date_to') final DateTime? dateTo, + @JsonKey(name: 'group_by') final String? groupBy, + @JsonKey(name: 'summary') final SalesAnalyticSummaryDto? summary, + @JsonKey(name: 'data') final List? data, + }) = _$SalesAnalyticDtoImpl; + const _SalesAnalyticDto._() : super._(); + + factory _SalesAnalyticDto.fromJson(Map json) = + _$SalesAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'date_from') + DateTime? get dateFrom; + @override + @JsonKey(name: 'date_to') + DateTime? get dateTo; + @override + @JsonKey(name: 'group_by') + String? get groupBy; + @override + @JsonKey(name: 'summary') + SalesAnalyticSummaryDto? get summary; + @override + @JsonKey(name: 'data') + List? get data; + + /// Create a copy of SalesAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesAnalyticDtoImplCopyWith<_$SalesAnalyticDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +SalesAnalyticSummaryDto _$SalesAnalyticSummaryDtoFromJson( + Map json, +) { + return _SalesAnalyticSummaryDto.fromJson(json); +} + +/// @nodoc +mixin _$SalesAnalyticSummaryDto { + @JsonKey(name: 'total_sales') + num? get totalSales => throw _privateConstructorUsedError; + @JsonKey(name: 'total_orders') + num? get totalOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'total_items') + num? get totalItems => throw _privateConstructorUsedError; + @JsonKey(name: 'average_order_value') + num? get averageOrderValue => throw _privateConstructorUsedError; + @JsonKey(name: 'total_tax') + num? get totalTax => throw _privateConstructorUsedError; + @JsonKey(name: 'total_discount') + num? get totalDiscount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_sales') + num? get netSales => throw _privateConstructorUsedError; + + /// Serializes this SalesAnalyticSummaryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SalesAnalyticSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesAnalyticSummaryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesAnalyticSummaryDtoCopyWith<$Res> { + factory $SalesAnalyticSummaryDtoCopyWith( + SalesAnalyticSummaryDto value, + $Res Function(SalesAnalyticSummaryDto) then, + ) = _$SalesAnalyticSummaryDtoCopyWithImpl<$Res, SalesAnalyticSummaryDto>; + @useResult + $Res call({ + @JsonKey(name: 'total_sales') num? totalSales, + @JsonKey(name: 'total_orders') num? totalOrders, + @JsonKey(name: 'total_items') num? totalItems, + @JsonKey(name: 'average_order_value') num? averageOrderValue, + @JsonKey(name: 'total_tax') num? totalTax, + @JsonKey(name: 'total_discount') num? totalDiscount, + @JsonKey(name: 'net_sales') num? netSales, + }); +} + +/// @nodoc +class _$SalesAnalyticSummaryDtoCopyWithImpl< + $Res, + $Val extends SalesAnalyticSummaryDto +> + implements $SalesAnalyticSummaryDtoCopyWith<$Res> { + _$SalesAnalyticSummaryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesAnalyticSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = freezed, + Object? totalOrders = freezed, + Object? totalItems = freezed, + Object? averageOrderValue = freezed, + Object? totalTax = freezed, + Object? totalDiscount = freezed, + Object? netSales = freezed, + }) { + return _then( + _value.copyWith( + totalSales: freezed == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as num?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as num?, + totalItems: freezed == totalItems + ? _value.totalItems + : totalItems // ignore: cast_nullable_to_non_nullable + as num?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as num?, + totalTax: freezed == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as num?, + totalDiscount: freezed == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as num?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as num?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$SalesAnalyticSummaryDtoImplCopyWith<$Res> + implements $SalesAnalyticSummaryDtoCopyWith<$Res> { + factory _$$SalesAnalyticSummaryDtoImplCopyWith( + _$SalesAnalyticSummaryDtoImpl value, + $Res Function(_$SalesAnalyticSummaryDtoImpl) then, + ) = __$$SalesAnalyticSummaryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'total_sales') num? totalSales, + @JsonKey(name: 'total_orders') num? totalOrders, + @JsonKey(name: 'total_items') num? totalItems, + @JsonKey(name: 'average_order_value') num? averageOrderValue, + @JsonKey(name: 'total_tax') num? totalTax, + @JsonKey(name: 'total_discount') num? totalDiscount, + @JsonKey(name: 'net_sales') num? netSales, + }); +} + +/// @nodoc +class __$$SalesAnalyticSummaryDtoImplCopyWithImpl<$Res> + extends + _$SalesAnalyticSummaryDtoCopyWithImpl< + $Res, + _$SalesAnalyticSummaryDtoImpl + > + implements _$$SalesAnalyticSummaryDtoImplCopyWith<$Res> { + __$$SalesAnalyticSummaryDtoImplCopyWithImpl( + _$SalesAnalyticSummaryDtoImpl _value, + $Res Function(_$SalesAnalyticSummaryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesAnalyticSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = freezed, + Object? totalOrders = freezed, + Object? totalItems = freezed, + Object? averageOrderValue = freezed, + Object? totalTax = freezed, + Object? totalDiscount = freezed, + Object? netSales = freezed, + }) { + return _then( + _$SalesAnalyticSummaryDtoImpl( + totalSales: freezed == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as num?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as num?, + totalItems: freezed == totalItems + ? _value.totalItems + : totalItems // ignore: cast_nullable_to_non_nullable + as num?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as num?, + totalTax: freezed == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as num?, + totalDiscount: freezed == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as num?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as num?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$SalesAnalyticSummaryDtoImpl extends _SalesAnalyticSummaryDto { + const _$SalesAnalyticSummaryDtoImpl({ + @JsonKey(name: 'total_sales') this.totalSales, + @JsonKey(name: 'total_orders') this.totalOrders, + @JsonKey(name: 'total_items') this.totalItems, + @JsonKey(name: 'average_order_value') this.averageOrderValue, + @JsonKey(name: 'total_tax') this.totalTax, + @JsonKey(name: 'total_discount') this.totalDiscount, + @JsonKey(name: 'net_sales') this.netSales, + }) : super._(); + + factory _$SalesAnalyticSummaryDtoImpl.fromJson(Map json) => + _$$SalesAnalyticSummaryDtoImplFromJson(json); + + @override + @JsonKey(name: 'total_sales') + final num? totalSales; + @override + @JsonKey(name: 'total_orders') + final num? totalOrders; + @override + @JsonKey(name: 'total_items') + final num? totalItems; + @override + @JsonKey(name: 'average_order_value') + final num? averageOrderValue; + @override + @JsonKey(name: 'total_tax') + final num? totalTax; + @override + @JsonKey(name: 'total_discount') + final num? totalDiscount; + @override + @JsonKey(name: 'net_sales') + final num? netSales; + + @override + String toString() { + return 'SalesAnalyticSummaryDto(totalSales: $totalSales, totalOrders: $totalOrders, totalItems: $totalItems, averageOrderValue: $averageOrderValue, totalTax: $totalTax, totalDiscount: $totalDiscount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesAnalyticSummaryDtoImpl && + (identical(other.totalSales, totalSales) || + other.totalSales == totalSales) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.totalItems, totalItems) || + other.totalItems == totalItems) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue) && + (identical(other.totalTax, totalTax) || + other.totalTax == totalTax) && + (identical(other.totalDiscount, totalDiscount) || + other.totalDiscount == totalDiscount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalSales, + totalOrders, + totalItems, + averageOrderValue, + totalTax, + totalDiscount, + netSales, + ); + + /// Create a copy of SalesAnalyticSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesAnalyticSummaryDtoImplCopyWith<_$SalesAnalyticSummaryDtoImpl> + get copyWith => + __$$SalesAnalyticSummaryDtoImplCopyWithImpl< + _$SalesAnalyticSummaryDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$SalesAnalyticSummaryDtoImplToJson(this); + } +} + +abstract class _SalesAnalyticSummaryDto extends SalesAnalyticSummaryDto { + const factory _SalesAnalyticSummaryDto({ + @JsonKey(name: 'total_sales') final num? totalSales, + @JsonKey(name: 'total_orders') final num? totalOrders, + @JsonKey(name: 'total_items') final num? totalItems, + @JsonKey(name: 'average_order_value') final num? averageOrderValue, + @JsonKey(name: 'total_tax') final num? totalTax, + @JsonKey(name: 'total_discount') final num? totalDiscount, + @JsonKey(name: 'net_sales') final num? netSales, + }) = _$SalesAnalyticSummaryDtoImpl; + const _SalesAnalyticSummaryDto._() : super._(); + + factory _SalesAnalyticSummaryDto.fromJson(Map json) = + _$SalesAnalyticSummaryDtoImpl.fromJson; + + @override + @JsonKey(name: 'total_sales') + num? get totalSales; + @override + @JsonKey(name: 'total_orders') + num? get totalOrders; + @override + @JsonKey(name: 'total_items') + num? get totalItems; + @override + @JsonKey(name: 'average_order_value') + num? get averageOrderValue; + @override + @JsonKey(name: 'total_tax') + num? get totalTax; + @override + @JsonKey(name: 'total_discount') + num? get totalDiscount; + @override + @JsonKey(name: 'net_sales') + num? get netSales; + + /// Create a copy of SalesAnalyticSummaryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesAnalyticSummaryDtoImplCopyWith<_$SalesAnalyticSummaryDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +SalesAnalyticDataDto _$SalesAnalyticDataDtoFromJson(Map json) { + return _SalesAnalyticDataDto.fromJson(json); +} + +/// @nodoc +mixin _$SalesAnalyticDataDto { + @JsonKey(name: 'date') + DateTime? get date => throw _privateConstructorUsedError; + @JsonKey(name: 'sales') + num? get sales => throw _privateConstructorUsedError; + @JsonKey(name: 'orders') + num? get orders => throw _privateConstructorUsedError; + @JsonKey(name: 'items') + num? get items => throw _privateConstructorUsedError; + @JsonKey(name: 'tax') + num? get tax => throw _privateConstructorUsedError; + @JsonKey(name: 'discount') + num? get discount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_sales') + num? get netSales => throw _privateConstructorUsedError; + + /// Serializes this SalesAnalyticDataDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of SalesAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SalesAnalyticDataDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SalesAnalyticDataDtoCopyWith<$Res> { + factory $SalesAnalyticDataDtoCopyWith( + SalesAnalyticDataDto value, + $Res Function(SalesAnalyticDataDto) then, + ) = _$SalesAnalyticDataDtoCopyWithImpl<$Res, SalesAnalyticDataDto>; + @useResult + $Res call({ + @JsonKey(name: 'date') DateTime? date, + @JsonKey(name: 'sales') num? sales, + @JsonKey(name: 'orders') num? orders, + @JsonKey(name: 'items') num? items, + @JsonKey(name: 'tax') num? tax, + @JsonKey(name: 'discount') num? discount, + @JsonKey(name: 'net_sales') num? netSales, + }); +} + +/// @nodoc +class _$SalesAnalyticDataDtoCopyWithImpl< + $Res, + $Val extends SalesAnalyticDataDto +> + implements $SalesAnalyticDataDtoCopyWith<$Res> { + _$SalesAnalyticDataDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SalesAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? sales = freezed, + Object? orders = freezed, + Object? items = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netSales = freezed, + }) { + return _then( + _value.copyWith( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime?, + sales: freezed == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as num?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as num?, + items: freezed == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as num?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as num?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as num?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as num?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$SalesAnalyticDataDtoImplCopyWith<$Res> + implements $SalesAnalyticDataDtoCopyWith<$Res> { + factory _$$SalesAnalyticDataDtoImplCopyWith( + _$SalesAnalyticDataDtoImpl value, + $Res Function(_$SalesAnalyticDataDtoImpl) then, + ) = __$$SalesAnalyticDataDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'date') DateTime? date, + @JsonKey(name: 'sales') num? sales, + @JsonKey(name: 'orders') num? orders, + @JsonKey(name: 'items') num? items, + @JsonKey(name: 'tax') num? tax, + @JsonKey(name: 'discount') num? discount, + @JsonKey(name: 'net_sales') num? netSales, + }); +} + +/// @nodoc +class __$$SalesAnalyticDataDtoImplCopyWithImpl<$Res> + extends _$SalesAnalyticDataDtoCopyWithImpl<$Res, _$SalesAnalyticDataDtoImpl> + implements _$$SalesAnalyticDataDtoImplCopyWith<$Res> { + __$$SalesAnalyticDataDtoImplCopyWithImpl( + _$SalesAnalyticDataDtoImpl _value, + $Res Function(_$SalesAnalyticDataDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SalesAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? sales = freezed, + Object? orders = freezed, + Object? items = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netSales = freezed, + }) { + return _then( + _$SalesAnalyticDataDtoImpl( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as DateTime?, + sales: freezed == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as num?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as num?, + items: freezed == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as num?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as num?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as num?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as num?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$SalesAnalyticDataDtoImpl extends _SalesAnalyticDataDto { + const _$SalesAnalyticDataDtoImpl({ + @JsonKey(name: 'date') this.date, + @JsonKey(name: 'sales') this.sales, + @JsonKey(name: 'orders') this.orders, + @JsonKey(name: 'items') this.items, + @JsonKey(name: 'tax') this.tax, + @JsonKey(name: 'discount') this.discount, + @JsonKey(name: 'net_sales') this.netSales, + }) : super._(); + + factory _$SalesAnalyticDataDtoImpl.fromJson(Map json) => + _$$SalesAnalyticDataDtoImplFromJson(json); + + @override + @JsonKey(name: 'date') + final DateTime? date; + @override + @JsonKey(name: 'sales') + final num? sales; + @override + @JsonKey(name: 'orders') + final num? orders; + @override + @JsonKey(name: 'items') + final num? items; + @override + @JsonKey(name: 'tax') + final num? tax; + @override + @JsonKey(name: 'discount') + final num? discount; + @override + @JsonKey(name: 'net_sales') + final num? netSales; + + @override + String toString() { + return 'SalesAnalyticDataDto(date: $date, sales: $sales, orders: $orders, items: $items, tax: $tax, discount: $discount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SalesAnalyticDataDtoImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.orders, orders) || other.orders == orders) && + (identical(other.items, items) || other.items == items) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + date, + sales, + orders, + items, + tax, + discount, + netSales, + ); + + /// Create a copy of SalesAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SalesAnalyticDataDtoImplCopyWith<_$SalesAnalyticDataDtoImpl> + get copyWith => + __$$SalesAnalyticDataDtoImplCopyWithImpl<_$SalesAnalyticDataDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$SalesAnalyticDataDtoImplToJson(this); + } +} + +abstract class _SalesAnalyticDataDto extends SalesAnalyticDataDto { + const factory _SalesAnalyticDataDto({ + @JsonKey(name: 'date') final DateTime? date, + @JsonKey(name: 'sales') final num? sales, + @JsonKey(name: 'orders') final num? orders, + @JsonKey(name: 'items') final num? items, + @JsonKey(name: 'tax') final num? tax, + @JsonKey(name: 'discount') final num? discount, + @JsonKey(name: 'net_sales') final num? netSales, + }) = _$SalesAnalyticDataDtoImpl; + const _SalesAnalyticDataDto._() : super._(); + + factory _SalesAnalyticDataDto.fromJson(Map json) = + _$SalesAnalyticDataDtoImpl.fromJson; + + @override + @JsonKey(name: 'date') + DateTime? get date; + @override + @JsonKey(name: 'sales') + num? get sales; + @override + @JsonKey(name: 'orders') + num? get orders; + @override + @JsonKey(name: 'items') + num? get items; + @override + @JsonKey(name: 'tax') + num? get tax; + @override + @JsonKey(name: 'discount') + num? get discount; + @override + @JsonKey(name: 'net_sales') + num? get netSales; + + /// Create a copy of SalesAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SalesAnalyticDataDtoImplCopyWith<_$SalesAnalyticDataDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossAnalyticDto _$ProfitLossAnalyticDtoFromJson( + Map json, +) { + return _ProfitLossAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'group_by') + String? get groupBy => throw _privateConstructorUsedError; + @JsonKey(name: 'summary') + ProfitLossSummaryDto? get summary => throw _privateConstructorUsedError; + @JsonKey(name: 'data') + List? get data => throw _privateConstructorUsedError; + @JsonKey(name: 'product_data') + List? get productData => + throw _privateConstructorUsedError; + + /// Serializes this ProfitLossAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossAnalyticDtoCopyWith<$Res> { + factory $ProfitLossAnalyticDtoCopyWith( + ProfitLossAnalyticDto value, + $Res Function(ProfitLossAnalyticDto) then, + ) = _$ProfitLossAnalyticDtoCopyWithImpl<$Res, ProfitLossAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') List? data, + @JsonKey(name: 'product_data') List? productData, + }); + + $ProfitLossSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class _$ProfitLossAnalyticDtoCopyWithImpl< + $Res, + $Val extends ProfitLossAnalyticDto +> + implements $ProfitLossAnalyticDtoCopyWith<$Res> { + _$ProfitLossAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + Object? productData = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummaryDto?, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List?, + productData: freezed == productData + ? _value.productData + : productData // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $ProfitLossSummaryDtoCopyWith<$Res>? get summary { + if (_value.summary == null) { + return null; + } + + return $ProfitLossSummaryDtoCopyWith<$Res>(_value.summary!, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$ProfitLossAnalyticDtoImplCopyWith<$Res> + implements $ProfitLossAnalyticDtoCopyWith<$Res> { + factory _$$ProfitLossAnalyticDtoImplCopyWith( + _$ProfitLossAnalyticDtoImpl value, + $Res Function(_$ProfitLossAnalyticDtoImpl) then, + ) = __$$ProfitLossAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') List? data, + @JsonKey(name: 'product_data') List? productData, + }); + + @override + $ProfitLossSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class __$$ProfitLossAnalyticDtoImplCopyWithImpl<$Res> + extends + _$ProfitLossAnalyticDtoCopyWithImpl<$Res, _$ProfitLossAnalyticDtoImpl> + implements _$$ProfitLossAnalyticDtoImplCopyWith<$Res> { + __$$ProfitLossAnalyticDtoImplCopyWithImpl( + _$ProfitLossAnalyticDtoImpl _value, + $Res Function(_$ProfitLossAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + Object? productData = freezed, + }) { + return _then( + _$ProfitLossAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as ProfitLossSummaryDto?, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List?, + productData: freezed == productData + ? _value._productData + : productData // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossAnalyticDtoImpl extends _ProfitLossAnalyticDto { + const _$ProfitLossAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'group_by') this.groupBy, + @JsonKey(name: 'summary') this.summary, + @JsonKey(name: 'data') final List? data, + @JsonKey(name: 'product_data') + final List? productData, + }) : _data = data, + _productData = productData, + super._(); + + factory _$ProfitLossAnalyticDtoImpl.fromJson(Map json) => + _$$ProfitLossAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + @override + @JsonKey(name: 'group_by') + final String? groupBy; + @override + @JsonKey(name: 'summary') + final ProfitLossSummaryDto? summary; + final List? _data; + @override + @JsonKey(name: 'data') + List? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _productData; + @override + @JsonKey(name: 'product_data') + List? get productData { + final value = _productData; + if (value == null) return null; + if (_productData is EqualUnmodifiableListView) return _productData; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'ProfitLossAnalyticDto(organizationId: $organizationId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data, productData: $productData)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data) && + const DeepCollectionEquality().equals( + other._productData, + _productData, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + const DeepCollectionEquality().hash(_productData), + ); + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossAnalyticDtoImplCopyWith<_$ProfitLossAnalyticDtoImpl> + get copyWith => + __$$ProfitLossAnalyticDtoImplCopyWithImpl<_$ProfitLossAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProfitLossAnalyticDtoImplToJson(this); + } +} + +abstract class _ProfitLossAnalyticDto extends ProfitLossAnalyticDto { + const factory _ProfitLossAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'group_by') final String? groupBy, + @JsonKey(name: 'summary') final ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') final List? data, + @JsonKey(name: 'product_data') + final List? productData, + }) = _$ProfitLossAnalyticDtoImpl; + const _ProfitLossAnalyticDto._() : super._(); + + factory _ProfitLossAnalyticDto.fromJson(Map json) = + _$ProfitLossAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'group_by') + String? get groupBy; + @override + @JsonKey(name: 'summary') + ProfitLossSummaryDto? get summary; + @override + @JsonKey(name: 'data') + List? get data; + @override + @JsonKey(name: 'product_data') + List? get productData; + + /// Create a copy of ProfitLossAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossAnalyticDtoImplCopyWith<_$ProfitLossAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossSummaryDto _$ProfitLossSummaryDtoFromJson(Map json) { + return _ProfitLossSummaryDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossSummaryDto { + @JsonKey(name: 'total_revenue') + int? get totalRevenue => throw _privateConstructorUsedError; + @JsonKey(name: 'total_cost') + int? get totalCost => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit') + int? get grossProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'total_tax') + int? get totalTax => throw _privateConstructorUsedError; + @JsonKey(name: 'total_discount') + int? get totalDiscount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit') + int? get netProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'total_orders') + int? get totalOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'average_profit') + double? get averageProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'profitability_ratio') + double? get profitabilityRatio => throw _privateConstructorUsedError; + + /// Serializes this ProfitLossSummaryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossSummaryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossSummaryDtoCopyWith<$Res> { + factory $ProfitLossSummaryDtoCopyWith( + ProfitLossSummaryDto value, + $Res Function(ProfitLossSummaryDto) then, + ) = _$ProfitLossSummaryDtoCopyWithImpl<$Res, ProfitLossSummaryDto>; + @useResult + $Res call({ + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'total_tax') int? totalTax, + @JsonKey(name: 'total_discount') int? totalDiscount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_profit') double? averageProfit, + @JsonKey(name: 'profitability_ratio') double? profitabilityRatio, + }); +} + +/// @nodoc +class _$ProfitLossSummaryDtoCopyWithImpl< + $Res, + $Val extends ProfitLossSummaryDto +> + implements $ProfitLossSummaryDtoCopyWith<$Res> { + _$ProfitLossSummaryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = freezed, + Object? totalCost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? totalTax = freezed, + Object? totalDiscount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? totalOrders = freezed, + Object? averageProfit = freezed, + Object? profitabilityRatio = freezed, + }) { + return _then( + _value.copyWith( + totalRevenue: freezed == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int?, + totalCost: freezed == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalTax: freezed == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int?, + totalDiscount: freezed == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageProfit: freezed == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double?, + profitabilityRatio: freezed == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossSummaryDtoImplCopyWith<$Res> + implements $ProfitLossSummaryDtoCopyWith<$Res> { + factory _$$ProfitLossSummaryDtoImplCopyWith( + _$ProfitLossSummaryDtoImpl value, + $Res Function(_$ProfitLossSummaryDtoImpl) then, + ) = __$$ProfitLossSummaryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'total_tax') int? totalTax, + @JsonKey(name: 'total_discount') int? totalDiscount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_profit') double? averageProfit, + @JsonKey(name: 'profitability_ratio') double? profitabilityRatio, + }); +} + +/// @nodoc +class __$$ProfitLossSummaryDtoImplCopyWithImpl<$Res> + extends _$ProfitLossSummaryDtoCopyWithImpl<$Res, _$ProfitLossSummaryDtoImpl> + implements _$$ProfitLossSummaryDtoImplCopyWith<$Res> { + __$$ProfitLossSummaryDtoImplCopyWithImpl( + _$ProfitLossSummaryDtoImpl _value, + $Res Function(_$ProfitLossSummaryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalRevenue = freezed, + Object? totalCost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? totalTax = freezed, + Object? totalDiscount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? totalOrders = freezed, + Object? averageProfit = freezed, + Object? profitabilityRatio = freezed, + }) { + return _then( + _$ProfitLossSummaryDtoImpl( + totalRevenue: freezed == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int?, + totalCost: freezed == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalTax: freezed == totalTax + ? _value.totalTax + : totalTax // ignore: cast_nullable_to_non_nullable + as int?, + totalDiscount: freezed == totalDiscount + ? _value.totalDiscount + : totalDiscount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageProfit: freezed == averageProfit + ? _value.averageProfit + : averageProfit // ignore: cast_nullable_to_non_nullable + as double?, + profitabilityRatio: freezed == profitabilityRatio + ? _value.profitabilityRatio + : profitabilityRatio // ignore: cast_nullable_to_non_nullable + as double?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossSummaryDtoImpl extends _ProfitLossSummaryDto { + const _$ProfitLossSummaryDtoImpl({ + @JsonKey(name: 'total_revenue') this.totalRevenue, + @JsonKey(name: 'total_cost') this.totalCost, + @JsonKey(name: 'gross_profit') this.grossProfit, + @JsonKey(name: 'gross_profit_margin') this.grossProfitMargin, + @JsonKey(name: 'total_tax') this.totalTax, + @JsonKey(name: 'total_discount') this.totalDiscount, + @JsonKey(name: 'net_profit') this.netProfit, + @JsonKey(name: 'net_profit_margin') this.netProfitMargin, + @JsonKey(name: 'total_orders') this.totalOrders, + @JsonKey(name: 'average_profit') this.averageProfit, + @JsonKey(name: 'profitability_ratio') this.profitabilityRatio, + }) : super._(); + + factory _$ProfitLossSummaryDtoImpl.fromJson(Map json) => + _$$ProfitLossSummaryDtoImplFromJson(json); + + @override + @JsonKey(name: 'total_revenue') + final int? totalRevenue; + @override + @JsonKey(name: 'total_cost') + final int? totalCost; + @override + @JsonKey(name: 'gross_profit') + final int? grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + final double? grossProfitMargin; + @override + @JsonKey(name: 'total_tax') + final int? totalTax; + @override + @JsonKey(name: 'total_discount') + final int? totalDiscount; + @override + @JsonKey(name: 'net_profit') + final int? netProfit; + @override + @JsonKey(name: 'net_profit_margin') + final double? netProfitMargin; + @override + @JsonKey(name: 'total_orders') + final int? totalOrders; + @override + @JsonKey(name: 'average_profit') + final double? averageProfit; + @override + @JsonKey(name: 'profitability_ratio') + final double? profitabilityRatio; + + @override + String toString() { + return 'ProfitLossSummaryDto(totalRevenue: $totalRevenue, totalCost: $totalCost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, totalTax: $totalTax, totalDiscount: $totalDiscount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, totalOrders: $totalOrders, averageProfit: $averageProfit, profitabilityRatio: $profitabilityRatio)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossSummaryDtoImpl && + (identical(other.totalRevenue, totalRevenue) || + other.totalRevenue == totalRevenue) && + (identical(other.totalCost, totalCost) || + other.totalCost == totalCost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.totalTax, totalTax) || + other.totalTax == totalTax) && + (identical(other.totalDiscount, totalDiscount) || + other.totalDiscount == totalDiscount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageProfit, averageProfit) || + other.averageProfit == averageProfit) && + (identical(other.profitabilityRatio, profitabilityRatio) || + other.profitabilityRatio == profitabilityRatio)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalRevenue, + totalCost, + grossProfit, + grossProfitMargin, + totalTax, + totalDiscount, + netProfit, + netProfitMargin, + totalOrders, + averageProfit, + profitabilityRatio, + ); + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossSummaryDtoImplCopyWith<_$ProfitLossSummaryDtoImpl> + get copyWith => + __$$ProfitLossSummaryDtoImplCopyWithImpl<_$ProfitLossSummaryDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProfitLossSummaryDtoImplToJson(this); + } +} + +abstract class _ProfitLossSummaryDto extends ProfitLossSummaryDto { + const factory _ProfitLossSummaryDto({ + @JsonKey(name: 'total_revenue') final int? totalRevenue, + @JsonKey(name: 'total_cost') final int? totalCost, + @JsonKey(name: 'gross_profit') final int? grossProfit, + @JsonKey(name: 'gross_profit_margin') final double? grossProfitMargin, + @JsonKey(name: 'total_tax') final int? totalTax, + @JsonKey(name: 'total_discount') final int? totalDiscount, + @JsonKey(name: 'net_profit') final int? netProfit, + @JsonKey(name: 'net_profit_margin') final double? netProfitMargin, + @JsonKey(name: 'total_orders') final int? totalOrders, + @JsonKey(name: 'average_profit') final double? averageProfit, + @JsonKey(name: 'profitability_ratio') final double? profitabilityRatio, + }) = _$ProfitLossSummaryDtoImpl; + const _ProfitLossSummaryDto._() : super._(); + + factory _ProfitLossSummaryDto.fromJson(Map json) = + _$ProfitLossSummaryDtoImpl.fromJson; + + @override + @JsonKey(name: 'total_revenue') + int? get totalRevenue; + @override + @JsonKey(name: 'total_cost') + int? get totalCost; + @override + @JsonKey(name: 'gross_profit') + int? get grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin; + @override + @JsonKey(name: 'total_tax') + int? get totalTax; + @override + @JsonKey(name: 'total_discount') + int? get totalDiscount; + @override + @JsonKey(name: 'net_profit') + int? get netProfit; + @override + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin; + @override + @JsonKey(name: 'total_orders') + int? get totalOrders; + @override + @JsonKey(name: 'average_profit') + double? get averageProfit; + @override + @JsonKey(name: 'profitability_ratio') + double? get profitabilityRatio; + + /// Create a copy of ProfitLossSummaryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossSummaryDtoImplCopyWith<_$ProfitLossSummaryDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossDailyDataDto _$ProfitLossDailyDataDtoFromJson( + Map json, +) { + return _ProfitLossDailyDataDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossDailyDataDto { + @JsonKey(name: 'date') + String? get date => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit') + int? get grossProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'tax') + int? get tax => throw _privateConstructorUsedError; + @JsonKey(name: 'discount') + int? get discount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit') + int? get netProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'orders') + int? get orders => throw _privateConstructorUsedError; + + /// Serializes this ProfitLossDailyDataDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossDailyDataDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossDailyDataDtoCopyWith<$Res> { + factory $ProfitLossDailyDataDtoCopyWith( + ProfitLossDailyDataDto value, + $Res Function(ProfitLossDailyDataDto) then, + ) = _$ProfitLossDailyDataDtoCopyWithImpl<$Res, ProfitLossDailyDataDto>; + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'orders') int? orders, + }); +} + +/// @nodoc +class _$ProfitLossDailyDataDtoCopyWithImpl< + $Res, + $Val extends ProfitLossDailyDataDto +> + implements $ProfitLossDailyDataDtoCopyWith<$Res> { + _$ProfitLossDailyDataDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? orders = freezed, + }) { + return _then( + _value.copyWith( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossDailyDataDtoImplCopyWith<$Res> + implements $ProfitLossDailyDataDtoCopyWith<$Res> { + factory _$$ProfitLossDailyDataDtoImplCopyWith( + _$ProfitLossDailyDataDtoImpl value, + $Res Function(_$ProfitLossDailyDataDtoImpl) then, + ) = __$$ProfitLossDailyDataDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'orders') int? orders, + }); +} + +/// @nodoc +class __$$ProfitLossDailyDataDtoImplCopyWithImpl<$Res> + extends + _$ProfitLossDailyDataDtoCopyWithImpl<$Res, _$ProfitLossDailyDataDtoImpl> + implements _$$ProfitLossDailyDataDtoImplCopyWith<$Res> { + __$$ProfitLossDailyDataDtoImplCopyWithImpl( + _$ProfitLossDailyDataDtoImpl _value, + $Res Function(_$ProfitLossDailyDataDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netProfit = freezed, + Object? netProfitMargin = freezed, + Object? orders = freezed, + }) { + return _then( + _$ProfitLossDailyDataDtoImpl( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netProfit: freezed == netProfit + ? _value.netProfit + : netProfit // ignore: cast_nullable_to_non_nullable + as int?, + netProfitMargin: freezed == netProfitMargin + ? _value.netProfitMargin + : netProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossDailyDataDtoImpl extends _ProfitLossDailyDataDto { + const _$ProfitLossDailyDataDtoImpl({ + @JsonKey(name: 'date') this.date, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'gross_profit') this.grossProfit, + @JsonKey(name: 'gross_profit_margin') this.grossProfitMargin, + @JsonKey(name: 'tax') this.tax, + @JsonKey(name: 'discount') this.discount, + @JsonKey(name: 'net_profit') this.netProfit, + @JsonKey(name: 'net_profit_margin') this.netProfitMargin, + @JsonKey(name: 'orders') this.orders, + }) : super._(); + + factory _$ProfitLossDailyDataDtoImpl.fromJson(Map json) => + _$$ProfitLossDailyDataDtoImplFromJson(json); + + @override + @JsonKey(name: 'date') + final String? date; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'cost') + final int? cost; + @override + @JsonKey(name: 'gross_profit') + final int? grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + final double? grossProfitMargin; + @override + @JsonKey(name: 'tax') + final int? tax; + @override + @JsonKey(name: 'discount') + final int? discount; + @override + @JsonKey(name: 'net_profit') + final int? netProfit; + @override + @JsonKey(name: 'net_profit_margin') + final double? netProfitMargin; + @override + @JsonKey(name: 'orders') + final int? orders; + + @override + String toString() { + return 'ProfitLossDailyDataDto(date: $date, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, tax: $tax, discount: $discount, netProfit: $netProfit, netProfitMargin: $netProfitMargin, orders: $orders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossDailyDataDtoImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netProfit, netProfit) || + other.netProfit == netProfit) && + (identical(other.netProfitMargin, netProfitMargin) || + other.netProfitMargin == netProfitMargin) && + (identical(other.orders, orders) || other.orders == orders)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + date, + revenue, + cost, + grossProfit, + grossProfitMargin, + tax, + discount, + netProfit, + netProfitMargin, + orders, + ); + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossDailyDataDtoImplCopyWith<_$ProfitLossDailyDataDtoImpl> + get copyWith => + __$$ProfitLossDailyDataDtoImplCopyWithImpl<_$ProfitLossDailyDataDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProfitLossDailyDataDtoImplToJson(this); + } +} + +abstract class _ProfitLossDailyDataDto extends ProfitLossDailyDataDto { + const factory _ProfitLossDailyDataDto({ + @JsonKey(name: 'date') final String? date, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'gross_profit') final int? grossProfit, + @JsonKey(name: 'gross_profit_margin') final double? grossProfitMargin, + @JsonKey(name: 'tax') final int? tax, + @JsonKey(name: 'discount') final int? discount, + @JsonKey(name: 'net_profit') final int? netProfit, + @JsonKey(name: 'net_profit_margin') final double? netProfitMargin, + @JsonKey(name: 'orders') final int? orders, + }) = _$ProfitLossDailyDataDtoImpl; + const _ProfitLossDailyDataDto._() : super._(); + + factory _ProfitLossDailyDataDto.fromJson(Map json) = + _$ProfitLossDailyDataDtoImpl.fromJson; + + @override + @JsonKey(name: 'date') + String? get date; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'gross_profit') + int? get grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin; + @override + @JsonKey(name: 'tax') + int? get tax; + @override + @JsonKey(name: 'discount') + int? get discount; + @override + @JsonKey(name: 'net_profit') + int? get netProfit; + @override + @JsonKey(name: 'net_profit_margin') + double? get netProfitMargin; + @override + @JsonKey(name: 'orders') + int? get orders; + + /// Create a copy of ProfitLossDailyDataDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossDailyDataDtoImplCopyWith<_$ProfitLossDailyDataDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProfitLossProductDataDto _$ProfitLossProductDataDtoFromJson( + Map json, +) { + return _ProfitLossProductDataDto.fromJson(json); +} + +/// @nodoc +mixin _$ProfitLossProductDataDto { + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_name') + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_name') + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: 'quantity_sold') + int? get quantitySold => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit') + int? get grossProfit => throw _privateConstructorUsedError; + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin => throw _privateConstructorUsedError; + @JsonKey(name: 'average_price') + int? get averagePrice => throw _privateConstructorUsedError; + @JsonKey(name: 'average_cost') + int? get averageCost => throw _privateConstructorUsedError; + @JsonKey(name: 'profit_per_unit') + int? get profitPerUnit => throw _privateConstructorUsedError; + + /// Serializes this ProfitLossProductDataDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProfitLossProductDataDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProfitLossProductDataDtoCopyWith<$Res> { + factory $ProfitLossProductDataDtoCopyWith( + ProfitLossProductDataDto value, + $Res Function(ProfitLossProductDataDto) then, + ) = _$ProfitLossProductDataDtoCopyWithImpl<$Res, ProfitLossProductDataDto>; + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'average_price') int? averagePrice, + @JsonKey(name: 'average_cost') int? averageCost, + @JsonKey(name: 'profit_per_unit') int? profitPerUnit, + }); +} + +/// @nodoc +class _$ProfitLossProductDataDtoCopyWithImpl< + $Res, + $Val extends ProfitLossProductDataDto +> + implements $ProfitLossProductDataDtoCopyWith<$Res> { + _$ProfitLossProductDataDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? averagePrice = freezed, + Object? averageCost = freezed, + Object? profitPerUnit = freezed, + }) { + return _then( + _value.copyWith( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int?, + averageCost: freezed == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int?, + profitPerUnit: freezed == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProfitLossProductDataDtoImplCopyWith<$Res> + implements $ProfitLossProductDataDtoCopyWith<$Res> { + factory _$$ProfitLossProductDataDtoImplCopyWith( + _$ProfitLossProductDataDtoImpl value, + $Res Function(_$ProfitLossProductDataDtoImpl) then, + ) = __$$ProfitLossProductDataDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'average_price') int? averagePrice, + @JsonKey(name: 'average_cost') int? averageCost, + @JsonKey(name: 'profit_per_unit') int? profitPerUnit, + }); +} + +/// @nodoc +class __$$ProfitLossProductDataDtoImplCopyWithImpl<$Res> + extends + _$ProfitLossProductDataDtoCopyWithImpl< + $Res, + _$ProfitLossProductDataDtoImpl + > + implements _$$ProfitLossProductDataDtoImplCopyWith<$Res> { + __$$ProfitLossProductDataDtoImplCopyWithImpl( + _$ProfitLossProductDataDtoImpl _value, + $Res Function(_$ProfitLossProductDataDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? cost = freezed, + Object? grossProfit = freezed, + Object? grossProfitMargin = freezed, + Object? averagePrice = freezed, + Object? averageCost = freezed, + Object? profitPerUnit = freezed, + }) { + return _then( + _$ProfitLossProductDataDtoImpl( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + grossProfit: freezed == grossProfit + ? _value.grossProfit + : grossProfit // ignore: cast_nullable_to_non_nullable + as int?, + grossProfitMargin: freezed == grossProfitMargin + ? _value.grossProfitMargin + : grossProfitMargin // ignore: cast_nullable_to_non_nullable + as double?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as int?, + averageCost: freezed == averageCost + ? _value.averageCost + : averageCost // ignore: cast_nullable_to_non_nullable + as int?, + profitPerUnit: freezed == profitPerUnit + ? _value.profitPerUnit + : profitPerUnit // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProfitLossProductDataDtoImpl extends _ProfitLossProductDataDto { + const _$ProfitLossProductDataDtoImpl({ + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'product_name') this.productName, + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'category_name') this.categoryName, + @JsonKey(name: 'quantity_sold') this.quantitySold, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'gross_profit') this.grossProfit, + @JsonKey(name: 'gross_profit_margin') this.grossProfitMargin, + @JsonKey(name: 'average_price') this.averagePrice, + @JsonKey(name: 'average_cost') this.averageCost, + @JsonKey(name: 'profit_per_unit') this.profitPerUnit, + }) : super._(); + + factory _$ProfitLossProductDataDtoImpl.fromJson(Map json) => + _$$ProfitLossProductDataDtoImplFromJson(json); + + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'product_name') + final String? productName; + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'category_name') + final String? categoryName; + @override + @JsonKey(name: 'quantity_sold') + final int? quantitySold; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'cost') + final int? cost; + @override + @JsonKey(name: 'gross_profit') + final int? grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + final double? grossProfitMargin; + @override + @JsonKey(name: 'average_price') + final int? averagePrice; + @override + @JsonKey(name: 'average_cost') + final int? averageCost; + @override + @JsonKey(name: 'profit_per_unit') + final int? profitPerUnit; + + @override + String toString() { + return 'ProfitLossProductDataDto(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, cost: $cost, grossProfit: $grossProfit, grossProfitMargin: $grossProfitMargin, averagePrice: $averagePrice, averageCost: $averageCost, profitPerUnit: $profitPerUnit)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProfitLossProductDataDtoImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.grossProfit, grossProfit) || + other.grossProfit == grossProfit) && + (identical(other.grossProfitMargin, grossProfitMargin) || + other.grossProfitMargin == grossProfitMargin) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.averageCost, averageCost) || + other.averageCost == averageCost) && + (identical(other.profitPerUnit, profitPerUnit) || + other.profitPerUnit == profitPerUnit)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + cost, + grossProfit, + grossProfitMargin, + averagePrice, + averageCost, + profitPerUnit, + ); + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProfitLossProductDataDtoImplCopyWith<_$ProfitLossProductDataDtoImpl> + get copyWith => + __$$ProfitLossProductDataDtoImplCopyWithImpl< + _$ProfitLossProductDataDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$ProfitLossProductDataDtoImplToJson(this); + } +} + +abstract class _ProfitLossProductDataDto extends ProfitLossProductDataDto { + const factory _ProfitLossProductDataDto({ + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'product_name') final String? productName, + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'category_name') final String? categoryName, + @JsonKey(name: 'quantity_sold') final int? quantitySold, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'gross_profit') final int? grossProfit, + @JsonKey(name: 'gross_profit_margin') final double? grossProfitMargin, + @JsonKey(name: 'average_price') final int? averagePrice, + @JsonKey(name: 'average_cost') final int? averageCost, + @JsonKey(name: 'profit_per_unit') final int? profitPerUnit, + }) = _$ProfitLossProductDataDtoImpl; + const _ProfitLossProductDataDto._() : super._(); + + factory _ProfitLossProductDataDto.fromJson(Map json) = + _$ProfitLossProductDataDtoImpl.fromJson; + + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'product_name') + String? get productName; + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'category_name') + String? get categoryName; + @override + @JsonKey(name: 'quantity_sold') + int? get quantitySold; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'gross_profit') + int? get grossProfit; + @override + @JsonKey(name: 'gross_profit_margin') + double? get grossProfitMargin; + @override + @JsonKey(name: 'average_price') + int? get averagePrice; + @override + @JsonKey(name: 'average_cost') + int? get averageCost; + @override + @JsonKey(name: 'profit_per_unit') + int? get profitPerUnit; + + /// Create a copy of ProfitLossProductDataDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProfitLossProductDataDtoImplCopyWith<_$ProfitLossProductDataDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +CategoryAnalyticDto _$CategoryAnalyticDtoFromJson(Map json) { + return _CategoryAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$CategoryAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'data') + List? get data => throw _privateConstructorUsedError; + + /// Serializes this CategoryAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of CategoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryAnalyticDtoCopyWith<$Res> { + factory $CategoryAnalyticDtoCopyWith( + CategoryAnalyticDto value, + $Res Function(CategoryAnalyticDto) then, + ) = _$CategoryAnalyticDtoCopyWithImpl<$Res, CategoryAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'data') List? data, + }); +} + +/// @nodoc +class _$CategoryAnalyticDtoCopyWithImpl<$Res, $Val extends CategoryAnalyticDto> + implements $CategoryAnalyticDtoCopyWith<$Res> { + _$CategoryAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? data = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryAnalyticDtoImplCopyWith<$Res> + implements $CategoryAnalyticDtoCopyWith<$Res> { + factory _$$CategoryAnalyticDtoImplCopyWith( + _$CategoryAnalyticDtoImpl value, + $Res Function(_$CategoryAnalyticDtoImpl) then, + ) = __$$CategoryAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'data') List? data, + }); +} + +/// @nodoc +class __$$CategoryAnalyticDtoImplCopyWithImpl<$Res> + extends _$CategoryAnalyticDtoCopyWithImpl<$Res, _$CategoryAnalyticDtoImpl> + implements _$$CategoryAnalyticDtoImplCopyWith<$Res> { + __$$CategoryAnalyticDtoImplCopyWithImpl( + _$CategoryAnalyticDtoImpl _value, + $Res Function(_$CategoryAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? data = freezed, + }) { + return _then( + _$CategoryAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$CategoryAnalyticDtoImpl extends _CategoryAnalyticDto { + const _$CategoryAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'data') final List? data, + }) : _data = data, + super._(); + + factory _$CategoryAnalyticDtoImpl.fromJson(Map json) => + _$$CategoryAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + final List? _data; + @override + @JsonKey(name: 'data') + List? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'CategoryAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of CategoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryAnalyticDtoImplCopyWith<_$CategoryAnalyticDtoImpl> get copyWith => + __$$CategoryAnalyticDtoImplCopyWithImpl<_$CategoryAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$CategoryAnalyticDtoImplToJson(this); + } +} + +abstract class _CategoryAnalyticDto extends CategoryAnalyticDto { + const factory _CategoryAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'data') final List? data, + }) = _$CategoryAnalyticDtoImpl; + const _CategoryAnalyticDto._() : super._(); + + factory _CategoryAnalyticDto.fromJson(Map json) = + _$CategoryAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'data') + List? get data; + + /// Create a copy of CategoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryAnalyticDtoImplCopyWith<_$CategoryAnalyticDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +CategoryAnalyticItemDto _$CategoryAnalyticItemDtoFromJson( + Map json, +) { + return _CategoryAnalyticItemDto.fromJson(json); +} + +/// @nodoc +mixin _$CategoryAnalyticItemDto { + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_name') + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: 'total_revenue') + int? get totalRevenue => throw _privateConstructorUsedError; + @JsonKey(name: 'total_quantity') + int? get totalQuantity => throw _privateConstructorUsedError; + @JsonKey(name: 'product_count') + int? get productCount => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + + /// Serializes this CategoryAnalyticItemDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of CategoryAnalyticItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryAnalyticItemDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryAnalyticItemDtoCopyWith<$Res> { + factory $CategoryAnalyticItemDtoCopyWith( + CategoryAnalyticItemDto value, + $Res Function(CategoryAnalyticItemDto) then, + ) = _$CategoryAnalyticItemDtoCopyWithImpl<$Res, CategoryAnalyticItemDto>; + @useResult + $Res call({ + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_quantity') int? totalQuantity, + @JsonKey(name: 'product_count') int? productCount, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class _$CategoryAnalyticItemDtoCopyWithImpl< + $Res, + $Val extends CategoryAnalyticItemDto +> + implements $CategoryAnalyticItemDtoCopyWith<$Res> { + _$CategoryAnalyticItemDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryAnalyticItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? totalRevenue = freezed, + Object? totalQuantity = freezed, + Object? productCount = freezed, + Object? orderCount = freezed, + }) { + return _then( + _value.copyWith( + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + totalRevenue: freezed == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int?, + totalQuantity: freezed == totalQuantity + ? _value.totalQuantity + : totalQuantity // ignore: cast_nullable_to_non_nullable + as int?, + productCount: freezed == productCount + ? _value.productCount + : productCount // ignore: cast_nullable_to_non_nullable + as int?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryAnalyticItemDtoImplCopyWith<$Res> + implements $CategoryAnalyticItemDtoCopyWith<$Res> { + factory _$$CategoryAnalyticItemDtoImplCopyWith( + _$CategoryAnalyticItemDtoImpl value, + $Res Function(_$CategoryAnalyticItemDtoImpl) then, + ) = __$$CategoryAnalyticItemDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_quantity') int? totalQuantity, + @JsonKey(name: 'product_count') int? productCount, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class __$$CategoryAnalyticItemDtoImplCopyWithImpl<$Res> + extends + _$CategoryAnalyticItemDtoCopyWithImpl< + $Res, + _$CategoryAnalyticItemDtoImpl + > + implements _$$CategoryAnalyticItemDtoImplCopyWith<$Res> { + __$$CategoryAnalyticItemDtoImplCopyWithImpl( + _$CategoryAnalyticItemDtoImpl _value, + $Res Function(_$CategoryAnalyticItemDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryAnalyticItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? totalRevenue = freezed, + Object? totalQuantity = freezed, + Object? productCount = freezed, + Object? orderCount = freezed, + }) { + return _then( + _$CategoryAnalyticItemDtoImpl( + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + totalRevenue: freezed == totalRevenue + ? _value.totalRevenue + : totalRevenue // ignore: cast_nullable_to_non_nullable + as int?, + totalQuantity: freezed == totalQuantity + ? _value.totalQuantity + : totalQuantity // ignore: cast_nullable_to_non_nullable + as int?, + productCount: freezed == productCount + ? _value.productCount + : productCount // ignore: cast_nullable_to_non_nullable + as int?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$CategoryAnalyticItemDtoImpl extends _CategoryAnalyticItemDto { + const _$CategoryAnalyticItemDtoImpl({ + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'category_name') this.categoryName, + @JsonKey(name: 'total_revenue') this.totalRevenue, + @JsonKey(name: 'total_quantity') this.totalQuantity, + @JsonKey(name: 'product_count') this.productCount, + @JsonKey(name: 'order_count') this.orderCount, + }) : super._(); + + factory _$CategoryAnalyticItemDtoImpl.fromJson(Map json) => + _$$CategoryAnalyticItemDtoImplFromJson(json); + + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'category_name') + final String? categoryName; + @override + @JsonKey(name: 'total_revenue') + final int? totalRevenue; + @override + @JsonKey(name: 'total_quantity') + final int? totalQuantity; + @override + @JsonKey(name: 'product_count') + final int? productCount; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + + @override + String toString() { + return 'CategoryAnalyticItemDto(categoryId: $categoryId, categoryName: $categoryName, totalRevenue: $totalRevenue, totalQuantity: $totalQuantity, productCount: $productCount, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryAnalyticItemDtoImpl && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.totalRevenue, totalRevenue) || + other.totalRevenue == totalRevenue) && + (identical(other.totalQuantity, totalQuantity) || + other.totalQuantity == totalQuantity) && + (identical(other.productCount, productCount) || + other.productCount == productCount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + categoryId, + categoryName, + totalRevenue, + totalQuantity, + productCount, + orderCount, + ); + + /// Create a copy of CategoryAnalyticItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryAnalyticItemDtoImplCopyWith<_$CategoryAnalyticItemDtoImpl> + get copyWith => + __$$CategoryAnalyticItemDtoImplCopyWithImpl< + _$CategoryAnalyticItemDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$CategoryAnalyticItemDtoImplToJson(this); + } +} + +abstract class _CategoryAnalyticItemDto extends CategoryAnalyticItemDto { + const factory _CategoryAnalyticItemDto({ + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'category_name') final String? categoryName, + @JsonKey(name: 'total_revenue') final int? totalRevenue, + @JsonKey(name: 'total_quantity') final int? totalQuantity, + @JsonKey(name: 'product_count') final int? productCount, + @JsonKey(name: 'order_count') final int? orderCount, + }) = _$CategoryAnalyticItemDtoImpl; + const _CategoryAnalyticItemDto._() : super._(); + + factory _CategoryAnalyticItemDto.fromJson(Map json) = + _$CategoryAnalyticItemDtoImpl.fromJson; + + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'category_name') + String? get categoryName; + @override + @JsonKey(name: 'total_revenue') + int? get totalRevenue; + @override + @JsonKey(name: 'total_quantity') + int? get totalQuantity; + @override + @JsonKey(name: 'product_count') + int? get productCount; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + + /// Create a copy of CategoryAnalyticItemDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryAnalyticItemDtoImplCopyWith<_$CategoryAnalyticItemDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +InventoryAnalyticDto _$InventoryAnalyticDtoFromJson(Map json) { + return _InventoryAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$InventoryAnalyticDto { + @JsonKey(name: "summary") + InventorySummaryDto? get summary => throw _privateConstructorUsedError; + @JsonKey(name: "products") + List? get products => throw _privateConstructorUsedError; + @JsonKey(name: "ingredients") + List? get ingredients => + throw _privateConstructorUsedError; + + /// Serializes this InventoryAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryAnalyticDtoCopyWith<$Res> { + factory $InventoryAnalyticDtoCopyWith( + InventoryAnalyticDto value, + $Res Function(InventoryAnalyticDto) then, + ) = _$InventoryAnalyticDtoCopyWithImpl<$Res, InventoryAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: "summary") InventorySummaryDto? summary, + @JsonKey(name: "products") List? products, + @JsonKey(name: "ingredients") List? ingredients, + }); + + $InventorySummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class _$InventoryAnalyticDtoCopyWithImpl< + $Res, + $Val extends InventoryAnalyticDto +> + implements $InventoryAnalyticDtoCopyWith<$Res> { + _$InventoryAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = freezed, + Object? products = freezed, + Object? ingredients = freezed, + }) { + return _then( + _value.copyWith( + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummaryDto?, + products: freezed == products + ? _value.products + : products // ignore: cast_nullable_to_non_nullable + as List?, + ingredients: freezed == ingredients + ? _value.ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $InventorySummaryDtoCopyWith<$Res>? get summary { + if (_value.summary == null) { + return null; + } + + return $InventorySummaryDtoCopyWith<$Res>(_value.summary!, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$InventoryAnalyticDtoImplCopyWith<$Res> + implements $InventoryAnalyticDtoCopyWith<$Res> { + factory _$$InventoryAnalyticDtoImplCopyWith( + _$InventoryAnalyticDtoImpl value, + $Res Function(_$InventoryAnalyticDtoImpl) then, + ) = __$$InventoryAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "summary") InventorySummaryDto? summary, + @JsonKey(name: "products") List? products, + @JsonKey(name: "ingredients") List? ingredients, + }); + + @override + $InventorySummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class __$$InventoryAnalyticDtoImplCopyWithImpl<$Res> + extends _$InventoryAnalyticDtoCopyWithImpl<$Res, _$InventoryAnalyticDtoImpl> + implements _$$InventoryAnalyticDtoImplCopyWith<$Res> { + __$$InventoryAnalyticDtoImplCopyWithImpl( + _$InventoryAnalyticDtoImpl _value, + $Res Function(_$InventoryAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? summary = freezed, + Object? products = freezed, + Object? ingredients = freezed, + }) { + return _then( + _$InventoryAnalyticDtoImpl( + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as InventorySummaryDto?, + products: freezed == products + ? _value._products + : products // ignore: cast_nullable_to_non_nullable + as List?, + ingredients: freezed == ingredients + ? _value._ingredients + : ingredients // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventoryAnalyticDtoImpl extends _InventoryAnalyticDto { + const _$InventoryAnalyticDtoImpl({ + @JsonKey(name: "summary") this.summary, + @JsonKey(name: "products") final List? products, + @JsonKey(name: "ingredients") + final List? ingredients, + }) : _products = products, + _ingredients = ingredients, + super._(); + + factory _$InventoryAnalyticDtoImpl.fromJson(Map json) => + _$$InventoryAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: "summary") + final InventorySummaryDto? summary; + final List? _products; + @override + @JsonKey(name: "products") + List? get products { + final value = _products; + if (value == null) return null; + if (_products is EqualUnmodifiableListView) return _products; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _ingredients; + @override + @JsonKey(name: "ingredients") + List? get ingredients { + final value = _ingredients; + if (value == null) return null; + if (_ingredients is EqualUnmodifiableListView) return _ingredients; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'InventoryAnalyticDto(summary: $summary, products: $products, ingredients: $ingredients)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryAnalyticDtoImpl && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._products, _products) && + const DeepCollectionEquality().equals( + other._ingredients, + _ingredients, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + summary, + const DeepCollectionEquality().hash(_products), + const DeepCollectionEquality().hash(_ingredients), + ); + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryAnalyticDtoImplCopyWith<_$InventoryAnalyticDtoImpl> + get copyWith => + __$$InventoryAnalyticDtoImplCopyWithImpl<_$InventoryAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventoryAnalyticDtoImplToJson(this); + } +} + +abstract class _InventoryAnalyticDto extends InventoryAnalyticDto { + const factory _InventoryAnalyticDto({ + @JsonKey(name: "summary") final InventorySummaryDto? summary, + @JsonKey(name: "products") final List? products, + @JsonKey(name: "ingredients") + final List? ingredients, + }) = _$InventoryAnalyticDtoImpl; + const _InventoryAnalyticDto._() : super._(); + + factory _InventoryAnalyticDto.fromJson(Map json) = + _$InventoryAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: "summary") + InventorySummaryDto? get summary; + @override + @JsonKey(name: "products") + List? get products; + @override + @JsonKey(name: "ingredients") + List? get ingredients; + + /// Create a copy of InventoryAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryAnalyticDtoImplCopyWith<_$InventoryAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +InventorySummaryDto _$InventorySummaryDtoFromJson(Map json) { + return _InventorySummaryDto.fromJson(json); +} + +/// @nodoc +mixin _$InventorySummaryDto { + @JsonKey(name: "total_products") + int? get totalProducts => throw _privateConstructorUsedError; + @JsonKey(name: "total_ingredients") + int? get totalIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "total_value") + int? get totalValue => throw _privateConstructorUsedError; + @JsonKey(name: "low_stock_products") + int? get lowStockProducts => throw _privateConstructorUsedError; + @JsonKey(name: "low_stock_ingredients") + int? get lowStockIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "zero_stock_products") + int? get zeroStockProducts => throw _privateConstructorUsedError; + @JsonKey(name: "zero_stock_ingredients") + int? get zeroStockIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "total_sold_products") + int? get totalSoldProducts => throw _privateConstructorUsedError; + @JsonKey(name: "total_sold_ingredients") + int? get totalSoldIngredients => throw _privateConstructorUsedError; + @JsonKey(name: "outlet_id") + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: "outlet_name") + String? get outletName => throw _privateConstructorUsedError; + @JsonKey(name: "generated_at") + String? get generatedAt => throw _privateConstructorUsedError; + + /// Serializes this InventorySummaryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventorySummaryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventorySummaryDtoCopyWith<$Res> { + factory $InventorySummaryDtoCopyWith( + InventorySummaryDto value, + $Res Function(InventorySummaryDto) then, + ) = _$InventorySummaryDtoCopyWithImpl<$Res, InventorySummaryDto>; + @useResult + $Res call({ + @JsonKey(name: "total_products") int? totalProducts, + @JsonKey(name: "total_ingredients") int? totalIngredients, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "low_stock_products") int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") int? totalSoldIngredients, + @JsonKey(name: "outlet_id") String? outletId, + @JsonKey(name: "outlet_name") String? outletName, + @JsonKey(name: "generated_at") String? generatedAt, + }); +} + +/// @nodoc +class _$InventorySummaryDtoCopyWithImpl<$Res, $Val extends InventorySummaryDto> + implements $InventorySummaryDtoCopyWith<$Res> { + _$InventorySummaryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = freezed, + Object? totalIngredients = freezed, + Object? totalValue = freezed, + Object? lowStockProducts = freezed, + Object? lowStockIngredients = freezed, + Object? zeroStockProducts = freezed, + Object? zeroStockIngredients = freezed, + Object? totalSoldProducts = freezed, + Object? totalSoldIngredients = freezed, + Object? outletId = freezed, + Object? outletName = freezed, + Object? generatedAt = freezed, + }) { + return _then( + _value.copyWith( + totalProducts: freezed == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalIngredients: freezed == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + lowStockProducts: freezed == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + lowStockIngredients: freezed == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockProducts: freezed == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockIngredients: freezed == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldProducts: freezed == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldIngredients: freezed == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + outletName: freezed == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String?, + generatedAt: freezed == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventorySummaryDtoImplCopyWith<$Res> + implements $InventorySummaryDtoCopyWith<$Res> { + factory _$$InventorySummaryDtoImplCopyWith( + _$InventorySummaryDtoImpl value, + $Res Function(_$InventorySummaryDtoImpl) then, + ) = __$$InventorySummaryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "total_products") int? totalProducts, + @JsonKey(name: "total_ingredients") int? totalIngredients, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "low_stock_products") int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") int? totalSoldIngredients, + @JsonKey(name: "outlet_id") String? outletId, + @JsonKey(name: "outlet_name") String? outletName, + @JsonKey(name: "generated_at") String? generatedAt, + }); +} + +/// @nodoc +class __$$InventorySummaryDtoImplCopyWithImpl<$Res> + extends _$InventorySummaryDtoCopyWithImpl<$Res, _$InventorySummaryDtoImpl> + implements _$$InventorySummaryDtoImplCopyWith<$Res> { + __$$InventorySummaryDtoImplCopyWithImpl( + _$InventorySummaryDtoImpl _value, + $Res Function(_$InventorySummaryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalProducts = freezed, + Object? totalIngredients = freezed, + Object? totalValue = freezed, + Object? lowStockProducts = freezed, + Object? lowStockIngredients = freezed, + Object? zeroStockProducts = freezed, + Object? zeroStockIngredients = freezed, + Object? totalSoldProducts = freezed, + Object? totalSoldIngredients = freezed, + Object? outletId = freezed, + Object? outletName = freezed, + Object? generatedAt = freezed, + }) { + return _then( + _$InventorySummaryDtoImpl( + totalProducts: freezed == totalProducts + ? _value.totalProducts + : totalProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalIngredients: freezed == totalIngredients + ? _value.totalIngredients + : totalIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + lowStockProducts: freezed == lowStockProducts + ? _value.lowStockProducts + : lowStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + lowStockIngredients: freezed == lowStockIngredients + ? _value.lowStockIngredients + : lowStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockProducts: freezed == zeroStockProducts + ? _value.zeroStockProducts + : zeroStockProducts // ignore: cast_nullable_to_non_nullable + as int?, + zeroStockIngredients: freezed == zeroStockIngredients + ? _value.zeroStockIngredients + : zeroStockIngredients // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldProducts: freezed == totalSoldProducts + ? _value.totalSoldProducts + : totalSoldProducts // ignore: cast_nullable_to_non_nullable + as int?, + totalSoldIngredients: freezed == totalSoldIngredients + ? _value.totalSoldIngredients + : totalSoldIngredients // ignore: cast_nullable_to_non_nullable + as int?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + outletName: freezed == outletName + ? _value.outletName + : outletName // ignore: cast_nullable_to_non_nullable + as String?, + generatedAt: freezed == generatedAt + ? _value.generatedAt + : generatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventorySummaryDtoImpl implements _InventorySummaryDto { + const _$InventorySummaryDtoImpl({ + @JsonKey(name: "total_products") this.totalProducts, + @JsonKey(name: "total_ingredients") this.totalIngredients, + @JsonKey(name: "total_value") this.totalValue, + @JsonKey(name: "low_stock_products") this.lowStockProducts, + @JsonKey(name: "low_stock_ingredients") this.lowStockIngredients, + @JsonKey(name: "zero_stock_products") this.zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") this.zeroStockIngredients, + @JsonKey(name: "total_sold_products") this.totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") this.totalSoldIngredients, + @JsonKey(name: "outlet_id") this.outletId, + @JsonKey(name: "outlet_name") this.outletName, + @JsonKey(name: "generated_at") this.generatedAt, + }); + + factory _$InventorySummaryDtoImpl.fromJson(Map json) => + _$$InventorySummaryDtoImplFromJson(json); + + @override + @JsonKey(name: "total_products") + final int? totalProducts; + @override + @JsonKey(name: "total_ingredients") + final int? totalIngredients; + @override + @JsonKey(name: "total_value") + final int? totalValue; + @override + @JsonKey(name: "low_stock_products") + final int? lowStockProducts; + @override + @JsonKey(name: "low_stock_ingredients") + final int? lowStockIngredients; + @override + @JsonKey(name: "zero_stock_products") + final int? zeroStockProducts; + @override + @JsonKey(name: "zero_stock_ingredients") + final int? zeroStockIngredients; + @override + @JsonKey(name: "total_sold_products") + final int? totalSoldProducts; + @override + @JsonKey(name: "total_sold_ingredients") + final int? totalSoldIngredients; + @override + @JsonKey(name: "outlet_id") + final String? outletId; + @override + @JsonKey(name: "outlet_name") + final String? outletName; + @override + @JsonKey(name: "generated_at") + final String? generatedAt; + + @override + String toString() { + return 'InventorySummaryDto(totalProducts: $totalProducts, totalIngredients: $totalIngredients, totalValue: $totalValue, lowStockProducts: $lowStockProducts, lowStockIngredients: $lowStockIngredients, zeroStockProducts: $zeroStockProducts, zeroStockIngredients: $zeroStockIngredients, totalSoldProducts: $totalSoldProducts, totalSoldIngredients: $totalSoldIngredients, outletId: $outletId, outletName: $outletName, generatedAt: $generatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventorySummaryDtoImpl && + (identical(other.totalProducts, totalProducts) || + other.totalProducts == totalProducts) && + (identical(other.totalIngredients, totalIngredients) || + other.totalIngredients == totalIngredients) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.lowStockProducts, lowStockProducts) || + other.lowStockProducts == lowStockProducts) && + (identical(other.lowStockIngredients, lowStockIngredients) || + other.lowStockIngredients == lowStockIngredients) && + (identical(other.zeroStockProducts, zeroStockProducts) || + other.zeroStockProducts == zeroStockProducts) && + (identical(other.zeroStockIngredients, zeroStockIngredients) || + other.zeroStockIngredients == zeroStockIngredients) && + (identical(other.totalSoldProducts, totalSoldProducts) || + other.totalSoldProducts == totalSoldProducts) && + (identical(other.totalSoldIngredients, totalSoldIngredients) || + other.totalSoldIngredients == totalSoldIngredients) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.outletName, outletName) || + other.outletName == outletName) && + (identical(other.generatedAt, generatedAt) || + other.generatedAt == generatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalProducts, + totalIngredients, + totalValue, + lowStockProducts, + lowStockIngredients, + zeroStockProducts, + zeroStockIngredients, + totalSoldProducts, + totalSoldIngredients, + outletId, + outletName, + generatedAt, + ); + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventorySummaryDtoImplCopyWith<_$InventorySummaryDtoImpl> get copyWith => + __$$InventorySummaryDtoImplCopyWithImpl<_$InventorySummaryDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventorySummaryDtoImplToJson(this); + } +} + +abstract class _InventorySummaryDto implements InventorySummaryDto { + const factory _InventorySummaryDto({ + @JsonKey(name: "total_products") final int? totalProducts, + @JsonKey(name: "total_ingredients") final int? totalIngredients, + @JsonKey(name: "total_value") final int? totalValue, + @JsonKey(name: "low_stock_products") final int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") final int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") final int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") final int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") final int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") final int? totalSoldIngredients, + @JsonKey(name: "outlet_id") final String? outletId, + @JsonKey(name: "outlet_name") final String? outletName, + @JsonKey(name: "generated_at") final String? generatedAt, + }) = _$InventorySummaryDtoImpl; + + factory _InventorySummaryDto.fromJson(Map json) = + _$InventorySummaryDtoImpl.fromJson; + + @override + @JsonKey(name: "total_products") + int? get totalProducts; + @override + @JsonKey(name: "total_ingredients") + int? get totalIngredients; + @override + @JsonKey(name: "total_value") + int? get totalValue; + @override + @JsonKey(name: "low_stock_products") + int? get lowStockProducts; + @override + @JsonKey(name: "low_stock_ingredients") + int? get lowStockIngredients; + @override + @JsonKey(name: "zero_stock_products") + int? get zeroStockProducts; + @override + @JsonKey(name: "zero_stock_ingredients") + int? get zeroStockIngredients; + @override + @JsonKey(name: "total_sold_products") + int? get totalSoldProducts; + @override + @JsonKey(name: "total_sold_ingredients") + int? get totalSoldIngredients; + @override + @JsonKey(name: "outlet_id") + String? get outletId; + @override + @JsonKey(name: "outlet_name") + String? get outletName; + @override + @JsonKey(name: "generated_at") + String? get generatedAt; + + /// Create a copy of InventorySummaryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventorySummaryDtoImplCopyWith<_$InventorySummaryDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +InventoryProductDto _$InventoryProductDtoFromJson(Map json) { + return _InventoryProductDto.fromJson(json); +} + +/// @nodoc +mixin _$InventoryProductDto { + @JsonKey(name: "id") + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: "product_id") + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: "product_name") + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: "category_name") + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: "quantity") + int? get quantity => throw _privateConstructorUsedError; + @JsonKey(name: "reorder_level") + int? get reorderLevel => throw _privateConstructorUsedError; + @JsonKey(name: "unit_cost") + int? get unitCost => throw _privateConstructorUsedError; + @JsonKey(name: "total_value") + int? get totalValue => throw _privateConstructorUsedError; + @JsonKey(name: "total_in") + int? get totalIn => throw _privateConstructorUsedError; + @JsonKey(name: "total_out") + int? get totalOut => throw _privateConstructorUsedError; + @JsonKey(name: "is_low_stock") + bool? get isLowStock => throw _privateConstructorUsedError; + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock => throw _privateConstructorUsedError; + @JsonKey(name: "updated_at") + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this InventoryProductDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryProductDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryProductDtoCopyWith<$Res> { + factory $InventoryProductDtoCopyWith( + InventoryProductDto value, + $Res Function(InventoryProductDto) then, + ) = _$InventoryProductDtoCopyWithImpl<$Res, InventoryProductDto>; + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "product_id") String? productId, + @JsonKey(name: "product_name") String? productName, + @JsonKey(name: "category_name") String? categoryName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class _$InventoryProductDtoCopyWithImpl<$Res, $Val extends InventoryProductDto> + implements $InventoryProductDtoCopyWith<$Res> { + _$InventoryProductDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? productId = freezed, + Object? productName = freezed, + Object? categoryName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryProductDtoImplCopyWith<$Res> + implements $InventoryProductDtoCopyWith<$Res> { + factory _$$InventoryProductDtoImplCopyWith( + _$InventoryProductDtoImpl value, + $Res Function(_$InventoryProductDtoImpl) then, + ) = __$$InventoryProductDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "product_id") String? productId, + @JsonKey(name: "product_name") String? productName, + @JsonKey(name: "category_name") String? categoryName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class __$$InventoryProductDtoImplCopyWithImpl<$Res> + extends _$InventoryProductDtoCopyWithImpl<$Res, _$InventoryProductDtoImpl> + implements _$$InventoryProductDtoImplCopyWith<$Res> { + __$$InventoryProductDtoImplCopyWithImpl( + _$InventoryProductDtoImpl _value, + $Res Function(_$InventoryProductDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? productId = freezed, + Object? productName = freezed, + Object? categoryName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$InventoryProductDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventoryProductDtoImpl implements _InventoryProductDto { + const _$InventoryProductDtoImpl({ + @JsonKey(name: "id") this.id, + @JsonKey(name: "product_id") this.productId, + @JsonKey(name: "product_name") this.productName, + @JsonKey(name: "category_name") this.categoryName, + @JsonKey(name: "quantity") this.quantity, + @JsonKey(name: "reorder_level") this.reorderLevel, + @JsonKey(name: "unit_cost") this.unitCost, + @JsonKey(name: "total_value") this.totalValue, + @JsonKey(name: "total_in") this.totalIn, + @JsonKey(name: "total_out") this.totalOut, + @JsonKey(name: "is_low_stock") this.isLowStock, + @JsonKey(name: "is_zero_stock") this.isZeroStock, + @JsonKey(name: "updated_at") this.updatedAt, + }); + + factory _$InventoryProductDtoImpl.fromJson(Map json) => + _$$InventoryProductDtoImplFromJson(json); + + @override + @JsonKey(name: "id") + final String? id; + @override + @JsonKey(name: "product_id") + final String? productId; + @override + @JsonKey(name: "product_name") + final String? productName; + @override + @JsonKey(name: "category_name") + final String? categoryName; + @override + @JsonKey(name: "quantity") + final int? quantity; + @override + @JsonKey(name: "reorder_level") + final int? reorderLevel; + @override + @JsonKey(name: "unit_cost") + final int? unitCost; + @override + @JsonKey(name: "total_value") + final int? totalValue; + @override + @JsonKey(name: "total_in") + final int? totalIn; + @override + @JsonKey(name: "total_out") + final int? totalOut; + @override + @JsonKey(name: "is_low_stock") + final bool? isLowStock; + @override + @JsonKey(name: "is_zero_stock") + final bool? isZeroStock; + @override + @JsonKey(name: "updated_at") + final String? updatedAt; + + @override + String toString() { + return 'InventoryProductDto(id: $id, productId: $productId, productName: $productName, categoryName: $categoryName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryProductDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + productId, + productName, + categoryName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryProductDtoImplCopyWith<_$InventoryProductDtoImpl> get copyWith => + __$$InventoryProductDtoImplCopyWithImpl<_$InventoryProductDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventoryProductDtoImplToJson(this); + } +} + +abstract class _InventoryProductDto implements InventoryProductDto { + const factory _InventoryProductDto({ + @JsonKey(name: "id") final String? id, + @JsonKey(name: "product_id") final String? productId, + @JsonKey(name: "product_name") final String? productName, + @JsonKey(name: "category_name") final String? categoryName, + @JsonKey(name: "quantity") final int? quantity, + @JsonKey(name: "reorder_level") final int? reorderLevel, + @JsonKey(name: "unit_cost") final int? unitCost, + @JsonKey(name: "total_value") final int? totalValue, + @JsonKey(name: "total_in") final int? totalIn, + @JsonKey(name: "total_out") final int? totalOut, + @JsonKey(name: "is_low_stock") final bool? isLowStock, + @JsonKey(name: "is_zero_stock") final bool? isZeroStock, + @JsonKey(name: "updated_at") final String? updatedAt, + }) = _$InventoryProductDtoImpl; + + factory _InventoryProductDto.fromJson(Map json) = + _$InventoryProductDtoImpl.fromJson; + + @override + @JsonKey(name: "id") + String? get id; + @override + @JsonKey(name: "product_id") + String? get productId; + @override + @JsonKey(name: "product_name") + String? get productName; + @override + @JsonKey(name: "category_name") + String? get categoryName; + @override + @JsonKey(name: "quantity") + int? get quantity; + @override + @JsonKey(name: "reorder_level") + int? get reorderLevel; + @override + @JsonKey(name: "unit_cost") + int? get unitCost; + @override + @JsonKey(name: "total_value") + int? get totalValue; + @override + @JsonKey(name: "total_in") + int? get totalIn; + @override + @JsonKey(name: "total_out") + int? get totalOut; + @override + @JsonKey(name: "is_low_stock") + bool? get isLowStock; + @override + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock; + @override + @JsonKey(name: "updated_at") + String? get updatedAt; + + /// Create a copy of InventoryProductDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryProductDtoImplCopyWith<_$InventoryProductDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +InventoryIngredientDto _$InventoryIngredientDtoFromJson( + Map json, +) { + return _InventoryIngredientDto.fromJson(json); +} + +/// @nodoc +mixin _$InventoryIngredientDto { + @JsonKey(name: "id") + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: "ingredient_id") + String? get ingredientId => throw _privateConstructorUsedError; + @JsonKey(name: "ingredient_name") + String? get ingredientName => throw _privateConstructorUsedError; + @JsonKey(name: "unit_name") + String? get unitName => throw _privateConstructorUsedError; + @JsonKey(name: "quantity") + int? get quantity => throw _privateConstructorUsedError; + @JsonKey(name: "reorder_level") + int? get reorderLevel => throw _privateConstructorUsedError; + @JsonKey(name: "unit_cost") + int? get unitCost => throw _privateConstructorUsedError; + @JsonKey(name: "total_value") + int? get totalValue => throw _privateConstructorUsedError; + @JsonKey(name: "total_in") + int? get totalIn => throw _privateConstructorUsedError; + @JsonKey(name: "total_out") + int? get totalOut => throw _privateConstructorUsedError; + @JsonKey(name: "is_low_stock") + bool? get isLowStock => throw _privateConstructorUsedError; + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock => throw _privateConstructorUsedError; + @JsonKey(name: "updated_at") + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this InventoryIngredientDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InventoryIngredientDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InventoryIngredientDtoCopyWith<$Res> { + factory $InventoryIngredientDtoCopyWith( + InventoryIngredientDto value, + $Res Function(InventoryIngredientDto) then, + ) = _$InventoryIngredientDtoCopyWithImpl<$Res, InventoryIngredientDto>; + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "ingredient_id") String? ingredientId, + @JsonKey(name: "ingredient_name") String? ingredientName, + @JsonKey(name: "unit_name") String? unitName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class _$InventoryIngredientDtoCopyWithImpl< + $Res, + $Val extends InventoryIngredientDto +> + implements $InventoryIngredientDtoCopyWith<$Res> { + _$InventoryIngredientDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? ingredientId = freezed, + Object? ingredientName = freezed, + Object? unitName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + ingredientId: freezed == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String?, + ingredientName: freezed == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String?, + unitName: freezed == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$InventoryIngredientDtoImplCopyWith<$Res> + implements $InventoryIngredientDtoCopyWith<$Res> { + factory _$$InventoryIngredientDtoImplCopyWith( + _$InventoryIngredientDtoImpl value, + $Res Function(_$InventoryIngredientDtoImpl) then, + ) = __$$InventoryIngredientDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "ingredient_id") String? ingredientId, + @JsonKey(name: "ingredient_name") String? ingredientName, + @JsonKey(name: "unit_name") String? unitName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class __$$InventoryIngredientDtoImplCopyWithImpl<$Res> + extends + _$InventoryIngredientDtoCopyWithImpl<$Res, _$InventoryIngredientDtoImpl> + implements _$$InventoryIngredientDtoImplCopyWith<$Res> { + __$$InventoryIngredientDtoImplCopyWithImpl( + _$InventoryIngredientDtoImpl _value, + $Res Function(_$InventoryIngredientDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? ingredientId = freezed, + Object? ingredientName = freezed, + Object? unitName = freezed, + Object? quantity = freezed, + Object? reorderLevel = freezed, + Object? unitCost = freezed, + Object? totalValue = freezed, + Object? totalIn = freezed, + Object? totalOut = freezed, + Object? isLowStock = freezed, + Object? isZeroStock = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$InventoryIngredientDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + ingredientId: freezed == ingredientId + ? _value.ingredientId + : ingredientId // ignore: cast_nullable_to_non_nullable + as String?, + ingredientName: freezed == ingredientName + ? _value.ingredientName + : ingredientName // ignore: cast_nullable_to_non_nullable + as String?, + unitName: freezed == unitName + ? _value.unitName + : unitName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + reorderLevel: freezed == reorderLevel + ? _value.reorderLevel + : reorderLevel // ignore: cast_nullable_to_non_nullable + as int?, + unitCost: freezed == unitCost + ? _value.unitCost + : unitCost // ignore: cast_nullable_to_non_nullable + as int?, + totalValue: freezed == totalValue + ? _value.totalValue + : totalValue // ignore: cast_nullable_to_non_nullable + as int?, + totalIn: freezed == totalIn + ? _value.totalIn + : totalIn // ignore: cast_nullable_to_non_nullable + as int?, + totalOut: freezed == totalOut + ? _value.totalOut + : totalOut // ignore: cast_nullable_to_non_nullable + as int?, + isLowStock: freezed == isLowStock + ? _value.isLowStock + : isLowStock // ignore: cast_nullable_to_non_nullable + as bool?, + isZeroStock: freezed == isZeroStock + ? _value.isZeroStock + : isZeroStock // ignore: cast_nullable_to_non_nullable + as bool?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$InventoryIngredientDtoImpl implements _InventoryIngredientDto { + const _$InventoryIngredientDtoImpl({ + @JsonKey(name: "id") this.id, + @JsonKey(name: "ingredient_id") this.ingredientId, + @JsonKey(name: "ingredient_name") this.ingredientName, + @JsonKey(name: "unit_name") this.unitName, + @JsonKey(name: "quantity") this.quantity, + @JsonKey(name: "reorder_level") this.reorderLevel, + @JsonKey(name: "unit_cost") this.unitCost, + @JsonKey(name: "total_value") this.totalValue, + @JsonKey(name: "total_in") this.totalIn, + @JsonKey(name: "total_out") this.totalOut, + @JsonKey(name: "is_low_stock") this.isLowStock, + @JsonKey(name: "is_zero_stock") this.isZeroStock, + @JsonKey(name: "updated_at") this.updatedAt, + }); + + factory _$InventoryIngredientDtoImpl.fromJson(Map json) => + _$$InventoryIngredientDtoImplFromJson(json); + + @override + @JsonKey(name: "id") + final String? id; + @override + @JsonKey(name: "ingredient_id") + final String? ingredientId; + @override + @JsonKey(name: "ingredient_name") + final String? ingredientName; + @override + @JsonKey(name: "unit_name") + final String? unitName; + @override + @JsonKey(name: "quantity") + final int? quantity; + @override + @JsonKey(name: "reorder_level") + final int? reorderLevel; + @override + @JsonKey(name: "unit_cost") + final int? unitCost; + @override + @JsonKey(name: "total_value") + final int? totalValue; + @override + @JsonKey(name: "total_in") + final int? totalIn; + @override + @JsonKey(name: "total_out") + final int? totalOut; + @override + @JsonKey(name: "is_low_stock") + final bool? isLowStock; + @override + @JsonKey(name: "is_zero_stock") + final bool? isZeroStock; + @override + @JsonKey(name: "updated_at") + final String? updatedAt; + + @override + String toString() { + return 'InventoryIngredientDto(id: $id, ingredientId: $ingredientId, ingredientName: $ingredientName, unitName: $unitName, quantity: $quantity, reorderLevel: $reorderLevel, unitCost: $unitCost, totalValue: $totalValue, totalIn: $totalIn, totalOut: $totalOut, isLowStock: $isLowStock, isZeroStock: $isZeroStock, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$InventoryIngredientDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.ingredientId, ingredientId) || + other.ingredientId == ingredientId) && + (identical(other.ingredientName, ingredientName) || + other.ingredientName == ingredientName) && + (identical(other.unitName, unitName) || + other.unitName == unitName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.reorderLevel, reorderLevel) || + other.reorderLevel == reorderLevel) && + (identical(other.unitCost, unitCost) || + other.unitCost == unitCost) && + (identical(other.totalValue, totalValue) || + other.totalValue == totalValue) && + (identical(other.totalIn, totalIn) || other.totalIn == totalIn) && + (identical(other.totalOut, totalOut) || + other.totalOut == totalOut) && + (identical(other.isLowStock, isLowStock) || + other.isLowStock == isLowStock) && + (identical(other.isZeroStock, isZeroStock) || + other.isZeroStock == isZeroStock) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + ingredientId, + ingredientName, + unitName, + quantity, + reorderLevel, + unitCost, + totalValue, + totalIn, + totalOut, + isLowStock, + isZeroStock, + updatedAt, + ); + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$InventoryIngredientDtoImplCopyWith<_$InventoryIngredientDtoImpl> + get copyWith => + __$$InventoryIngredientDtoImplCopyWithImpl<_$InventoryIngredientDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$InventoryIngredientDtoImplToJson(this); + } +} + +abstract class _InventoryIngredientDto implements InventoryIngredientDto { + const factory _InventoryIngredientDto({ + @JsonKey(name: "id") final String? id, + @JsonKey(name: "ingredient_id") final String? ingredientId, + @JsonKey(name: "ingredient_name") final String? ingredientName, + @JsonKey(name: "unit_name") final String? unitName, + @JsonKey(name: "quantity") final int? quantity, + @JsonKey(name: "reorder_level") final int? reorderLevel, + @JsonKey(name: "unit_cost") final int? unitCost, + @JsonKey(name: "total_value") final int? totalValue, + @JsonKey(name: "total_in") final int? totalIn, + @JsonKey(name: "total_out") final int? totalOut, + @JsonKey(name: "is_low_stock") final bool? isLowStock, + @JsonKey(name: "is_zero_stock") final bool? isZeroStock, + @JsonKey(name: "updated_at") final String? updatedAt, + }) = _$InventoryIngredientDtoImpl; + + factory _InventoryIngredientDto.fromJson(Map json) = + _$InventoryIngredientDtoImpl.fromJson; + + @override + @JsonKey(name: "id") + String? get id; + @override + @JsonKey(name: "ingredient_id") + String? get ingredientId; + @override + @JsonKey(name: "ingredient_name") + String? get ingredientName; + @override + @JsonKey(name: "unit_name") + String? get unitName; + @override + @JsonKey(name: "quantity") + int? get quantity; + @override + @JsonKey(name: "reorder_level") + int? get reorderLevel; + @override + @JsonKey(name: "unit_cost") + int? get unitCost; + @override + @JsonKey(name: "total_value") + int? get totalValue; + @override + @JsonKey(name: "total_in") + int? get totalIn; + @override + @JsonKey(name: "total_out") + int? get totalOut; + @override + @JsonKey(name: "is_low_stock") + bool? get isLowStock; + @override + @JsonKey(name: "is_zero_stock") + bool? get isZeroStock; + @override + @JsonKey(name: "updated_at") + String? get updatedAt; + + /// Create a copy of InventoryIngredientDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$InventoryIngredientDtoImplCopyWith<_$InventoryIngredientDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardAnalyticDto _$DashboardAnalyticDtoFromJson(Map json) { + return _DashboardAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'overview') + DashboardOverviewDto? get overview => throw _privateConstructorUsedError; + @JsonKey(name: 'top_products') + List? get topProducts => + throw _privateConstructorUsedError; + @JsonKey(name: 'payment_methods') + List? get paymentMethods => + throw _privateConstructorUsedError; + @JsonKey(name: 'recent_sales') + List? get recentSales => + throw _privateConstructorUsedError; + + /// Serializes this DashboardAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardAnalyticDtoCopyWith<$Res> { + factory $DashboardAnalyticDtoCopyWith( + DashboardAnalyticDto value, + $Res Function(DashboardAnalyticDto) then, + ) = _$DashboardAnalyticDtoCopyWithImpl<$Res, DashboardAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'overview') DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') List? topProducts, + @JsonKey(name: 'payment_methods') + List? paymentMethods, + @JsonKey(name: 'recent_sales') List? recentSales, + }); + + $DashboardOverviewDtoCopyWith<$Res>? get overview; +} + +/// @nodoc +class _$DashboardAnalyticDtoCopyWithImpl< + $Res, + $Val extends DashboardAnalyticDto +> + implements $DashboardAnalyticDtoCopyWith<$Res> { + _$DashboardAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? overview = freezed, + Object? topProducts = freezed, + Object? paymentMethods = freezed, + Object? recentSales = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + overview: freezed == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverviewDto?, + topProducts: freezed == topProducts + ? _value.topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List?, + paymentMethods: freezed == paymentMethods + ? _value.paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List?, + recentSales: freezed == recentSales + ? _value.recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $DashboardOverviewDtoCopyWith<$Res>? get overview { + if (_value.overview == null) { + return null; + } + + return $DashboardOverviewDtoCopyWith<$Res>(_value.overview!, (value) { + return _then(_value.copyWith(overview: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$DashboardAnalyticDtoImplCopyWith<$Res> + implements $DashboardAnalyticDtoCopyWith<$Res> { + factory _$$DashboardAnalyticDtoImplCopyWith( + _$DashboardAnalyticDtoImpl value, + $Res Function(_$DashboardAnalyticDtoImpl) then, + ) = __$$DashboardAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'overview') DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') List? topProducts, + @JsonKey(name: 'payment_methods') + List? paymentMethods, + @JsonKey(name: 'recent_sales') List? recentSales, + }); + + @override + $DashboardOverviewDtoCopyWith<$Res>? get overview; +} + +/// @nodoc +class __$$DashboardAnalyticDtoImplCopyWithImpl<$Res> + extends _$DashboardAnalyticDtoCopyWithImpl<$Res, _$DashboardAnalyticDtoImpl> + implements _$$DashboardAnalyticDtoImplCopyWith<$Res> { + __$$DashboardAnalyticDtoImplCopyWithImpl( + _$DashboardAnalyticDtoImpl _value, + $Res Function(_$DashboardAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? overview = freezed, + Object? topProducts = freezed, + Object? paymentMethods = freezed, + Object? recentSales = freezed, + }) { + return _then( + _$DashboardAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + overview: freezed == overview + ? _value.overview + : overview // ignore: cast_nullable_to_non_nullable + as DashboardOverviewDto?, + topProducts: freezed == topProducts + ? _value._topProducts + : topProducts // ignore: cast_nullable_to_non_nullable + as List?, + paymentMethods: freezed == paymentMethods + ? _value._paymentMethods + : paymentMethods // ignore: cast_nullable_to_non_nullable + as List?, + recentSales: freezed == recentSales + ? _value._recentSales + : recentSales // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardAnalyticDtoImpl extends _DashboardAnalyticDto { + const _$DashboardAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'overview') this.overview, + @JsonKey(name: 'top_products') + final List? topProducts, + @JsonKey(name: 'payment_methods') + final List? paymentMethods, + @JsonKey(name: 'recent_sales') + final List? recentSales, + }) : _topProducts = topProducts, + _paymentMethods = paymentMethods, + _recentSales = recentSales, + super._(); + + factory _$DashboardAnalyticDtoImpl.fromJson(Map json) => + _$$DashboardAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + @override + @JsonKey(name: 'overview') + final DashboardOverviewDto? overview; + final List? _topProducts; + @override + @JsonKey(name: 'top_products') + List? get topProducts { + final value = _topProducts; + if (value == null) return null; + if (_topProducts is EqualUnmodifiableListView) return _topProducts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _paymentMethods; + @override + @JsonKey(name: 'payment_methods') + List? get paymentMethods { + final value = _paymentMethods; + if (value == null) return null; + if (_paymentMethods is EqualUnmodifiableListView) return _paymentMethods; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _recentSales; + @override + @JsonKey(name: 'recent_sales') + List? get recentSales { + final value = _recentSales; + if (value == null) return null; + if (_recentSales is EqualUnmodifiableListView) return _recentSales; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'DashboardAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, overview: $overview, topProducts: $topProducts, paymentMethods: $paymentMethods, recentSales: $recentSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.overview, overview) || + other.overview == overview) && + const DeepCollectionEquality().equals( + other._topProducts, + _topProducts, + ) && + const DeepCollectionEquality().equals( + other._paymentMethods, + _paymentMethods, + ) && + const DeepCollectionEquality().equals( + other._recentSales, + _recentSales, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + overview, + const DeepCollectionEquality().hash(_topProducts), + const DeepCollectionEquality().hash(_paymentMethods), + const DeepCollectionEquality().hash(_recentSales), + ); + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardAnalyticDtoImplCopyWith<_$DashboardAnalyticDtoImpl> + get copyWith => + __$$DashboardAnalyticDtoImplCopyWithImpl<_$DashboardAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardAnalyticDtoImplToJson(this); + } +} + +abstract class _DashboardAnalyticDto extends DashboardAnalyticDto { + const factory _DashboardAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'overview') final DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') + final List? topProducts, + @JsonKey(name: 'payment_methods') + final List? paymentMethods, + @JsonKey(name: 'recent_sales') + final List? recentSales, + }) = _$DashboardAnalyticDtoImpl; + const _DashboardAnalyticDto._() : super._(); + + factory _DashboardAnalyticDto.fromJson(Map json) = + _$DashboardAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'overview') + DashboardOverviewDto? get overview; + @override + @JsonKey(name: 'top_products') + List? get topProducts; + @override + @JsonKey(name: 'payment_methods') + List? get paymentMethods; + @override + @JsonKey(name: 'recent_sales') + List? get recentSales; + + /// Create a copy of DashboardAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardAnalyticDtoImplCopyWith<_$DashboardAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardOverviewDto _$DashboardOverviewDtoFromJson(Map json) { + return _DashboardOverviewDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardOverviewDto { + @JsonKey(name: 'total_sales') + int? get totalSales => throw _privateConstructorUsedError; + @JsonKey(name: 'total_orders') + int? get totalOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'average_order_value') + double? get averageOrderValue => throw _privateConstructorUsedError; + @JsonKey(name: 'total_customers') + int? get totalCustomers => throw _privateConstructorUsedError; + @JsonKey(name: 'voided_orders') + int? get voidedOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'refunded_orders') + int? get refundedOrders => throw _privateConstructorUsedError; + + /// Serializes this DashboardOverviewDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardOverviewDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardOverviewDtoCopyWith<$Res> { + factory $DashboardOverviewDtoCopyWith( + DashboardOverviewDto value, + $Res Function(DashboardOverviewDto) then, + ) = _$DashboardOverviewDtoCopyWithImpl<$Res, DashboardOverviewDto>; + @useResult + $Res call({ + @JsonKey(name: 'total_sales') int? totalSales, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + @JsonKey(name: 'total_customers') int? totalCustomers, + @JsonKey(name: 'voided_orders') int? voidedOrders, + @JsonKey(name: 'refunded_orders') int? refundedOrders, + }); +} + +/// @nodoc +class _$DashboardOverviewDtoCopyWithImpl< + $Res, + $Val extends DashboardOverviewDto +> + implements $DashboardOverviewDtoCopyWith<$Res> { + _$DashboardOverviewDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = freezed, + Object? totalOrders = freezed, + Object? averageOrderValue = freezed, + Object? totalCustomers = freezed, + Object? voidedOrders = freezed, + Object? refundedOrders = freezed, + }) { + return _then( + _value.copyWith( + totalSales: freezed == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double?, + totalCustomers: freezed == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int?, + voidedOrders: freezed == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int?, + refundedOrders: freezed == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardOverviewDtoImplCopyWith<$Res> + implements $DashboardOverviewDtoCopyWith<$Res> { + factory _$$DashboardOverviewDtoImplCopyWith( + _$DashboardOverviewDtoImpl value, + $Res Function(_$DashboardOverviewDtoImpl) then, + ) = __$$DashboardOverviewDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'total_sales') int? totalSales, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + @JsonKey(name: 'total_customers') int? totalCustomers, + @JsonKey(name: 'voided_orders') int? voidedOrders, + @JsonKey(name: 'refunded_orders') int? refundedOrders, + }); +} + +/// @nodoc +class __$$DashboardOverviewDtoImplCopyWithImpl<$Res> + extends _$DashboardOverviewDtoCopyWithImpl<$Res, _$DashboardOverviewDtoImpl> + implements _$$DashboardOverviewDtoImplCopyWith<$Res> { + __$$DashboardOverviewDtoImplCopyWithImpl( + _$DashboardOverviewDtoImpl _value, + $Res Function(_$DashboardOverviewDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalSales = freezed, + Object? totalOrders = freezed, + Object? averageOrderValue = freezed, + Object? totalCustomers = freezed, + Object? voidedOrders = freezed, + Object? refundedOrders = freezed, + }) { + return _then( + _$DashboardOverviewDtoImpl( + totalSales: freezed == totalSales + ? _value.totalSales + : totalSales // ignore: cast_nullable_to_non_nullable + as int?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double?, + totalCustomers: freezed == totalCustomers + ? _value.totalCustomers + : totalCustomers // ignore: cast_nullable_to_non_nullable + as int?, + voidedOrders: freezed == voidedOrders + ? _value.voidedOrders + : voidedOrders // ignore: cast_nullable_to_non_nullable + as int?, + refundedOrders: freezed == refundedOrders + ? _value.refundedOrders + : refundedOrders // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardOverviewDtoImpl extends _DashboardOverviewDto { + const _$DashboardOverviewDtoImpl({ + @JsonKey(name: 'total_sales') this.totalSales, + @JsonKey(name: 'total_orders') this.totalOrders, + @JsonKey(name: 'average_order_value') this.averageOrderValue, + @JsonKey(name: 'total_customers') this.totalCustomers, + @JsonKey(name: 'voided_orders') this.voidedOrders, + @JsonKey(name: 'refunded_orders') this.refundedOrders, + }) : super._(); + + factory _$DashboardOverviewDtoImpl.fromJson(Map json) => + _$$DashboardOverviewDtoImplFromJson(json); + + @override + @JsonKey(name: 'total_sales') + final int? totalSales; + @override + @JsonKey(name: 'total_orders') + final int? totalOrders; + @override + @JsonKey(name: 'average_order_value') + final double? averageOrderValue; + @override + @JsonKey(name: 'total_customers') + final int? totalCustomers; + @override + @JsonKey(name: 'voided_orders') + final int? voidedOrders; + @override + @JsonKey(name: 'refunded_orders') + final int? refundedOrders; + + @override + String toString() { + return 'DashboardOverviewDto(totalSales: $totalSales, totalOrders: $totalOrders, averageOrderValue: $averageOrderValue, totalCustomers: $totalCustomers, voidedOrders: $voidedOrders, refundedOrders: $refundedOrders)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardOverviewDtoImpl && + (identical(other.totalSales, totalSales) || + other.totalSales == totalSales) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue) && + (identical(other.totalCustomers, totalCustomers) || + other.totalCustomers == totalCustomers) && + (identical(other.voidedOrders, voidedOrders) || + other.voidedOrders == voidedOrders) && + (identical(other.refundedOrders, refundedOrders) || + other.refundedOrders == refundedOrders)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalSales, + totalOrders, + averageOrderValue, + totalCustomers, + voidedOrders, + refundedOrders, + ); + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardOverviewDtoImplCopyWith<_$DashboardOverviewDtoImpl> + get copyWith => + __$$DashboardOverviewDtoImplCopyWithImpl<_$DashboardOverviewDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardOverviewDtoImplToJson(this); + } +} + +abstract class _DashboardOverviewDto extends DashboardOverviewDto { + const factory _DashboardOverviewDto({ + @JsonKey(name: 'total_sales') final int? totalSales, + @JsonKey(name: 'total_orders') final int? totalOrders, + @JsonKey(name: 'average_order_value') final double? averageOrderValue, + @JsonKey(name: 'total_customers') final int? totalCustomers, + @JsonKey(name: 'voided_orders') final int? voidedOrders, + @JsonKey(name: 'refunded_orders') final int? refundedOrders, + }) = _$DashboardOverviewDtoImpl; + const _DashboardOverviewDto._() : super._(); + + factory _DashboardOverviewDto.fromJson(Map json) = + _$DashboardOverviewDtoImpl.fromJson; + + @override + @JsonKey(name: 'total_sales') + int? get totalSales; + @override + @JsonKey(name: 'total_orders') + int? get totalOrders; + @override + @JsonKey(name: 'average_order_value') + double? get averageOrderValue; + @override + @JsonKey(name: 'total_customers') + int? get totalCustomers; + @override + @JsonKey(name: 'voided_orders') + int? get voidedOrders; + @override + @JsonKey(name: 'refunded_orders') + int? get refundedOrders; + + /// Create a copy of DashboardOverviewDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardOverviewDtoImplCopyWith<_$DashboardOverviewDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardTopProductDto _$DashboardTopProductDtoFromJson( + Map json, +) { + return _DashboardTopProductDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardTopProductDto { + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_name') + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_name') + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: 'quantity_sold') + int? get quantitySold => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'average_price') + double? get averagePrice => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + + /// Serializes this DashboardTopProductDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardTopProductDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardTopProductDtoCopyWith<$Res> { + factory $DashboardTopProductDtoCopyWith( + DashboardTopProductDto value, + $Res Function(DashboardTopProductDto) then, + ) = _$DashboardTopProductDtoCopyWithImpl<$Res, DashboardTopProductDto>; + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class _$DashboardTopProductDtoCopyWithImpl< + $Res, + $Val extends DashboardTopProductDto +> + implements $DashboardTopProductDtoCopyWith<$Res> { + _$DashboardTopProductDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? averagePrice = freezed, + Object? orderCount = freezed, + }) { + return _then( + _value.copyWith( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardTopProductDtoImplCopyWith<$Res> + implements $DashboardTopProductDtoCopyWith<$Res> { + factory _$$DashboardTopProductDtoImplCopyWith( + _$DashboardTopProductDtoImpl value, + $Res Function(_$DashboardTopProductDtoImpl) then, + ) = __$$DashboardTopProductDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class __$$DashboardTopProductDtoImplCopyWithImpl<$Res> + extends + _$DashboardTopProductDtoCopyWithImpl<$Res, _$DashboardTopProductDtoImpl> + implements _$$DashboardTopProductDtoImplCopyWith<$Res> { + __$$DashboardTopProductDtoImplCopyWithImpl( + _$DashboardTopProductDtoImpl _value, + $Res Function(_$DashboardTopProductDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? averagePrice = freezed, + Object? orderCount = freezed, + }) { + return _then( + _$DashboardTopProductDtoImpl( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardTopProductDtoImpl extends _DashboardTopProductDto { + const _$DashboardTopProductDtoImpl({ + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'product_name') this.productName, + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'category_name') this.categoryName, + @JsonKey(name: 'quantity_sold') this.quantitySold, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'average_price') this.averagePrice, + @JsonKey(name: 'order_count') this.orderCount, + }) : super._(); + + factory _$DashboardTopProductDtoImpl.fromJson(Map json) => + _$$DashboardTopProductDtoImplFromJson(json); + + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'product_name') + final String? productName; + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'category_name') + final String? categoryName; + @override + @JsonKey(name: 'quantity_sold') + final int? quantitySold; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'average_price') + final double? averagePrice; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + + @override + String toString() { + return 'DashboardTopProductDto(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, averagePrice: $averagePrice, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardTopProductDtoImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + averagePrice, + orderCount, + ); + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardTopProductDtoImplCopyWith<_$DashboardTopProductDtoImpl> + get copyWith => + __$$DashboardTopProductDtoImplCopyWithImpl<_$DashboardTopProductDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardTopProductDtoImplToJson(this); + } +} + +abstract class _DashboardTopProductDto extends DashboardTopProductDto { + const factory _DashboardTopProductDto({ + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'product_name') final String? productName, + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'category_name') final String? categoryName, + @JsonKey(name: 'quantity_sold') final int? quantitySold, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'average_price') final double? averagePrice, + @JsonKey(name: 'order_count') final int? orderCount, + }) = _$DashboardTopProductDtoImpl; + const _DashboardTopProductDto._() : super._(); + + factory _DashboardTopProductDto.fromJson(Map json) = + _$DashboardTopProductDtoImpl.fromJson; + + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'product_name') + String? get productName; + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'category_name') + String? get categoryName; + @override + @JsonKey(name: 'quantity_sold') + int? get quantitySold; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'average_price') + double? get averagePrice; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + + /// Create a copy of DashboardTopProductDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardTopProductDtoImplCopyWith<_$DashboardTopProductDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardPaymentMethodDto _$DashboardPaymentMethodDtoFromJson( + Map json, +) { + return _DashboardPaymentMethodDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardPaymentMethodDto { + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType => throw _privateConstructorUsedError; + @JsonKey(name: 'total_amount') + int? get totalAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_count') + int? get paymentCount => throw _privateConstructorUsedError; + @JsonKey(name: 'percentage') + double? get percentage => throw _privateConstructorUsedError; + + /// Serializes this DashboardPaymentMethodDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardPaymentMethodDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardPaymentMethodDtoCopyWith<$Res> { + factory $DashboardPaymentMethodDtoCopyWith( + DashboardPaymentMethodDto value, + $Res Function(DashboardPaymentMethodDto) then, + ) = _$DashboardPaymentMethodDtoCopyWithImpl<$Res, DashboardPaymentMethodDto>; + @useResult + $Res call({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }); +} + +/// @nodoc +class _$DashboardPaymentMethodDtoCopyWithImpl< + $Res, + $Val extends DashboardPaymentMethodDto +> + implements $DashboardPaymentMethodDtoCopyWith<$Res> { + _$DashboardPaymentMethodDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? totalAmount = freezed, + Object? orderCount = freezed, + Object? paymentCount = freezed, + Object? percentage = freezed, + }) { + return _then( + _value.copyWith( + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + percentage: freezed == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardPaymentMethodDtoImplCopyWith<$Res> + implements $DashboardPaymentMethodDtoCopyWith<$Res> { + factory _$$DashboardPaymentMethodDtoImplCopyWith( + _$DashboardPaymentMethodDtoImpl value, + $Res Function(_$DashboardPaymentMethodDtoImpl) then, + ) = __$$DashboardPaymentMethodDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }); +} + +/// @nodoc +class __$$DashboardPaymentMethodDtoImplCopyWithImpl<$Res> + extends + _$DashboardPaymentMethodDtoCopyWithImpl< + $Res, + _$DashboardPaymentMethodDtoImpl + > + implements _$$DashboardPaymentMethodDtoImplCopyWith<$Res> { + __$$DashboardPaymentMethodDtoImplCopyWithImpl( + _$DashboardPaymentMethodDtoImpl _value, + $Res Function(_$DashboardPaymentMethodDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? totalAmount = freezed, + Object? orderCount = freezed, + Object? paymentCount = freezed, + Object? percentage = freezed, + }) { + return _then( + _$DashboardPaymentMethodDtoImpl( + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + percentage: freezed == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardPaymentMethodDtoImpl extends _DashboardPaymentMethodDto { + const _$DashboardPaymentMethodDtoImpl({ + @JsonKey(name: 'payment_method_id') this.paymentMethodId, + @JsonKey(name: 'payment_method_name') this.paymentMethodName, + @JsonKey(name: 'payment_method_type') this.paymentMethodType, + @JsonKey(name: 'total_amount') this.totalAmount, + @JsonKey(name: 'order_count') this.orderCount, + @JsonKey(name: 'payment_count') this.paymentCount, + @JsonKey(name: 'percentage') this.percentage, + }) : super._(); + + factory _$DashboardPaymentMethodDtoImpl.fromJson(Map json) => + _$$DashboardPaymentMethodDtoImplFromJson(json); + + @override + @JsonKey(name: 'payment_method_id') + final String? paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + final String? paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + final String? paymentMethodType; + @override + @JsonKey(name: 'total_amount') + final int? totalAmount; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + @override + @JsonKey(name: 'payment_count') + final int? paymentCount; + @override + @JsonKey(name: 'percentage') + final double? percentage; + + @override + String toString() { + return 'DashboardPaymentMethodDto(paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, totalAmount: $totalAmount, orderCount: $orderCount, paymentCount: $paymentCount, percentage: $percentage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardPaymentMethodDtoImpl && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.percentage, percentage) || + other.percentage == percentage)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodId, + paymentMethodName, + paymentMethodType, + totalAmount, + orderCount, + paymentCount, + percentage, + ); + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardPaymentMethodDtoImplCopyWith<_$DashboardPaymentMethodDtoImpl> + get copyWith => + __$$DashboardPaymentMethodDtoImplCopyWithImpl< + _$DashboardPaymentMethodDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$DashboardPaymentMethodDtoImplToJson(this); + } +} + +abstract class _DashboardPaymentMethodDto extends DashboardPaymentMethodDto { + const factory _DashboardPaymentMethodDto({ + @JsonKey(name: 'payment_method_id') final String? paymentMethodId, + @JsonKey(name: 'payment_method_name') final String? paymentMethodName, + @JsonKey(name: 'payment_method_type') final String? paymentMethodType, + @JsonKey(name: 'total_amount') final int? totalAmount, + @JsonKey(name: 'order_count') final int? orderCount, + @JsonKey(name: 'payment_count') final int? paymentCount, + @JsonKey(name: 'percentage') final double? percentage, + }) = _$DashboardPaymentMethodDtoImpl; + const _DashboardPaymentMethodDto._() : super._(); + + factory _DashboardPaymentMethodDto.fromJson(Map json) = + _$DashboardPaymentMethodDtoImpl.fromJson; + + @override + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType; + @override + @JsonKey(name: 'total_amount') + int? get totalAmount; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + @override + @JsonKey(name: 'payment_count') + int? get paymentCount; + @override + @JsonKey(name: 'percentage') + double? get percentage; + + /// Create a copy of DashboardPaymentMethodDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardPaymentMethodDtoImplCopyWith<_$DashboardPaymentMethodDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +DashboardRecentSaleDto _$DashboardRecentSaleDtoFromJson( + Map json, +) { + return _DashboardRecentSaleDto.fromJson(json); +} + +/// @nodoc +mixin _$DashboardRecentSaleDto { + @JsonKey(name: 'date') + String? get date => throw _privateConstructorUsedError; + @JsonKey(name: 'sales') + int? get sales => throw _privateConstructorUsedError; + @JsonKey(name: 'orders') + int? get orders => throw _privateConstructorUsedError; + @JsonKey(name: 'items') + int? get items => throw _privateConstructorUsedError; + @JsonKey(name: 'tax') + int? get tax => throw _privateConstructorUsedError; + @JsonKey(name: 'discount') + int? get discount => throw _privateConstructorUsedError; + @JsonKey(name: 'net_sales') + int? get netSales => throw _privateConstructorUsedError; + + /// Serializes this DashboardRecentSaleDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $DashboardRecentSaleDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DashboardRecentSaleDtoCopyWith<$Res> { + factory $DashboardRecentSaleDtoCopyWith( + DashboardRecentSaleDto value, + $Res Function(DashboardRecentSaleDto) then, + ) = _$DashboardRecentSaleDtoCopyWithImpl<$Res, DashboardRecentSaleDto>; + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'sales') int? sales, + @JsonKey(name: 'orders') int? orders, + @JsonKey(name: 'items') int? items, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_sales') int? netSales, + }); +} + +/// @nodoc +class _$DashboardRecentSaleDtoCopyWithImpl< + $Res, + $Val extends DashboardRecentSaleDto +> + implements $DashboardRecentSaleDtoCopyWith<$Res> { + _$DashboardRecentSaleDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? sales = freezed, + Object? orders = freezed, + Object? items = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netSales = freezed, + }) { + return _then( + _value.copyWith( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + sales: freezed == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + items: freezed == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$DashboardRecentSaleDtoImplCopyWith<$Res> + implements $DashboardRecentSaleDtoCopyWith<$Res> { + factory _$$DashboardRecentSaleDtoImplCopyWith( + _$DashboardRecentSaleDtoImpl value, + $Res Function(_$DashboardRecentSaleDtoImpl) then, + ) = __$$DashboardRecentSaleDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'sales') int? sales, + @JsonKey(name: 'orders') int? orders, + @JsonKey(name: 'items') int? items, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_sales') int? netSales, + }); +} + +/// @nodoc +class __$$DashboardRecentSaleDtoImplCopyWithImpl<$Res> + extends + _$DashboardRecentSaleDtoCopyWithImpl<$Res, _$DashboardRecentSaleDtoImpl> + implements _$$DashboardRecentSaleDtoImplCopyWith<$Res> { + __$$DashboardRecentSaleDtoImplCopyWithImpl( + _$DashboardRecentSaleDtoImpl _value, + $Res Function(_$DashboardRecentSaleDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? date = freezed, + Object? sales = freezed, + Object? orders = freezed, + Object? items = freezed, + Object? tax = freezed, + Object? discount = freezed, + Object? netSales = freezed, + }) { + return _then( + _$DashboardRecentSaleDtoImpl( + date: freezed == date + ? _value.date + : date // ignore: cast_nullable_to_non_nullable + as String?, + sales: freezed == sales + ? _value.sales + : sales // ignore: cast_nullable_to_non_nullable + as int?, + orders: freezed == orders + ? _value.orders + : orders // ignore: cast_nullable_to_non_nullable + as int?, + items: freezed == items + ? _value.items + : items // ignore: cast_nullable_to_non_nullable + as int?, + tax: freezed == tax + ? _value.tax + : tax // ignore: cast_nullable_to_non_nullable + as int?, + discount: freezed == discount + ? _value.discount + : discount // ignore: cast_nullable_to_non_nullable + as int?, + netSales: freezed == netSales + ? _value.netSales + : netSales // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$DashboardRecentSaleDtoImpl extends _DashboardRecentSaleDto { + const _$DashboardRecentSaleDtoImpl({ + @JsonKey(name: 'date') this.date, + @JsonKey(name: 'sales') this.sales, + @JsonKey(name: 'orders') this.orders, + @JsonKey(name: 'items') this.items, + @JsonKey(name: 'tax') this.tax, + @JsonKey(name: 'discount') this.discount, + @JsonKey(name: 'net_sales') this.netSales, + }) : super._(); + + factory _$DashboardRecentSaleDtoImpl.fromJson(Map json) => + _$$DashboardRecentSaleDtoImplFromJson(json); + + @override + @JsonKey(name: 'date') + final String? date; + @override + @JsonKey(name: 'sales') + final int? sales; + @override + @JsonKey(name: 'orders') + final int? orders; + @override + @JsonKey(name: 'items') + final int? items; + @override + @JsonKey(name: 'tax') + final int? tax; + @override + @JsonKey(name: 'discount') + final int? discount; + @override + @JsonKey(name: 'net_sales') + final int? netSales; + + @override + String toString() { + return 'DashboardRecentSaleDto(date: $date, sales: $sales, orders: $orders, items: $items, tax: $tax, discount: $discount, netSales: $netSales)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$DashboardRecentSaleDtoImpl && + (identical(other.date, date) || other.date == date) && + (identical(other.sales, sales) || other.sales == sales) && + (identical(other.orders, orders) || other.orders == orders) && + (identical(other.items, items) || other.items == items) && + (identical(other.tax, tax) || other.tax == tax) && + (identical(other.discount, discount) || + other.discount == discount) && + (identical(other.netSales, netSales) || + other.netSales == netSales)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + date, + sales, + orders, + items, + tax, + discount, + netSales, + ); + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$DashboardRecentSaleDtoImplCopyWith<_$DashboardRecentSaleDtoImpl> + get copyWith => + __$$DashboardRecentSaleDtoImplCopyWithImpl<_$DashboardRecentSaleDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$DashboardRecentSaleDtoImplToJson(this); + } +} + +abstract class _DashboardRecentSaleDto extends DashboardRecentSaleDto { + const factory _DashboardRecentSaleDto({ + @JsonKey(name: 'date') final String? date, + @JsonKey(name: 'sales') final int? sales, + @JsonKey(name: 'orders') final int? orders, + @JsonKey(name: 'items') final int? items, + @JsonKey(name: 'tax') final int? tax, + @JsonKey(name: 'discount') final int? discount, + @JsonKey(name: 'net_sales') final int? netSales, + }) = _$DashboardRecentSaleDtoImpl; + const _DashboardRecentSaleDto._() : super._(); + + factory _DashboardRecentSaleDto.fromJson(Map json) = + _$DashboardRecentSaleDtoImpl.fromJson; + + @override + @JsonKey(name: 'date') + String? get date; + @override + @JsonKey(name: 'sales') + int? get sales; + @override + @JsonKey(name: 'orders') + int? get orders; + @override + @JsonKey(name: 'items') + int? get items; + @override + @JsonKey(name: 'tax') + int? get tax; + @override + @JsonKey(name: 'discount') + int? get discount; + @override + @JsonKey(name: 'net_sales') + int? get netSales; + + /// Create a copy of DashboardRecentSaleDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$DashboardRecentSaleDtoImplCopyWith<_$DashboardRecentSaleDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ProductAnalyticDto _$ProductAnalyticDtoFromJson(Map json) { + return _ProductAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$ProductAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'data') + List? get data => throw _privateConstructorUsedError; + + /// Serializes this ProductAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProductAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductAnalyticDtoCopyWith<$Res> { + factory $ProductAnalyticDtoCopyWith( + ProductAnalyticDto value, + $Res Function(ProductAnalyticDto) then, + ) = _$ProductAnalyticDtoCopyWithImpl<$Res, ProductAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'data') List? data, + }); +} + +/// @nodoc +class _$ProductAnalyticDtoCopyWithImpl<$Res, $Val extends ProductAnalyticDto> + implements $ProductAnalyticDtoCopyWith<$Res> { + _$ProductAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? data = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductAnalyticDtoImplCopyWith<$Res> + implements $ProductAnalyticDtoCopyWith<$Res> { + factory _$$ProductAnalyticDtoImplCopyWith( + _$ProductAnalyticDtoImpl value, + $Res Function(_$ProductAnalyticDtoImpl) then, + ) = __$$ProductAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'data') List? data, + }); +} + +/// @nodoc +class __$$ProductAnalyticDtoImplCopyWithImpl<$Res> + extends _$ProductAnalyticDtoCopyWithImpl<$Res, _$ProductAnalyticDtoImpl> + implements _$$ProductAnalyticDtoImplCopyWith<$Res> { + __$$ProductAnalyticDtoImplCopyWithImpl( + _$ProductAnalyticDtoImpl _value, + $Res Function(_$ProductAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? data = freezed, + }) { + return _then( + _$ProductAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProductAnalyticDtoImpl extends _ProductAnalyticDto { + const _$ProductAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'data') final List? data, + }) : _data = data, + super._(); + + factory _$ProductAnalyticDtoImpl.fromJson(Map json) => + _$$ProductAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + final List? _data; + @override + @JsonKey(name: 'data') + List? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'ProductAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of ProductAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductAnalyticDtoImplCopyWith<_$ProductAnalyticDtoImpl> get copyWith => + __$$ProductAnalyticDtoImplCopyWithImpl<_$ProductAnalyticDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProductAnalyticDtoImplToJson(this); + } +} + +abstract class _ProductAnalyticDto extends ProductAnalyticDto { + const factory _ProductAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'data') final List? data, + }) = _$ProductAnalyticDtoImpl; + const _ProductAnalyticDto._() : super._(); + + factory _ProductAnalyticDto.fromJson(Map json) = + _$ProductAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'data') + List? get data; + + /// Create a copy of ProductAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductAnalyticDtoImplCopyWith<_$ProductAnalyticDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +ProductAnalyticDataDto _$ProductAnalyticDataDtoFromJson( + Map json, +) { + return _ProductAnalyticDataDto.fromJson(json); +} + +/// @nodoc +mixin _$ProductAnalyticDataDto { + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_name') + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_name') + String? get categoryName => throw _privateConstructorUsedError; + @JsonKey(name: 'quantity_sold') + int? get quantitySold => throw _privateConstructorUsedError; + @JsonKey(name: 'revenue') + int? get revenue => throw _privateConstructorUsedError; + @JsonKey(name: 'average_price') + double? get averagePrice => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + + /// Serializes this ProductAnalyticDataDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProductAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductAnalyticDataDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductAnalyticDataDtoCopyWith<$Res> { + factory $ProductAnalyticDataDtoCopyWith( + ProductAnalyticDataDto value, + $Res Function(ProductAnalyticDataDto) then, + ) = _$ProductAnalyticDataDtoCopyWithImpl<$Res, ProductAnalyticDataDto>; + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class _$ProductAnalyticDataDtoCopyWithImpl< + $Res, + $Val extends ProductAnalyticDataDto +> + implements $ProductAnalyticDataDtoCopyWith<$Res> { + _$ProductAnalyticDataDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? averagePrice = freezed, + Object? orderCount = freezed, + }) { + return _then( + _value.copyWith( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductAnalyticDataDtoImplCopyWith<$Res> + implements $ProductAnalyticDataDtoCopyWith<$Res> { + factory _$$ProductAnalyticDataDtoImplCopyWith( + _$ProductAnalyticDataDtoImpl value, + $Res Function(_$ProductAnalyticDataDtoImpl) then, + ) = __$$ProductAnalyticDataDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }); +} + +/// @nodoc +class __$$ProductAnalyticDataDtoImplCopyWithImpl<$Res> + extends + _$ProductAnalyticDataDtoCopyWithImpl<$Res, _$ProductAnalyticDataDtoImpl> + implements _$$ProductAnalyticDataDtoImplCopyWith<$Res> { + __$$ProductAnalyticDataDtoImplCopyWithImpl( + _$ProductAnalyticDataDtoImpl _value, + $Res Function(_$ProductAnalyticDataDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productId = freezed, + Object? productName = freezed, + Object? categoryId = freezed, + Object? categoryName = freezed, + Object? quantitySold = freezed, + Object? revenue = freezed, + Object? averagePrice = freezed, + Object? orderCount = freezed, + }) { + return _then( + _$ProductAnalyticDataDtoImpl( + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + categoryName: freezed == categoryName + ? _value.categoryName + : categoryName // ignore: cast_nullable_to_non_nullable + as String?, + quantitySold: freezed == quantitySold + ? _value.quantitySold + : quantitySold // ignore: cast_nullable_to_non_nullable + as int?, + revenue: freezed == revenue + ? _value.revenue + : revenue // ignore: cast_nullable_to_non_nullable + as int?, + averagePrice: freezed == averagePrice + ? _value.averagePrice + : averagePrice // ignore: cast_nullable_to_non_nullable + as double?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProductAnalyticDataDtoImpl extends _ProductAnalyticDataDto { + const _$ProductAnalyticDataDtoImpl({ + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'product_name') this.productName, + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'category_name') this.categoryName, + @JsonKey(name: 'quantity_sold') this.quantitySold, + @JsonKey(name: 'revenue') this.revenue, + @JsonKey(name: 'average_price') this.averagePrice, + @JsonKey(name: 'order_count') this.orderCount, + }) : super._(); + + factory _$ProductAnalyticDataDtoImpl.fromJson(Map json) => + _$$ProductAnalyticDataDtoImplFromJson(json); + + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'product_name') + final String? productName; + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'category_name') + final String? categoryName; + @override + @JsonKey(name: 'quantity_sold') + final int? quantitySold; + @override + @JsonKey(name: 'revenue') + final int? revenue; + @override + @JsonKey(name: 'average_price') + final double? averagePrice; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + + @override + String toString() { + return 'ProductAnalyticDataDto(productId: $productId, productName: $productName, categoryId: $categoryId, categoryName: $categoryName, quantitySold: $quantitySold, revenue: $revenue, averagePrice: $averagePrice, orderCount: $orderCount)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductAnalyticDataDtoImpl && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.categoryName, categoryName) || + other.categoryName == categoryName) && + (identical(other.quantitySold, quantitySold) || + other.quantitySold == quantitySold) && + (identical(other.revenue, revenue) || other.revenue == revenue) && + (identical(other.averagePrice, averagePrice) || + other.averagePrice == averagePrice) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + productId, + productName, + categoryId, + categoryName, + quantitySold, + revenue, + averagePrice, + orderCount, + ); + + /// Create a copy of ProductAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductAnalyticDataDtoImplCopyWith<_$ProductAnalyticDataDtoImpl> + get copyWith => + __$$ProductAnalyticDataDtoImplCopyWithImpl<_$ProductAnalyticDataDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProductAnalyticDataDtoImplToJson(this); + } +} + +abstract class _ProductAnalyticDataDto extends ProductAnalyticDataDto { + const factory _ProductAnalyticDataDto({ + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'product_name') final String? productName, + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'category_name') final String? categoryName, + @JsonKey(name: 'quantity_sold') final int? quantitySold, + @JsonKey(name: 'revenue') final int? revenue, + @JsonKey(name: 'average_price') final double? averagePrice, + @JsonKey(name: 'order_count') final int? orderCount, + }) = _$ProductAnalyticDataDtoImpl; + const _ProductAnalyticDataDto._() : super._(); + + factory _ProductAnalyticDataDto.fromJson(Map json) = + _$ProductAnalyticDataDtoImpl.fromJson; + + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'product_name') + String? get productName; + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'category_name') + String? get categoryName; + @override + @JsonKey(name: 'quantity_sold') + int? get quantitySold; + @override + @JsonKey(name: 'revenue') + int? get revenue; + @override + @JsonKey(name: 'average_price') + double? get averagePrice; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + + /// Create a copy of ProductAnalyticDataDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductAnalyticDataDtoImplCopyWith<_$ProductAnalyticDataDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +PaymentMethodAnalyticDto _$PaymentMethodAnalyticDtoFromJson( + Map json, +) { + return _PaymentMethodAnalyticDto.fromJson(json); +} + +/// @nodoc +mixin _$PaymentMethodAnalyticDto { + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'date_from') + String? get dateFrom => throw _privateConstructorUsedError; + @JsonKey(name: 'date_to') + String? get dateTo => throw _privateConstructorUsedError; + @JsonKey(name: 'group_by') + String? get groupBy => throw _privateConstructorUsedError; + @JsonKey(name: 'summary') + PaymentMethodSummaryDto? get summary => throw _privateConstructorUsedError; + @JsonKey(name: 'data') + List? get data => throw _privateConstructorUsedError; + + /// Serializes this PaymentMethodAnalyticDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodAnalyticDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodAnalyticDtoCopyWith<$Res> { + factory $PaymentMethodAnalyticDtoCopyWith( + PaymentMethodAnalyticDto value, + $Res Function(PaymentMethodAnalyticDto) then, + ) = _$PaymentMethodAnalyticDtoCopyWithImpl<$Res, PaymentMethodAnalyticDto>; + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') PaymentMethodSummaryDto? summary, + @JsonKey(name: 'data') List? data, + }); + + $PaymentMethodSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class _$PaymentMethodAnalyticDtoCopyWithImpl< + $Res, + $Val extends PaymentMethodAnalyticDto +> + implements $PaymentMethodAnalyticDtoCopyWith<$Res> { + _$PaymentMethodAnalyticDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + }) { + return _then( + _value.copyWith( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as PaymentMethodSummaryDto?, + data: freezed == data + ? _value.data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } + + /// Create a copy of PaymentMethodAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $PaymentMethodSummaryDtoCopyWith<$Res>? get summary { + if (_value.summary == null) { + return null; + } + + return $PaymentMethodSummaryDtoCopyWith<$Res>(_value.summary!, (value) { + return _then(_value.copyWith(summary: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$PaymentMethodAnalyticDtoImplCopyWith<$Res> + implements $PaymentMethodAnalyticDtoCopyWith<$Res> { + factory _$$PaymentMethodAnalyticDtoImplCopyWith( + _$PaymentMethodAnalyticDtoImpl value, + $Res Function(_$PaymentMethodAnalyticDtoImpl) then, + ) = __$$PaymentMethodAnalyticDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') PaymentMethodSummaryDto? summary, + @JsonKey(name: 'data') List? data, + }); + + @override + $PaymentMethodSummaryDtoCopyWith<$Res>? get summary; +} + +/// @nodoc +class __$$PaymentMethodAnalyticDtoImplCopyWithImpl<$Res> + extends + _$PaymentMethodAnalyticDtoCopyWithImpl< + $Res, + _$PaymentMethodAnalyticDtoImpl + > + implements _$$PaymentMethodAnalyticDtoImplCopyWith<$Res> { + __$$PaymentMethodAnalyticDtoImplCopyWithImpl( + _$PaymentMethodAnalyticDtoImpl _value, + $Res Function(_$PaymentMethodAnalyticDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? organizationId = freezed, + Object? outletId = freezed, + Object? dateFrom = freezed, + Object? dateTo = freezed, + Object? groupBy = freezed, + Object? summary = freezed, + Object? data = freezed, + }) { + return _then( + _$PaymentMethodAnalyticDtoImpl( + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + dateFrom: freezed == dateFrom + ? _value.dateFrom + : dateFrom // ignore: cast_nullable_to_non_nullable + as String?, + dateTo: freezed == dateTo + ? _value.dateTo + : dateTo // ignore: cast_nullable_to_non_nullable + as String?, + groupBy: freezed == groupBy + ? _value.groupBy + : groupBy // ignore: cast_nullable_to_non_nullable + as String?, + summary: freezed == summary + ? _value.summary + : summary // ignore: cast_nullable_to_non_nullable + as PaymentMethodSummaryDto?, + data: freezed == data + ? _value._data + : data // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$PaymentMethodAnalyticDtoImpl extends _PaymentMethodAnalyticDto { + const _$PaymentMethodAnalyticDtoImpl({ + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'date_from') this.dateFrom, + @JsonKey(name: 'date_to') this.dateTo, + @JsonKey(name: 'group_by') this.groupBy, + @JsonKey(name: 'summary') this.summary, + @JsonKey(name: 'data') final List? data, + }) : _data = data, + super._(); + + factory _$PaymentMethodAnalyticDtoImpl.fromJson(Map json) => + _$$PaymentMethodAnalyticDtoImplFromJson(json); + + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'date_from') + final String? dateFrom; + @override + @JsonKey(name: 'date_to') + final String? dateTo; + @override + @JsonKey(name: 'group_by') + final String? groupBy; + @override + @JsonKey(name: 'summary') + final PaymentMethodSummaryDto? summary; + final List? _data; + @override + @JsonKey(name: 'data') + List? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableListView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'PaymentMethodAnalyticDto(organizationId: $organizationId, outletId: $outletId, dateFrom: $dateFrom, dateTo: $dateTo, groupBy: $groupBy, summary: $summary, data: $data)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodAnalyticDtoImpl && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.dateFrom, dateFrom) || + other.dateFrom == dateFrom) && + (identical(other.dateTo, dateTo) || other.dateTo == dateTo) && + (identical(other.groupBy, groupBy) || other.groupBy == groupBy) && + (identical(other.summary, summary) || other.summary == summary) && + const DeepCollectionEquality().equals(other._data, _data)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + organizationId, + outletId, + dateFrom, + dateTo, + groupBy, + summary, + const DeepCollectionEquality().hash(_data), + ); + + /// Create a copy of PaymentMethodAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodAnalyticDtoImplCopyWith<_$PaymentMethodAnalyticDtoImpl> + get copyWith => + __$$PaymentMethodAnalyticDtoImplCopyWithImpl< + _$PaymentMethodAnalyticDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$PaymentMethodAnalyticDtoImplToJson(this); + } +} + +abstract class _PaymentMethodAnalyticDto extends PaymentMethodAnalyticDto { + const factory _PaymentMethodAnalyticDto({ + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'date_from') final String? dateFrom, + @JsonKey(name: 'date_to') final String? dateTo, + @JsonKey(name: 'group_by') final String? groupBy, + @JsonKey(name: 'summary') final PaymentMethodSummaryDto? summary, + @JsonKey(name: 'data') final List? data, + }) = _$PaymentMethodAnalyticDtoImpl; + const _PaymentMethodAnalyticDto._() : super._(); + + factory _PaymentMethodAnalyticDto.fromJson(Map json) = + _$PaymentMethodAnalyticDtoImpl.fromJson; + + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'date_from') + String? get dateFrom; + @override + @JsonKey(name: 'date_to') + String? get dateTo; + @override + @JsonKey(name: 'group_by') + String? get groupBy; + @override + @JsonKey(name: 'summary') + PaymentMethodSummaryDto? get summary; + @override + @JsonKey(name: 'data') + List? get data; + + /// Create a copy of PaymentMethodAnalyticDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodAnalyticDtoImplCopyWith<_$PaymentMethodAnalyticDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +PaymentMethodItemDto _$PaymentMethodItemDtoFromJson(Map json) { + return _PaymentMethodItemDto.fromJson(json); +} + +/// @nodoc +mixin _$PaymentMethodItemDto { + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType => throw _privateConstructorUsedError; + @JsonKey(name: 'total_amount') + num? get totalAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'order_count') + int? get orderCount => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_count') + int? get paymentCount => throw _privateConstructorUsedError; + @JsonKey(name: 'percentage') + double? get percentage => throw _privateConstructorUsedError; + + /// Serializes this PaymentMethodItemDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodItemDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodItemDtoCopyWith<$Res> { + factory $PaymentMethodItemDtoCopyWith( + PaymentMethodItemDto value, + $Res Function(PaymentMethodItemDto) then, + ) = _$PaymentMethodItemDtoCopyWithImpl<$Res, PaymentMethodItemDto>; + @useResult + $Res call({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') num? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }); +} + +/// @nodoc +class _$PaymentMethodItemDtoCopyWithImpl< + $Res, + $Val extends PaymentMethodItemDto +> + implements $PaymentMethodItemDtoCopyWith<$Res> { + _$PaymentMethodItemDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? totalAmount = freezed, + Object? orderCount = freezed, + Object? paymentCount = freezed, + Object? percentage = freezed, + }) { + return _then( + _value.copyWith( + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + percentage: freezed == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$PaymentMethodItemDtoImplCopyWith<$Res> + implements $PaymentMethodItemDtoCopyWith<$Res> { + factory _$$PaymentMethodItemDtoImplCopyWith( + _$PaymentMethodItemDtoImpl value, + $Res Function(_$PaymentMethodItemDtoImpl) then, + ) = __$$PaymentMethodItemDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') num? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }); +} + +/// @nodoc +class __$$PaymentMethodItemDtoImplCopyWithImpl<$Res> + extends _$PaymentMethodItemDtoCopyWithImpl<$Res, _$PaymentMethodItemDtoImpl> + implements _$$PaymentMethodItemDtoImplCopyWith<$Res> { + __$$PaymentMethodItemDtoImplCopyWithImpl( + _$PaymentMethodItemDtoImpl _value, + $Res Function(_$PaymentMethodItemDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? totalAmount = freezed, + Object? orderCount = freezed, + Object? paymentCount = freezed, + Object? percentage = freezed, + }) { + return _then( + _$PaymentMethodItemDtoImpl( + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num?, + orderCount: freezed == orderCount + ? _value.orderCount + : orderCount // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + percentage: freezed == percentage + ? _value.percentage + : percentage // ignore: cast_nullable_to_non_nullable + as double?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$PaymentMethodItemDtoImpl extends _PaymentMethodItemDto { + const _$PaymentMethodItemDtoImpl({ + @JsonKey(name: 'payment_method_id') this.paymentMethodId, + @JsonKey(name: 'payment_method_name') this.paymentMethodName, + @JsonKey(name: 'payment_method_type') this.paymentMethodType, + @JsonKey(name: 'total_amount') this.totalAmount, + @JsonKey(name: 'order_count') this.orderCount, + @JsonKey(name: 'payment_count') this.paymentCount, + @JsonKey(name: 'percentage') this.percentage, + }) : super._(); + + factory _$PaymentMethodItemDtoImpl.fromJson(Map json) => + _$$PaymentMethodItemDtoImplFromJson(json); + + @override + @JsonKey(name: 'payment_method_id') + final String? paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + final String? paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + final String? paymentMethodType; + @override + @JsonKey(name: 'total_amount') + final num? totalAmount; + @override + @JsonKey(name: 'order_count') + final int? orderCount; + @override + @JsonKey(name: 'payment_count') + final int? paymentCount; + @override + @JsonKey(name: 'percentage') + final double? percentage; + + @override + String toString() { + return 'PaymentMethodItemDto(paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, totalAmount: $totalAmount, orderCount: $orderCount, paymentCount: $paymentCount, percentage: $percentage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodItemDtoImpl && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.orderCount, orderCount) || + other.orderCount == orderCount) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.percentage, percentage) || + other.percentage == percentage)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + paymentMethodId, + paymentMethodName, + paymentMethodType, + totalAmount, + orderCount, + paymentCount, + percentage, + ); + + /// Create a copy of PaymentMethodItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodItemDtoImplCopyWith<_$PaymentMethodItemDtoImpl> + get copyWith => + __$$PaymentMethodItemDtoImplCopyWithImpl<_$PaymentMethodItemDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$PaymentMethodItemDtoImplToJson(this); + } +} + +abstract class _PaymentMethodItemDto extends PaymentMethodItemDto { + const factory _PaymentMethodItemDto({ + @JsonKey(name: 'payment_method_id') final String? paymentMethodId, + @JsonKey(name: 'payment_method_name') final String? paymentMethodName, + @JsonKey(name: 'payment_method_type') final String? paymentMethodType, + @JsonKey(name: 'total_amount') final num? totalAmount, + @JsonKey(name: 'order_count') final int? orderCount, + @JsonKey(name: 'payment_count') final int? paymentCount, + @JsonKey(name: 'percentage') final double? percentage, + }) = _$PaymentMethodItemDtoImpl; + const _PaymentMethodItemDto._() : super._(); + + factory _PaymentMethodItemDto.fromJson(Map json) = + _$PaymentMethodItemDtoImpl.fromJson; + + @override + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType; + @override + @JsonKey(name: 'total_amount') + num? get totalAmount; + @override + @JsonKey(name: 'order_count') + int? get orderCount; + @override + @JsonKey(name: 'payment_count') + int? get paymentCount; + @override + @JsonKey(name: 'percentage') + double? get percentage; + + /// Create a copy of PaymentMethodItemDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodItemDtoImplCopyWith<_$PaymentMethodItemDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} + +PaymentMethodSummaryDto _$PaymentMethodSummaryDtoFromJson( + Map json, +) { + return _PaymentMethodSummaryDto.fromJson(json); +} + +/// @nodoc +mixin _$PaymentMethodSummaryDto { + @JsonKey(name: 'total_amount') + num? get totalAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'total_orders') + int? get totalOrders => throw _privateConstructorUsedError; + @JsonKey(name: 'total_payments') + int? get totalPayments => throw _privateConstructorUsedError; + @JsonKey(name: 'average_order_value') + double? get averageOrderValue => throw _privateConstructorUsedError; + + /// Serializes this PaymentMethodSummaryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of PaymentMethodSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentMethodSummaryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentMethodSummaryDtoCopyWith<$Res> { + factory $PaymentMethodSummaryDtoCopyWith( + PaymentMethodSummaryDto value, + $Res Function(PaymentMethodSummaryDto) then, + ) = _$PaymentMethodSummaryDtoCopyWithImpl<$Res, PaymentMethodSummaryDto>; + @useResult + $Res call({ + @JsonKey(name: 'total_amount') num? totalAmount, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'total_payments') int? totalPayments, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + }); +} + +/// @nodoc +class _$PaymentMethodSummaryDtoCopyWithImpl< + $Res, + $Val extends PaymentMethodSummaryDto +> + implements $PaymentMethodSummaryDtoCopyWith<$Res> { + _$PaymentMethodSummaryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentMethodSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalAmount = freezed, + Object? totalOrders = freezed, + Object? totalPayments = freezed, + Object? averageOrderValue = freezed, + }) { + return _then( + _value.copyWith( + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + totalPayments: freezed == totalPayments + ? _value.totalPayments + : totalPayments // ignore: cast_nullable_to_non_nullable + as int?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$PaymentMethodSummaryDtoImplCopyWith<$Res> + implements $PaymentMethodSummaryDtoCopyWith<$Res> { + factory _$$PaymentMethodSummaryDtoImplCopyWith( + _$PaymentMethodSummaryDtoImpl value, + $Res Function(_$PaymentMethodSummaryDtoImpl) then, + ) = __$$PaymentMethodSummaryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'total_amount') num? totalAmount, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'total_payments') int? totalPayments, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + }); +} + +/// @nodoc +class __$$PaymentMethodSummaryDtoImplCopyWithImpl<$Res> + extends + _$PaymentMethodSummaryDtoCopyWithImpl< + $Res, + _$PaymentMethodSummaryDtoImpl + > + implements _$$PaymentMethodSummaryDtoImplCopyWith<$Res> { + __$$PaymentMethodSummaryDtoImplCopyWithImpl( + _$PaymentMethodSummaryDtoImpl _value, + $Res Function(_$PaymentMethodSummaryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentMethodSummaryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? totalAmount = freezed, + Object? totalOrders = freezed, + Object? totalPayments = freezed, + Object? averageOrderValue = freezed, + }) { + return _then( + _$PaymentMethodSummaryDtoImpl( + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as num?, + totalOrders: freezed == totalOrders + ? _value.totalOrders + : totalOrders // ignore: cast_nullable_to_non_nullable + as int?, + totalPayments: freezed == totalPayments + ? _value.totalPayments + : totalPayments // ignore: cast_nullable_to_non_nullable + as int?, + averageOrderValue: freezed == averageOrderValue + ? _value.averageOrderValue + : averageOrderValue // ignore: cast_nullable_to_non_nullable + as double?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$PaymentMethodSummaryDtoImpl extends _PaymentMethodSummaryDto { + const _$PaymentMethodSummaryDtoImpl({ + @JsonKey(name: 'total_amount') this.totalAmount, + @JsonKey(name: 'total_orders') this.totalOrders, + @JsonKey(name: 'total_payments') this.totalPayments, + @JsonKey(name: 'average_order_value') this.averageOrderValue, + }) : super._(); + + factory _$PaymentMethodSummaryDtoImpl.fromJson(Map json) => + _$$PaymentMethodSummaryDtoImplFromJson(json); + + @override + @JsonKey(name: 'total_amount') + final num? totalAmount; + @override + @JsonKey(name: 'total_orders') + final int? totalOrders; + @override + @JsonKey(name: 'total_payments') + final int? totalPayments; + @override + @JsonKey(name: 'average_order_value') + final double? averageOrderValue; + + @override + String toString() { + return 'PaymentMethodSummaryDto(totalAmount: $totalAmount, totalOrders: $totalOrders, totalPayments: $totalPayments, averageOrderValue: $averageOrderValue)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentMethodSummaryDtoImpl && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.totalOrders, totalOrders) || + other.totalOrders == totalOrders) && + (identical(other.totalPayments, totalPayments) || + other.totalPayments == totalPayments) && + (identical(other.averageOrderValue, averageOrderValue) || + other.averageOrderValue == averageOrderValue)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + totalAmount, + totalOrders, + totalPayments, + averageOrderValue, + ); + + /// Create a copy of PaymentMethodSummaryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentMethodSummaryDtoImplCopyWith<_$PaymentMethodSummaryDtoImpl> + get copyWith => + __$$PaymentMethodSummaryDtoImplCopyWithImpl< + _$PaymentMethodSummaryDtoImpl + >(this, _$identity); + + @override + Map toJson() { + return _$$PaymentMethodSummaryDtoImplToJson(this); + } +} + +abstract class _PaymentMethodSummaryDto extends PaymentMethodSummaryDto { + const factory _PaymentMethodSummaryDto({ + @JsonKey(name: 'total_amount') final num? totalAmount, + @JsonKey(name: 'total_orders') final int? totalOrders, + @JsonKey(name: 'total_payments') final int? totalPayments, + @JsonKey(name: 'average_order_value') final double? averageOrderValue, + }) = _$PaymentMethodSummaryDtoImpl; + const _PaymentMethodSummaryDto._() : super._(); + + factory _PaymentMethodSummaryDto.fromJson(Map json) = + _$PaymentMethodSummaryDtoImpl.fromJson; + + @override + @JsonKey(name: 'total_amount') + num? get totalAmount; + @override + @JsonKey(name: 'total_orders') + int? get totalOrders; + @override + @JsonKey(name: 'total_payments') + int? get totalPayments; + @override + @JsonKey(name: 'average_order_value') + double? get averageOrderValue; + + /// Create a copy of PaymentMethodSummaryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentMethodSummaryDtoImplCopyWith<_$PaymentMethodSummaryDtoImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/analytic/analytic_dtos.g.dart b/lib/infrastructure/analytic/analytic_dtos.g.dart new file mode 100644 index 0000000..fbdd5a6 --- /dev/null +++ b/lib/infrastructure/analytic/analytic_dtos.g.dart @@ -0,0 +1,639 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'analytic_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$SalesAnalyticDtoImpl _$$SalesAnalyticDtoImplFromJson( + Map json, +) => _$SalesAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] 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), + groupBy: json['group_by'] as String?, + summary: json['summary'] == null + ? null + : SalesAnalyticSummaryDto.fromJson( + json['summary'] as Map, + ), + data: (json['data'] as List?) + ?.map((e) => SalesAnalyticDataDto.fromJson(e as Map)) + .toList(), +); + +Map _$$SalesAnalyticDtoImplToJson( + _$SalesAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'date_from': instance.dateFrom?.toIso8601String(), + 'date_to': instance.dateTo?.toIso8601String(), + 'group_by': instance.groupBy, + 'summary': instance.summary, + 'data': instance.data, +}; + +_$SalesAnalyticSummaryDtoImpl _$$SalesAnalyticSummaryDtoImplFromJson( + Map json, +) => _$SalesAnalyticSummaryDtoImpl( + totalSales: json['total_sales'] as num?, + totalOrders: json['total_orders'] as num?, + totalItems: json['total_items'] as num?, + averageOrderValue: json['average_order_value'] as num?, + totalTax: json['total_tax'] as num?, + totalDiscount: json['total_discount'] as num?, + netSales: json['net_sales'] as num?, +); + +Map _$$SalesAnalyticSummaryDtoImplToJson( + _$SalesAnalyticSummaryDtoImpl instance, +) => { + 'total_sales': instance.totalSales, + 'total_orders': instance.totalOrders, + 'total_items': instance.totalItems, + 'average_order_value': instance.averageOrderValue, + 'total_tax': instance.totalTax, + 'total_discount': instance.totalDiscount, + 'net_sales': instance.netSales, +}; + +_$SalesAnalyticDataDtoImpl _$$SalesAnalyticDataDtoImplFromJson( + Map json, +) => _$SalesAnalyticDataDtoImpl( + date: json['date'] == null ? null : DateTime.parse(json['date'] as String), + sales: json['sales'] as num?, + orders: json['orders'] as num?, + items: json['items'] as num?, + tax: json['tax'] as num?, + discount: json['discount'] as num?, + netSales: json['net_sales'] as num?, +); + +Map _$$SalesAnalyticDataDtoImplToJson( + _$SalesAnalyticDataDtoImpl instance, +) => { + 'date': instance.date?.toIso8601String(), + 'sales': instance.sales, + 'orders': instance.orders, + 'items': instance.items, + 'tax': instance.tax, + 'discount': instance.discount, + 'net_sales': instance.netSales, +}; + +_$ProfitLossAnalyticDtoImpl _$$ProfitLossAnalyticDtoImplFromJson( + Map json, +) => _$ProfitLossAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + groupBy: json['group_by'] as String?, + summary: json['summary'] == null + ? null + : ProfitLossSummaryDto.fromJson(json['summary'] as Map), + data: (json['data'] as List?) + ?.map((e) => ProfitLossDailyDataDto.fromJson(e as Map)) + .toList(), + productData: (json['product_data'] as List?) + ?.map((e) => ProfitLossProductDataDto.fromJson(e as Map)) + .toList(), +); + +Map _$$ProfitLossAnalyticDtoImplToJson( + _$ProfitLossAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'group_by': instance.groupBy, + 'summary': instance.summary, + 'data': instance.data, + 'product_data': instance.productData, +}; + +_$ProfitLossSummaryDtoImpl _$$ProfitLossSummaryDtoImplFromJson( + Map json, +) => _$ProfitLossSummaryDtoImpl( + totalRevenue: (json['total_revenue'] as num?)?.toInt(), + totalCost: (json['total_cost'] as num?)?.toInt(), + grossProfit: (json['gross_profit'] as num?)?.toInt(), + grossProfitMargin: (json['gross_profit_margin'] as num?)?.toDouble(), + totalTax: (json['total_tax'] as num?)?.toInt(), + totalDiscount: (json['total_discount'] as num?)?.toInt(), + netProfit: (json['net_profit'] as num?)?.toInt(), + netProfitMargin: (json['net_profit_margin'] as num?)?.toDouble(), + totalOrders: (json['total_orders'] as num?)?.toInt(), + averageProfit: (json['average_profit'] as num?)?.toDouble(), + profitabilityRatio: (json['profitability_ratio'] as num?)?.toDouble(), +); + +Map _$$ProfitLossSummaryDtoImplToJson( + _$ProfitLossSummaryDtoImpl instance, +) => { + 'total_revenue': instance.totalRevenue, + 'total_cost': instance.totalCost, + 'gross_profit': instance.grossProfit, + 'gross_profit_margin': instance.grossProfitMargin, + 'total_tax': instance.totalTax, + 'total_discount': instance.totalDiscount, + 'net_profit': instance.netProfit, + 'net_profit_margin': instance.netProfitMargin, + 'total_orders': instance.totalOrders, + 'average_profit': instance.averageProfit, + 'profitability_ratio': instance.profitabilityRatio, +}; + +_$ProfitLossDailyDataDtoImpl _$$ProfitLossDailyDataDtoImplFromJson( + Map json, +) => _$ProfitLossDailyDataDtoImpl( + date: json['date'] as String?, + revenue: (json['revenue'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + grossProfit: (json['gross_profit'] as num?)?.toInt(), + grossProfitMargin: (json['gross_profit_margin'] as num?)?.toDouble(), + tax: (json['tax'] as num?)?.toInt(), + discount: (json['discount'] as num?)?.toInt(), + netProfit: (json['net_profit'] as num?)?.toInt(), + netProfitMargin: (json['net_profit_margin'] as num?)?.toDouble(), + orders: (json['orders'] as num?)?.toInt(), +); + +Map _$$ProfitLossDailyDataDtoImplToJson( + _$ProfitLossDailyDataDtoImpl instance, +) => { + 'date': instance.date, + 'revenue': instance.revenue, + 'cost': instance.cost, + 'gross_profit': instance.grossProfit, + 'gross_profit_margin': instance.grossProfitMargin, + 'tax': instance.tax, + 'discount': instance.discount, + 'net_profit': instance.netProfit, + 'net_profit_margin': instance.netProfitMargin, + 'orders': instance.orders, +}; + +_$ProfitLossProductDataDtoImpl _$$ProfitLossProductDataDtoImplFromJson( + Map json, +) => _$ProfitLossProductDataDtoImpl( + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryId: json['category_id'] as String?, + categoryName: json['category_name'] as String?, + quantitySold: (json['quantity_sold'] as num?)?.toInt(), + revenue: (json['revenue'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + grossProfit: (json['gross_profit'] as num?)?.toInt(), + grossProfitMargin: (json['gross_profit_margin'] as num?)?.toDouble(), + averagePrice: (json['average_price'] as num?)?.toInt(), + averageCost: (json['average_cost'] as num?)?.toInt(), + profitPerUnit: (json['profit_per_unit'] as num?)?.toInt(), +); + +Map _$$ProfitLossProductDataDtoImplToJson( + _$ProfitLossProductDataDtoImpl instance, +) => { + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_id': instance.categoryId, + 'category_name': instance.categoryName, + 'quantity_sold': instance.quantitySold, + 'revenue': instance.revenue, + 'cost': instance.cost, + 'gross_profit': instance.grossProfit, + 'gross_profit_margin': instance.grossProfitMargin, + 'average_price': instance.averagePrice, + 'average_cost': instance.averageCost, + 'profit_per_unit': instance.profitPerUnit, +}; + +_$CategoryAnalyticDtoImpl _$$CategoryAnalyticDtoImplFromJson( + Map json, +) => _$CategoryAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + data: (json['data'] as List?) + ?.map((e) => CategoryAnalyticItemDto.fromJson(e as Map)) + .toList(), +); + +Map _$$CategoryAnalyticDtoImplToJson( + _$CategoryAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'data': instance.data, +}; + +_$CategoryAnalyticItemDtoImpl _$$CategoryAnalyticItemDtoImplFromJson( + Map json, +) => _$CategoryAnalyticItemDtoImpl( + categoryId: json['category_id'] as String?, + categoryName: json['category_name'] as String?, + totalRevenue: (json['total_revenue'] as num?)?.toInt(), + totalQuantity: (json['total_quantity'] as num?)?.toInt(), + productCount: (json['product_count'] as num?)?.toInt(), + orderCount: (json['order_count'] as num?)?.toInt(), +); + +Map _$$CategoryAnalyticItemDtoImplToJson( + _$CategoryAnalyticItemDtoImpl instance, +) => { + 'category_id': instance.categoryId, + 'category_name': instance.categoryName, + 'total_revenue': instance.totalRevenue, + 'total_quantity': instance.totalQuantity, + 'product_count': instance.productCount, + 'order_count': instance.orderCount, +}; + +_$InventoryAnalyticDtoImpl _$$InventoryAnalyticDtoImplFromJson( + Map json, +) => _$InventoryAnalyticDtoImpl( + summary: json['summary'] == null + ? null + : InventorySummaryDto.fromJson(json['summary'] as Map), + products: (json['products'] as List?) + ?.map((e) => InventoryProductDto.fromJson(e as Map)) + .toList(), + ingredients: (json['ingredients'] as List?) + ?.map((e) => InventoryIngredientDto.fromJson(e as Map)) + .toList(), +); + +Map _$$InventoryAnalyticDtoImplToJson( + _$InventoryAnalyticDtoImpl instance, +) => { + 'summary': instance.summary, + 'products': instance.products, + 'ingredients': instance.ingredients, +}; + +_$InventorySummaryDtoImpl _$$InventorySummaryDtoImplFromJson( + Map json, +) => _$InventorySummaryDtoImpl( + totalProducts: (json['total_products'] as num?)?.toInt(), + totalIngredients: (json['total_ingredients'] as num?)?.toInt(), + totalValue: (json['total_value'] as num?)?.toInt(), + lowStockProducts: (json['low_stock_products'] as num?)?.toInt(), + lowStockIngredients: (json['low_stock_ingredients'] as num?)?.toInt(), + zeroStockProducts: (json['zero_stock_products'] as num?)?.toInt(), + zeroStockIngredients: (json['zero_stock_ingredients'] as num?)?.toInt(), + totalSoldProducts: (json['total_sold_products'] as num?)?.toInt(), + totalSoldIngredients: (json['total_sold_ingredients'] as num?)?.toInt(), + outletId: json['outlet_id'] as String?, + outletName: json['outlet_name'] as String?, + generatedAt: json['generated_at'] as String?, +); + +Map _$$InventorySummaryDtoImplToJson( + _$InventorySummaryDtoImpl instance, +) => { + 'total_products': instance.totalProducts, + 'total_ingredients': instance.totalIngredients, + 'total_value': instance.totalValue, + 'low_stock_products': instance.lowStockProducts, + 'low_stock_ingredients': instance.lowStockIngredients, + 'zero_stock_products': instance.zeroStockProducts, + 'zero_stock_ingredients': instance.zeroStockIngredients, + 'total_sold_products': instance.totalSoldProducts, + 'total_sold_ingredients': instance.totalSoldIngredients, + 'outlet_id': instance.outletId, + 'outlet_name': instance.outletName, + 'generated_at': instance.generatedAt, +}; + +_$InventoryProductDtoImpl _$$InventoryProductDtoImplFromJson( + Map json, +) => _$InventoryProductDtoImpl( + id: json['id'] as String?, + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryName: json['category_name'] as String?, + quantity: (json['quantity'] as num?)?.toInt(), + reorderLevel: (json['reorder_level'] as num?)?.toInt(), + unitCost: (json['unit_cost'] as num?)?.toInt(), + totalValue: (json['total_value'] as num?)?.toInt(), + totalIn: (json['total_in'] as num?)?.toInt(), + totalOut: (json['total_out'] as num?)?.toInt(), + isLowStock: json['is_low_stock'] as bool?, + isZeroStock: json['is_zero_stock'] as bool?, + updatedAt: json['updated_at'] as String?, +); + +Map _$$InventoryProductDtoImplToJson( + _$InventoryProductDtoImpl instance, +) => { + 'id': instance.id, + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_name': instance.categoryName, + 'quantity': instance.quantity, + 'reorder_level': instance.reorderLevel, + 'unit_cost': instance.unitCost, + 'total_value': instance.totalValue, + 'total_in': instance.totalIn, + 'total_out': instance.totalOut, + 'is_low_stock': instance.isLowStock, + 'is_zero_stock': instance.isZeroStock, + 'updated_at': instance.updatedAt, +}; + +_$InventoryIngredientDtoImpl _$$InventoryIngredientDtoImplFromJson( + Map json, +) => _$InventoryIngredientDtoImpl( + id: json['id'] as String?, + ingredientId: json['ingredient_id'] as String?, + ingredientName: json['ingredient_name'] as String?, + unitName: json['unit_name'] as String?, + quantity: (json['quantity'] as num?)?.toInt(), + reorderLevel: (json['reorder_level'] as num?)?.toInt(), + unitCost: (json['unit_cost'] as num?)?.toInt(), + totalValue: (json['total_value'] as num?)?.toInt(), + totalIn: (json['total_in'] as num?)?.toInt(), + totalOut: (json['total_out'] as num?)?.toInt(), + isLowStock: json['is_low_stock'] as bool?, + isZeroStock: json['is_zero_stock'] as bool?, + updatedAt: json['updated_at'] as String?, +); + +Map _$$InventoryIngredientDtoImplToJson( + _$InventoryIngredientDtoImpl instance, +) => { + 'id': instance.id, + 'ingredient_id': instance.ingredientId, + 'ingredient_name': instance.ingredientName, + 'unit_name': instance.unitName, + 'quantity': instance.quantity, + 'reorder_level': instance.reorderLevel, + 'unit_cost': instance.unitCost, + 'total_value': instance.totalValue, + 'total_in': instance.totalIn, + 'total_out': instance.totalOut, + 'is_low_stock': instance.isLowStock, + 'is_zero_stock': instance.isZeroStock, + 'updated_at': instance.updatedAt, +}; + +_$DashboardAnalyticDtoImpl _$$DashboardAnalyticDtoImplFromJson( + Map json, +) => _$DashboardAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + overview: json['overview'] == null + ? null + : DashboardOverviewDto.fromJson(json['overview'] as Map), + topProducts: (json['top_products'] as List?) + ?.map((e) => DashboardTopProductDto.fromJson(e as Map)) + .toList(), + paymentMethods: (json['payment_methods'] as List?) + ?.map( + (e) => DashboardPaymentMethodDto.fromJson(e as Map), + ) + .toList(), + recentSales: (json['recent_sales'] as List?) + ?.map((e) => DashboardRecentSaleDto.fromJson(e as Map)) + .toList(), +); + +Map _$$DashboardAnalyticDtoImplToJson( + _$DashboardAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'overview': instance.overview, + 'top_products': instance.topProducts, + 'payment_methods': instance.paymentMethods, + 'recent_sales': instance.recentSales, +}; + +_$DashboardOverviewDtoImpl _$$DashboardOverviewDtoImplFromJson( + Map json, +) => _$DashboardOverviewDtoImpl( + totalSales: (json['total_sales'] as num?)?.toInt(), + totalOrders: (json['total_orders'] as num?)?.toInt(), + averageOrderValue: (json['average_order_value'] as num?)?.toDouble(), + totalCustomers: (json['total_customers'] as num?)?.toInt(), + voidedOrders: (json['voided_orders'] as num?)?.toInt(), + refundedOrders: (json['refunded_orders'] as num?)?.toInt(), +); + +Map _$$DashboardOverviewDtoImplToJson( + _$DashboardOverviewDtoImpl instance, +) => { + 'total_sales': instance.totalSales, + 'total_orders': instance.totalOrders, + 'average_order_value': instance.averageOrderValue, + 'total_customers': instance.totalCustomers, + 'voided_orders': instance.voidedOrders, + 'refunded_orders': instance.refundedOrders, +}; + +_$DashboardTopProductDtoImpl _$$DashboardTopProductDtoImplFromJson( + Map json, +) => _$DashboardTopProductDtoImpl( + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryId: json['category_id'] as String?, + categoryName: json['category_name'] as String?, + quantitySold: (json['quantity_sold'] as num?)?.toInt(), + revenue: (json['revenue'] as num?)?.toInt(), + averagePrice: (json['average_price'] as num?)?.toDouble(), + orderCount: (json['order_count'] as num?)?.toInt(), +); + +Map _$$DashboardTopProductDtoImplToJson( + _$DashboardTopProductDtoImpl instance, +) => { + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_id': instance.categoryId, + 'category_name': instance.categoryName, + 'quantity_sold': instance.quantitySold, + 'revenue': instance.revenue, + 'average_price': instance.averagePrice, + 'order_count': instance.orderCount, +}; + +_$DashboardPaymentMethodDtoImpl _$$DashboardPaymentMethodDtoImplFromJson( + Map json, +) => _$DashboardPaymentMethodDtoImpl( + paymentMethodId: json['payment_method_id'] as String?, + paymentMethodName: json['payment_method_name'] as String?, + paymentMethodType: json['payment_method_type'] as String?, + totalAmount: (json['total_amount'] as num?)?.toInt(), + orderCount: (json['order_count'] as num?)?.toInt(), + paymentCount: (json['payment_count'] as num?)?.toInt(), + percentage: (json['percentage'] as num?)?.toDouble(), +); + +Map _$$DashboardPaymentMethodDtoImplToJson( + _$DashboardPaymentMethodDtoImpl instance, +) => { + 'payment_method_id': instance.paymentMethodId, + 'payment_method_name': instance.paymentMethodName, + 'payment_method_type': instance.paymentMethodType, + 'total_amount': instance.totalAmount, + 'order_count': instance.orderCount, + 'payment_count': instance.paymentCount, + 'percentage': instance.percentage, +}; + +_$DashboardRecentSaleDtoImpl _$$DashboardRecentSaleDtoImplFromJson( + Map json, +) => _$DashboardRecentSaleDtoImpl( + date: json['date'] as String?, + sales: (json['sales'] as num?)?.toInt(), + orders: (json['orders'] as num?)?.toInt(), + items: (json['items'] as num?)?.toInt(), + tax: (json['tax'] as num?)?.toInt(), + discount: (json['discount'] as num?)?.toInt(), + netSales: (json['net_sales'] as num?)?.toInt(), +); + +Map _$$DashboardRecentSaleDtoImplToJson( + _$DashboardRecentSaleDtoImpl instance, +) => { + 'date': instance.date, + 'sales': instance.sales, + 'orders': instance.orders, + 'items': instance.items, + 'tax': instance.tax, + 'discount': instance.discount, + 'net_sales': instance.netSales, +}; + +_$ProductAnalyticDtoImpl _$$ProductAnalyticDtoImplFromJson( + Map json, +) => _$ProductAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + data: (json['data'] as List?) + ?.map((e) => ProductAnalyticDataDto.fromJson(e as Map)) + .toList(), +); + +Map _$$ProductAnalyticDtoImplToJson( + _$ProductAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'data': instance.data, +}; + +_$ProductAnalyticDataDtoImpl _$$ProductAnalyticDataDtoImplFromJson( + Map json, +) => _$ProductAnalyticDataDtoImpl( + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + categoryId: json['category_id'] as String?, + categoryName: json['category_name'] as String?, + quantitySold: (json['quantity_sold'] as num?)?.toInt(), + revenue: (json['revenue'] as num?)?.toInt(), + averagePrice: (json['average_price'] as num?)?.toDouble(), + orderCount: (json['order_count'] as num?)?.toInt(), +); + +Map _$$ProductAnalyticDataDtoImplToJson( + _$ProductAnalyticDataDtoImpl instance, +) => { + 'product_id': instance.productId, + 'product_name': instance.productName, + 'category_id': instance.categoryId, + 'category_name': instance.categoryName, + 'quantity_sold': instance.quantitySold, + 'revenue': instance.revenue, + 'average_price': instance.averagePrice, + 'order_count': instance.orderCount, +}; + +_$PaymentMethodAnalyticDtoImpl _$$PaymentMethodAnalyticDtoImplFromJson( + Map json, +) => _$PaymentMethodAnalyticDtoImpl( + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] as String?, + dateFrom: json['date_from'] as String?, + dateTo: json['date_to'] as String?, + groupBy: json['group_by'] as String?, + summary: json['summary'] == null + ? null + : PaymentMethodSummaryDto.fromJson( + json['summary'] as Map, + ), + data: (json['data'] as List?) + ?.map((e) => PaymentMethodItemDto.fromJson(e as Map)) + .toList(), +); + +Map _$$PaymentMethodAnalyticDtoImplToJson( + _$PaymentMethodAnalyticDtoImpl instance, +) => { + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'date_from': instance.dateFrom, + 'date_to': instance.dateTo, + 'group_by': instance.groupBy, + 'summary': instance.summary, + 'data': instance.data, +}; + +_$PaymentMethodItemDtoImpl _$$PaymentMethodItemDtoImplFromJson( + Map json, +) => _$PaymentMethodItemDtoImpl( + paymentMethodId: json['payment_method_id'] as String?, + paymentMethodName: json['payment_method_name'] as String?, + paymentMethodType: json['payment_method_type'] as String?, + totalAmount: json['total_amount'] as num?, + orderCount: (json['order_count'] as num?)?.toInt(), + paymentCount: (json['payment_count'] as num?)?.toInt(), + percentage: (json['percentage'] as num?)?.toDouble(), +); + +Map _$$PaymentMethodItemDtoImplToJson( + _$PaymentMethodItemDtoImpl instance, +) => { + 'payment_method_id': instance.paymentMethodId, + 'payment_method_name': instance.paymentMethodName, + 'payment_method_type': instance.paymentMethodType, + 'total_amount': instance.totalAmount, + 'order_count': instance.orderCount, + 'payment_count': instance.paymentCount, + 'percentage': instance.percentage, +}; + +_$PaymentMethodSummaryDtoImpl _$$PaymentMethodSummaryDtoImplFromJson( + Map json, +) => _$PaymentMethodSummaryDtoImpl( + totalAmount: json['total_amount'] as num?, + totalOrders: (json['total_orders'] as num?)?.toInt(), + totalPayments: (json['total_payments'] as num?)?.toInt(), + averageOrderValue: (json['average_order_value'] as num?)?.toDouble(), +); + +Map _$$PaymentMethodSummaryDtoImplToJson( + _$PaymentMethodSummaryDtoImpl instance, +) => { + 'total_amount': instance.totalAmount, + 'total_orders': instance.totalOrders, + 'total_payments': instance.totalPayments, + 'average_order_value': instance.averageOrderValue, +}; diff --git a/lib/infrastructure/analytic/datasource/remote_data_provider.dart b/lib/infrastructure/analytic/datasource/remote_data_provider.dart new file mode 100644 index 0000000..29cf105 --- /dev/null +++ b/lib/infrastructure/analytic/datasource/remote_data_provider.dart @@ -0,0 +1,234 @@ +import 'dart:developer'; + +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../analytic_dtos.dart'; + +@injectable +class AnalyticRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = "AnalyticRemoteDataProvider"; + + AnalyticRemoteDataProvider(this._apiClient); + + Future> fetchSales({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final Map params = { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + if (outletId != null) params['outlet_id'] = outletId; + + final response = await _apiClient.get( + ApiPath.salesAnalytic, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = SalesAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchSalesError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } + + Future> fetchProfitLoss({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final Map params = { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + if (outletId != null) params['outlet_id'] = outletId; + + final response = await _apiClient.get( + ApiPath.profitLossAnalytic, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = ProfitLossAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchProfitLossError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } + + Future> fetchCategory({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final Map params = { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + if (outletId != null) params['outlet_id'] = outletId; + + final response = await _apiClient.get( + ApiPath.categoryAnalytic, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = CategoryAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchCategoryError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } + + Future> fetchInventory({ + required String outletId, + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + final response = await _apiClient.get( + '${ApiPath.inventoryReportDetail}/$outletId', + params: { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = InventoryAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchInventoryError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } + + Future> fetchDashboard({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final Map params = { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + if (outletId != null) params['outlet_id'] = outletId; + + final response = await _apiClient.get( + ApiPath.dashboardAnalytic, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = DashboardAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchDashboardError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } + + Future> fetchProduct({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final Map params = { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + if (outletId != null) params['outlet_id'] = outletId; + + final response = await _apiClient.get( + ApiPath.productAnalytic, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = ProductAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchProductError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } + + Future> fetchPaymentMethod({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final Map params = { + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + if (outletId != null) params['outlet_id'] = outletId; + + final response = await _apiClient.get( + ApiPath.paymentMethodAnalytic, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(AnalyticFailure.empty()); + } + + final dto = PaymentMethodAnalyticDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchPaymentMethodError', name: _logName, error: e, stackTrace: s); + return DC.error(AnalyticFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/analytic/dto/category_analytic_dto.dart b/lib/infrastructure/analytic/dto/category_analytic_dto.dart new file mode 100644 index 0000000..55c43ce --- /dev/null +++ b/lib/infrastructure/analytic/dto/category_analytic_dto.dart @@ -0,0 +1,51 @@ +part of '../analytic_dtos.dart'; + +@freezed +class CategoryAnalyticDto with _$CategoryAnalyticDto { + const CategoryAnalyticDto._(); + + const factory CategoryAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'data') List? data, + }) = _CategoryAnalyticDto; + + factory CategoryAnalyticDto.fromJson(Map json) => + _$CategoryAnalyticDtoFromJson(json); + + CategoryAnalytic toDomain() => CategoryAnalytic( + organizationId: organizationId ?? "", + outletId: outletId ?? "", + dateFrom: dateFrom ?? "", + dateTo: dateTo ?? "", + data: data?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class CategoryAnalyticItemDto with _$CategoryAnalyticItemDto { + const CategoryAnalyticItemDto._(); + + const factory CategoryAnalyticItemDto({ + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_quantity') int? totalQuantity, + @JsonKey(name: 'product_count') int? productCount, + @JsonKey(name: 'order_count') int? orderCount, + }) = _CategoryAnalyticItemDto; + + factory CategoryAnalyticItemDto.fromJson(Map json) => + _$CategoryAnalyticItemDtoFromJson(json); + + CategoryAnalyticItem toDomain() => CategoryAnalyticItem( + categoryId: categoryId ?? "", + categoryName: categoryName ?? "", + totalRevenue: totalRevenue ?? 0, + totalQuantity: totalQuantity ?? 0, + productCount: productCount ?? 0, + orderCount: orderCount ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/dto/dashboard_analytic_dto.dart b/lib/infrastructure/analytic/dto/dashboard_analytic_dto.dart new file mode 100644 index 0000000..f17bfe5 --- /dev/null +++ b/lib/infrastructure/analytic/dto/dashboard_analytic_dto.dart @@ -0,0 +1,145 @@ +part of '../analytic_dtos.dart'; + +@freezed +class DashboardAnalyticDto with _$DashboardAnalyticDto { + const DashboardAnalyticDto._(); + + const factory DashboardAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'overview') DashboardOverviewDto? overview, + @JsonKey(name: 'top_products') List? topProducts, + @JsonKey(name: 'payment_methods') + List? paymentMethods, + @JsonKey(name: 'recent_sales') List? recentSales, + }) = _DashboardAnalyticDto; + + factory DashboardAnalyticDto.fromJson(Map json) => + _$DashboardAnalyticDtoFromJson(json); + + DashboardAnalytic toDomain() => DashboardAnalytic( + organizationId: organizationId ?? '', + outletId: outletId ?? '', + dateFrom: dateFrom ?? '', + dateTo: dateTo ?? '', + overview: overview?.toDomain() ?? DashboardOverview.empty(), + topProducts: topProducts?.map((e) => e.toDomain()).toList() ?? [], + paymentMethods: paymentMethods?.map((e) => e.toDomain()).toList() ?? [], + recentSales: recentSales?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class DashboardOverviewDto with _$DashboardOverviewDto { + const DashboardOverviewDto._(); + + const factory DashboardOverviewDto({ + @JsonKey(name: 'total_sales') int? totalSales, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + @JsonKey(name: 'total_customers') int? totalCustomers, + @JsonKey(name: 'voided_orders') int? voidedOrders, + @JsonKey(name: 'refunded_orders') int? refundedOrders, + }) = _DashboardOverviewDto; + + factory DashboardOverviewDto.fromJson(Map json) => + _$DashboardOverviewDtoFromJson(json); + + DashboardOverview toDomain() => DashboardOverview( + totalSales: totalSales ?? 0, + totalOrders: totalOrders ?? 0, + averageOrderValue: averageOrderValue ?? 0.0, + totalCustomers: totalCustomers ?? 0, + voidedOrders: voidedOrders ?? 0, + refundedOrders: refundedOrders ?? 0, + ); +} + +@freezed +class DashboardTopProductDto with _$DashboardTopProductDto { + const DashboardTopProductDto._(); + + const factory DashboardTopProductDto({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }) = _DashboardTopProductDto; + + factory DashboardTopProductDto.fromJson(Map json) => + _$DashboardTopProductDtoFromJson(json); + + DashboardTopProduct toDomain() => DashboardTopProduct( + productId: productId ?? '', + productName: productName ?? '', + categoryId: categoryId ?? '', + categoryName: categoryName ?? '', + quantitySold: quantitySold ?? 0, + revenue: revenue ?? 0, + averagePrice: averagePrice ?? 0.0, + orderCount: orderCount ?? 0, + ); +} + +@freezed +class DashboardPaymentMethodDto with _$DashboardPaymentMethodDto { + const DashboardPaymentMethodDto._(); + + const factory DashboardPaymentMethodDto({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }) = _DashboardPaymentMethodDto; + + factory DashboardPaymentMethodDto.fromJson(Map json) => + _$DashboardPaymentMethodDtoFromJson(json); + + DashboardPaymentMethod toDomain() => DashboardPaymentMethod( + paymentMethodId: paymentMethodId ?? '', + paymentMethodName: paymentMethodName ?? '', + paymentMethodType: paymentMethodType ?? '', + totalAmount: totalAmount ?? 0, + orderCount: orderCount ?? 0, + paymentCount: paymentCount ?? 0, + percentage: percentage ?? 0.0, + ); +} + +/// ===================== RECENT SALE DTO ===================== +@freezed +class DashboardRecentSaleDto with _$DashboardRecentSaleDto { + const DashboardRecentSaleDto._(); + + const factory DashboardRecentSaleDto({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'sales') int? sales, + @JsonKey(name: 'orders') int? orders, + @JsonKey(name: 'items') int? items, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_sales') int? netSales, + }) = _DashboardRecentSaleDto; + + factory DashboardRecentSaleDto.fromJson(Map json) => + _$DashboardRecentSaleDtoFromJson(json); + + DashboardRecentSale toDomain() => DashboardRecentSale( + date: date ?? '', + sales: sales ?? 0, + orders: orders ?? 0, + items: items ?? 0, + tax: tax ?? 0, + discount: discount ?? 0, + netSales: netSales ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/dto/inventory_analytic_dto.dart b/lib/infrastructure/analytic/dto/inventory_analytic_dto.dart new file mode 100644 index 0000000..a76c149 --- /dev/null +++ b/lib/infrastructure/analytic/dto/inventory_analytic_dto.dart @@ -0,0 +1,139 @@ +part of '../analytic_dtos.dart'; + +@freezed +class InventoryAnalyticDto with _$InventoryAnalyticDto { + const InventoryAnalyticDto._(); + + const factory InventoryAnalyticDto({ + @JsonKey(name: "summary") InventorySummaryDto? summary, + @JsonKey(name: "products") List? products, + @JsonKey(name: "ingredients") List? ingredients, + }) = _InventoryAnalyticDto; + + factory InventoryAnalyticDto.fromJson(Map json) => + _$InventoryAnalyticDtoFromJson(json); + + InventoryAnalytic toDomain() => InventoryAnalytic( + summary: summary?.toDomain() ?? InventorySummary.empty(), + products: products?.map((e) => e.toDomain()).toList() ?? [], + ingredients: ingredients?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class InventorySummaryDto with _$InventorySummaryDto { + const factory InventorySummaryDto({ + @JsonKey(name: "total_products") int? totalProducts, + @JsonKey(name: "total_ingredients") int? totalIngredients, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "low_stock_products") int? lowStockProducts, + @JsonKey(name: "low_stock_ingredients") int? lowStockIngredients, + @JsonKey(name: "zero_stock_products") int? zeroStockProducts, + @JsonKey(name: "zero_stock_ingredients") int? zeroStockIngredients, + @JsonKey(name: "total_sold_products") int? totalSoldProducts, + @JsonKey(name: "total_sold_ingredients") int? totalSoldIngredients, + @JsonKey(name: "outlet_id") String? outletId, + @JsonKey(name: "outlet_name") String? outletName, + @JsonKey(name: "generated_at") String? generatedAt, + }) = _InventorySummaryDto; + + factory InventorySummaryDto.fromJson(Map json) => + _$InventorySummaryDtoFromJson(json); +} + +extension InventorySummaryDtoX on InventorySummaryDto { + InventorySummary toDomain() => InventorySummary( + totalProducts: totalProducts ?? 0, + totalIngredients: totalIngredients ?? 0, + totalValue: totalValue ?? 0, + lowStockProducts: lowStockProducts ?? 0, + lowStockIngredients: lowStockIngredients ?? 0, + zeroStockProducts: zeroStockProducts ?? 0, + zeroStockIngredients: zeroStockIngredients ?? 0, + totalSoldProducts: totalSoldProducts ?? 0, + totalSoldIngredients: totalSoldIngredients ?? 0, + outletId: outletId ?? "", + outletName: outletName ?? "", + generatedAt: generatedAt ?? "", + ); +} + +@freezed +class InventoryProductDto with _$InventoryProductDto { + const factory InventoryProductDto({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "product_id") String? productId, + @JsonKey(name: "product_name") String? productName, + @JsonKey(name: "category_name") String? categoryName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }) = _InventoryProductDto; + + factory InventoryProductDto.fromJson(Map json) => + _$InventoryProductDtoFromJson(json); +} + +extension InventoryProductDtoX on InventoryProductDto { + InventoryProduct toDomain() => InventoryProduct( + id: id ?? "", + productId: productId ?? "", + productName: productName ?? "", + categoryName: categoryName ?? "", + quantity: quantity ?? 0, + reorderLevel: reorderLevel ?? 0, + unitCost: unitCost ?? 0, + totalValue: totalValue ?? 0, + totalIn: totalIn ?? 0, + totalOut: totalOut ?? 0, + isLowStock: isLowStock ?? false, + isZeroStock: isZeroStock ?? false, + updatedAt: updatedAt ?? "", + ); +} + +@freezed +class InventoryIngredientDto with _$InventoryIngredientDto { + const factory InventoryIngredientDto({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "ingredient_id") String? ingredientId, + @JsonKey(name: "ingredient_name") String? ingredientName, + @JsonKey(name: "unit_name") String? unitName, + @JsonKey(name: "quantity") int? quantity, + @JsonKey(name: "reorder_level") int? reorderLevel, + @JsonKey(name: "unit_cost") int? unitCost, + @JsonKey(name: "total_value") int? totalValue, + @JsonKey(name: "total_in") int? totalIn, + @JsonKey(name: "total_out") int? totalOut, + @JsonKey(name: "is_low_stock") bool? isLowStock, + @JsonKey(name: "is_zero_stock") bool? isZeroStock, + @JsonKey(name: "updated_at") String? updatedAt, + }) = _InventoryIngredientDto; + + factory InventoryIngredientDto.fromJson(Map json) => + _$InventoryIngredientDtoFromJson(json); +} + +extension InventoryIngredientDtoX on InventoryIngredientDto { + InventoryIngredient toDomain() => InventoryIngredient( + id: id ?? "", + ingredientId: ingredientId ?? "", + ingredientName: ingredientName ?? "", + unitName: unitName ?? "", + quantity: quantity ?? 0, + reorderLevel: reorderLevel ?? 0, + unitCost: unitCost ?? 0, + totalValue: totalValue ?? 0, + totalIn: totalIn ?? 0, + totalOut: totalOut ?? 0, + isLowStock: isLowStock ?? false, + isZeroStock: isZeroStock ?? false, + updatedAt: updatedAt ?? "", + ); +} diff --git a/lib/infrastructure/analytic/dto/payment_method_analytic_dto.dart b/lib/infrastructure/analytic/dto/payment_method_analytic_dto.dart new file mode 100644 index 0000000..b29f877 --- /dev/null +++ b/lib/infrastructure/analytic/dto/payment_method_analytic_dto.dart @@ -0,0 +1,85 @@ +part of '../analytic_dtos.dart'; + +@freezed +class PaymentMethodAnalyticDto with _$PaymentMethodAnalyticDto { + const PaymentMethodAnalyticDto._(); + + const factory PaymentMethodAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') PaymentMethodSummaryDto? summary, + @JsonKey(name: 'data') List? data, + }) = _PaymentMethodAnalyticDto; + + factory PaymentMethodAnalyticDto.fromJson(Map json) => + _$PaymentMethodAnalyticDtoFromJson(json); + + PaymentMethodAnalytic toDomain() { + return PaymentMethodAnalytic( + organizationId: organizationId ?? '', + outletId: outletId ?? '', + dateFrom: dateFrom ?? '', + dateTo: dateTo ?? '', + groupBy: groupBy ?? '', + summary: summary?.toDomain() ?? PaymentMethodSummary.empty(), + data: data?.map((e) => e.toDomain()).toList() ?? [], + ); + } +} + +@freezed +class PaymentMethodItemDto with _$PaymentMethodItemDto { + const PaymentMethodItemDto._(); + + const factory PaymentMethodItemDto({ + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'total_amount') num? totalAmount, + @JsonKey(name: 'order_count') int? orderCount, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'percentage') double? percentage, + }) = _PaymentMethodItemDto; + + factory PaymentMethodItemDto.fromJson(Map json) => + _$PaymentMethodItemDtoFromJson(json); + + PaymentMethodItem toDomain() { + return PaymentMethodItem( + paymentMethodId: paymentMethodId ?? '', + paymentMethodName: paymentMethodName ?? '', + paymentMethodType: paymentMethodType ?? '', + totalAmount: totalAmount ?? 0, + orderCount: orderCount ?? 0, + paymentCount: paymentCount ?? 0, + percentage: percentage ?? 0.0, + ); + } +} + +@freezed +class PaymentMethodSummaryDto with _$PaymentMethodSummaryDto { + const PaymentMethodSummaryDto._(); + + const factory PaymentMethodSummaryDto({ + @JsonKey(name: 'total_amount') num? totalAmount, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'total_payments') int? totalPayments, + @JsonKey(name: 'average_order_value') double? averageOrderValue, + }) = _PaymentMethodSummaryDto; + + factory PaymentMethodSummaryDto.fromJson(Map json) => + _$PaymentMethodSummaryDtoFromJson(json); + + PaymentMethodSummary toDomain() { + return PaymentMethodSummary( + totalAmount: totalAmount ?? 0, + totalOrders: totalOrders ?? 0, + totalPayments: totalPayments ?? 0, + averageOrderValue: averageOrderValue ?? 0.0, + ); + } +} diff --git a/lib/infrastructure/analytic/dto/product_analytic_dto.dart b/lib/infrastructure/analytic/dto/product_analytic_dto.dart new file mode 100644 index 0000000..b143e1e --- /dev/null +++ b/lib/infrastructure/analytic/dto/product_analytic_dto.dart @@ -0,0 +1,55 @@ +part of '../analytic_dtos.dart'; + +@freezed +class ProductAnalyticDto with _$ProductAnalyticDto { + const ProductAnalyticDto._(); + + const factory ProductAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'data') List? data, + }) = _ProductAnalyticDto; + + factory ProductAnalyticDto.fromJson(Map json) => + _$ProductAnalyticDtoFromJson(json); + + ProductAnalytic toDomain() => ProductAnalytic( + organizationId: organizationId ?? "", + outletId: outletId ?? "", + dateFrom: dateFrom ?? "", + dateTo: dateTo ?? "", + data: data?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class ProductAnalyticDataDto with _$ProductAnalyticDataDto { + const ProductAnalyticDataDto._(); + + const factory ProductAnalyticDataDto({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'average_price') double? averagePrice, + @JsonKey(name: 'order_count') int? orderCount, + }) = _ProductAnalyticDataDto; + + factory ProductAnalyticDataDto.fromJson(Map json) => + _$ProductAnalyticDataDtoFromJson(json); + + ProductAnalyticData toDomain() => ProductAnalyticData( + productId: productId ?? "", + productName: productName ?? "", + categoryId: categoryId ?? "", + categoryName: categoryName ?? "", + quantitySold: quantitySold ?? 0, + revenue: revenue ?? 0, + averagePrice: averagePrice ?? 0, + orderCount: orderCount ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart b/lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart new file mode 100644 index 0000000..2741495 --- /dev/null +++ b/lib/infrastructure/analytic/dto/profit_loss_analytic_dto.dart @@ -0,0 +1,137 @@ +part of '../analytic_dtos.dart'; + +@freezed +class ProfitLossAnalyticDto with _$ProfitLossAnalyticDto { + const ProfitLossAnalyticDto._(); + + const factory ProfitLossAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'date_from') String? dateFrom, + @JsonKey(name: 'date_to') String? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') ProfitLossSummaryDto? summary, + @JsonKey(name: 'data') List? data, + @JsonKey(name: 'product_data') List? productData, + }) = _ProfitLossAnalyticDto; + + factory ProfitLossAnalyticDto.fromJson(Map json) => + _$ProfitLossAnalyticDtoFromJson(json); + + ProfitLossAnalytic toDomain() => ProfitLossAnalytic( + organizationId: organizationId ?? '', + dateFrom: dateFrom ?? '', + dateTo: dateTo ?? '', + groupBy: groupBy ?? '', + summary: summary?.toDomain() ?? ProfitLossSummary.empty(), + data: (data ?? []).map((e) => e.toDomain()).toList(), + productData: (productData ?? []).map((e) => e.toDomain()).toList(), + ); +} + +@freezed +class ProfitLossSummaryDto with _$ProfitLossSummaryDto { + const ProfitLossSummaryDto._(); + + const factory ProfitLossSummaryDto({ + @JsonKey(name: 'total_revenue') int? totalRevenue, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'total_tax') int? totalTax, + @JsonKey(name: 'total_discount') int? totalDiscount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'total_orders') int? totalOrders, + @JsonKey(name: 'average_profit') double? averageProfit, + @JsonKey(name: 'profitability_ratio') double? profitabilityRatio, + }) = _ProfitLossSummaryDto; + + factory ProfitLossSummaryDto.fromJson(Map json) => + _$ProfitLossSummaryDtoFromJson(json); + + ProfitLossSummary toDomain() => ProfitLossSummary( + totalRevenue: totalRevenue ?? 0, + totalCost: totalCost ?? 0, + grossProfit: grossProfit ?? 0, + grossProfitMargin: grossProfitMargin ?? 0.0, + totalTax: totalTax ?? 0, + totalDiscount: totalDiscount ?? 0, + netProfit: netProfit ?? 0, + netProfitMargin: netProfitMargin ?? 0.0, + totalOrders: totalOrders ?? 0, + averageProfit: averageProfit ?? 0.0, + profitabilityRatio: profitabilityRatio ?? 0.0, + ); +} + +@freezed +class ProfitLossDailyDataDto with _$ProfitLossDailyDataDto { + const ProfitLossDailyDataDto._(); + + const factory ProfitLossDailyDataDto({ + @JsonKey(name: 'date') String? date, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'tax') int? tax, + @JsonKey(name: 'discount') int? discount, + @JsonKey(name: 'net_profit') int? netProfit, + @JsonKey(name: 'net_profit_margin') double? netProfitMargin, + @JsonKey(name: 'orders') int? orders, + }) = _ProfitLossDailyDataDto; + + factory ProfitLossDailyDataDto.fromJson(Map json) => + _$ProfitLossDailyDataDtoFromJson(json); + + ProfitLossDailyData toDomain() => ProfitLossDailyData( + date: date ?? '', + revenue: revenue ?? 0, + cost: cost ?? 0, + grossProfit: grossProfit ?? 0, + grossProfitMargin: grossProfitMargin ?? 0.0, + tax: tax ?? 0, + discount: discount ?? 0, + netProfit: netProfit ?? 0, + netProfitMargin: netProfitMargin ?? 0.0, + orders: orders ?? 0, + ); +} + +@freezed +class ProfitLossProductDataDto with _$ProfitLossProductDataDto { + const ProfitLossProductDataDto._(); + + const factory ProfitLossProductDataDto({ + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'category_name') String? categoryName, + @JsonKey(name: 'quantity_sold') int? quantitySold, + @JsonKey(name: 'revenue') int? revenue, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'gross_profit') int? grossProfit, + @JsonKey(name: 'gross_profit_margin') double? grossProfitMargin, + @JsonKey(name: 'average_price') int? averagePrice, + @JsonKey(name: 'average_cost') int? averageCost, + @JsonKey(name: 'profit_per_unit') int? profitPerUnit, + }) = _ProfitLossProductDataDto; + + factory ProfitLossProductDataDto.fromJson(Map json) => + _$ProfitLossProductDataDtoFromJson(json); + + ProfitLossProductData toDomain() => ProfitLossProductData( + productId: productId ?? '', + productName: productName ?? '', + categoryId: categoryId ?? '', + categoryName: categoryName ?? '', + quantitySold: quantitySold ?? 0, + revenue: revenue ?? 0, + cost: cost ?? 0, + grossProfit: grossProfit ?? 0, + grossProfitMargin: grossProfitMargin ?? 0.0, + averagePrice: averagePrice ?? 0, + averageCost: averageCost ?? 0, + profitPerUnit: profitPerUnit ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/dto/sales_analytic_dto.dart b/lib/infrastructure/analytic/dto/sales_analytic_dto.dart new file mode 100644 index 0000000..c4453c9 --- /dev/null +++ b/lib/infrastructure/analytic/dto/sales_analytic_dto.dart @@ -0,0 +1,85 @@ +part of '../analytic_dtos.dart'; + +@freezed +class SalesAnalyticDto with _$SalesAnalyticDto { + const SalesAnalyticDto._(); + + const factory SalesAnalyticDto({ + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'date_from') DateTime? dateFrom, + @JsonKey(name: 'date_to') DateTime? dateTo, + @JsonKey(name: 'group_by') String? groupBy, + @JsonKey(name: 'summary') SalesAnalyticSummaryDto? summary, + @JsonKey(name: 'data') List? data, + }) = _SalesAnalyticDto; + + factory SalesAnalyticDto.fromJson(Map json) => + _$SalesAnalyticDtoFromJson(json); + + SalesAnalytic toDomain() => SalesAnalytic( + organizationId: organizationId ?? '', + outletId: outletId ?? '', + dateFrom: dateFrom ?? DateTime.fromMillisecondsSinceEpoch(0), + dateTo: dateTo ?? DateTime.fromMillisecondsSinceEpoch(0), + groupBy: groupBy ?? '', + summary: summary?.toDomain() ?? SalesAnalyticSummary.empty(), + data: data?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class SalesAnalyticSummaryDto with _$SalesAnalyticSummaryDto { + const SalesAnalyticSummaryDto._(); + + const factory SalesAnalyticSummaryDto({ + @JsonKey(name: 'total_sales') num? totalSales, + @JsonKey(name: 'total_orders') num? totalOrders, + @JsonKey(name: 'total_items') num? totalItems, + @JsonKey(name: 'average_order_value') num? averageOrderValue, + @JsonKey(name: 'total_tax') num? totalTax, + @JsonKey(name: 'total_discount') num? totalDiscount, + @JsonKey(name: 'net_sales') num? netSales, + }) = _SalesAnalyticSummaryDto; + + factory SalesAnalyticSummaryDto.fromJson(Map json) => + _$SalesAnalyticSummaryDtoFromJson(json); + + SalesAnalyticSummary toDomain() => SalesAnalyticSummary( + totalSales: totalSales?.toInt() ?? 0, + totalOrders: totalOrders?.toInt() ?? 0, + totalItems: totalItems?.toInt() ?? 0, + averageOrderValue: averageOrderValue?.toDouble() ?? 0, + totalTax: totalTax?.toInt() ?? 0, + totalDiscount: totalDiscount?.toInt() ?? 0, + netSales: netSales?.toInt() ?? 0, + ); +} + +@freezed +class SalesAnalyticDataDto with _$SalesAnalyticDataDto { + const SalesAnalyticDataDto._(); + + const factory SalesAnalyticDataDto({ + @JsonKey(name: 'date') DateTime? date, + @JsonKey(name: 'sales') num? sales, + @JsonKey(name: 'orders') num? orders, + @JsonKey(name: 'items') num? items, + @JsonKey(name: 'tax') num? tax, + @JsonKey(name: 'discount') num? discount, + @JsonKey(name: 'net_sales') num? netSales, + }) = _SalesAnalyticDataDto; + + factory SalesAnalyticDataDto.fromJson(Map json) => + _$SalesAnalyticDataDtoFromJson(json); + + SalesAnalyticData toDomain() => SalesAnalyticData( + date: date ?? DateTime.fromMillisecondsSinceEpoch(0), + sales: sales?.toInt() ?? 0, + orders: orders?.toInt() ?? 0, + items: items?.toInt() ?? 0, + tax: tax?.toInt() ?? 0, + discount: discount?.toInt() ?? 0, + netSales: netSales?.toInt() ?? 0, + ); +} diff --git a/lib/infrastructure/analytic/repositories/analytic_repository.dart b/lib/infrastructure/analytic/repositories/analytic_repository.dart new file mode 100644 index 0000000..c32832e --- /dev/null +++ b/lib/infrastructure/analytic/repositories/analytic_repository.dart @@ -0,0 +1,179 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/analytic/analytic.dart'; +import '../../../domain/analytic/repositories/i_analytic_repository.dart'; +import '../../auth/datasources/local_data_provider.dart'; +import '../../outlet/datasource/local_data_provider.dart'; +import '../datasource/remote_data_provider.dart'; + +@Injectable(as: IAnalyticRepository) +class AnalyticRepository implements IAnalyticRepository { + final AnalyticRemoteDataProvider _dataProvider; + final AuthLocalDataProvider _authLocalDataProvider; + final OutletLocalDataProvider _outletLocalDataProvider; + final String _logName = 'AnalyticRepository'; + + AnalyticRepository( + this._dataProvider, + this._authLocalDataProvider, + this._outletLocalDataProvider, + ); + + /// Resolves outlet_id: pakai param jika ada, fallback ke shared pref + String? _resolveOutletId(String? outletId) { + return outletId ?? _outletLocalDataProvider.getSelectedOutletId(); + } + + @override + Future> getSales({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final result = await _dataProvider.fetchSales( + dateFrom: dateFrom, + dateTo: dateTo, + outletId: _resolveOutletId(outletId), + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getSalesError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } + + @override + Future> getProfitLoss({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final result = await _dataProvider.fetchProfitLoss( + dateFrom: dateFrom, + dateTo: dateTo, + outletId: _resolveOutletId(outletId), + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getProfitLossError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } + + @override + Future> getCategory({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final result = await _dataProvider.fetchCategory( + dateFrom: dateFrom, + dateTo: dateTo, + outletId: _resolveOutletId(outletId), + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getCategoryError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } + + @override + Future> getInventory({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final currentUser = await _authLocalDataProvider.currentUser(); + final resolvedId = _resolveOutletId(outletId) ?? currentUser.outletId; + + final result = await _dataProvider.fetchInventory( + outletId: resolvedId, + dateFrom: dateFrom, + dateTo: dateTo, + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getInventoryError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } + + @override + Future> getDashboard({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final result = await _dataProvider.fetchDashboard( + dateFrom: dateFrom, + dateTo: dateTo, + outletId: _resolveOutletId(outletId), + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getDashboardError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } + + @override + Future> getProduct({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final result = await _dataProvider.fetchProduct( + dateFrom: dateFrom, + dateTo: dateTo, + outletId: _resolveOutletId(outletId), + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getProductError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } + + @override + Future> getPaymentMethod({ + required DateTime dateFrom, + required DateTime dateTo, + String? outletId, + }) async { + try { + final result = await _dataProvider.fetchPaymentMethod( + dateFrom: dateFrom, + dateTo: dateTo, + outletId: _resolveOutletId(outletId), + ); + + if (result.hasError) return left(result.error!); + return right(result.data!.toDomain()); + } catch (e, s) { + log('getPaymentMethodError', name: _logName, error: e, stackTrace: s); + return left(const AnalyticFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/auth/auth_dtos.dart b/lib/infrastructure/auth/auth_dtos.dart new file mode 100644 index 0000000..2ad030f --- /dev/null +++ b/lib/infrastructure/auth/auth_dtos.dart @@ -0,0 +1,10 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/auth/auth.dart'; +import '../../domain/user/user.dart'; +import '../user/user_dtos.dart'; + +part 'auth_dtos.freezed.dart'; +part 'auth_dtos.g.dart'; + +part 'dto/auth_dto.dart'; diff --git a/lib/infrastructure/auth/auth_dtos.freezed.dart b/lib/infrastructure/auth/auth_dtos.freezed.dart new file mode 100644 index 0000000..9911ea7 --- /dev/null +++ b/lib/infrastructure/auth/auth_dtos.freezed.dart @@ -0,0 +1,244 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'auth_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T 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', +); + +AuthDto _$AuthDtoFromJson(Map json) { + return _AuthDto.fromJson(json); +} + +/// @nodoc +mixin _$AuthDto { + @JsonKey(name: 'token') + String? get token => throw _privateConstructorUsedError; + @JsonKey(name: 'expires_at') + String? get expiresAt => throw _privateConstructorUsedError; + @JsonKey(name: 'user') + UserDto? get user => throw _privateConstructorUsedError; + + /// Serializes this AuthDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of AuthDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $AuthDtoCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $AuthDtoCopyWith<$Res> { + factory $AuthDtoCopyWith(AuthDto value, $Res Function(AuthDto) then) = + _$AuthDtoCopyWithImpl<$Res, AuthDto>; + @useResult + $Res call({ + @JsonKey(name: 'token') String? token, + @JsonKey(name: 'expires_at') String? expiresAt, + @JsonKey(name: 'user') UserDto? user, + }); + + $UserDtoCopyWith<$Res>? get user; +} + +/// @nodoc +class _$AuthDtoCopyWithImpl<$Res, $Val extends AuthDto> + implements $AuthDtoCopyWith<$Res> { + _$AuthDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of AuthDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = freezed, + Object? expiresAt = freezed, + Object? user = freezed, + }) { + return _then( + _value.copyWith( + token: freezed == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String?, + expiresAt: freezed == expiresAt + ? _value.expiresAt + : expiresAt // ignore: cast_nullable_to_non_nullable + as String?, + user: freezed == user + ? _value.user + : user // ignore: cast_nullable_to_non_nullable + as UserDto?, + ) + as $Val, + ); + } + + /// Create a copy of AuthDto + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $UserDtoCopyWith<$Res>? get user { + if (_value.user == null) { + return null; + } + + return $UserDtoCopyWith<$Res>(_value.user!, (value) { + return _then(_value.copyWith(user: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$AuthDtoImplCopyWith<$Res> implements $AuthDtoCopyWith<$Res> { + factory _$$AuthDtoImplCopyWith( + _$AuthDtoImpl value, + $Res Function(_$AuthDtoImpl) then, + ) = __$$AuthDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'token') String? token, + @JsonKey(name: 'expires_at') String? expiresAt, + @JsonKey(name: 'user') UserDto? user, + }); + + @override + $UserDtoCopyWith<$Res>? get user; +} + +/// @nodoc +class __$$AuthDtoImplCopyWithImpl<$Res> + extends _$AuthDtoCopyWithImpl<$Res, _$AuthDtoImpl> + implements _$$AuthDtoImplCopyWith<$Res> { + __$$AuthDtoImplCopyWithImpl( + _$AuthDtoImpl _value, + $Res Function(_$AuthDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of AuthDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? token = freezed, + Object? expiresAt = freezed, + Object? user = freezed, + }) { + return _then( + _$AuthDtoImpl( + token: freezed == token + ? _value.token + : token // ignore: cast_nullable_to_non_nullable + as String?, + expiresAt: freezed == expiresAt + ? _value.expiresAt + : expiresAt // ignore: cast_nullable_to_non_nullable + as String?, + user: freezed == user + ? _value.user + : user // ignore: cast_nullable_to_non_nullable + as UserDto?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$AuthDtoImpl extends _AuthDto { + const _$AuthDtoImpl({ + @JsonKey(name: 'token') this.token, + @JsonKey(name: 'expires_at') this.expiresAt, + @JsonKey(name: 'user') this.user, + }) : super._(); + + factory _$AuthDtoImpl.fromJson(Map json) => + _$$AuthDtoImplFromJson(json); + + @override + @JsonKey(name: 'token') + final String? token; + @override + @JsonKey(name: 'expires_at') + final String? expiresAt; + @override + @JsonKey(name: 'user') + final UserDto? user; + + @override + String toString() { + return 'AuthDto(token: $token, expiresAt: $expiresAt, user: $user)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$AuthDtoImpl && + (identical(other.token, token) || other.token == token) && + (identical(other.expiresAt, expiresAt) || + other.expiresAt == expiresAt) && + (identical(other.user, user) || other.user == user)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, token, expiresAt, user); + + /// Create a copy of AuthDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$AuthDtoImplCopyWith<_$AuthDtoImpl> get copyWith => + __$$AuthDtoImplCopyWithImpl<_$AuthDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$AuthDtoImplToJson(this); + } +} + +abstract class _AuthDto extends AuthDto { + const factory _AuthDto({ + @JsonKey(name: 'token') final String? token, + @JsonKey(name: 'expires_at') final String? expiresAt, + @JsonKey(name: 'user') final UserDto? user, + }) = _$AuthDtoImpl; + const _AuthDto._() : super._(); + + factory _AuthDto.fromJson(Map json) = _$AuthDtoImpl.fromJson; + + @override + @JsonKey(name: 'token') + String? get token; + @override + @JsonKey(name: 'expires_at') + String? get expiresAt; + @override + @JsonKey(name: 'user') + UserDto? get user; + + /// Create a copy of AuthDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$AuthDtoImplCopyWith<_$AuthDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/auth/auth_dtos.g.dart b/lib/infrastructure/auth/auth_dtos.g.dart new file mode 100644 index 0000000..3937bd4 --- /dev/null +++ b/lib/infrastructure/auth/auth_dtos.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'auth_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$AuthDtoImpl _$$AuthDtoImplFromJson(Map json) => + _$AuthDtoImpl( + token: json['token'] as String?, + expiresAt: json['expires_at'] as String?, + user: json['user'] == null + ? null + : UserDto.fromJson(json['user'] as Map), + ); + +Map _$$AuthDtoImplToJson(_$AuthDtoImpl instance) => + { + 'token': instance.token, + 'expires_at': instance.expiresAt, + 'user': instance.user, + }; diff --git a/lib/infrastructure/auth/datasources/local_data_provider.dart b/lib/infrastructure/auth/datasources/local_data_provider.dart new file mode 100644 index 0000000..8f9536c --- /dev/null +++ b/lib/infrastructure/auth/datasources/local_data_provider.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:injectable/injectable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../../common/constant/local_storage_key.dart'; +import '../../../domain/user/user.dart'; +import '../../user/user_dtos.dart'; + +@injectable +class AuthLocalDataProvider { + final SharedPreferences _sharedPreferences; + final String _logName = 'AuthLocalDataProvider'; + + AuthLocalDataProvider(this._sharedPreferences); + + Future saveToken(String token) async { + await _sharedPreferences.setString(LocalStorageKey.token, token); + } + + Future getToken() async { + return _sharedPreferences.getString(LocalStorageKey.token); + } + + Future deleteToken() async { + await _sharedPreferences.remove(LocalStorageKey.token); + } + + Future hasToken() async { + return _sharedPreferences.containsKey(LocalStorageKey.token); + } + + Future saveCurrentUser(UserDto user) async { + final userJsonString = jsonEncode(user.toJson()); + await _sharedPreferences.setString(LocalStorageKey.user, userJsonString); + } + + Future currentUser() async { + final userString = _sharedPreferences.getString(LocalStorageKey.user); + if (userString == null) return User.empty(); + + final Map userMap = jsonDecode(userString); + final userDto = UserDto.fromJson(userMap); + return userDto.toDomain(); + } + + Future deleteCurrentUser() async { + await _sharedPreferences.remove(LocalStorageKey.user); + } + + Future deleteAllAuth() async { + try { + await _sharedPreferences.remove(LocalStorageKey.token); + await _sharedPreferences.remove(LocalStorageKey.user); + } catch (e) { + log('deleteAllAuthError', name: _logName, error: e); + } + } +} diff --git a/lib/infrastructure/auth/datasources/remote_data_provider.dart b/lib/infrastructure/auth/datasources/remote_data_provider.dart new file mode 100644 index 0000000..70c0cc1 --- /dev/null +++ b/lib/infrastructure/auth/datasources/remote_data_provider.dart @@ -0,0 +1,73 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; +import 'package:data_channel/data_channel.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/auth/auth.dart'; +import '../auth_dtos.dart'; + +@injectable +class AuthRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = "AuthRemoteDataProvider"; + + AuthRemoteDataProvider(this._apiClient); + + Future> login({ + required String email, + required String password, + required String deviceId, + required String deviceName, + required String deviceType, + required String platform, + required String osVersion, + required String appVersion, + String? fcmToken, + }) async { + try { + final response = await _apiClient.post( + ApiPath.login, + data: { + 'email': email, + 'password': password, + 'device_id': deviceId, + 'device_name': deviceName, + 'device_type': deviceType, + 'platform': platform, + 'os_version': osVersion, + 'app_version': appVersion, + if (fcmToken != null) 'fcm_token': fcmToken, + }, + ); + + if (response.data['code'] == 401) { + return DC.error( + AuthFailure.serverError( + ApiFailure.unauthorized('Incorrect email or password'), + ), + ); + } + + final dto = AuthDto.fromJson(response.data['data']); + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('login', name: _logName, error: e, stackTrace: s); + return DC.error(AuthFailure.serverError(e)); + } + } + + Future> logout() async { + try { + await _apiClient.post(ApiPath.logout, headers: getAuthorizationHeader()); + return DC.data(unit); + } on ApiFailure catch (e, s) { + log('login', name: _logName, error: e, stackTrace: s); + return DC.error(AuthFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/auth/dto/auth_dto.dart b/lib/infrastructure/auth/dto/auth_dto.dart new file mode 100644 index 0000000..8ee5a68 --- /dev/null +++ b/lib/infrastructure/auth/dto/auth_dto.dart @@ -0,0 +1,23 @@ +part of '../auth_dtos.dart'; + +@freezed +class AuthDto with _$AuthDto { + const AuthDto._(); + + const factory AuthDto({ + @JsonKey(name: 'token') String? token, + @JsonKey(name: 'expires_at') String? expiresAt, + @JsonKey(name: 'user') UserDto? user, + }) = _AuthDto; + + factory AuthDto.fromJson(Map json) => + _$AuthDtoFromJson(json); + + Auth toDomain() => Auth( + token: token ?? '', + expiresAt: expiresAt != null + ? DateTime.parse(expiresAt ?? "") + : DateTime.fromMillisecondsSinceEpoch(0), + user: user?.toDomain() ?? User.empty(), + ); +} diff --git a/lib/infrastructure/auth/repositories/auth_repository.dart b/lib/infrastructure/auth/repositories/auth_repository.dart new file mode 100644 index 0000000..7e1e12d --- /dev/null +++ b/lib/infrastructure/auth/repositories/auth_repository.dart @@ -0,0 +1,92 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/auth/auth.dart'; +import '../../../domain/user/user.dart'; +import '../datasources/local_data_provider.dart'; +import '../datasources/remote_data_provider.dart'; + +@Injectable(as: IAuthRepository) +class AuthRepository implements IAuthRepository { + final AuthLocalDataProvider _localDataProvider; + final AuthRemoteDataProvider _remoteDataProvider; + + final String _logName = 'AuthRepository'; + + AuthRepository(this._localDataProvider, this._remoteDataProvider); + + @override + Future> login({ + required String email, + required String password, + required String deviceId, + required String deviceName, + required String deviceType, + required String platform, + required String osVersion, + required String appVersion, + String? fcmToken, + }) async { + try { + final result = await _remoteDataProvider.login( + email: email, + password: password, + deviceId: deviceId, + deviceName: deviceName, + deviceType: deviceType, + platform: platform, + osVersion: osVersion, + appVersion: appVersion, + fcmToken: fcmToken, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + await _localDataProvider.saveToken(auth.token); + await _localDataProvider.saveCurrentUser(result.data!.user!); + + return right(auth); + } catch (e, s) { + log('loginError', name: _logName, error: e, stackTrace: s); + return left(const AuthFailure.unexpectedError()); + } + } + + @override + Future> currentUser() async { + try { + User user = await _localDataProvider.currentUser(); + return right(user); + } catch (e, s) { + log('currentUserError', name: _logName, error: e, stackTrace: s); + return left(const AuthFailure.unexpectedError()); + } + } + + @override + Future hasToken() async { + return await _localDataProvider.hasToken(); + } + + @override + Future> logout() async { + try { + final result = await _remoteDataProvider.logout(); + if (result.hasError) { + return left(result.error!); + } + + await _localDataProvider.deleteAllAuth(); + return right(unit); + } catch (e, s) { + log('logoutError', name: _logName, error: e, stackTrace: s); + return left(const AuthFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/category/category_dtos.dart b/lib/infrastructure/category/category_dtos.dart new file mode 100644 index 0000000..f07cffc --- /dev/null +++ b/lib/infrastructure/category/category_dtos.dart @@ -0,0 +1,8 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/category/category.dart'; + +part 'category_dtos.freezed.dart'; +part 'category_dtos.g.dart'; + +part 'dto/category_dto.dart'; diff --git a/lib/infrastructure/category/category_dtos.freezed.dart b/lib/infrastructure/category/category_dtos.freezed.dart new file mode 100644 index 0000000..fb9448a --- /dev/null +++ b/lib/infrastructure/category/category_dtos.freezed.dart @@ -0,0 +1,368 @@ +// 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 'category_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +CategoryDto _$CategoryDtoFromJson(Map json) { + return _CategoryDto.fromJson(json); +} + +/// @nodoc +mixin _$CategoryDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'name') + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: 'description') + String? get description => throw _privateConstructorUsedError; + @JsonKey(name: 'business_type') + String? get businessType => throw _privateConstructorUsedError; + @JsonKey(name: 'metadata') + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + DateTime? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + DateTime? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this CategoryDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of CategoryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CategoryDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CategoryDtoCopyWith<$Res> { + factory $CategoryDtoCopyWith( + CategoryDto value, + $Res Function(CategoryDto) then, + ) = _$CategoryDtoCopyWithImpl<$Res, CategoryDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'description') String? description, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + }); +} + +/// @nodoc +class _$CategoryDtoCopyWithImpl<$Res, $Val extends CategoryDto> + implements $CategoryDtoCopyWith<$Res> { + _$CategoryDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CategoryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? name = freezed, + Object? description = freezed, + Object? businessType = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + businessType: freezed == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CategoryDtoImplCopyWith<$Res> + implements $CategoryDtoCopyWith<$Res> { + factory _$$CategoryDtoImplCopyWith( + _$CategoryDtoImpl value, + $Res Function(_$CategoryDtoImpl) then, + ) = __$$CategoryDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'description') String? description, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + }); +} + +/// @nodoc +class __$$CategoryDtoImplCopyWithImpl<$Res> + extends _$CategoryDtoCopyWithImpl<$Res, _$CategoryDtoImpl> + implements _$$CategoryDtoImplCopyWith<$Res> { + __$$CategoryDtoImplCopyWithImpl( + _$CategoryDtoImpl _value, + $Res Function(_$CategoryDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CategoryDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? name = freezed, + Object? description = freezed, + Object? businessType = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$CategoryDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + businessType: freezed == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$CategoryDtoImpl extends _CategoryDto { + const _$CategoryDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'name') this.name, + @JsonKey(name: 'description') this.description, + @JsonKey(name: 'business_type') this.businessType, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + }) : _metadata = metadata, + super._(); + + factory _$CategoryDtoImpl.fromJson(Map json) => + _$$CategoryDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'name') + final String? name; + @override + @JsonKey(name: 'description') + final String? description; + @override + @JsonKey(name: 'business_type') + final String? businessType; + final Map? _metadata; + @override + @JsonKey(name: 'metadata') + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'created_at') + final DateTime? createdAt; + @override + @JsonKey(name: 'updated_at') + final DateTime? updatedAt; + + @override + String toString() { + return 'CategoryDto(id: $id, organizationId: $organizationId, name: $name, description: $description, businessType: $businessType, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CategoryDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.name, name) || other.name == name) && + (identical(other.description, description) || + other.description == description) && + (identical(other.businessType, businessType) || + other.businessType == businessType) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + name, + description, + businessType, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of CategoryDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CategoryDtoImplCopyWith<_$CategoryDtoImpl> get copyWith => + __$$CategoryDtoImplCopyWithImpl<_$CategoryDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$CategoryDtoImplToJson(this); + } +} + +abstract class _CategoryDto extends CategoryDto { + const factory _CategoryDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'name') final String? name, + @JsonKey(name: 'description') final String? description, + @JsonKey(name: 'business_type') final String? businessType, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') final DateTime? createdAt, + @JsonKey(name: 'updated_at') final DateTime? updatedAt, + }) = _$CategoryDtoImpl; + const _CategoryDto._() : super._(); + + factory _CategoryDto.fromJson(Map json) = + _$CategoryDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'name') + String? get name; + @override + @JsonKey(name: 'description') + String? get description; + @override + @JsonKey(name: 'business_type') + String? get businessType; + @override + @JsonKey(name: 'metadata') + Map? get metadata; + @override + @JsonKey(name: 'created_at') + DateTime? get createdAt; + @override + @JsonKey(name: 'updated_at') + DateTime? get updatedAt; + + /// Create a copy of CategoryDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CategoryDtoImplCopyWith<_$CategoryDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/category/category_dtos.g.dart b/lib/infrastructure/category/category_dtos.g.dart new file mode 100644 index 0000000..d41549d --- /dev/null +++ b/lib/infrastructure/category/category_dtos.g.dart @@ -0,0 +1,35 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'category_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$CategoryDtoImpl _$$CategoryDtoImplFromJson(Map json) => + _$CategoryDtoImpl( + id: json['id'] as String?, + organizationId: json['organization_id'] as String?, + name: json['name'] as String?, + description: json['description'] as String?, + businessType: json['business_type'] as String?, + metadata: json['metadata'] as Map?, + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json['created_at'] as String), + updatedAt: json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String), + ); + +Map _$$CategoryDtoImplToJson(_$CategoryDtoImpl instance) => + { + 'id': instance.id, + 'organization_id': instance.organizationId, + 'name': instance.name, + 'description': instance.description, + 'business_type': instance.businessType, + 'metadata': instance.metadata, + 'created_at': instance.createdAt?.toIso8601String(), + 'updated_at': instance.updatedAt?.toIso8601String(), + }; diff --git a/lib/infrastructure/category/datasource/remote_data_provider.dart b/lib/infrastructure/category/datasource/remote_data_provider.dart new file mode 100644 index 0000000..62d916c --- /dev/null +++ b/lib/infrastructure/category/datasource/remote_data_provider.dart @@ -0,0 +1,46 @@ +import 'dart:developer'; + +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/category/category.dart'; +import '../category_dtos.dart'; + +@injectable +class CategoryRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = 'CategoryRemoteDataProvider'; + + CategoryRemoteDataProvider(this._apiClient); + + Future>> fetch({ + int page = 1, + int limit = 20, + bool isActive = true, + }) async { + try { + final response = await _apiClient.get( + ApiPath.category, + params: {'page': page, 'limit': limit, 'is_active': isActive}, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(CategoryFailure.empty()); + } + + final dto = (response.data['data']['categories'] as List) + .map((item) => CategoryDto.fromJson(item)) + .toList(); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchCategoryError', name: _logName, error: e, stackTrace: s); + return DC.error(CategoryFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/category/dto/category_dto.dart b/lib/infrastructure/category/dto/category_dto.dart new file mode 100644 index 0000000..7894f0c --- /dev/null +++ b/lib/infrastructure/category/dto/category_dto.dart @@ -0,0 +1,31 @@ +part of '../category_dtos.dart'; + +@freezed +class CategoryDto with _$CategoryDto { + const CategoryDto._(); + + const factory CategoryDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'description') String? description, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + }) = _CategoryDto; + + factory CategoryDto.fromJson(Map json) => + _$CategoryDtoFromJson(json); + + Category toDomain() => Category( + id: id ?? '', + organizationId: organizationId ?? '', + name: name ?? '', + description: description ?? '', + businessType: businessType ?? '', + metadata: metadata ?? {}, + createdAt: createdAt, + updatedAt: updatedAt, + ); +} diff --git a/lib/infrastructure/category/repositories/category_repository.dart b/lib/infrastructure/category/repositories/category_repository.dart new file mode 100644 index 0000000..73e96fe --- /dev/null +++ b/lib/infrastructure/category/repositories/category_repository.dart @@ -0,0 +1,41 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/category/category.dart'; +import '../datasource/remote_data_provider.dart'; + +@Injectable(as: ICategoryRepository) +class CategoryRepository implements ICategoryRepository { + final CategoryRemoteDataProvider _dataProvider; + final String _logName = 'CategoryRepository'; + + CategoryRepository(this._dataProvider); + + @override + Future>> get({ + int page = 1, + int limit = 20, + bool isActive = true, + }) async { + try { + final result = await _dataProvider.fetch( + page: page, + limit: limit, + isActive: isActive, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.map((e) => e.toDomain()).toList(); + + return right(auth); + } catch (e, s) { + log('getCategoryError', name: _logName, error: e, stackTrace: s); + return left(const CategoryFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/customer/customer_dtos.dart b/lib/infrastructure/customer/customer_dtos.dart new file mode 100644 index 0000000..ca0a1f0 --- /dev/null +++ b/lib/infrastructure/customer/customer_dtos.dart @@ -0,0 +1,8 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/customer/customer.dart'; + +part 'customer_dtos.freezed.dart'; +part 'customer_dtos.g.dart'; + +part 'dto/customer_dto.dart'; diff --git a/lib/infrastructure/customer/customer_dtos.freezed.dart b/lib/infrastructure/customer/customer_dtos.freezed.dart new file mode 100644 index 0000000..1f3f52d --- /dev/null +++ b/lib/infrastructure/customer/customer_dtos.freezed.dart @@ -0,0 +1,440 @@ +// 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 'customer_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +CustomerDto _$CustomerDtoFromJson(Map json) { + return _CustomerDto.fromJson(json); +} + +/// @nodoc +mixin _$CustomerDto { + @JsonKey(name: "id") + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: "organization_id") + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: "name") + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: "email") + String? get email => throw _privateConstructorUsedError; + @JsonKey(name: "phone") + String? get phone => throw _privateConstructorUsedError; + @JsonKey(name: "address") + String? get address => throw _privateConstructorUsedError; + @JsonKey(name: "is_default") + bool? get isDefault => throw _privateConstructorUsedError; + @JsonKey(name: "is_active") + bool? get isActive => throw _privateConstructorUsedError; + @JsonKey(name: "metadata") + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: "created_at") + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: "updated_at") + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this CustomerDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of CustomerDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $CustomerDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CustomerDtoCopyWith<$Res> { + factory $CustomerDtoCopyWith( + CustomerDto value, + $Res Function(CustomerDto) then, + ) = _$CustomerDtoCopyWithImpl<$Res, CustomerDto>; + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "organization_id") String? organizationId, + @JsonKey(name: "name") String? name, + @JsonKey(name: "email") String? email, + @JsonKey(name: "phone") String? phone, + @JsonKey(name: "address") String? address, + @JsonKey(name: "is_default") bool? isDefault, + @JsonKey(name: "is_active") bool? isActive, + @JsonKey(name: "metadata") Map? metadata, + @JsonKey(name: "created_at") String? createdAt, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class _$CustomerDtoCopyWithImpl<$Res, $Val extends CustomerDto> + implements $CustomerDtoCopyWith<$Res> { + _$CustomerDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of CustomerDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? name = freezed, + Object? email = freezed, + Object? phone = freezed, + Object? address = freezed, + Object? isDefault = freezed, + Object? isActive = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + email: freezed == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String?, + phone: freezed == phone + ? _value.phone + : phone // ignore: cast_nullable_to_non_nullable + as String?, + address: freezed == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String?, + isDefault: freezed == isDefault + ? _value.isDefault + : isDefault // ignore: cast_nullable_to_non_nullable + as bool?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$CustomerDtoImplCopyWith<$Res> + implements $CustomerDtoCopyWith<$Res> { + factory _$$CustomerDtoImplCopyWith( + _$CustomerDtoImpl value, + $Res Function(_$CustomerDtoImpl) then, + ) = __$$CustomerDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "organization_id") String? organizationId, + @JsonKey(name: "name") String? name, + @JsonKey(name: "email") String? email, + @JsonKey(name: "phone") String? phone, + @JsonKey(name: "address") String? address, + @JsonKey(name: "is_default") bool? isDefault, + @JsonKey(name: "is_active") bool? isActive, + @JsonKey(name: "metadata") Map? metadata, + @JsonKey(name: "created_at") String? createdAt, + @JsonKey(name: "updated_at") String? updatedAt, + }); +} + +/// @nodoc +class __$$CustomerDtoImplCopyWithImpl<$Res> + extends _$CustomerDtoCopyWithImpl<$Res, _$CustomerDtoImpl> + implements _$$CustomerDtoImplCopyWith<$Res> { + __$$CustomerDtoImplCopyWithImpl( + _$CustomerDtoImpl _value, + $Res Function(_$CustomerDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of CustomerDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? name = freezed, + Object? email = freezed, + Object? phone = freezed, + Object? address = freezed, + Object? isDefault = freezed, + Object? isActive = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$CustomerDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + email: freezed == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String?, + phone: freezed == phone + ? _value.phone + : phone // ignore: cast_nullable_to_non_nullable + as String?, + address: freezed == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String?, + isDefault: freezed == isDefault + ? _value.isDefault + : isDefault // ignore: cast_nullable_to_non_nullable + as bool?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$CustomerDtoImpl extends _CustomerDto { + const _$CustomerDtoImpl({ + @JsonKey(name: "id") this.id, + @JsonKey(name: "organization_id") this.organizationId, + @JsonKey(name: "name") this.name, + @JsonKey(name: "email") this.email, + @JsonKey(name: "phone") this.phone, + @JsonKey(name: "address") this.address, + @JsonKey(name: "is_default") this.isDefault, + @JsonKey(name: "is_active") this.isActive, + @JsonKey(name: "metadata") final Map? metadata, + @JsonKey(name: "created_at") this.createdAt, + @JsonKey(name: "updated_at") this.updatedAt, + }) : _metadata = metadata, + super._(); + + factory _$CustomerDtoImpl.fromJson(Map json) => + _$$CustomerDtoImplFromJson(json); + + @override + @JsonKey(name: "id") + final String? id; + @override + @JsonKey(name: "organization_id") + final String? organizationId; + @override + @JsonKey(name: "name") + final String? name; + @override + @JsonKey(name: "email") + final String? email; + @override + @JsonKey(name: "phone") + final String? phone; + @override + @JsonKey(name: "address") + final String? address; + @override + @JsonKey(name: "is_default") + final bool? isDefault; + @override + @JsonKey(name: "is_active") + final bool? isActive; + final Map? _metadata; + @override + @JsonKey(name: "metadata") + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: "created_at") + final String? createdAt; + @override + @JsonKey(name: "updated_at") + final String? updatedAt; + + @override + String toString() { + return 'CustomerDto(id: $id, organizationId: $organizationId, name: $name, email: $email, phone: $phone, address: $address, isDefault: $isDefault, isActive: $isActive, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CustomerDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.name, name) || other.name == name) && + (identical(other.email, email) || other.email == email) && + (identical(other.phone, phone) || other.phone == phone) && + (identical(other.address, address) || other.address == address) && + (identical(other.isDefault, isDefault) || + other.isDefault == isDefault) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + name, + email, + phone, + address, + isDefault, + isActive, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of CustomerDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CustomerDtoImplCopyWith<_$CustomerDtoImpl> get copyWith => + __$$CustomerDtoImplCopyWithImpl<_$CustomerDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$CustomerDtoImplToJson(this); + } +} + +abstract class _CustomerDto extends CustomerDto { + const factory _CustomerDto({ + @JsonKey(name: "id") final String? id, + @JsonKey(name: "organization_id") final String? organizationId, + @JsonKey(name: "name") final String? name, + @JsonKey(name: "email") final String? email, + @JsonKey(name: "phone") final String? phone, + @JsonKey(name: "address") final String? address, + @JsonKey(name: "is_default") final bool? isDefault, + @JsonKey(name: "is_active") final bool? isActive, + @JsonKey(name: "metadata") final Map? metadata, + @JsonKey(name: "created_at") final String? createdAt, + @JsonKey(name: "updated_at") final String? updatedAt, + }) = _$CustomerDtoImpl; + const _CustomerDto._() : super._(); + + factory _CustomerDto.fromJson(Map json) = + _$CustomerDtoImpl.fromJson; + + @override + @JsonKey(name: "id") + String? get id; + @override + @JsonKey(name: "organization_id") + String? get organizationId; + @override + @JsonKey(name: "name") + String? get name; + @override + @JsonKey(name: "email") + String? get email; + @override + @JsonKey(name: "phone") + String? get phone; + @override + @JsonKey(name: "address") + String? get address; + @override + @JsonKey(name: "is_default") + bool? get isDefault; + @override + @JsonKey(name: "is_active") + bool? get isActive; + @override + @JsonKey(name: "metadata") + Map? get metadata; + @override + @JsonKey(name: "created_at") + String? get createdAt; + @override + @JsonKey(name: "updated_at") + String? get updatedAt; + + /// Create a copy of CustomerDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CustomerDtoImplCopyWith<_$CustomerDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/customer/customer_dtos.g.dart b/lib/infrastructure/customer/customer_dtos.g.dart new file mode 100644 index 0000000..148d005 --- /dev/null +++ b/lib/infrastructure/customer/customer_dtos.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'customer_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$CustomerDtoImpl _$$CustomerDtoImplFromJson(Map json) => + _$CustomerDtoImpl( + id: json['id'] as String?, + organizationId: json['organization_id'] as String?, + name: json['name'] as String?, + email: json['email'] as String?, + phone: json['phone'] as String?, + address: json['address'] as String?, + isDefault: json['is_default'] as bool?, + isActive: json['is_active'] as bool?, + metadata: json['metadata'] as Map?, + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, + ); + +Map _$$CustomerDtoImplToJson(_$CustomerDtoImpl instance) => + { + 'id': instance.id, + 'organization_id': instance.organizationId, + 'name': instance.name, + 'email': instance.email, + 'phone': instance.phone, + 'address': instance.address, + 'is_default': instance.isDefault, + 'is_active': instance.isActive, + 'metadata': instance.metadata, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, + }; diff --git a/lib/infrastructure/customer/datasources/remote_data_provider.dart b/lib/infrastructure/customer/datasources/remote_data_provider.dart new file mode 100644 index 0000000..442a093 --- /dev/null +++ b/lib/infrastructure/customer/datasources/remote_data_provider.dart @@ -0,0 +1,52 @@ +import 'dart:developer'; + +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/customer/customer.dart'; +import '../customer_dtos.dart'; + +@injectable +class CustomerRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = "CustomerRemoteDataProvider"; + + CustomerRemoteDataProvider(this._apiClient); + + Future>> fetch({ + int page = 1, + int limit = 20, + String? search, + }) async { + try { + Map params = {'page': page, 'limit': limit}; + + if (search != null && search.isNotEmpty) { + params['search'] = search; + } + + final response = await _apiClient.get( + ApiPath.customer, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(CustomerFailure.empty()); + } + + final dto = (response.data['data']['data'] as List) + .map((e) => CustomerDto.fromJson(e)) + .toList(); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchCustomerError', name: _logName, error: e, stackTrace: s); + return DC.error(CustomerFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/customer/dto/customer_dto.dart b/lib/infrastructure/customer/dto/customer_dto.dart new file mode 100644 index 0000000..46cba2a --- /dev/null +++ b/lib/infrastructure/customer/dto/customer_dto.dart @@ -0,0 +1,39 @@ +part of '../customer_dtos.dart'; + +@freezed +class CustomerDto with _$CustomerDto { + const CustomerDto._(); + + const factory CustomerDto({ + @JsonKey(name: "id") String? id, + @JsonKey(name: "organization_id") String? organizationId, + @JsonKey(name: "name") String? name, + @JsonKey(name: "email") String? email, + @JsonKey(name: "phone") String? phone, + @JsonKey(name: "address") String? address, + @JsonKey(name: "is_default") bool? isDefault, + @JsonKey(name: "is_active") bool? isActive, + @JsonKey(name: "metadata") Map? metadata, + @JsonKey(name: "created_at") String? createdAt, + @JsonKey(name: "updated_at") String? updatedAt, + }) = _CustomerDto; + + factory CustomerDto.fromJson(Map json) => + _$CustomerDtoFromJson(json); + + Customer toDomain() { + return Customer( + id: id ?? '', + organizationId: organizationId ?? '', + name: name ?? '', + email: email ?? '', + phone: phone ?? '', + address: address ?? '', + isDefault: isDefault ?? false, + isActive: isActive ?? false, + metadata: metadata ?? {}, + createdAt: createdAt ?? '', + updatedAt: updatedAt ?? '', + ); + } +} diff --git a/lib/infrastructure/customer/repositories/customer_repository.dart b/lib/infrastructure/customer/repositories/customer_repository.dart new file mode 100644 index 0000000..b826b8d --- /dev/null +++ b/lib/infrastructure/customer/repositories/customer_repository.dart @@ -0,0 +1,41 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/customer/customer.dart'; +import '../datasources/remote_data_provider.dart'; + +@Injectable(as: ICustomerRepository) +class CustomerRepository implements ICustomerRepository { + final CustomerRemoteDataProvider _dataProvider; + final String _logName = 'CustomerRepository'; + + CustomerRepository(this._dataProvider); + + @override + Future>> get({ + int page = 1, + int limit = 20, + String? search, + }) async { + try { + final result = await _dataProvider.fetch( + page: page, + limit: limit, + search: search, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.map((item) => item.toDomain()).toList(); + + return right(auth); + } catch (e, s) { + log('getCustomerError', name: _logName, error: e, stackTrace: s); + return left(const CustomerFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/language/language.dart b/lib/infrastructure/language/language.dart new file mode 100644 index 0000000..ef06c40 --- /dev/null +++ b/lib/infrastructure/language/language.dart @@ -0,0 +1,18 @@ +import 'dart:ui'; + +import '../../domain/language/language.dart'; + +List languages = [ + Language( + locale: const Locale('id', 'ID'), + name: 'Indonesian', + path: '🇮🇩', + nativeName: 'Bahasa Indonesia', + ), + Language( + locale: const Locale('en', 'US'), + name: 'English', + path: '🇺🇸', + nativeName: 'English', + ), +]; diff --git a/lib/infrastructure/order/datasource/remote_data_provider.dart b/lib/infrastructure/order/datasource/remote_data_provider.dart new file mode 100644 index 0000000..ecc4fda --- /dev/null +++ b/lib/infrastructure/order/datasource/remote_data_provider.dart @@ -0,0 +1,70 @@ +import 'dart:developer'; + +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/order/order.dart'; +import '../order_dtos.dart'; + +@injectable +class OrderRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = 'OrderRemoteDataProvider'; + + OrderRemoteDataProvider(this._apiClient); + + Future>> fetch({ + int page = 1, + int limit = 10, + String? status, + String? search, + String? outletId, + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + Map params = { + 'page': page, + 'limit': limit, + 'date_from': dateFrom.toServerDate, + 'date_to': dateTo.toServerDate, + }; + + if (status != null && status.isNotEmpty) { + params['status'] = status; + } + + if (search != null && search.isNotEmpty) { + params['search'] = search; + } + + // if (outletId != null) { + // params['outlet_id'] = outletId; + // } + + final response = await _apiClient.get( + ApiPath.order, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(OrderFailure.empty()); + } + + final dto = (response.data['data']['orders'] as List) + .map((item) => OrderDto.fromJson(item)) + .toList(); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchOrderError', name: _logName, error: e, stackTrace: s); + return DC.error(OrderFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/order/dto/order_dto.dart b/lib/infrastructure/order/dto/order_dto.dart new file mode 100644 index 0000000..56d5818 --- /dev/null +++ b/lib/infrastructure/order/dto/order_dto.dart @@ -0,0 +1,183 @@ +part of '../order_dtos.dart'; + +@freezed +class OrderDto with _$OrderDto { + const OrderDto._(); + + const factory OrderDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_number') String? orderNumber, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'user_id') String? userId, + @JsonKey(name: 'table_number') String? tableNumber, + @JsonKey(name: 'order_type') String? orderType, + @JsonKey(name: 'status') String? status, + @JsonKey(name: 'subtotal') int? subtotal, + @JsonKey(name: 'tax_amount') int? taxAmount, + @JsonKey(name: 'discount_amount') int? discountAmount, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'remaining_amount') int? remainingAmount, + @JsonKey(name: 'payment_status') String? paymentStatus, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'is_void') bool? isVoid, + @JsonKey(name: 'is_refund') bool? isRefund, + @JsonKey(name: 'notes') String? notes, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + @JsonKey(name: 'order_items') List? orderItems, + @JsonKey(name: 'payments') List? payments, + @JsonKey(name: 'total_paid') int? totalPaid, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'split_type') String? splitType, + }) = _OrderDto; + + factory OrderDto.fromJson(Map json) => + _$OrderDtoFromJson(json); + + Order toDomain() => Order( + id: id ?? '', + orderNumber: orderNumber ?? '', + outletId: outletId ?? '', + userId: userId ?? '', + tableNumber: tableNumber ?? '', + orderType: orderType ?? '', + status: status ?? '', + subtotal: subtotal ?? 0, + taxAmount: taxAmount ?? 0, + discountAmount: discountAmount ?? 0, + totalAmount: totalAmount ?? 0, + totalCost: totalCost ?? 0, + remainingAmount: remainingAmount ?? 0, + paymentStatus: paymentStatus ?? '', + refundAmount: refundAmount ?? 0, + isVoid: isVoid ?? false, + isRefund: isRefund ?? false, + notes: notes ?? '', + metadata: metadata ?? {}, + createdAt: createdAt ?? '', + updatedAt: updatedAt ?? '', + orderItems: orderItems?.map((e) => e.toDomain()).toList() ?? [], + payments: payments?.map((e) => e.toDomain()).toList() ?? [], + totalPaid: totalPaid ?? 0, + paymentCount: paymentCount ?? 0, + splitType: splitType ?? '', + ); +} + +@freezed +class OrderItemDto with _$OrderItemDto { + const OrderItemDto._(); + + const factory OrderItemDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'quantity') int? quantity, + @JsonKey(name: 'price') int? price, + @JsonKey(name: 'subtotal') int? subtotal, + @JsonKey(name: 'discount_amount') int? discountAmount, + @JsonKey(name: 'total') int? total, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }) = _OrderItemDto; + + factory OrderItemDto.fromJson(Map json) => + _$OrderItemDtoFromJson(json); + + OrderItem toDomain() => OrderItem( + id: id ?? '', + orderId: orderId ?? '', + productId: productId ?? '', + productName: productName ?? '', + quantity: quantity ?? 0, + price: price ?? 0, + subtotal: subtotal ?? 0, + discountAmount: discountAmount ?? 0, + total: total ?? 0, + cost: cost ?? 0, + metadata: metadata ?? {}, + createdAt: createdAt ?? '', + updatedAt: updatedAt ?? '', + ); +} + +@freezed +class OrderPaymentDto with _$OrderPaymentDto { + const OrderPaymentDto._(); + + const factory OrderPaymentDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'amount') int? amount, + @JsonKey(name: 'status') String? status, + @JsonKey(name: 'split_number') int? splitNumber, + @JsonKey(name: 'split_total') int? splitTotal, + @JsonKey(name: 'split_type') String? splitType, + @JsonKey(name: 'split_description') String? splitDescription, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + @JsonKey(name: 'payment_order_items') + List? paymentOrderItems, + }) = _OrderPaymentDto; + + factory OrderPaymentDto.fromJson(Map json) => + _$OrderPaymentDtoFromJson(json); + + OrderPayment toDomain() => OrderPayment( + id: id ?? '', + orderId: orderId ?? '', + paymentMethodId: paymentMethodId ?? '', + paymentMethodName: paymentMethodName ?? '', + paymentMethodType: paymentMethodType ?? '', + amount: amount ?? 0, + status: status ?? '', + splitNumber: splitNumber ?? 0, + splitTotal: splitTotal ?? 0, + splitType: splitType ?? '', + splitDescription: splitDescription ?? '', + refundAmount: refundAmount ?? 0, + metadata: metadata ?? {}, + createdAt: createdAt ?? '', + updatedAt: updatedAt ?? '', + paymentOrderItems: + paymentOrderItems?.map((e) => e.toDomain()).toList() ?? [], + ); +} + +@freezed +class PaymentOrderItemDto with _$PaymentOrderItemDto { + const PaymentOrderItemDto._(); + + const factory PaymentOrderItemDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_payment_id') String? orderPaymentId, + @JsonKey(name: 'order_item_id') String? orderItemId, + @JsonKey(name: 'amount') int? amount, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }) = _PaymentOrderItemDto; + + factory PaymentOrderItemDto.fromJson(Map json) => + _$PaymentOrderItemDtoFromJson(json); + + PaymentOrderItem toDomain() => PaymentOrderItem( + id: id ?? '', + orderPaymentId: orderPaymentId ?? '', + orderItemId: orderItemId ?? '', + amount: amount ?? 0, + refundAmount: refundAmount ?? 0, + createdAt: createdAt ?? '', + updatedAt: updatedAt ?? '', + ); +} diff --git a/lib/infrastructure/order/order_dtos.dart b/lib/infrastructure/order/order_dtos.dart new file mode 100644 index 0000000..9855ed4 --- /dev/null +++ b/lib/infrastructure/order/order_dtos.dart @@ -0,0 +1,8 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/order/order.dart'; + +part 'order_dtos.freezed.dart'; +part 'order_dtos.g.dart'; + +part 'dto/order_dto.dart'; diff --git a/lib/infrastructure/order/order_dtos.freezed.dart b/lib/infrastructure/order/order_dtos.freezed.dart new file mode 100644 index 0000000..7b4f88e --- /dev/null +++ b/lib/infrastructure/order/order_dtos.freezed.dart @@ -0,0 +1,2197 @@ +// 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 'order_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +OrderDto _$OrderDtoFromJson(Map json) { + return _OrderDto.fromJson(json); +} + +/// @nodoc +mixin _$OrderDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'order_number') + String? get orderNumber => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'user_id') + String? get userId => throw _privateConstructorUsedError; + @JsonKey(name: 'table_number') + String? get tableNumber => throw _privateConstructorUsedError; + @JsonKey(name: 'order_type') + String? get orderType => throw _privateConstructorUsedError; + @JsonKey(name: 'status') + String? get status => throw _privateConstructorUsedError; + @JsonKey(name: 'subtotal') + int? get subtotal => throw _privateConstructorUsedError; + @JsonKey(name: 'tax_amount') + int? get taxAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'discount_amount') + int? get discountAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'total_amount') + int? get totalAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'total_cost') + int? get totalCost => throw _privateConstructorUsedError; + @JsonKey(name: 'remaining_amount') + int? get remainingAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_status') + String? get paymentStatus => throw _privateConstructorUsedError; + @JsonKey(name: 'refund_amount') + int? get refundAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'is_void') + bool? get isVoid => throw _privateConstructorUsedError; + @JsonKey(name: 'is_refund') + bool? get isRefund => throw _privateConstructorUsedError; + @JsonKey(name: 'notes') + String? get notes => throw _privateConstructorUsedError; + @JsonKey(name: 'metadata') + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + String? get updatedAt => throw _privateConstructorUsedError; + @JsonKey(name: 'order_items') + List? get orderItems => throw _privateConstructorUsedError; + @JsonKey(name: 'payments') + List? get payments => throw _privateConstructorUsedError; + @JsonKey(name: 'total_paid') + int? get totalPaid => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_count') + int? get paymentCount => throw _privateConstructorUsedError; + @JsonKey(name: 'split_type') + String? get splitType => throw _privateConstructorUsedError; + + /// Serializes this OrderDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of OrderDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderDtoCopyWith<$Res> { + factory $OrderDtoCopyWith(OrderDto value, $Res Function(OrderDto) then) = + _$OrderDtoCopyWithImpl<$Res, OrderDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_number') String? orderNumber, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'user_id') String? userId, + @JsonKey(name: 'table_number') String? tableNumber, + @JsonKey(name: 'order_type') String? orderType, + @JsonKey(name: 'status') String? status, + @JsonKey(name: 'subtotal') int? subtotal, + @JsonKey(name: 'tax_amount') int? taxAmount, + @JsonKey(name: 'discount_amount') int? discountAmount, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'remaining_amount') int? remainingAmount, + @JsonKey(name: 'payment_status') String? paymentStatus, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'is_void') bool? isVoid, + @JsonKey(name: 'is_refund') bool? isRefund, + @JsonKey(name: 'notes') String? notes, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + @JsonKey(name: 'order_items') List? orderItems, + @JsonKey(name: 'payments') List? payments, + @JsonKey(name: 'total_paid') int? totalPaid, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'split_type') String? splitType, + }); +} + +/// @nodoc +class _$OrderDtoCopyWithImpl<$Res, $Val extends OrderDto> + implements $OrderDtoCopyWith<$Res> { + _$OrderDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderNumber = freezed, + Object? outletId = freezed, + Object? userId = freezed, + Object? tableNumber = freezed, + Object? orderType = freezed, + Object? status = freezed, + Object? subtotal = freezed, + Object? taxAmount = freezed, + Object? discountAmount = freezed, + Object? totalAmount = freezed, + Object? totalCost = freezed, + Object? remainingAmount = freezed, + Object? paymentStatus = freezed, + Object? refundAmount = freezed, + Object? isVoid = freezed, + Object? isRefund = freezed, + Object? notes = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + Object? orderItems = freezed, + Object? payments = freezed, + Object? totalPaid = freezed, + Object? paymentCount = freezed, + Object? splitType = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderNumber: freezed == orderNumber + ? _value.orderNumber + : orderNumber // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + userId: freezed == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String?, + tableNumber: freezed == tableNumber + ? _value.tableNumber + : tableNumber // ignore: cast_nullable_to_non_nullable + as String?, + orderType: freezed == orderType + ? _value.orderType + : orderType // ignore: cast_nullable_to_non_nullable + as String?, + status: freezed == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String?, + subtotal: freezed == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int?, + taxAmount: freezed == taxAmount + ? _value.taxAmount + : taxAmount // ignore: cast_nullable_to_non_nullable + as int?, + discountAmount: freezed == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int?, + totalCost: freezed == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int?, + remainingAmount: freezed == remainingAmount + ? _value.remainingAmount + : remainingAmount // ignore: cast_nullable_to_non_nullable + as int?, + paymentStatus: freezed == paymentStatus + ? _value.paymentStatus + : paymentStatus // ignore: cast_nullable_to_non_nullable + as String?, + refundAmount: freezed == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int?, + isVoid: freezed == isVoid + ? _value.isVoid + : isVoid // ignore: cast_nullable_to_non_nullable + as bool?, + isRefund: freezed == isRefund + ? _value.isRefund + : isRefund // ignore: cast_nullable_to_non_nullable + as bool?, + notes: freezed == notes + ? _value.notes + : notes // ignore: cast_nullable_to_non_nullable + as String?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + orderItems: freezed == orderItems + ? _value.orderItems + : orderItems // ignore: cast_nullable_to_non_nullable + as List?, + payments: freezed == payments + ? _value.payments + : payments // ignore: cast_nullable_to_non_nullable + as List?, + totalPaid: freezed == totalPaid + ? _value.totalPaid + : totalPaid // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + splitType: freezed == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OrderDtoImplCopyWith<$Res> + implements $OrderDtoCopyWith<$Res> { + factory _$$OrderDtoImplCopyWith( + _$OrderDtoImpl value, + $Res Function(_$OrderDtoImpl) then, + ) = __$$OrderDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_number') String? orderNumber, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'user_id') String? userId, + @JsonKey(name: 'table_number') String? tableNumber, + @JsonKey(name: 'order_type') String? orderType, + @JsonKey(name: 'status') String? status, + @JsonKey(name: 'subtotal') int? subtotal, + @JsonKey(name: 'tax_amount') int? taxAmount, + @JsonKey(name: 'discount_amount') int? discountAmount, + @JsonKey(name: 'total_amount') int? totalAmount, + @JsonKey(name: 'total_cost') int? totalCost, + @JsonKey(name: 'remaining_amount') int? remainingAmount, + @JsonKey(name: 'payment_status') String? paymentStatus, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'is_void') bool? isVoid, + @JsonKey(name: 'is_refund') bool? isRefund, + @JsonKey(name: 'notes') String? notes, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + @JsonKey(name: 'order_items') List? orderItems, + @JsonKey(name: 'payments') List? payments, + @JsonKey(name: 'total_paid') int? totalPaid, + @JsonKey(name: 'payment_count') int? paymentCount, + @JsonKey(name: 'split_type') String? splitType, + }); +} + +/// @nodoc +class __$$OrderDtoImplCopyWithImpl<$Res> + extends _$OrderDtoCopyWithImpl<$Res, _$OrderDtoImpl> + implements _$$OrderDtoImplCopyWith<$Res> { + __$$OrderDtoImplCopyWithImpl( + _$OrderDtoImpl _value, + $Res Function(_$OrderDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderNumber = freezed, + Object? outletId = freezed, + Object? userId = freezed, + Object? tableNumber = freezed, + Object? orderType = freezed, + Object? status = freezed, + Object? subtotal = freezed, + Object? taxAmount = freezed, + Object? discountAmount = freezed, + Object? totalAmount = freezed, + Object? totalCost = freezed, + Object? remainingAmount = freezed, + Object? paymentStatus = freezed, + Object? refundAmount = freezed, + Object? isVoid = freezed, + Object? isRefund = freezed, + Object? notes = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + Object? orderItems = freezed, + Object? payments = freezed, + Object? totalPaid = freezed, + Object? paymentCount = freezed, + Object? splitType = freezed, + }) { + return _then( + _$OrderDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderNumber: freezed == orderNumber + ? _value.orderNumber + : orderNumber // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + userId: freezed == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String?, + tableNumber: freezed == tableNumber + ? _value.tableNumber + : tableNumber // ignore: cast_nullable_to_non_nullable + as String?, + orderType: freezed == orderType + ? _value.orderType + : orderType // ignore: cast_nullable_to_non_nullable + as String?, + status: freezed == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String?, + subtotal: freezed == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int?, + taxAmount: freezed == taxAmount + ? _value.taxAmount + : taxAmount // ignore: cast_nullable_to_non_nullable + as int?, + discountAmount: freezed == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int?, + totalAmount: freezed == totalAmount + ? _value.totalAmount + : totalAmount // ignore: cast_nullable_to_non_nullable + as int?, + totalCost: freezed == totalCost + ? _value.totalCost + : totalCost // ignore: cast_nullable_to_non_nullable + as int?, + remainingAmount: freezed == remainingAmount + ? _value.remainingAmount + : remainingAmount // ignore: cast_nullable_to_non_nullable + as int?, + paymentStatus: freezed == paymentStatus + ? _value.paymentStatus + : paymentStatus // ignore: cast_nullable_to_non_nullable + as String?, + refundAmount: freezed == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int?, + isVoid: freezed == isVoid + ? _value.isVoid + : isVoid // ignore: cast_nullable_to_non_nullable + as bool?, + isRefund: freezed == isRefund + ? _value.isRefund + : isRefund // ignore: cast_nullable_to_non_nullable + as bool?, + notes: freezed == notes + ? _value.notes + : notes // ignore: cast_nullable_to_non_nullable + as String?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + orderItems: freezed == orderItems + ? _value._orderItems + : orderItems // ignore: cast_nullable_to_non_nullable + as List?, + payments: freezed == payments + ? _value._payments + : payments // ignore: cast_nullable_to_non_nullable + as List?, + totalPaid: freezed == totalPaid + ? _value.totalPaid + : totalPaid // ignore: cast_nullable_to_non_nullable + as int?, + paymentCount: freezed == paymentCount + ? _value.paymentCount + : paymentCount // ignore: cast_nullable_to_non_nullable + as int?, + splitType: freezed == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$OrderDtoImpl extends _OrderDto { + const _$OrderDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'order_number') this.orderNumber, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'user_id') this.userId, + @JsonKey(name: 'table_number') this.tableNumber, + @JsonKey(name: 'order_type') this.orderType, + @JsonKey(name: 'status') this.status, + @JsonKey(name: 'subtotal') this.subtotal, + @JsonKey(name: 'tax_amount') this.taxAmount, + @JsonKey(name: 'discount_amount') this.discountAmount, + @JsonKey(name: 'total_amount') this.totalAmount, + @JsonKey(name: 'total_cost') this.totalCost, + @JsonKey(name: 'remaining_amount') this.remainingAmount, + @JsonKey(name: 'payment_status') this.paymentStatus, + @JsonKey(name: 'refund_amount') this.refundAmount, + @JsonKey(name: 'is_void') this.isVoid, + @JsonKey(name: 'is_refund') this.isRefund, + @JsonKey(name: 'notes') this.notes, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + @JsonKey(name: 'order_items') final List? orderItems, + @JsonKey(name: 'payments') final List? payments, + @JsonKey(name: 'total_paid') this.totalPaid, + @JsonKey(name: 'payment_count') this.paymentCount, + @JsonKey(name: 'split_type') this.splitType, + }) : _metadata = metadata, + _orderItems = orderItems, + _payments = payments, + super._(); + + factory _$OrderDtoImpl.fromJson(Map json) => + _$$OrderDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'order_number') + final String? orderNumber; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'user_id') + final String? userId; + @override + @JsonKey(name: 'table_number') + final String? tableNumber; + @override + @JsonKey(name: 'order_type') + final String? orderType; + @override + @JsonKey(name: 'status') + final String? status; + @override + @JsonKey(name: 'subtotal') + final int? subtotal; + @override + @JsonKey(name: 'tax_amount') + final int? taxAmount; + @override + @JsonKey(name: 'discount_amount') + final int? discountAmount; + @override + @JsonKey(name: 'total_amount') + final int? totalAmount; + @override + @JsonKey(name: 'total_cost') + final int? totalCost; + @override + @JsonKey(name: 'remaining_amount') + final int? remainingAmount; + @override + @JsonKey(name: 'payment_status') + final String? paymentStatus; + @override + @JsonKey(name: 'refund_amount') + final int? refundAmount; + @override + @JsonKey(name: 'is_void') + final bool? isVoid; + @override + @JsonKey(name: 'is_refund') + final bool? isRefund; + @override + @JsonKey(name: 'notes') + final String? notes; + final Map? _metadata; + @override + @JsonKey(name: 'metadata') + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'created_at') + final String? createdAt; + @override + @JsonKey(name: 'updated_at') + final String? updatedAt; + final List? _orderItems; + @override + @JsonKey(name: 'order_items') + List? get orderItems { + final value = _orderItems; + if (value == null) return null; + if (_orderItems is EqualUnmodifiableListView) return _orderItems; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + final List? _payments; + @override + @JsonKey(name: 'payments') + List? get payments { + final value = _payments; + if (value == null) return null; + if (_payments is EqualUnmodifiableListView) return _payments; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + @JsonKey(name: 'total_paid') + final int? totalPaid; + @override + @JsonKey(name: 'payment_count') + final int? paymentCount; + @override + @JsonKey(name: 'split_type') + final String? splitType; + + @override + String toString() { + return 'OrderDto(id: $id, orderNumber: $orderNumber, outletId: $outletId, userId: $userId, tableNumber: $tableNumber, orderType: $orderType, status: $status, subtotal: $subtotal, taxAmount: $taxAmount, discountAmount: $discountAmount, totalAmount: $totalAmount, totalCost: $totalCost, remainingAmount: $remainingAmount, paymentStatus: $paymentStatus, refundAmount: $refundAmount, isVoid: $isVoid, isRefund: $isRefund, notes: $notes, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt, orderItems: $orderItems, payments: $payments, totalPaid: $totalPaid, paymentCount: $paymentCount, splitType: $splitType)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderNumber, orderNumber) || + other.orderNumber == orderNumber) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.userId, userId) || other.userId == userId) && + (identical(other.tableNumber, tableNumber) || + other.tableNumber == tableNumber) && + (identical(other.orderType, orderType) || + other.orderType == orderType) && + (identical(other.status, status) || other.status == status) && + (identical(other.subtotal, subtotal) || + other.subtotal == subtotal) && + (identical(other.taxAmount, taxAmount) || + other.taxAmount == taxAmount) && + (identical(other.discountAmount, discountAmount) || + other.discountAmount == discountAmount) && + (identical(other.totalAmount, totalAmount) || + other.totalAmount == totalAmount) && + (identical(other.totalCost, totalCost) || + other.totalCost == totalCost) && + (identical(other.remainingAmount, remainingAmount) || + other.remainingAmount == remainingAmount) && + (identical(other.paymentStatus, paymentStatus) || + other.paymentStatus == paymentStatus) && + (identical(other.refundAmount, refundAmount) || + other.refundAmount == refundAmount) && + (identical(other.isVoid, isVoid) || other.isVoid == isVoid) && + (identical(other.isRefund, isRefund) || + other.isRefund == isRefund) && + (identical(other.notes, notes) || other.notes == notes) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals( + other._orderItems, + _orderItems, + ) && + const DeepCollectionEquality().equals(other._payments, _payments) && + (identical(other.totalPaid, totalPaid) || + other.totalPaid == totalPaid) && + (identical(other.paymentCount, paymentCount) || + other.paymentCount == paymentCount) && + (identical(other.splitType, splitType) || + other.splitType == splitType)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hashAll([ + runtimeType, + id, + orderNumber, + outletId, + userId, + tableNumber, + orderType, + status, + subtotal, + taxAmount, + discountAmount, + totalAmount, + totalCost, + remainingAmount, + paymentStatus, + refundAmount, + isVoid, + isRefund, + notes, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + const DeepCollectionEquality().hash(_orderItems), + const DeepCollectionEquality().hash(_payments), + totalPaid, + paymentCount, + splitType, + ]); + + /// Create a copy of OrderDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderDtoImplCopyWith<_$OrderDtoImpl> get copyWith => + __$$OrderDtoImplCopyWithImpl<_$OrderDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$OrderDtoImplToJson(this); + } +} + +abstract class _OrderDto extends OrderDto { + const factory _OrderDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'order_number') final String? orderNumber, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'user_id') final String? userId, + @JsonKey(name: 'table_number') final String? tableNumber, + @JsonKey(name: 'order_type') final String? orderType, + @JsonKey(name: 'status') final String? status, + @JsonKey(name: 'subtotal') final int? subtotal, + @JsonKey(name: 'tax_amount') final int? taxAmount, + @JsonKey(name: 'discount_amount') final int? discountAmount, + @JsonKey(name: 'total_amount') final int? totalAmount, + @JsonKey(name: 'total_cost') final int? totalCost, + @JsonKey(name: 'remaining_amount') final int? remainingAmount, + @JsonKey(name: 'payment_status') final String? paymentStatus, + @JsonKey(name: 'refund_amount') final int? refundAmount, + @JsonKey(name: 'is_void') final bool? isVoid, + @JsonKey(name: 'is_refund') final bool? isRefund, + @JsonKey(name: 'notes') final String? notes, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') final String? createdAt, + @JsonKey(name: 'updated_at') final String? updatedAt, + @JsonKey(name: 'order_items') final List? orderItems, + @JsonKey(name: 'payments') final List? payments, + @JsonKey(name: 'total_paid') final int? totalPaid, + @JsonKey(name: 'payment_count') final int? paymentCount, + @JsonKey(name: 'split_type') final String? splitType, + }) = _$OrderDtoImpl; + const _OrderDto._() : super._(); + + factory _OrderDto.fromJson(Map json) = + _$OrderDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'order_number') + String? get orderNumber; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'user_id') + String? get userId; + @override + @JsonKey(name: 'table_number') + String? get tableNumber; + @override + @JsonKey(name: 'order_type') + String? get orderType; + @override + @JsonKey(name: 'status') + String? get status; + @override + @JsonKey(name: 'subtotal') + int? get subtotal; + @override + @JsonKey(name: 'tax_amount') + int? get taxAmount; + @override + @JsonKey(name: 'discount_amount') + int? get discountAmount; + @override + @JsonKey(name: 'total_amount') + int? get totalAmount; + @override + @JsonKey(name: 'total_cost') + int? get totalCost; + @override + @JsonKey(name: 'remaining_amount') + int? get remainingAmount; + @override + @JsonKey(name: 'payment_status') + String? get paymentStatus; + @override + @JsonKey(name: 'refund_amount') + int? get refundAmount; + @override + @JsonKey(name: 'is_void') + bool? get isVoid; + @override + @JsonKey(name: 'is_refund') + bool? get isRefund; + @override + @JsonKey(name: 'notes') + String? get notes; + @override + @JsonKey(name: 'metadata') + Map? get metadata; + @override + @JsonKey(name: 'created_at') + String? get createdAt; + @override + @JsonKey(name: 'updated_at') + String? get updatedAt; + @override + @JsonKey(name: 'order_items') + List? get orderItems; + @override + @JsonKey(name: 'payments') + List? get payments; + @override + @JsonKey(name: 'total_paid') + int? get totalPaid; + @override + @JsonKey(name: 'payment_count') + int? get paymentCount; + @override + @JsonKey(name: 'split_type') + String? get splitType; + + /// Create a copy of OrderDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderDtoImplCopyWith<_$OrderDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +OrderItemDto _$OrderItemDtoFromJson(Map json) { + return _OrderItemDto.fromJson(json); +} + +/// @nodoc +mixin _$OrderItemDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'order_id') + String? get orderId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'product_name') + String? get productName => throw _privateConstructorUsedError; + @JsonKey(name: 'quantity') + int? get quantity => throw _privateConstructorUsedError; + @JsonKey(name: 'price') + int? get price => throw _privateConstructorUsedError; + @JsonKey(name: 'subtotal') + int? get subtotal => throw _privateConstructorUsedError; + @JsonKey(name: 'discount_amount') + int? get discountAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'total') + int? get total => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'metadata') + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this OrderItemDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of OrderItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderItemDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderItemDtoCopyWith<$Res> { + factory $OrderItemDtoCopyWith( + OrderItemDto value, + $Res Function(OrderItemDto) then, + ) = _$OrderItemDtoCopyWithImpl<$Res, OrderItemDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'quantity') int? quantity, + @JsonKey(name: 'price') int? price, + @JsonKey(name: 'subtotal') int? subtotal, + @JsonKey(name: 'discount_amount') int? discountAmount, + @JsonKey(name: 'total') int? total, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class _$OrderItemDtoCopyWithImpl<$Res, $Val extends OrderItemDto> + implements $OrderItemDtoCopyWith<$Res> { + _$OrderItemDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderId = freezed, + Object? productId = freezed, + Object? productName = freezed, + Object? quantity = freezed, + Object? price = freezed, + Object? subtotal = freezed, + Object? discountAmount = freezed, + Object? total = freezed, + Object? cost = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderId: freezed == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + price: freezed == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int?, + subtotal: freezed == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int?, + discountAmount: freezed == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int?, + total: freezed == total + ? _value.total + : total // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OrderItemDtoImplCopyWith<$Res> + implements $OrderItemDtoCopyWith<$Res> { + factory _$$OrderItemDtoImplCopyWith( + _$OrderItemDtoImpl value, + $Res Function(_$OrderItemDtoImpl) then, + ) = __$$OrderItemDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'product_name') String? productName, + @JsonKey(name: 'quantity') int? quantity, + @JsonKey(name: 'price') int? price, + @JsonKey(name: 'subtotal') int? subtotal, + @JsonKey(name: 'discount_amount') int? discountAmount, + @JsonKey(name: 'total') int? total, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class __$$OrderItemDtoImplCopyWithImpl<$Res> + extends _$OrderItemDtoCopyWithImpl<$Res, _$OrderItemDtoImpl> + implements _$$OrderItemDtoImplCopyWith<$Res> { + __$$OrderItemDtoImplCopyWithImpl( + _$OrderItemDtoImpl _value, + $Res Function(_$OrderItemDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderId = freezed, + Object? productId = freezed, + Object? productName = freezed, + Object? quantity = freezed, + Object? price = freezed, + Object? subtotal = freezed, + Object? discountAmount = freezed, + Object? total = freezed, + Object? cost = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$OrderItemDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderId: freezed == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + productName: freezed == productName + ? _value.productName + : productName // ignore: cast_nullable_to_non_nullable + as String?, + quantity: freezed == quantity + ? _value.quantity + : quantity // ignore: cast_nullable_to_non_nullable + as int?, + price: freezed == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int?, + subtotal: freezed == subtotal + ? _value.subtotal + : subtotal // ignore: cast_nullable_to_non_nullable + as int?, + discountAmount: freezed == discountAmount + ? _value.discountAmount + : discountAmount // ignore: cast_nullable_to_non_nullable + as int?, + total: freezed == total + ? _value.total + : total // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$OrderItemDtoImpl extends _OrderItemDto { + const _$OrderItemDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'order_id') this.orderId, + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'product_name') this.productName, + @JsonKey(name: 'quantity') this.quantity, + @JsonKey(name: 'price') this.price, + @JsonKey(name: 'subtotal') this.subtotal, + @JsonKey(name: 'discount_amount') this.discountAmount, + @JsonKey(name: 'total') this.total, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + }) : _metadata = metadata, + super._(); + + factory _$OrderItemDtoImpl.fromJson(Map json) => + _$$OrderItemDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'order_id') + final String? orderId; + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'product_name') + final String? productName; + @override + @JsonKey(name: 'quantity') + final int? quantity; + @override + @JsonKey(name: 'price') + final int? price; + @override + @JsonKey(name: 'subtotal') + final int? subtotal; + @override + @JsonKey(name: 'discount_amount') + final int? discountAmount; + @override + @JsonKey(name: 'total') + final int? total; + @override + @JsonKey(name: 'cost') + final int? cost; + final Map? _metadata; + @override + @JsonKey(name: 'metadata') + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'created_at') + final String? createdAt; + @override + @JsonKey(name: 'updated_at') + final String? updatedAt; + + @override + String toString() { + return 'OrderItemDto(id: $id, orderId: $orderId, productId: $productId, productName: $productName, quantity: $quantity, price: $price, subtotal: $subtotal, discountAmount: $discountAmount, total: $total, cost: $cost, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderItemDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderId, orderId) || other.orderId == orderId) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.productName, productName) || + other.productName == productName) && + (identical(other.quantity, quantity) || + other.quantity == quantity) && + (identical(other.price, price) || other.price == price) && + (identical(other.subtotal, subtotal) || + other.subtotal == subtotal) && + (identical(other.discountAmount, discountAmount) || + other.discountAmount == discountAmount) && + (identical(other.total, total) || other.total == total) && + (identical(other.cost, cost) || other.cost == cost) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + orderId, + productId, + productName, + quantity, + price, + subtotal, + discountAmount, + total, + cost, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of OrderItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderItemDtoImplCopyWith<_$OrderItemDtoImpl> get copyWith => + __$$OrderItemDtoImplCopyWithImpl<_$OrderItemDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$OrderItemDtoImplToJson(this); + } +} + +abstract class _OrderItemDto extends OrderItemDto { + const factory _OrderItemDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'order_id') final String? orderId, + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'product_name') final String? productName, + @JsonKey(name: 'quantity') final int? quantity, + @JsonKey(name: 'price') final int? price, + @JsonKey(name: 'subtotal') final int? subtotal, + @JsonKey(name: 'discount_amount') final int? discountAmount, + @JsonKey(name: 'total') final int? total, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') final String? createdAt, + @JsonKey(name: 'updated_at') final String? updatedAt, + }) = _$OrderItemDtoImpl; + const _OrderItemDto._() : super._(); + + factory _OrderItemDto.fromJson(Map json) = + _$OrderItemDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'order_id') + String? get orderId; + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'product_name') + String? get productName; + @override + @JsonKey(name: 'quantity') + int? get quantity; + @override + @JsonKey(name: 'price') + int? get price; + @override + @JsonKey(name: 'subtotal') + int? get subtotal; + @override + @JsonKey(name: 'discount_amount') + int? get discountAmount; + @override + @JsonKey(name: 'total') + int? get total; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'metadata') + Map? get metadata; + @override + @JsonKey(name: 'created_at') + String? get createdAt; + @override + @JsonKey(name: 'updated_at') + String? get updatedAt; + + /// Create a copy of OrderItemDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderItemDtoImplCopyWith<_$OrderItemDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +OrderPaymentDto _$OrderPaymentDtoFromJson(Map json) { + return _OrderPaymentDto.fromJson(json); +} + +/// @nodoc +mixin _$OrderPaymentDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'order_id') + String? get orderId => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType => throw _privateConstructorUsedError; + @JsonKey(name: 'amount') + int? get amount => throw _privateConstructorUsedError; + @JsonKey(name: 'status') + String? get status => throw _privateConstructorUsedError; + @JsonKey(name: 'split_number') + int? get splitNumber => throw _privateConstructorUsedError; + @JsonKey(name: 'split_total') + int? get splitTotal => throw _privateConstructorUsedError; + @JsonKey(name: 'split_type') + String? get splitType => throw _privateConstructorUsedError; + @JsonKey(name: 'split_description') + String? get splitDescription => throw _privateConstructorUsedError; + @JsonKey(name: 'refund_amount') + int? get refundAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'metadata') + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + String? get updatedAt => throw _privateConstructorUsedError; + @JsonKey(name: 'payment_order_items') + List? get paymentOrderItems => + throw _privateConstructorUsedError; + + /// Serializes this OrderPaymentDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of OrderPaymentDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OrderPaymentDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OrderPaymentDtoCopyWith<$Res> { + factory $OrderPaymentDtoCopyWith( + OrderPaymentDto value, + $Res Function(OrderPaymentDto) then, + ) = _$OrderPaymentDtoCopyWithImpl<$Res, OrderPaymentDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'amount') int? amount, + @JsonKey(name: 'status') String? status, + @JsonKey(name: 'split_number') int? splitNumber, + @JsonKey(name: 'split_total') int? splitTotal, + @JsonKey(name: 'split_type') String? splitType, + @JsonKey(name: 'split_description') String? splitDescription, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + @JsonKey(name: 'payment_order_items') + List? paymentOrderItems, + }); +} + +/// @nodoc +class _$OrderPaymentDtoCopyWithImpl<$Res, $Val extends OrderPaymentDto> + implements $OrderPaymentDtoCopyWith<$Res> { + _$OrderPaymentDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OrderPaymentDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderId = freezed, + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? amount = freezed, + Object? status = freezed, + Object? splitNumber = freezed, + Object? splitTotal = freezed, + Object? splitType = freezed, + Object? splitDescription = freezed, + Object? refundAmount = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + Object? paymentOrderItems = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderId: freezed == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + amount: freezed == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int?, + status: freezed == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String?, + splitNumber: freezed == splitNumber + ? _value.splitNumber + : splitNumber // ignore: cast_nullable_to_non_nullable + as int?, + splitTotal: freezed == splitTotal + ? _value.splitTotal + : splitTotal // ignore: cast_nullable_to_non_nullable + as int?, + splitType: freezed == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String?, + splitDescription: freezed == splitDescription + ? _value.splitDescription + : splitDescription // ignore: cast_nullable_to_non_nullable + as String?, + refundAmount: freezed == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + paymentOrderItems: freezed == paymentOrderItems + ? _value.paymentOrderItems + : paymentOrderItems // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OrderPaymentDtoImplCopyWith<$Res> + implements $OrderPaymentDtoCopyWith<$Res> { + factory _$$OrderPaymentDtoImplCopyWith( + _$OrderPaymentDtoImpl value, + $Res Function(_$OrderPaymentDtoImpl) then, + ) = __$$OrderPaymentDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_id') String? orderId, + @JsonKey(name: 'payment_method_id') String? paymentMethodId, + @JsonKey(name: 'payment_method_name') String? paymentMethodName, + @JsonKey(name: 'payment_method_type') String? paymentMethodType, + @JsonKey(name: 'amount') int? amount, + @JsonKey(name: 'status') String? status, + @JsonKey(name: 'split_number') int? splitNumber, + @JsonKey(name: 'split_total') int? splitTotal, + @JsonKey(name: 'split_type') String? splitType, + @JsonKey(name: 'split_description') String? splitDescription, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + @JsonKey(name: 'payment_order_items') + List? paymentOrderItems, + }); +} + +/// @nodoc +class __$$OrderPaymentDtoImplCopyWithImpl<$Res> + extends _$OrderPaymentDtoCopyWithImpl<$Res, _$OrderPaymentDtoImpl> + implements _$$OrderPaymentDtoImplCopyWith<$Res> { + __$$OrderPaymentDtoImplCopyWithImpl( + _$OrderPaymentDtoImpl _value, + $Res Function(_$OrderPaymentDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OrderPaymentDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderId = freezed, + Object? paymentMethodId = freezed, + Object? paymentMethodName = freezed, + Object? paymentMethodType = freezed, + Object? amount = freezed, + Object? status = freezed, + Object? splitNumber = freezed, + Object? splitTotal = freezed, + Object? splitType = freezed, + Object? splitDescription = freezed, + Object? refundAmount = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + Object? paymentOrderItems = freezed, + }) { + return _then( + _$OrderPaymentDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderId: freezed == orderId + ? _value.orderId + : orderId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodId: freezed == paymentMethodId + ? _value.paymentMethodId + : paymentMethodId // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodName: freezed == paymentMethodName + ? _value.paymentMethodName + : paymentMethodName // ignore: cast_nullable_to_non_nullable + as String?, + paymentMethodType: freezed == paymentMethodType + ? _value.paymentMethodType + : paymentMethodType // ignore: cast_nullable_to_non_nullable + as String?, + amount: freezed == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int?, + status: freezed == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String?, + splitNumber: freezed == splitNumber + ? _value.splitNumber + : splitNumber // ignore: cast_nullable_to_non_nullable + as int?, + splitTotal: freezed == splitTotal + ? _value.splitTotal + : splitTotal // ignore: cast_nullable_to_non_nullable + as int?, + splitType: freezed == splitType + ? _value.splitType + : splitType // ignore: cast_nullable_to_non_nullable + as String?, + splitDescription: freezed == splitDescription + ? _value.splitDescription + : splitDescription // ignore: cast_nullable_to_non_nullable + as String?, + refundAmount: freezed == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + paymentOrderItems: freezed == paymentOrderItems + ? _value._paymentOrderItems + : paymentOrderItems // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$OrderPaymentDtoImpl extends _OrderPaymentDto { + const _$OrderPaymentDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'order_id') this.orderId, + @JsonKey(name: 'payment_method_id') this.paymentMethodId, + @JsonKey(name: 'payment_method_name') this.paymentMethodName, + @JsonKey(name: 'payment_method_type') this.paymentMethodType, + @JsonKey(name: 'amount') this.amount, + @JsonKey(name: 'status') this.status, + @JsonKey(name: 'split_number') this.splitNumber, + @JsonKey(name: 'split_total') this.splitTotal, + @JsonKey(name: 'split_type') this.splitType, + @JsonKey(name: 'split_description') this.splitDescription, + @JsonKey(name: 'refund_amount') this.refundAmount, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + @JsonKey(name: 'payment_order_items') + final List? paymentOrderItems, + }) : _metadata = metadata, + _paymentOrderItems = paymentOrderItems, + super._(); + + factory _$OrderPaymentDtoImpl.fromJson(Map json) => + _$$OrderPaymentDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'order_id') + final String? orderId; + @override + @JsonKey(name: 'payment_method_id') + final String? paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + final String? paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + final String? paymentMethodType; + @override + @JsonKey(name: 'amount') + final int? amount; + @override + @JsonKey(name: 'status') + final String? status; + @override + @JsonKey(name: 'split_number') + final int? splitNumber; + @override + @JsonKey(name: 'split_total') + final int? splitTotal; + @override + @JsonKey(name: 'split_type') + final String? splitType; + @override + @JsonKey(name: 'split_description') + final String? splitDescription; + @override + @JsonKey(name: 'refund_amount') + final int? refundAmount; + final Map? _metadata; + @override + @JsonKey(name: 'metadata') + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'created_at') + final String? createdAt; + @override + @JsonKey(name: 'updated_at') + final String? updatedAt; + final List? _paymentOrderItems; + @override + @JsonKey(name: 'payment_order_items') + List? get paymentOrderItems { + final value = _paymentOrderItems; + if (value == null) return null; + if (_paymentOrderItems is EqualUnmodifiableListView) + return _paymentOrderItems; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'OrderPaymentDto(id: $id, orderId: $orderId, paymentMethodId: $paymentMethodId, paymentMethodName: $paymentMethodName, paymentMethodType: $paymentMethodType, amount: $amount, status: $status, splitNumber: $splitNumber, splitTotal: $splitTotal, splitType: $splitType, splitDescription: $splitDescription, refundAmount: $refundAmount, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt, paymentOrderItems: $paymentOrderItems)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OrderPaymentDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderId, orderId) || other.orderId == orderId) && + (identical(other.paymentMethodId, paymentMethodId) || + other.paymentMethodId == paymentMethodId) && + (identical(other.paymentMethodName, paymentMethodName) || + other.paymentMethodName == paymentMethodName) && + (identical(other.paymentMethodType, paymentMethodType) || + other.paymentMethodType == paymentMethodType) && + (identical(other.amount, amount) || other.amount == amount) && + (identical(other.status, status) || other.status == status) && + (identical(other.splitNumber, splitNumber) || + other.splitNumber == splitNumber) && + (identical(other.splitTotal, splitTotal) || + other.splitTotal == splitTotal) && + (identical(other.splitType, splitType) || + other.splitType == splitType) && + (identical(other.splitDescription, splitDescription) || + other.splitDescription == splitDescription) && + (identical(other.refundAmount, refundAmount) || + other.refundAmount == refundAmount) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals( + other._paymentOrderItems, + _paymentOrderItems, + )); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + orderId, + paymentMethodId, + paymentMethodName, + paymentMethodType, + amount, + status, + splitNumber, + splitTotal, + splitType, + splitDescription, + refundAmount, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + const DeepCollectionEquality().hash(_paymentOrderItems), + ); + + /// Create a copy of OrderPaymentDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OrderPaymentDtoImplCopyWith<_$OrderPaymentDtoImpl> get copyWith => + __$$OrderPaymentDtoImplCopyWithImpl<_$OrderPaymentDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$OrderPaymentDtoImplToJson(this); + } +} + +abstract class _OrderPaymentDto extends OrderPaymentDto { + const factory _OrderPaymentDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'order_id') final String? orderId, + @JsonKey(name: 'payment_method_id') final String? paymentMethodId, + @JsonKey(name: 'payment_method_name') final String? paymentMethodName, + @JsonKey(name: 'payment_method_type') final String? paymentMethodType, + @JsonKey(name: 'amount') final int? amount, + @JsonKey(name: 'status') final String? status, + @JsonKey(name: 'split_number') final int? splitNumber, + @JsonKey(name: 'split_total') final int? splitTotal, + @JsonKey(name: 'split_type') final String? splitType, + @JsonKey(name: 'split_description') final String? splitDescription, + @JsonKey(name: 'refund_amount') final int? refundAmount, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') final String? createdAt, + @JsonKey(name: 'updated_at') final String? updatedAt, + @JsonKey(name: 'payment_order_items') + final List? paymentOrderItems, + }) = _$OrderPaymentDtoImpl; + const _OrderPaymentDto._() : super._(); + + factory _OrderPaymentDto.fromJson(Map json) = + _$OrderPaymentDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'order_id') + String? get orderId; + @override + @JsonKey(name: 'payment_method_id') + String? get paymentMethodId; + @override + @JsonKey(name: 'payment_method_name') + String? get paymentMethodName; + @override + @JsonKey(name: 'payment_method_type') + String? get paymentMethodType; + @override + @JsonKey(name: 'amount') + int? get amount; + @override + @JsonKey(name: 'status') + String? get status; + @override + @JsonKey(name: 'split_number') + int? get splitNumber; + @override + @JsonKey(name: 'split_total') + int? get splitTotal; + @override + @JsonKey(name: 'split_type') + String? get splitType; + @override + @JsonKey(name: 'split_description') + String? get splitDescription; + @override + @JsonKey(name: 'refund_amount') + int? get refundAmount; + @override + @JsonKey(name: 'metadata') + Map? get metadata; + @override + @JsonKey(name: 'created_at') + String? get createdAt; + @override + @JsonKey(name: 'updated_at') + String? get updatedAt; + @override + @JsonKey(name: 'payment_order_items') + List? get paymentOrderItems; + + /// Create a copy of OrderPaymentDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OrderPaymentDtoImplCopyWith<_$OrderPaymentDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +PaymentOrderItemDto _$PaymentOrderItemDtoFromJson(Map json) { + return _PaymentOrderItemDto.fromJson(json); +} + +/// @nodoc +mixin _$PaymentOrderItemDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'order_payment_id') + String? get orderPaymentId => throw _privateConstructorUsedError; + @JsonKey(name: 'order_item_id') + String? get orderItemId => throw _privateConstructorUsedError; + @JsonKey(name: 'amount') + int? get amount => throw _privateConstructorUsedError; + @JsonKey(name: 'refund_amount') + int? get refundAmount => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this PaymentOrderItemDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of PaymentOrderItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PaymentOrderItemDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PaymentOrderItemDtoCopyWith<$Res> { + factory $PaymentOrderItemDtoCopyWith( + PaymentOrderItemDto value, + $Res Function(PaymentOrderItemDto) then, + ) = _$PaymentOrderItemDtoCopyWithImpl<$Res, PaymentOrderItemDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_payment_id') String? orderPaymentId, + @JsonKey(name: 'order_item_id') String? orderItemId, + @JsonKey(name: 'amount') int? amount, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class _$PaymentOrderItemDtoCopyWithImpl<$Res, $Val extends PaymentOrderItemDto> + implements $PaymentOrderItemDtoCopyWith<$Res> { + _$PaymentOrderItemDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PaymentOrderItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderPaymentId = freezed, + Object? orderItemId = freezed, + Object? amount = freezed, + Object? refundAmount = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderPaymentId: freezed == orderPaymentId + ? _value.orderPaymentId + : orderPaymentId // ignore: cast_nullable_to_non_nullable + as String?, + orderItemId: freezed == orderItemId + ? _value.orderItemId + : orderItemId // ignore: cast_nullable_to_non_nullable + as String?, + amount: freezed == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int?, + refundAmount: freezed == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$PaymentOrderItemDtoImplCopyWith<$Res> + implements $PaymentOrderItemDtoCopyWith<$Res> { + factory _$$PaymentOrderItemDtoImplCopyWith( + _$PaymentOrderItemDtoImpl value, + $Res Function(_$PaymentOrderItemDtoImpl) then, + ) = __$$PaymentOrderItemDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'order_payment_id') String? orderPaymentId, + @JsonKey(name: 'order_item_id') String? orderItemId, + @JsonKey(name: 'amount') int? amount, + @JsonKey(name: 'refund_amount') int? refundAmount, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class __$$PaymentOrderItemDtoImplCopyWithImpl<$Res> + extends _$PaymentOrderItemDtoCopyWithImpl<$Res, _$PaymentOrderItemDtoImpl> + implements _$$PaymentOrderItemDtoImplCopyWith<$Res> { + __$$PaymentOrderItemDtoImplCopyWithImpl( + _$PaymentOrderItemDtoImpl _value, + $Res Function(_$PaymentOrderItemDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of PaymentOrderItemDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? orderPaymentId = freezed, + Object? orderItemId = freezed, + Object? amount = freezed, + Object? refundAmount = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$PaymentOrderItemDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + orderPaymentId: freezed == orderPaymentId + ? _value.orderPaymentId + : orderPaymentId // ignore: cast_nullable_to_non_nullable + as String?, + orderItemId: freezed == orderItemId + ? _value.orderItemId + : orderItemId // ignore: cast_nullable_to_non_nullable + as String?, + amount: freezed == amount + ? _value.amount + : amount // ignore: cast_nullable_to_non_nullable + as int?, + refundAmount: freezed == refundAmount + ? _value.refundAmount + : refundAmount // ignore: cast_nullable_to_non_nullable + as int?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$PaymentOrderItemDtoImpl extends _PaymentOrderItemDto { + const _$PaymentOrderItemDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'order_payment_id') this.orderPaymentId, + @JsonKey(name: 'order_item_id') this.orderItemId, + @JsonKey(name: 'amount') this.amount, + @JsonKey(name: 'refund_amount') this.refundAmount, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + }) : super._(); + + factory _$PaymentOrderItemDtoImpl.fromJson(Map json) => + _$$PaymentOrderItemDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'order_payment_id') + final String? orderPaymentId; + @override + @JsonKey(name: 'order_item_id') + final String? orderItemId; + @override + @JsonKey(name: 'amount') + final int? amount; + @override + @JsonKey(name: 'refund_amount') + final int? refundAmount; + @override + @JsonKey(name: 'created_at') + final String? createdAt; + @override + @JsonKey(name: 'updated_at') + final String? updatedAt; + + @override + String toString() { + return 'PaymentOrderItemDto(id: $id, orderPaymentId: $orderPaymentId, orderItemId: $orderItemId, amount: $amount, refundAmount: $refundAmount, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PaymentOrderItemDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.orderPaymentId, orderPaymentId) || + other.orderPaymentId == orderPaymentId) && + (identical(other.orderItemId, orderItemId) || + other.orderItemId == orderItemId) && + (identical(other.amount, amount) || other.amount == amount) && + (identical(other.refundAmount, refundAmount) || + other.refundAmount == refundAmount) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + orderPaymentId, + orderItemId, + amount, + refundAmount, + createdAt, + updatedAt, + ); + + /// Create a copy of PaymentOrderItemDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PaymentOrderItemDtoImplCopyWith<_$PaymentOrderItemDtoImpl> get copyWith => + __$$PaymentOrderItemDtoImplCopyWithImpl<_$PaymentOrderItemDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$PaymentOrderItemDtoImplToJson(this); + } +} + +abstract class _PaymentOrderItemDto extends PaymentOrderItemDto { + const factory _PaymentOrderItemDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'order_payment_id') final String? orderPaymentId, + @JsonKey(name: 'order_item_id') final String? orderItemId, + @JsonKey(name: 'amount') final int? amount, + @JsonKey(name: 'refund_amount') final int? refundAmount, + @JsonKey(name: 'created_at') final String? createdAt, + @JsonKey(name: 'updated_at') final String? updatedAt, + }) = _$PaymentOrderItemDtoImpl; + const _PaymentOrderItemDto._() : super._(); + + factory _PaymentOrderItemDto.fromJson(Map json) = + _$PaymentOrderItemDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'order_payment_id') + String? get orderPaymentId; + @override + @JsonKey(name: 'order_item_id') + String? get orderItemId; + @override + @JsonKey(name: 'amount') + int? get amount; + @override + @JsonKey(name: 'refund_amount') + int? get refundAmount; + @override + @JsonKey(name: 'created_at') + String? get createdAt; + @override + @JsonKey(name: 'updated_at') + String? get updatedAt; + + /// Create a copy of PaymentOrderItemDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PaymentOrderItemDtoImplCopyWith<_$PaymentOrderItemDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/order/order_dtos.g.dart b/lib/infrastructure/order/order_dtos.g.dart new file mode 100644 index 0000000..de95ff2 --- /dev/null +++ b/lib/infrastructure/order/order_dtos.g.dart @@ -0,0 +1,173 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'order_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$OrderDtoImpl _$$OrderDtoImplFromJson(Map json) => + _$OrderDtoImpl( + id: json['id'] as String?, + orderNumber: json['order_number'] as String?, + outletId: json['outlet_id'] as String?, + userId: json['user_id'] as String?, + tableNumber: json['table_number'] as String?, + orderType: json['order_type'] as String?, + status: json['status'] as String?, + subtotal: (json['subtotal'] as num?)?.toInt(), + taxAmount: (json['tax_amount'] as num?)?.toInt(), + discountAmount: (json['discount_amount'] as num?)?.toInt(), + totalAmount: (json['total_amount'] as num?)?.toInt(), + totalCost: (json['total_cost'] as num?)?.toInt(), + remainingAmount: (json['remaining_amount'] as num?)?.toInt(), + paymentStatus: json['payment_status'] as String?, + refundAmount: (json['refund_amount'] as num?)?.toInt(), + isVoid: json['is_void'] as bool?, + isRefund: json['is_refund'] as bool?, + notes: json['notes'] as String?, + metadata: json['metadata'] as Map?, + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, + orderItems: (json['order_items'] as List?) + ?.map((e) => OrderItemDto.fromJson(e as Map)) + .toList(), + payments: (json['payments'] as List?) + ?.map((e) => OrderPaymentDto.fromJson(e as Map)) + .toList(), + totalPaid: (json['total_paid'] as num?)?.toInt(), + paymentCount: (json['payment_count'] as num?)?.toInt(), + splitType: json['split_type'] as String?, + ); + +Map _$$OrderDtoImplToJson(_$OrderDtoImpl instance) => + { + 'id': instance.id, + 'order_number': instance.orderNumber, + 'outlet_id': instance.outletId, + 'user_id': instance.userId, + 'table_number': instance.tableNumber, + 'order_type': instance.orderType, + 'status': instance.status, + 'subtotal': instance.subtotal, + 'tax_amount': instance.taxAmount, + 'discount_amount': instance.discountAmount, + 'total_amount': instance.totalAmount, + 'total_cost': instance.totalCost, + 'remaining_amount': instance.remainingAmount, + 'payment_status': instance.paymentStatus, + 'refund_amount': instance.refundAmount, + 'is_void': instance.isVoid, + 'is_refund': instance.isRefund, + 'notes': instance.notes, + 'metadata': instance.metadata, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, + 'order_items': instance.orderItems, + 'payments': instance.payments, + 'total_paid': instance.totalPaid, + 'payment_count': instance.paymentCount, + 'split_type': instance.splitType, + }; + +_$OrderItemDtoImpl _$$OrderItemDtoImplFromJson(Map json) => + _$OrderItemDtoImpl( + id: json['id'] as String?, + orderId: json['order_id'] as String?, + productId: json['product_id'] as String?, + productName: json['product_name'] as String?, + quantity: (json['quantity'] as num?)?.toInt(), + price: (json['price'] as num?)?.toInt(), + subtotal: (json['subtotal'] as num?)?.toInt(), + discountAmount: (json['discount_amount'] as num?)?.toInt(), + total: (json['total'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + metadata: json['metadata'] as Map?, + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, + ); + +Map _$$OrderItemDtoImplToJson(_$OrderItemDtoImpl instance) => + { + 'id': instance.id, + 'order_id': instance.orderId, + 'product_id': instance.productId, + 'product_name': instance.productName, + 'quantity': instance.quantity, + 'price': instance.price, + 'subtotal': instance.subtotal, + 'discount_amount': instance.discountAmount, + 'total': instance.total, + 'cost': instance.cost, + 'metadata': instance.metadata, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, + }; + +_$OrderPaymentDtoImpl _$$OrderPaymentDtoImplFromJson( + Map json, +) => _$OrderPaymentDtoImpl( + id: json['id'] as String?, + orderId: json['order_id'] as String?, + paymentMethodId: json['payment_method_id'] as String?, + paymentMethodName: json['payment_method_name'] as String?, + paymentMethodType: json['payment_method_type'] as String?, + amount: (json['amount'] as num?)?.toInt(), + status: json['status'] as String?, + splitNumber: (json['split_number'] as num?)?.toInt(), + splitTotal: (json['split_total'] as num?)?.toInt(), + splitType: json['split_type'] as String?, + splitDescription: json['split_description'] as String?, + refundAmount: (json['refund_amount'] as num?)?.toInt(), + metadata: json['metadata'] as Map?, + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, + paymentOrderItems: (json['payment_order_items'] as List?) + ?.map((e) => PaymentOrderItemDto.fromJson(e as Map)) + .toList(), +); + +Map _$$OrderPaymentDtoImplToJson( + _$OrderPaymentDtoImpl instance, +) => { + 'id': instance.id, + 'order_id': instance.orderId, + 'payment_method_id': instance.paymentMethodId, + 'payment_method_name': instance.paymentMethodName, + 'payment_method_type': instance.paymentMethodType, + 'amount': instance.amount, + 'status': instance.status, + 'split_number': instance.splitNumber, + 'split_total': instance.splitTotal, + 'split_type': instance.splitType, + 'split_description': instance.splitDescription, + 'refund_amount': instance.refundAmount, + 'metadata': instance.metadata, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, + 'payment_order_items': instance.paymentOrderItems, +}; + +_$PaymentOrderItemDtoImpl _$$PaymentOrderItemDtoImplFromJson( + Map json, +) => _$PaymentOrderItemDtoImpl( + id: json['id'] as String?, + orderPaymentId: json['order_payment_id'] as String?, + orderItemId: json['order_item_id'] as String?, + amount: (json['amount'] as num?)?.toInt(), + refundAmount: (json['refund_amount'] as num?)?.toInt(), + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, +); + +Map _$$PaymentOrderItemDtoImplToJson( + _$PaymentOrderItemDtoImpl instance, +) => { + 'id': instance.id, + 'order_payment_id': instance.orderPaymentId, + 'order_item_id': instance.orderItemId, + 'amount': instance.amount, + 'refund_amount': instance.refundAmount, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, +}; diff --git a/lib/infrastructure/order/repositories/order_repository.dart b/lib/infrastructure/order/repositories/order_repository.dart new file mode 100644 index 0000000..6317fe8 --- /dev/null +++ b/lib/infrastructure/order/repositories/order_repository.dart @@ -0,0 +1,54 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart' hide Order; +import 'package:injectable/injectable.dart' hide Order; + +import '../../../domain/order/order.dart'; +import '../../outlet/datasource/local_data_provider.dart'; +import '../datasource/remote_data_provider.dart'; + +@Injectable(as: IOrderRepository) +class OrderRepository implements IOrderRepository { + final OrderRemoteDataProvider _dataProvider; + final OutletLocalDataProvider _outletLocalDataProvider; + final String _logName = 'OrderRepository'; + + OrderRepository(this._dataProvider, this._outletLocalDataProvider); + + @override + Future>> get({ + int page = 1, + int limit = 20, + String? status, + String? search, + String? outletId, + required DateTime dateFrom, + required DateTime dateTo, + }) async { + try { + final resolvedOutletId = + outletId ?? _outletLocalDataProvider.getSelectedOutletId(); + + final result = await _dataProvider.fetch( + page: page, + limit: limit, + status: status, + search: search, + outletId: resolvedOutletId, + dateFrom: dateFrom, + dateTo: dateTo, + ); + + if (result.hasError) { + return left(result.error!); + } + + final orders = result.data!.map((e) => e.toDomain()).toList(); + + return right(orders); + } catch (e, s) { + log('getOrderError', name: _logName, error: e, stackTrace: s); + return left(const OrderFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/outlet/datasource/local_data_provider.dart b/lib/infrastructure/outlet/datasource/local_data_provider.dart new file mode 100644 index 0000000..8fe1b93 --- /dev/null +++ b/lib/infrastructure/outlet/datasource/local_data_provider.dart @@ -0,0 +1,26 @@ +import 'package:injectable/injectable.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../../common/constant/local_storage_key.dart'; + +@injectable +class OutletLocalDataProvider { + final SharedPreferences _sharedPreferences; + + OutletLocalDataProvider(this._sharedPreferences); + + Future saveSelectedOutletId(String outletId) async { + await _sharedPreferences.setString( + LocalStorageKey.selectedOutletId, + outletId, + ); + } + + String? getSelectedOutletId() { + return _sharedPreferences.getString(LocalStorageKey.selectedOutletId); + } + + Future deleteSelectedOutletId() async { + await _sharedPreferences.remove(LocalStorageKey.selectedOutletId); + } +} diff --git a/lib/infrastructure/outlet/datasource/remote_data_provider.dart b/lib/infrastructure/outlet/datasource/remote_data_provider.dart new file mode 100644 index 0000000..b7d406a --- /dev/null +++ b/lib/infrastructure/outlet/datasource/remote_data_provider.dart @@ -0,0 +1,74 @@ +import 'dart:developer'; + +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/outlet/outlet.dart'; +import '../outlet_dtos.dart'; + +@injectable +class OutletRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = 'OutletRemoteDataProvider'; + + OutletRemoteDataProvider(this._apiClient); + + Future> fetchById({required outletId}) async { + try { + final response = await _apiClient.get( + '${ApiPath.outlet}/detail/$outletId', + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(OutletFailure.empty()); + } + + final dto = OutletDto.fromJson(response.data['data']); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchOutletByIdError', name: _logName, error: e, stackTrace: s); + return DC.error(OutletFailure.serverError(e)); + } + } + + Future>> fetchList({ + int page = 1, + int limit = 10, + String? search, + bool? isActive, + }) async { + try { + final Map params = { + 'page': page, + 'limit': limit, + 'search': search ?? 'null', + 'is_active': isActive != null ? isActive.toString() : 'null', + }; + + final response = await _apiClient.get( + '${ApiPath.outlet}/list', + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(OutletFailure.empty()); + } + + final dto = (response.data['data']['outlets'] as List) + .map((item) => OutletDto.fromJson(item)) + .toList(); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchOutletListError', name: _logName, error: e, stackTrace: s); + return DC.error(OutletFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/outlet/dto/outlet_dto.dart b/lib/infrastructure/outlet/dto/outlet_dto.dart new file mode 100644 index 0000000..2e46eeb --- /dev/null +++ b/lib/infrastructure/outlet/dto/outlet_dto.dart @@ -0,0 +1,44 @@ +part of '../outlet_dtos.dart'; + +@freezed +class OutletDto with _$OutletDto { + const OutletDto._(); + + const factory OutletDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'address') String? address, + @JsonKey(name: 'phone_number') String? phoneNumber, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'currency') String? currency, + @JsonKey(name: 'tax_rate') int? taxRate, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }) = _OutletDto; + + factory OutletDto.fromJson(Map json) => + _$OutletDtoFromJson(json); + + /// Mapper ke domain + Outlet toDomain() { + return Outlet( + id: id ?? '', + organizationId: organizationId ?? '', + name: name ?? '', + address: address ?? '', + phoneNumber: phoneNumber ?? '', + businessType: businessType ?? '', + currency: currency ?? '', + taxRate: taxRate ?? 0, + isActive: isActive ?? false, + createdAt: createdAt != null + ? DateTime.tryParse(createdAt!) ?? DateTime(1970) + : DateTime(1970), + updatedAt: updatedAt != null + ? DateTime.tryParse(updatedAt!) ?? DateTime(1970) + : DateTime(1970), + ); + } +} diff --git a/lib/infrastructure/outlet/outlet_dtos.dart b/lib/infrastructure/outlet/outlet_dtos.dart new file mode 100644 index 0000000..b028073 --- /dev/null +++ b/lib/infrastructure/outlet/outlet_dtos.dart @@ -0,0 +1,8 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/outlet/outlet.dart'; + +part 'outlet_dtos.freezed.dart'; +part 'outlet_dtos.g.dart'; + +part 'dto/outlet_dto.dart'; diff --git a/lib/infrastructure/outlet/outlet_dtos.freezed.dart b/lib/infrastructure/outlet/outlet_dtos.freezed.dart new file mode 100644 index 0000000..97b4392 --- /dev/null +++ b/lib/infrastructure/outlet/outlet_dtos.freezed.dart @@ -0,0 +1,431 @@ +// 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 'outlet_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +OutletDto _$OutletDtoFromJson(Map json) { + return _OutletDto.fromJson(json); +} + +/// @nodoc +mixin _$OutletDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'name') + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: 'address') + String? get address => throw _privateConstructorUsedError; + @JsonKey(name: 'phone_number') + String? get phoneNumber => throw _privateConstructorUsedError; + @JsonKey(name: 'business_type') + String? get businessType => throw _privateConstructorUsedError; + @JsonKey(name: 'currency') + String? get currency => throw _privateConstructorUsedError; + @JsonKey(name: 'tax_rate') + int? get taxRate => throw _privateConstructorUsedError; + @JsonKey(name: 'is_active') + bool? get isActive => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this OutletDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of OutletDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $OutletDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $OutletDtoCopyWith<$Res> { + factory $OutletDtoCopyWith(OutletDto value, $Res Function(OutletDto) then) = + _$OutletDtoCopyWithImpl<$Res, OutletDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'address') String? address, + @JsonKey(name: 'phone_number') String? phoneNumber, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'currency') String? currency, + @JsonKey(name: 'tax_rate') int? taxRate, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class _$OutletDtoCopyWithImpl<$Res, $Val extends OutletDto> + implements $OutletDtoCopyWith<$Res> { + _$OutletDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of OutletDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? name = freezed, + Object? address = freezed, + Object? phoneNumber = freezed, + Object? businessType = freezed, + Object? currency = freezed, + Object? taxRate = freezed, + Object? isActive = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + address: freezed == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String?, + phoneNumber: freezed == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String?, + businessType: freezed == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String?, + currency: freezed == currency + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String?, + taxRate: freezed == taxRate + ? _value.taxRate + : taxRate // ignore: cast_nullable_to_non_nullable + as int?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$OutletDtoImplCopyWith<$Res> + implements $OutletDtoCopyWith<$Res> { + factory _$$OutletDtoImplCopyWith( + _$OutletDtoImpl value, + $Res Function(_$OutletDtoImpl) then, + ) = __$$OutletDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'address') String? address, + @JsonKey(name: 'phone_number') String? phoneNumber, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'currency') String? currency, + @JsonKey(name: 'tax_rate') int? taxRate, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class __$$OutletDtoImplCopyWithImpl<$Res> + extends _$OutletDtoCopyWithImpl<$Res, _$OutletDtoImpl> + implements _$$OutletDtoImplCopyWith<$Res> { + __$$OutletDtoImplCopyWithImpl( + _$OutletDtoImpl _value, + $Res Function(_$OutletDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of OutletDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? name = freezed, + Object? address = freezed, + Object? phoneNumber = freezed, + Object? businessType = freezed, + Object? currency = freezed, + Object? taxRate = freezed, + Object? isActive = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$OutletDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + address: freezed == address + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as String?, + phoneNumber: freezed == phoneNumber + ? _value.phoneNumber + : phoneNumber // ignore: cast_nullable_to_non_nullable + as String?, + businessType: freezed == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String?, + currency: freezed == currency + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String?, + taxRate: freezed == taxRate + ? _value.taxRate + : taxRate // ignore: cast_nullable_to_non_nullable + as int?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$OutletDtoImpl extends _OutletDto { + const _$OutletDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'name') this.name, + @JsonKey(name: 'address') this.address, + @JsonKey(name: 'phone_number') this.phoneNumber, + @JsonKey(name: 'business_type') this.businessType, + @JsonKey(name: 'currency') this.currency, + @JsonKey(name: 'tax_rate') this.taxRate, + @JsonKey(name: 'is_active') this.isActive, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + }) : super._(); + + factory _$OutletDtoImpl.fromJson(Map json) => + _$$OutletDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'name') + final String? name; + @override + @JsonKey(name: 'address') + final String? address; + @override + @JsonKey(name: 'phone_number') + final String? phoneNumber; + @override + @JsonKey(name: 'business_type') + final String? businessType; + @override + @JsonKey(name: 'currency') + final String? currency; + @override + @JsonKey(name: 'tax_rate') + final int? taxRate; + @override + @JsonKey(name: 'is_active') + final bool? isActive; + @override + @JsonKey(name: 'created_at') + final String? createdAt; + @override + @JsonKey(name: 'updated_at') + final String? updatedAt; + + @override + String toString() { + return 'OutletDto(id: $id, organizationId: $organizationId, name: $name, address: $address, phoneNumber: $phoneNumber, businessType: $businessType, currency: $currency, taxRate: $taxRate, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$OutletDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.name, name) || other.name == name) && + (identical(other.address, address) || other.address == address) && + (identical(other.phoneNumber, phoneNumber) || + other.phoneNumber == phoneNumber) && + (identical(other.businessType, businessType) || + other.businessType == businessType) && + (identical(other.currency, currency) || + other.currency == currency) && + (identical(other.taxRate, taxRate) || other.taxRate == taxRate) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + name, + address, + phoneNumber, + businessType, + currency, + taxRate, + isActive, + createdAt, + updatedAt, + ); + + /// Create a copy of OutletDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$OutletDtoImplCopyWith<_$OutletDtoImpl> get copyWith => + __$$OutletDtoImplCopyWithImpl<_$OutletDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$OutletDtoImplToJson(this); + } +} + +abstract class _OutletDto extends OutletDto { + const factory _OutletDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'name') final String? name, + @JsonKey(name: 'address') final String? address, + @JsonKey(name: 'phone_number') final String? phoneNumber, + @JsonKey(name: 'business_type') final String? businessType, + @JsonKey(name: 'currency') final String? currency, + @JsonKey(name: 'tax_rate') final int? taxRate, + @JsonKey(name: 'is_active') final bool? isActive, + @JsonKey(name: 'created_at') final String? createdAt, + @JsonKey(name: 'updated_at') final String? updatedAt, + }) = _$OutletDtoImpl; + const _OutletDto._() : super._(); + + factory _OutletDto.fromJson(Map json) = + _$OutletDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'name') + String? get name; + @override + @JsonKey(name: 'address') + String? get address; + @override + @JsonKey(name: 'phone_number') + String? get phoneNumber; + @override + @JsonKey(name: 'business_type') + String? get businessType; + @override + @JsonKey(name: 'currency') + String? get currency; + @override + @JsonKey(name: 'tax_rate') + int? get taxRate; + @override + @JsonKey(name: 'is_active') + bool? get isActive; + @override + @JsonKey(name: 'created_at') + String? get createdAt; + @override + @JsonKey(name: 'updated_at') + String? get updatedAt; + + /// Create a copy of OutletDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$OutletDtoImplCopyWith<_$OutletDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/outlet/outlet_dtos.g.dart b/lib/infrastructure/outlet/outlet_dtos.g.dart new file mode 100644 index 0000000..0c125d3 --- /dev/null +++ b/lib/infrastructure/outlet/outlet_dtos.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'outlet_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$OutletDtoImpl _$$OutletDtoImplFromJson(Map json) => + _$OutletDtoImpl( + id: json['id'] as String?, + organizationId: json['organization_id'] as String?, + name: json['name'] as String?, + address: json['address'] as String?, + phoneNumber: json['phone_number'] as String?, + businessType: json['business_type'] as String?, + currency: json['currency'] as String?, + taxRate: (json['tax_rate'] as num?)?.toInt(), + isActive: json['is_active'] as bool?, + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, + ); + +Map _$$OutletDtoImplToJson(_$OutletDtoImpl instance) => + { + 'id': instance.id, + 'organization_id': instance.organizationId, + 'name': instance.name, + 'address': instance.address, + 'phone_number': instance.phoneNumber, + 'business_type': instance.businessType, + 'currency': instance.currency, + 'tax_rate': instance.taxRate, + 'is_active': instance.isActive, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, + }; diff --git a/lib/infrastructure/outlet/repositories/outlet_repository.dart b/lib/infrastructure/outlet/repositories/outlet_repository.dart new file mode 100644 index 0000000..857ef71 --- /dev/null +++ b/lib/infrastructure/outlet/repositories/outlet_repository.dart @@ -0,0 +1,64 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/outlet/outlet.dart'; +import '../../auth/datasources/local_data_provider.dart'; +import '../datasource/remote_data_provider.dart'; + +@Injectable(as: IOutletRepository) +class OutletRepository implements IOutletRepository { + final OutletRemoteDataProvider _dataProvider; + final AuthLocalDataProvider _authLocalDataProvider; + final String _logName = 'OutletRepository'; + + OutletRepository(this._dataProvider, this._authLocalDataProvider); + + @override + Future> currentOutlet() async { + try { + final authData = await _authLocalDataProvider.currentUser(); + final result = await _dataProvider.fetchById(outletId: authData.outletId); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + return right(auth); + } catch (e, s) { + log('currentOutletError', name: _logName, error: e, stackTrace: s); + return left(const OutletFailure.unexpectedError()); + } + } + + @override + Future>> getList({ + int page = 1, + int limit = 10, + String? search, + bool? isActive, + }) async { + try { + final result = await _dataProvider.fetchList( + page: page, + limit: limit, + search: search, + isActive: isActive, + ); + + if (result.hasError) { + return left(result.error!); + } + + final outlets = result.data!.map((e) => e.toDomain()).toList(); + + return right(outlets); + } catch (e, s) { + log('getOutletListError', name: _logName, error: e, stackTrace: s); + return left(const OutletFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/product/datasources/remote_data_provider.dart b/lib/infrastructure/product/datasources/remote_data_provider.dart new file mode 100644 index 0000000..b105ce7 --- /dev/null +++ b/lib/infrastructure/product/datasources/remote_data_provider.dart @@ -0,0 +1,57 @@ +import 'dart:developer'; + +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/product/product.dart'; +import '../product_dtos.dart'; + +@injectable +class ProductRemoteDataProvider { + final ApiClient _apiClient; + final String _logName = 'ProductRemoteDataProvider'; + + ProductRemoteDataProvider(this._apiClient); + + Future>> fetch({ + int page = 1, + int limit = 10, + String? categoryId, + String? search, + }) async { + try { + Map params = {'page': page, 'limit': limit}; + + if (categoryId != null) { + params['category_id'] = categoryId; + } + + if (search != null) { + params['search'] = search; + } + + final response = await _apiClient.get( + ApiPath.product, + params: params, + headers: getAuthorizationHeader(), + ); + + if (response.data['data'] == null) { + return DC.error(ProductFailure.empty()); + } + + final dto = (response.data['data']['products'] as List) + .map((item) => ProductDto.fromJson(item)) + .toList(); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('fetchProductError', name: _logName, error: e, stackTrace: s); + return DC.error(ProductFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/product/dto/product_dto.dart b/lib/infrastructure/product/dto/product_dto.dart new file mode 100644 index 0000000..03b0b39 --- /dev/null +++ b/lib/infrastructure/product/dto/product_dto.dart @@ -0,0 +1,70 @@ +part of '../product_dtos.dart'; + +@freezed +class ProductDto with _$ProductDto { + const ProductDto._(); + + const factory ProductDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'sku') String? sku, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'description') String? description, + @JsonKey(name: 'price') int? price, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'image_url') String? imageUrl, + @JsonKey(name: 'printer_type') String? printerType, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + @JsonKey(name: 'variants') List? variants, + }) = _ProductDto; + + factory ProductDto.fromJson(Map json) => + _$ProductDtoFromJson(json); + + /// DTO -> Domain (isi default kalau null) + Product toDomain() => Product( + id: id ?? '', + organizationId: organizationId ?? '', + categoryId: categoryId ?? '', + sku: sku ?? '', + name: name ?? '', + description: description ?? '', + price: price ?? 0, + cost: cost ?? 0, + businessType: businessType ?? '', + imageUrl: imageUrl ?? '', + printerType: printerType ?? '', + metadata: metadata ?? {}, + isActive: isActive ?? false, + createdAt: createdAt ?? DateTime.now(), + updatedAt: updatedAt ?? DateTime.now(), + variants: variants?.map((v) => v.toDomain()).toList() ?? [], + ); + + /// Domain -> DTO + factory ProductDto.fromDomain(Product product) => ProductDto( + id: product.id, + organizationId: product.organizationId, + categoryId: product.categoryId, + sku: product.sku, + name: product.name, + description: product.description, + price: product.price, + cost: product.cost, + businessType: product.businessType, + imageUrl: product.imageUrl, + printerType: product.printerType, + metadata: product.metadata, + isActive: product.isActive, + createdAt: product.createdAt, + updatedAt: product.updatedAt, + variants: product.variants + .map((v) => ProductVariantDto.fromDomain(v)) + .toList(), + ); +} diff --git a/lib/infrastructure/product/dto/product_variant_dto.dart b/lib/infrastructure/product/dto/product_variant_dto.dart new file mode 100644 index 0000000..10b94b4 --- /dev/null +++ b/lib/infrastructure/product/dto/product_variant_dto.dart @@ -0,0 +1,45 @@ +part of '../product_dtos.dart'; + +@freezed +class ProductVariantDto with _$ProductVariantDto { + const ProductVariantDto._(); + + const factory ProductVariantDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'price_modifier') int? priceModifier, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + }) = _ProductVariantDto; + + factory ProductVariantDto.fromJson(Map json) => + _$ProductVariantDtoFromJson(json); + + /// DTO -> Domain + ProductVariant toDomain() => ProductVariant( + id: id ?? '', + productId: productId ?? '', + name: name ?? '', + priceModifier: priceModifier ?? 0, + cost: cost ?? 0, + metadata: metadata ?? {}, + createdAt: createdAt ?? DateTime.now(), + updatedAt: updatedAt ?? DateTime.now(), + ); + + /// Domain -> DTO + factory ProductVariantDto.fromDomain(ProductVariant variant) => + ProductVariantDto( + id: variant.id, + productId: variant.productId, + name: variant.name, + priceModifier: variant.priceModifier, + cost: variant.cost, + metadata: variant.metadata, + createdAt: variant.createdAt, + updatedAt: variant.updatedAt, + ); +} diff --git a/lib/infrastructure/product/product_dtos.dart b/lib/infrastructure/product/product_dtos.dart new file mode 100644 index 0000000..1d606ca --- /dev/null +++ b/lib/infrastructure/product/product_dtos.dart @@ -0,0 +1,9 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/product/product.dart'; + +part 'product_dtos.freezed.dart'; +part 'product_dtos.g.dart'; + +part 'dto/product_dto.dart'; +part 'dto/product_variant_dto.dart'; diff --git a/lib/infrastructure/product/product_dtos.freezed.dart b/lib/infrastructure/product/product_dtos.freezed.dart new file mode 100644 index 0000000..61a3ed4 --- /dev/null +++ b/lib/infrastructure/product/product_dtos.freezed.dart @@ -0,0 +1,926 @@ +// 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 'product_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +ProductDto _$ProductDtoFromJson(Map json) { + return _ProductDto.fromJson(json); +} + +/// @nodoc +mixin _$ProductDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'category_id') + String? get categoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'sku') + String? get sku => throw _privateConstructorUsedError; + @JsonKey(name: 'name') + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: 'description') + String? get description => throw _privateConstructorUsedError; + @JsonKey(name: 'price') + int? get price => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'business_type') + String? get businessType => throw _privateConstructorUsedError; + @JsonKey(name: 'image_url') + String? get imageUrl => throw _privateConstructorUsedError; + @JsonKey(name: 'printer_type') + String? get printerType => throw _privateConstructorUsedError; + @JsonKey(name: 'metadata') + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: 'is_active') + bool? get isActive => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + DateTime? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + DateTime? get updatedAt => throw _privateConstructorUsedError; + @JsonKey(name: 'variants') + List? get variants => throw _privateConstructorUsedError; + + /// Serializes this ProductDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductDtoCopyWith<$Res> { + factory $ProductDtoCopyWith( + ProductDto value, + $Res Function(ProductDto) then, + ) = _$ProductDtoCopyWithImpl<$Res, ProductDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'sku') String? sku, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'description') String? description, + @JsonKey(name: 'price') int? price, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'image_url') String? imageUrl, + @JsonKey(name: 'printer_type') String? printerType, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + @JsonKey(name: 'variants') List? variants, + }); +} + +/// @nodoc +class _$ProductDtoCopyWithImpl<$Res, $Val extends ProductDto> + implements $ProductDtoCopyWith<$Res> { + _$ProductDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? categoryId = freezed, + Object? sku = freezed, + Object? name = freezed, + Object? description = freezed, + Object? price = freezed, + Object? cost = freezed, + Object? businessType = freezed, + Object? imageUrl = freezed, + Object? printerType = freezed, + Object? metadata = freezed, + Object? isActive = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + Object? variants = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + sku: freezed == sku + ? _value.sku + : sku // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + price: freezed == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + businessType: freezed == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String?, + imageUrl: freezed == imageUrl + ? _value.imageUrl + : imageUrl // ignore: cast_nullable_to_non_nullable + as String?, + printerType: freezed == printerType + ? _value.printerType + : printerType // ignore: cast_nullable_to_non_nullable + as String?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + variants: freezed == variants + ? _value.variants + : variants // ignore: cast_nullable_to_non_nullable + as List?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductDtoImplCopyWith<$Res> + implements $ProductDtoCopyWith<$Res> { + factory _$$ProductDtoImplCopyWith( + _$ProductDtoImpl value, + $Res Function(_$ProductDtoImpl) then, + ) = __$$ProductDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'category_id') String? categoryId, + @JsonKey(name: 'sku') String? sku, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'description') String? description, + @JsonKey(name: 'price') int? price, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'business_type') String? businessType, + @JsonKey(name: 'image_url') String? imageUrl, + @JsonKey(name: 'printer_type') String? printerType, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + @JsonKey(name: 'variants') List? variants, + }); +} + +/// @nodoc +class __$$ProductDtoImplCopyWithImpl<$Res> + extends _$ProductDtoCopyWithImpl<$Res, _$ProductDtoImpl> + implements _$$ProductDtoImplCopyWith<$Res> { + __$$ProductDtoImplCopyWithImpl( + _$ProductDtoImpl _value, + $Res Function(_$ProductDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? categoryId = freezed, + Object? sku = freezed, + Object? name = freezed, + Object? description = freezed, + Object? price = freezed, + Object? cost = freezed, + Object? businessType = freezed, + Object? imageUrl = freezed, + Object? printerType = freezed, + Object? metadata = freezed, + Object? isActive = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + Object? variants = freezed, + }) { + return _then( + _$ProductDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + categoryId: freezed == categoryId + ? _value.categoryId + : categoryId // ignore: cast_nullable_to_non_nullable + as String?, + sku: freezed == sku + ? _value.sku + : sku // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + description: freezed == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String?, + price: freezed == price + ? _value.price + : price // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + businessType: freezed == businessType + ? _value.businessType + : businessType // ignore: cast_nullable_to_non_nullable + as String?, + imageUrl: freezed == imageUrl + ? _value.imageUrl + : imageUrl // ignore: cast_nullable_to_non_nullable + as String?, + printerType: freezed == printerType + ? _value.printerType + : printerType // ignore: cast_nullable_to_non_nullable + as String?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + variants: freezed == variants + ? _value._variants + : variants // ignore: cast_nullable_to_non_nullable + as List?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProductDtoImpl extends _ProductDto { + const _$ProductDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'category_id') this.categoryId, + @JsonKey(name: 'sku') this.sku, + @JsonKey(name: 'name') this.name, + @JsonKey(name: 'description') this.description, + @JsonKey(name: 'price') this.price, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'business_type') this.businessType, + @JsonKey(name: 'image_url') this.imageUrl, + @JsonKey(name: 'printer_type') this.printerType, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'is_active') this.isActive, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + @JsonKey(name: 'variants') final List? variants, + }) : _metadata = metadata, + _variants = variants, + super._(); + + factory _$ProductDtoImpl.fromJson(Map json) => + _$$ProductDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'category_id') + final String? categoryId; + @override + @JsonKey(name: 'sku') + final String? sku; + @override + @JsonKey(name: 'name') + final String? name; + @override + @JsonKey(name: 'description') + final String? description; + @override + @JsonKey(name: 'price') + final int? price; + @override + @JsonKey(name: 'cost') + final int? cost; + @override + @JsonKey(name: 'business_type') + final String? businessType; + @override + @JsonKey(name: 'image_url') + final String? imageUrl; + @override + @JsonKey(name: 'printer_type') + final String? printerType; + final Map? _metadata; + @override + @JsonKey(name: 'metadata') + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'is_active') + final bool? isActive; + @override + @JsonKey(name: 'created_at') + final DateTime? createdAt; + @override + @JsonKey(name: 'updated_at') + final DateTime? updatedAt; + final List? _variants; + @override + @JsonKey(name: 'variants') + List? get variants { + final value = _variants; + if (value == null) return null; + if (_variants is EqualUnmodifiableListView) return _variants; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); + } + + @override + String toString() { + return 'ProductDto(id: $id, organizationId: $organizationId, categoryId: $categoryId, sku: $sku, name: $name, description: $description, price: $price, cost: $cost, businessType: $businessType, imageUrl: $imageUrl, printerType: $printerType, metadata: $metadata, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt, variants: $variants)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.categoryId, categoryId) || + other.categoryId == categoryId) && + (identical(other.sku, sku) || other.sku == sku) && + (identical(other.name, name) || other.name == name) && + (identical(other.description, description) || + other.description == description) && + (identical(other.price, price) || other.price == price) && + (identical(other.cost, cost) || other.cost == cost) && + (identical(other.businessType, businessType) || + other.businessType == businessType) && + (identical(other.imageUrl, imageUrl) || + other.imageUrl == imageUrl) && + (identical(other.printerType, printerType) || + other.printerType == printerType) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt) && + const DeepCollectionEquality().equals(other._variants, _variants)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + categoryId, + sku, + name, + description, + price, + cost, + businessType, + imageUrl, + printerType, + const DeepCollectionEquality().hash(_metadata), + isActive, + createdAt, + updatedAt, + const DeepCollectionEquality().hash(_variants), + ); + + /// Create a copy of ProductDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductDtoImplCopyWith<_$ProductDtoImpl> get copyWith => + __$$ProductDtoImplCopyWithImpl<_$ProductDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ProductDtoImplToJson(this); + } +} + +abstract class _ProductDto extends ProductDto { + const factory _ProductDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'category_id') final String? categoryId, + @JsonKey(name: 'sku') final String? sku, + @JsonKey(name: 'name') final String? name, + @JsonKey(name: 'description') final String? description, + @JsonKey(name: 'price') final int? price, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'business_type') final String? businessType, + @JsonKey(name: 'image_url') final String? imageUrl, + @JsonKey(name: 'printer_type') final String? printerType, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'is_active') final bool? isActive, + @JsonKey(name: 'created_at') final DateTime? createdAt, + @JsonKey(name: 'updated_at') final DateTime? updatedAt, + @JsonKey(name: 'variants') final List? variants, + }) = _$ProductDtoImpl; + const _ProductDto._() : super._(); + + factory _ProductDto.fromJson(Map json) = + _$ProductDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'category_id') + String? get categoryId; + @override + @JsonKey(name: 'sku') + String? get sku; + @override + @JsonKey(name: 'name') + String? get name; + @override + @JsonKey(name: 'description') + String? get description; + @override + @JsonKey(name: 'price') + int? get price; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'business_type') + String? get businessType; + @override + @JsonKey(name: 'image_url') + String? get imageUrl; + @override + @JsonKey(name: 'printer_type') + String? get printerType; + @override + @JsonKey(name: 'metadata') + Map? get metadata; + @override + @JsonKey(name: 'is_active') + bool? get isActive; + @override + @JsonKey(name: 'created_at') + DateTime? get createdAt; + @override + @JsonKey(name: 'updated_at') + DateTime? get updatedAt; + @override + @JsonKey(name: 'variants') + List? get variants; + + /// Create a copy of ProductDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductDtoImplCopyWith<_$ProductDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} + +ProductVariantDto _$ProductVariantDtoFromJson(Map json) { + return _ProductVariantDto.fromJson(json); +} + +/// @nodoc +mixin _$ProductVariantDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'product_id') + String? get productId => throw _privateConstructorUsedError; + @JsonKey(name: 'name') + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: 'price_modifier') + int? get priceModifier => throw _privateConstructorUsedError; + @JsonKey(name: 'cost') + int? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'metadata') + Map? get metadata => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + DateTime? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + DateTime? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this ProductVariantDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ProductVariantDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ProductVariantDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ProductVariantDtoCopyWith<$Res> { + factory $ProductVariantDtoCopyWith( + ProductVariantDto value, + $Res Function(ProductVariantDto) then, + ) = _$ProductVariantDtoCopyWithImpl<$Res, ProductVariantDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'price_modifier') int? priceModifier, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + }); +} + +/// @nodoc +class _$ProductVariantDtoCopyWithImpl<$Res, $Val extends ProductVariantDto> + implements $ProductVariantDtoCopyWith<$Res> { + _$ProductVariantDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ProductVariantDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? productId = freezed, + Object? name = freezed, + Object? priceModifier = freezed, + Object? cost = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + priceModifier: freezed == priceModifier + ? _value.priceModifier + : priceModifier // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + metadata: freezed == metadata + ? _value.metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ProductVariantDtoImplCopyWith<$Res> + implements $ProductVariantDtoCopyWith<$Res> { + factory _$$ProductVariantDtoImplCopyWith( + _$ProductVariantDtoImpl value, + $Res Function(_$ProductVariantDtoImpl) then, + ) = __$$ProductVariantDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'product_id') String? productId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'price_modifier') int? priceModifier, + @JsonKey(name: 'cost') int? cost, + @JsonKey(name: 'metadata') Map? metadata, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, + }); +} + +/// @nodoc +class __$$ProductVariantDtoImplCopyWithImpl<$Res> + extends _$ProductVariantDtoCopyWithImpl<$Res, _$ProductVariantDtoImpl> + implements _$$ProductVariantDtoImplCopyWith<$Res> { + __$$ProductVariantDtoImplCopyWithImpl( + _$ProductVariantDtoImpl _value, + $Res Function(_$ProductVariantDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ProductVariantDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? productId = freezed, + Object? name = freezed, + Object? priceModifier = freezed, + Object? cost = freezed, + Object? metadata = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$ProductVariantDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + productId: freezed == productId + ? _value.productId + : productId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + priceModifier: freezed == priceModifier + ? _value.priceModifier + : priceModifier // ignore: cast_nullable_to_non_nullable + as int?, + cost: freezed == cost + ? _value.cost + : cost // ignore: cast_nullable_to_non_nullable + as int?, + metadata: freezed == metadata + ? _value._metadata + : metadata // ignore: cast_nullable_to_non_nullable + as Map?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ProductVariantDtoImpl extends _ProductVariantDto { + const _$ProductVariantDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'product_id') this.productId, + @JsonKey(name: 'name') this.name, + @JsonKey(name: 'price_modifier') this.priceModifier, + @JsonKey(name: 'cost') this.cost, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + }) : _metadata = metadata, + super._(); + + factory _$ProductVariantDtoImpl.fromJson(Map json) => + _$$ProductVariantDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'product_id') + final String? productId; + @override + @JsonKey(name: 'name') + final String? name; + @override + @JsonKey(name: 'price_modifier') + final int? priceModifier; + @override + @JsonKey(name: 'cost') + final int? cost; + final Map? _metadata; + @override + @JsonKey(name: 'metadata') + Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'created_at') + final DateTime? createdAt; + @override + @JsonKey(name: 'updated_at') + final DateTime? updatedAt; + + @override + String toString() { + return 'ProductVariantDto(id: $id, productId: $productId, name: $name, priceModifier: $priceModifier, cost: $cost, metadata: $metadata, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ProductVariantDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.productId, productId) || + other.productId == productId) && + (identical(other.name, name) || other.name == name) && + (identical(other.priceModifier, priceModifier) || + other.priceModifier == priceModifier) && + (identical(other.cost, cost) || other.cost == cost) && + const DeepCollectionEquality().equals(other._metadata, _metadata) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + productId, + name, + priceModifier, + cost, + const DeepCollectionEquality().hash(_metadata), + createdAt, + updatedAt, + ); + + /// Create a copy of ProductVariantDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ProductVariantDtoImplCopyWith<_$ProductVariantDtoImpl> get copyWith => + __$$ProductVariantDtoImplCopyWithImpl<_$ProductVariantDtoImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ProductVariantDtoImplToJson(this); + } +} + +abstract class _ProductVariantDto extends ProductVariantDto { + const factory _ProductVariantDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'product_id') final String? productId, + @JsonKey(name: 'name') final String? name, + @JsonKey(name: 'price_modifier') final int? priceModifier, + @JsonKey(name: 'cost') final int? cost, + @JsonKey(name: 'metadata') final Map? metadata, + @JsonKey(name: 'created_at') final DateTime? createdAt, + @JsonKey(name: 'updated_at') final DateTime? updatedAt, + }) = _$ProductVariantDtoImpl; + const _ProductVariantDto._() : super._(); + + factory _ProductVariantDto.fromJson(Map json) = + _$ProductVariantDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'product_id') + String? get productId; + @override + @JsonKey(name: 'name') + String? get name; + @override + @JsonKey(name: 'price_modifier') + int? get priceModifier; + @override + @JsonKey(name: 'cost') + int? get cost; + @override + @JsonKey(name: 'metadata') + Map? get metadata; + @override + @JsonKey(name: 'created_at') + DateTime? get createdAt; + @override + @JsonKey(name: 'updated_at') + DateTime? get updatedAt; + + /// Create a copy of ProductVariantDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ProductVariantDtoImplCopyWith<_$ProductVariantDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/product/product_dtos.g.dart b/lib/infrastructure/product/product_dtos.g.dart new file mode 100644 index 0000000..e15a390 --- /dev/null +++ b/lib/infrastructure/product/product_dtos.g.dart @@ -0,0 +1,83 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'product_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$ProductDtoImpl _$$ProductDtoImplFromJson(Map json) => + _$ProductDtoImpl( + id: json['id'] as String?, + organizationId: json['organization_id'] as String?, + categoryId: json['category_id'] as String?, + sku: json['sku'] as String?, + name: json['name'] as String?, + description: json['description'] as String?, + price: (json['price'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + businessType: json['business_type'] as String?, + imageUrl: json['image_url'] as String?, + printerType: json['printer_type'] as String?, + metadata: json['metadata'] as Map?, + isActive: json['is_active'] as bool?, + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json['created_at'] as String), + updatedAt: json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String), + variants: (json['variants'] as List?) + ?.map((e) => ProductVariantDto.fromJson(e as Map)) + .toList(), + ); + +Map _$$ProductDtoImplToJson(_$ProductDtoImpl instance) => + { + 'id': instance.id, + 'organization_id': instance.organizationId, + 'category_id': instance.categoryId, + 'sku': instance.sku, + 'name': instance.name, + 'description': instance.description, + 'price': instance.price, + 'cost': instance.cost, + 'business_type': instance.businessType, + 'image_url': instance.imageUrl, + 'printer_type': instance.printerType, + 'metadata': instance.metadata, + 'is_active': instance.isActive, + 'created_at': instance.createdAt?.toIso8601String(), + 'updated_at': instance.updatedAt?.toIso8601String(), + 'variants': instance.variants, + }; + +_$ProductVariantDtoImpl _$$ProductVariantDtoImplFromJson( + Map json, +) => _$ProductVariantDtoImpl( + id: json['id'] as String?, + productId: json['product_id'] as String?, + name: json['name'] as String?, + priceModifier: (json['price_modifier'] as num?)?.toInt(), + cost: (json['cost'] as num?)?.toInt(), + metadata: json['metadata'] as Map?, + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json['created_at'] as String), + updatedAt: json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at'] as String), +); + +Map _$$ProductVariantDtoImplToJson( + _$ProductVariantDtoImpl instance, +) => { + 'id': instance.id, + 'product_id': instance.productId, + 'name': instance.name, + 'price_modifier': instance.priceModifier, + 'cost': instance.cost, + 'metadata': instance.metadata, + 'created_at': instance.createdAt?.toIso8601String(), + 'updated_at': instance.updatedAt?.toIso8601String(), +}; diff --git a/lib/infrastructure/product/repositories/product_repository.dart b/lib/infrastructure/product/repositories/product_repository.dart new file mode 100644 index 0000000..32bb7bc --- /dev/null +++ b/lib/infrastructure/product/repositories/product_repository.dart @@ -0,0 +1,43 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/product/product.dart'; +import '../datasources/remote_data_provider.dart'; + +@Injectable(as: IProductRepository) +class ProductRepository implements IProductRepository { + final ProductRemoteDataProvider _dataProvider; + final String _logName = 'ProductRepository'; + + ProductRepository(this._dataProvider); + + @override + Future>> get({ + int page = 1, + int limit = 10, + String? categoryId, + String? search, + }) async { + try { + final result = await _dataProvider.fetch( + page: page, + limit: limit, + categoryId: categoryId, + search: search, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.map((e) => e.toDomain()).toList(); + + return right(auth); + } catch (e, s) { + log('getProductError', name: _logName, error: e, stackTrace: s); + return left(const ProductFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/user/datasource/remote_data_provider.dart b/lib/infrastructure/user/datasource/remote_data_provider.dart new file mode 100644 index 0000000..f92a5b7 --- /dev/null +++ b/lib/infrastructure/user/datasource/remote_data_provider.dart @@ -0,0 +1,83 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:data_channel/data_channel.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../common/api/api_client.dart'; +import '../../../common/api/api_failure.dart'; +import '../../../common/function/app_function.dart'; +import '../../../common/url/api_path.dart'; +import '../../../domain/user/user.dart'; +import '../user_dtos.dart'; + +@injectable +class UserRemoteDataProvider { + final ApiClient _apiClient; + + static const _logName = 'UserRemoteDataProvider'; + + UserRemoteDataProvider(this._apiClient); + + Future> updateUser({ + required String name, + required String userId, + }) async { + try { + final response = await _apiClient.put( + '${ApiPath.user}/$userId', + data: {'name': name, 'is_active': true}, + headers: getAuthorizationHeader(), + ); + + if (response.statusCode == 400) { + return DC.error(UserFailure.unexpectedError()); + } + + if (response.statusCode != 200) { + return DC.error( + UserFailure.dynamicErrorMessage(response.data['message']), + ); + } + + final dto = UserDto.fromJson(response.data); + + return DC.data(dto); + } on ApiFailure catch (e, s) { + log('updateUser', name: _logName, error: e, stackTrace: s); + return DC.error(UserFailure.serverError(e)); + } + } + + Future> changePassword({ + required String newPassword, + required String currentPassword, + required String userId, + }) async { + try { + final response = await _apiClient.put( + '${ApiPath.user}/$userId/password', + data: { + 'new_password': newPassword, + 'current_password': currentPassword, + }, + headers: getAuthorizationHeader(), + ); + + if (response.statusCode == 400) { + return DC.error(UserFailure.unexpectedError()); + } + + if (response.statusCode != 200) { + return DC.error( + UserFailure.dynamicErrorMessage(response.data['error']), + ); + } + + return DC.data(unit); + } on ApiFailure catch (e, s) { + log('changePassword', name: _logName, error: e, stackTrace: s); + return DC.error(UserFailure.serverError(e)); + } + } +} diff --git a/lib/infrastructure/user/dto/user_dto.dart b/lib/infrastructure/user/dto/user_dto.dart new file mode 100644 index 0000000..f1ad1e6 --- /dev/null +++ b/lib/infrastructure/user/dto/user_dto.dart @@ -0,0 +1,39 @@ +part of '../user_dtos.dart'; + +@freezed +class UserDto with _$UserDto { + const UserDto._(); + + const factory UserDto({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'email') String? email, + @JsonKey(name: 'role') String? role, + @JsonKey(name: 'permissions') Map? permissions, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }) = _UserDto; + + factory UserDto.fromJson(Map json) => + _$UserDtoFromJson(json); + + User toDomain() => User( + id: id ?? '', + organizationId: organizationId ?? '', + outletId: outletId ?? '', + name: name ?? '', + email: email ?? '', + role: role ?? '', + permissions: permissions ?? {}, + isActive: isActive ?? false, + createdAt: createdAt != null + ? DateTime.parse(createdAt ?? "") + : DateTime.fromMillisecondsSinceEpoch(0), + updatedAt: updatedAt != null + ? DateTime.parse(updatedAt ?? "") + : DateTime.fromMillisecondsSinceEpoch(0), + ); +} diff --git a/lib/infrastructure/user/repositories/user_repository.dart b/lib/infrastructure/user/repositories/user_repository.dart new file mode 100644 index 0000000..d5ab224 --- /dev/null +++ b/lib/infrastructure/user/repositories/user_repository.dart @@ -0,0 +1,66 @@ +import 'dart:developer'; + +import 'package:dartz/dartz.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/user/user.dart'; +import '../../auth/datasources/local_data_provider.dart'; +import '../datasource/remote_data_provider.dart'; + +@Injectable(as: IUserRepository) +class UserRepository implements IUserRepository { + final UserRemoteDataProvider _dataProvider; + final AuthLocalDataProvider _authLocalDataProvider; + + final String _logName = 'UserRepository'; + + UserRepository(this._dataProvider, this._authLocalDataProvider); + + @override + Future> editUser({required String name}) async { + try { + User currentUser = await _authLocalDataProvider.currentUser(); + final result = await _dataProvider.updateUser( + name: name, + userId: currentUser.id, + ); + + if (result.hasError) { + return left(result.error!); + } + + final auth = result.data!.toDomain(); + + await _authLocalDataProvider.saveCurrentUser(result.data!); + + return right(auth); + } catch (e, s) { + log('editUserError', name: _logName, error: e, stackTrace: s); + return left(const UserFailure.unexpectedError()); + } + } + + @override + Future> changePassword({ + required String newPassword, + required String currentPassword, + }) async { + try { + User currentUser = await _authLocalDataProvider.currentUser(); + final result = await _dataProvider.changePassword( + newPassword: newPassword, + currentPassword: currentPassword, + userId: currentUser.id, + ); + + if (result.hasError) { + return left(result.error!); + } + + return right(unit); + } catch (e, s) { + log('changePasswordError', name: _logName, error: e, stackTrace: s); + return left(const UserFailure.unexpectedError()); + } + } +} diff --git a/lib/infrastructure/user/user_dtos.dart b/lib/infrastructure/user/user_dtos.dart new file mode 100644 index 0000000..48458fe --- /dev/null +++ b/lib/infrastructure/user/user_dtos.dart @@ -0,0 +1,8 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import '../../domain/user/user.dart'; + +part 'user_dtos.freezed.dart'; +part 'user_dtos.g.dart'; + +part 'dto/user_dto.dart'; diff --git a/lib/infrastructure/user/user_dtos.freezed.dart b/lib/infrastructure/user/user_dtos.freezed.dart new file mode 100644 index 0000000..6c51cd9 --- /dev/null +++ b/lib/infrastructure/user/user_dtos.freezed.dart @@ -0,0 +1,414 @@ +// 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 'user_dtos.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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', +); + +UserDto _$UserDtoFromJson(Map json) { + return _UserDto.fromJson(json); +} + +/// @nodoc +mixin _$UserDto { + @JsonKey(name: 'id') + String? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'organization_id') + String? get organizationId => throw _privateConstructorUsedError; + @JsonKey(name: 'outlet_id') + String? get outletId => throw _privateConstructorUsedError; + @JsonKey(name: 'name') + String? get name => throw _privateConstructorUsedError; + @JsonKey(name: 'email') + String? get email => throw _privateConstructorUsedError; + @JsonKey(name: 'role') + String? get role => throw _privateConstructorUsedError; + @JsonKey(name: 'permissions') + Map? get permissions => throw _privateConstructorUsedError; + @JsonKey(name: 'is_active') + bool? get isActive => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at') + String? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at') + String? get updatedAt => throw _privateConstructorUsedError; + + /// Serializes this UserDto to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of UserDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $UserDtoCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $UserDtoCopyWith<$Res> { + factory $UserDtoCopyWith(UserDto value, $Res Function(UserDto) then) = + _$UserDtoCopyWithImpl<$Res, UserDto>; + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'email') String? email, + @JsonKey(name: 'role') String? role, + @JsonKey(name: 'permissions') Map? permissions, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class _$UserDtoCopyWithImpl<$Res, $Val extends UserDto> + implements $UserDtoCopyWith<$Res> { + _$UserDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of UserDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? outletId = freezed, + Object? name = freezed, + Object? email = freezed, + Object? role = freezed, + Object? permissions = freezed, + Object? isActive = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + email: freezed == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String?, + role: freezed == role + ? _value.role + : role // ignore: cast_nullable_to_non_nullable + as String?, + permissions: freezed == permissions + ? _value.permissions + : permissions // ignore: cast_nullable_to_non_nullable + as Map?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$UserDtoImplCopyWith<$Res> implements $UserDtoCopyWith<$Res> { + factory _$$UserDtoImplCopyWith( + _$UserDtoImpl value, + $Res Function(_$UserDtoImpl) then, + ) = __$$UserDtoImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(name: 'id') String? id, + @JsonKey(name: 'organization_id') String? organizationId, + @JsonKey(name: 'outlet_id') String? outletId, + @JsonKey(name: 'name') String? name, + @JsonKey(name: 'email') String? email, + @JsonKey(name: 'role') String? role, + @JsonKey(name: 'permissions') Map? permissions, + @JsonKey(name: 'is_active') bool? isActive, + @JsonKey(name: 'created_at') String? createdAt, + @JsonKey(name: 'updated_at') String? updatedAt, + }); +} + +/// @nodoc +class __$$UserDtoImplCopyWithImpl<$Res> + extends _$UserDtoCopyWithImpl<$Res, _$UserDtoImpl> + implements _$$UserDtoImplCopyWith<$Res> { + __$$UserDtoImplCopyWithImpl( + _$UserDtoImpl _value, + $Res Function(_$UserDtoImpl) _then, + ) : super(_value, _then); + + /// Create a copy of UserDto + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? organizationId = freezed, + Object? outletId = freezed, + Object? name = freezed, + Object? email = freezed, + Object? role = freezed, + Object? permissions = freezed, + Object? isActive = freezed, + Object? createdAt = freezed, + Object? updatedAt = freezed, + }) { + return _then( + _$UserDtoImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + organizationId: freezed == organizationId + ? _value.organizationId + : organizationId // ignore: cast_nullable_to_non_nullable + as String?, + outletId: freezed == outletId + ? _value.outletId + : outletId // ignore: cast_nullable_to_non_nullable + as String?, + name: freezed == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + email: freezed == email + ? _value.email + : email // ignore: cast_nullable_to_non_nullable + as String?, + role: freezed == role + ? _value.role + : role // ignore: cast_nullable_to_non_nullable + as String?, + permissions: freezed == permissions + ? _value._permissions + : permissions // ignore: cast_nullable_to_non_nullable + as Map?, + isActive: freezed == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool?, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as String?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as String?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$UserDtoImpl extends _UserDto { + const _$UserDtoImpl({ + @JsonKey(name: 'id') this.id, + @JsonKey(name: 'organization_id') this.organizationId, + @JsonKey(name: 'outlet_id') this.outletId, + @JsonKey(name: 'name') this.name, + @JsonKey(name: 'email') this.email, + @JsonKey(name: 'role') this.role, + @JsonKey(name: 'permissions') final Map? permissions, + @JsonKey(name: 'is_active') this.isActive, + @JsonKey(name: 'created_at') this.createdAt, + @JsonKey(name: 'updated_at') this.updatedAt, + }) : _permissions = permissions, + super._(); + + factory _$UserDtoImpl.fromJson(Map json) => + _$$UserDtoImplFromJson(json); + + @override + @JsonKey(name: 'id') + final String? id; + @override + @JsonKey(name: 'organization_id') + final String? organizationId; + @override + @JsonKey(name: 'outlet_id') + final String? outletId; + @override + @JsonKey(name: 'name') + final String? name; + @override + @JsonKey(name: 'email') + final String? email; + @override + @JsonKey(name: 'role') + final String? role; + final Map? _permissions; + @override + @JsonKey(name: 'permissions') + Map? get permissions { + final value = _permissions; + if (value == null) return null; + if (_permissions is EqualUnmodifiableMapView) return _permissions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + @JsonKey(name: 'is_active') + final bool? isActive; + @override + @JsonKey(name: 'created_at') + final String? createdAt; + @override + @JsonKey(name: 'updated_at') + final String? updatedAt; + + @override + String toString() { + return 'UserDto(id: $id, organizationId: $organizationId, outletId: $outletId, name: $name, email: $email, role: $role, permissions: $permissions, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$UserDtoImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.organizationId, organizationId) || + other.organizationId == organizationId) && + (identical(other.outletId, outletId) || + other.outletId == outletId) && + (identical(other.name, name) || other.name == name) && + (identical(other.email, email) || other.email == email) && + (identical(other.role, role) || other.role == role) && + const DeepCollectionEquality().equals( + other._permissions, + _permissions, + ) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + organizationId, + outletId, + name, + email, + role, + const DeepCollectionEquality().hash(_permissions), + isActive, + createdAt, + updatedAt, + ); + + /// Create a copy of UserDto + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$UserDtoImplCopyWith<_$UserDtoImpl> get copyWith => + __$$UserDtoImplCopyWithImpl<_$UserDtoImpl>(this, _$identity); + + @override + Map toJson() { + return _$$UserDtoImplToJson(this); + } +} + +abstract class _UserDto extends UserDto { + const factory _UserDto({ + @JsonKey(name: 'id') final String? id, + @JsonKey(name: 'organization_id') final String? organizationId, + @JsonKey(name: 'outlet_id') final String? outletId, + @JsonKey(name: 'name') final String? name, + @JsonKey(name: 'email') final String? email, + @JsonKey(name: 'role') final String? role, + @JsonKey(name: 'permissions') final Map? permissions, + @JsonKey(name: 'is_active') final bool? isActive, + @JsonKey(name: 'created_at') final String? createdAt, + @JsonKey(name: 'updated_at') final String? updatedAt, + }) = _$UserDtoImpl; + const _UserDto._() : super._(); + + factory _UserDto.fromJson(Map json) = _$UserDtoImpl.fromJson; + + @override + @JsonKey(name: 'id') + String? get id; + @override + @JsonKey(name: 'organization_id') + String? get organizationId; + @override + @JsonKey(name: 'outlet_id') + String? get outletId; + @override + @JsonKey(name: 'name') + String? get name; + @override + @JsonKey(name: 'email') + String? get email; + @override + @JsonKey(name: 'role') + String? get role; + @override + @JsonKey(name: 'permissions') + Map? get permissions; + @override + @JsonKey(name: 'is_active') + bool? get isActive; + @override + @JsonKey(name: 'created_at') + String? get createdAt; + @override + @JsonKey(name: 'updated_at') + String? get updatedAt; + + /// Create a copy of UserDto + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$UserDtoImplCopyWith<_$UserDtoImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/infrastructure/user/user_dtos.g.dart b/lib/infrastructure/user/user_dtos.g.dart new file mode 100644 index 0000000..80c6411 --- /dev/null +++ b/lib/infrastructure/user/user_dtos.g.dart @@ -0,0 +1,35 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_dtos.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$UserDtoImpl _$$UserDtoImplFromJson(Map json) => + _$UserDtoImpl( + id: json['id'] as String?, + organizationId: json['organization_id'] as String?, + outletId: json['outlet_id'] as String?, + name: json['name'] as String?, + email: json['email'] as String?, + role: json['role'] as String?, + permissions: json['permissions'] as Map?, + isActive: json['is_active'] as bool?, + createdAt: json['created_at'] as String?, + updatedAt: json['updated_at'] as String?, + ); + +Map _$$UserDtoImplToJson(_$UserDtoImpl instance) => + { + 'id': instance.id, + 'organization_id': instance.organizationId, + 'outlet_id': instance.outletId, + 'name': instance.name, + 'email': instance.email, + 'role': instance.role, + 'permissions': instance.permissions, + 'is_active': instance.isActive, + 'created_at': instance.createdAt, + 'updated_at': instance.updatedAt, + }; diff --git a/lib/injection.config.dart b/lib/injection.config.dart index 96db829..e48e26d 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -9,21 +9,117 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:apskel_owner_flutter/application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart' + as _i1038; +import 'package:apskel_owner_flutter/application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart' + as _i516; +import 'package:apskel_owner_flutter/application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart' + as _i785; +import 'package:apskel_owner_flutter/application/analytic/payment_method_analytic_loader/payment_method_analytic_loader_bloc.dart' + as _i552; +import 'package:apskel_owner_flutter/application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart' + as _i221; +import 'package:apskel_owner_flutter/application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart' + as _i11; +import 'package:apskel_owner_flutter/application/analytic/sales_loader/sales_loader_bloc.dart' + as _i889; +import 'package:apskel_owner_flutter/application/auth/auth_bloc.dart' as _i945; +import 'package:apskel_owner_flutter/application/auth/login_form/login_form_bloc.dart' + as _i775; +import 'package:apskel_owner_flutter/application/auth/logout_form/logout_form_bloc.dart' + as _i574; +import 'package:apskel_owner_flutter/application/category/category_loader/category_loader_bloc.dart' + as _i183; +import 'package:apskel_owner_flutter/application/customer/customer_loader/customer_loader_bloc.dart' + as _i972; +import 'package:apskel_owner_flutter/application/home/home_bloc.dart' as _i473; +import 'package:apskel_owner_flutter/application/language/language_bloc.dart' + as _i455; +import 'package:apskel_owner_flutter/application/order/order_loader/order_loader_bloc.dart' + as _i1058; +import 'package:apskel_owner_flutter/application/outlet/current_outlet_loader/current_outlet_loader_bloc.dart' + as _i337; +import 'package:apskel_owner_flutter/application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart' + as _i877; +import 'package:apskel_owner_flutter/application/outlet/selected_outlet/selected_outlet_bloc.dart' + as _i678; +import 'package:apskel_owner_flutter/application/product/product_loader/product_loader_bloc.dart' + as _i458; +import 'package:apskel_owner_flutter/application/report/inventory_report/inventory_report_bloc.dart' + as _i346; +import 'package:apskel_owner_flutter/application/report/transaction_report/transaction_report_bloc.dart' + as _i605; +import 'package:apskel_owner_flutter/application/user/change_password_form/change_password_form_bloc.dart' + as _i1030; +import 'package:apskel_owner_flutter/application/user/user_edit_form/user_edit_form_bloc.dart' + as _i147; import 'package:apskel_owner_flutter/common/api/api_client.dart' as _i115; import 'package:apskel_owner_flutter/common/di/di_auto_route.dart' as _i311; import 'package:apskel_owner_flutter/common/di/di_connectivity.dart' as _i586; import 'package:apskel_owner_flutter/common/di/di_dio.dart' as _i103; +import 'package:apskel_owner_flutter/common/di/di_firebase.dart' as _i73; +import 'package:apskel_owner_flutter/common/di/di_package_info.dart' as _i227; import 'package:apskel_owner_flutter/common/di/di_shared_preferences.dart' as _i402; import 'package:apskel_owner_flutter/common/network/network_client.dart' as _i543; +import 'package:apskel_owner_flutter/common/utils/device_info_service.dart' + as _i902; +import 'package:apskel_owner_flutter/common/utils/fcm_service.dart' as _i179; +import 'package:apskel_owner_flutter/domain/analytic/repositories/i_analytic_repository.dart' + as _i477; +import 'package:apskel_owner_flutter/domain/auth/auth.dart' as _i49; +import 'package:apskel_owner_flutter/domain/category/category.dart' as _i1020; +import 'package:apskel_owner_flutter/domain/customer/customer.dart' as _i48; +import 'package:apskel_owner_flutter/domain/order/order.dart' as _i219; +import 'package:apskel_owner_flutter/domain/outlet/outlet.dart' as _i197; +import 'package:apskel_owner_flutter/domain/product/product.dart' as _i419; +import 'package:apskel_owner_flutter/domain/user/user.dart' as _i635; import 'package:apskel_owner_flutter/env.dart' as _i6; +import 'package:apskel_owner_flutter/infrastructure/analytic/datasource/remote_data_provider.dart' + as _i866; +import 'package:apskel_owner_flutter/infrastructure/analytic/repositories/analytic_repository.dart' + as _i393; +import 'package:apskel_owner_flutter/infrastructure/auth/datasources/local_data_provider.dart' + as _i991; +import 'package:apskel_owner_flutter/infrastructure/auth/datasources/remote_data_provider.dart' + as _i17; +import 'package:apskel_owner_flutter/infrastructure/auth/repositories/auth_repository.dart' + as _i1035; +import 'package:apskel_owner_flutter/infrastructure/category/datasource/remote_data_provider.dart' + as _i333; +import 'package:apskel_owner_flutter/infrastructure/category/repositories/category_repository.dart' + as _i869; +import 'package:apskel_owner_flutter/infrastructure/customer/datasources/remote_data_provider.dart' + as _i1006; +import 'package:apskel_owner_flutter/infrastructure/customer/repositories/customer_repository.dart' + as _i550; +import 'package:apskel_owner_flutter/infrastructure/order/datasource/remote_data_provider.dart' + as _i130; +import 'package:apskel_owner_flutter/infrastructure/order/repositories/order_repository.dart' + as _i641; +import 'package:apskel_owner_flutter/infrastructure/outlet/datasource/local_data_provider.dart' + as _i850; +import 'package:apskel_owner_flutter/infrastructure/outlet/datasource/remote_data_provider.dart' + as _i27; +import 'package:apskel_owner_flutter/infrastructure/outlet/repositories/outlet_repository.dart' + as _i13; +import 'package:apskel_owner_flutter/infrastructure/product/datasources/remote_data_provider.dart' + as _i823; +import 'package:apskel_owner_flutter/infrastructure/product/repositories/product_repository.dart' + as _i121; +import 'package:apskel_owner_flutter/infrastructure/user/datasource/remote_data_provider.dart' + as _i785; +import 'package:apskel_owner_flutter/infrastructure/user/repositories/user_repository.dart' + as _i754; import 'package:apskel_owner_flutter/presentation/router/app_router.dart' as _i258; import 'package:connectivity_plus/connectivity_plus.dart' as _i895; import 'package:dio/dio.dart' as _i361; +import 'package:firebase_core/firebase_core.dart' as _i982; import 'package:get_it/get_it.dart' as _i174; import 'package:injectable/injectable.dart' as _i526; +import 'package:package_info_plus/package_info_plus.dart' as _i655; import 'package:shared_preferences/shared_preferences.dart' as _i460; const String _dev = 'dev'; @@ -36,33 +132,200 @@ extension GetItInjectableX on _i174.GetIt { _i526.EnvironmentFilter? environmentFilter, }) async { final gh = _i526.GetItHelper(this, environment, environmentFilter); + final firebaseDi = _$FirebaseDi(); final sharedPreferencesDi = _$SharedPreferencesDi(); - final dioDi = _$DioDi(); final autoRouteDi = _$AutoRouteDi(); final connectivityDi = _$ConnectivityDi(); + final dioDi = _$DioDi(); + final packageInfoDi = _$PackageInfoDi(); + await gh.factoryAsync<_i982.FirebaseApp>( + () => firebaseDi.firebaseApp, + preResolve: true, + ); await gh.factoryAsync<_i460.SharedPreferences>( () => sharedPreferencesDi.prefs, preResolve: true, ); - gh.lazySingleton<_i361.Dio>(() => dioDi.dio); gh.lazySingleton<_i258.AppRouter>(() => autoRouteDi.appRouter); gh.lazySingleton<_i895.Connectivity>(() => connectivityDi.connectivity); + gh.lazySingleton<_i361.Dio>(() => dioDi.dio); + await gh.lazySingletonAsync<_i655.PackageInfo>( + () => packageInfoDi.packageInfo, + preResolve: true, + ); + gh.lazySingleton<_i902.DeviceInfoService>(() => _i902.DeviceInfoService()); + gh.lazySingleton<_i179.FcmService>(() => _i179.FcmService()); gh.lazySingleton<_i543.NetworkClient>( () => _i543.NetworkClient(gh<_i895.Connectivity>()), ); + gh.factory<_i455.LanguageBloc>( + () => _i455.LanguageBloc(gh<_i460.SharedPreferences>()), + ); gh.factory<_i6.Env>(() => _i6.DevEnv(), registerFor: {_dev}); + gh.factory<_i991.AuthLocalDataProvider>( + () => _i991.AuthLocalDataProvider(gh<_i460.SharedPreferences>()), + ); + gh.factory<_i850.OutletLocalDataProvider>( + () => _i850.OutletLocalDataProvider(gh<_i460.SharedPreferences>()), + ); gh.lazySingleton<_i115.ApiClient>( () => _i115.ApiClient(gh<_i361.Dio>(), gh<_i6.Env>()), ); gh.factory<_i6.Env>(() => _i6.ProdEnv(), registerFor: {_prod}); + gh.factory<_i866.AnalyticRemoteDataProvider>( + () => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i17.AuthRemoteDataProvider>( + () => _i17.AuthRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i333.CategoryRemoteDataProvider>( + () => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i1006.CustomerRemoteDataProvider>( + () => _i1006.CustomerRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i130.OrderRemoteDataProvider>( + () => _i130.OrderRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i27.OutletRemoteDataProvider>( + () => _i27.OutletRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i823.ProductRemoteDataProvider>( + () => _i823.ProductRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i785.UserRemoteDataProvider>( + () => _i785.UserRemoteDataProvider(gh<_i115.ApiClient>()), + ); + gh.factory<_i48.ICustomerRepository>( + () => _i550.CustomerRepository(gh<_i1006.CustomerRemoteDataProvider>()), + ); + gh.factory<_i49.IAuthRepository>( + () => _i1035.AuthRepository( + gh<_i991.AuthLocalDataProvider>(), + gh<_i17.AuthRemoteDataProvider>(), + ), + ); + gh.factory<_i678.SelectedOutletBloc>( + () => _i678.SelectedOutletBloc(gh<_i850.OutletLocalDataProvider>()), + ); + gh.factory<_i635.IUserRepository>( + () => _i754.UserRepository( + gh<_i785.UserRemoteDataProvider>(), + gh<_i991.AuthLocalDataProvider>(), + ), + ); + gh.factory<_i419.IProductRepository>( + () => _i121.ProductRepository(gh<_i823.ProductRemoteDataProvider>()), + ); + gh.factory<_i219.IOrderRepository>( + () => _i641.OrderRepository( + gh<_i130.OrderRemoteDataProvider>(), + gh<_i850.OutletLocalDataProvider>(), + ), + ); + gh.factory<_i972.CustomerLoaderBloc>( + () => _i972.CustomerLoaderBloc(gh<_i48.ICustomerRepository>()), + ); + gh.factory<_i1020.ICategoryRepository>( + () => _i869.CategoryRepository(gh<_i333.CategoryRemoteDataProvider>()), + ); + gh.factory<_i197.IOutletRepository>( + () => _i13.OutletRepository( + gh<_i27.OutletRemoteDataProvider>(), + gh<_i991.AuthLocalDataProvider>(), + ), + ); + gh.factory<_i458.ProductLoaderBloc>( + () => _i458.ProductLoaderBloc(gh<_i419.IProductRepository>()), + ); + gh.factory<_i183.CategoryLoaderBloc>( + () => _i183.CategoryLoaderBloc(gh<_i1020.ICategoryRepository>()), + ); + gh.factory<_i477.IAnalyticRepository>( + () => _i393.AnalyticRepository( + gh<_i866.AnalyticRemoteDataProvider>(), + gh<_i991.AuthLocalDataProvider>(), + gh<_i850.OutletLocalDataProvider>(), + ), + ); + gh.factory<_i889.SalesLoaderBloc>( + () => _i889.SalesLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i473.HomeBloc>( + () => _i473.HomeBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i877.OutletListLoaderBloc>( + () => _i877.OutletListLoaderBloc(gh<_i197.IOutletRepository>()), + ); + gh.factory<_i337.CurrentOutletLoaderBloc>( + () => _i337.CurrentOutletLoaderBloc(gh<_i197.IOutletRepository>()), + ); + gh.factory<_i1038.CategoryAnalyticLoaderBloc>( + () => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i516.DashboardAnalyticLoaderBloc>( + () => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i785.InventoryAnalyticLoaderBloc>( + () => _i785.InventoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i552.PaymentMethodAnalyticLoaderBloc>( + () => _i552.PaymentMethodAnalyticLoaderBloc( + gh<_i477.IAnalyticRepository>(), + ), + ); + gh.factory<_i221.ProductAnalyticLoaderBloc>( + () => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i11.ProfitLossLoaderBloc>( + () => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()), + ); + gh.factory<_i945.AuthBloc>( + () => _i945.AuthBloc(gh<_i49.IAuthRepository>()), + ); + gh.factory<_i574.LogoutFormBloc>( + () => _i574.LogoutFormBloc(gh<_i49.IAuthRepository>()), + ); + gh.factory<_i1058.OrderLoaderBloc>( + () => _i1058.OrderLoaderBloc(gh<_i219.IOrderRepository>()), + ); + gh.factory<_i1030.ChangePasswordFormBloc>( + () => _i1030.ChangePasswordFormBloc(gh<_i635.IUserRepository>()), + ); + gh.factory<_i147.UserEditFormBloc>( + () => _i147.UserEditFormBloc(gh<_i635.IUserRepository>()), + ); + gh.factory<_i775.LoginFormBloc>( + () => _i775.LoginFormBloc( + gh<_i49.IAuthRepository>(), + gh<_i902.DeviceInfoService>(), + gh<_i179.FcmService>(), + ), + ); + gh.factory<_i346.InventoryReportBloc>( + () => _i346.InventoryReportBloc( + gh<_i477.IAnalyticRepository>(), + gh<_i197.IOutletRepository>(), + ), + ); + gh.factory<_i605.TransactionReportBloc>( + () => _i605.TransactionReportBloc( + gh<_i477.IAnalyticRepository>(), + gh<_i197.IOutletRepository>(), + ), + ); return this; } } -class _$SharedPreferencesDi extends _i402.SharedPreferencesDi {} +class _$FirebaseDi extends _i73.FirebaseDi {} -class _$DioDi extends _i103.DioDi {} +class _$SharedPreferencesDi extends _i402.SharedPreferencesDi {} class _$AutoRouteDi extends _i311.AutoRouteDi {} class _$ConnectivityDi extends _i586.ConnectivityDi {} + +class _$DioDi extends _i103.DioDi {} + +class _$PackageInfoDi extends _i227.PackageInfoDi {} diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb new file mode 100644 index 0000000..44777f0 --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,435 @@ +{ + "@@locale": "en", + "indonesian": "Indonesian", + "@indonesian": {}, + "english": "English", + "@english": {}, + "language": "Language", + "@language": {}, + "version": "Version", + "@version": {}, + "select_language": "Select Language", + "@select_language": {}, + "login_header": "Welcome back", + "@login_header": {}, + "login_desc": "Sign in to your account", + "@login_desc": {}, + "email": "Email", + "@email": {}, + "email_placeholder": "Enter your email", + "@email_placeholder": {}, + "password": "Password", + "@password": {}, + "password_placeholder": "Enter your password", + "@password_placeholder": {}, + "forgot_password": "Forgot Password", + "@forgot_password": {}, + "sign_in": "Sign In", + "@sign_in": {}, + "good_morning": "Good Morning", + "@good_morning": {}, + "good_afternoon": "Good Afternoon", + "@good_afternoon": {}, + "good_evening": "Good Evening", + "@good_evening": {}, + "good_night": "Good Night", + "@good_night": {}, + "home_header_desc": "Let's improve your business performance today", + "@home_header_desc": {}, + "home": "Home", + "@home": {}, + "transaction": "Transaction", + "@transaction": {}, + "transactions": "Transactions", + "@transactions": {}, + "report": "Report", + "@report": {}, + "reports": "Reports", + "@reports": {}, + "profile": "Profile", + "@profile": {}, + "sales_today": "Sales today", + "@sales_today": {}, + "order": "Order", + "@order": {}, + "sales": "Sales", + "@sales": {}, + "finance": "Finance", + "@finance": {}, + "product": "Product", + "@product": {}, + "form": "Form", + "@form": {}, + "schedule": "Schedule", + "@schedule": {}, + "inventory": "Inventory", + "@inventory": {}, + "customer": "Customer", + "@customer": {}, + "purchase": "Purchase", + "@purchase": {}, + "today_summary": "Today's Summary", + "@today_summary": {}, + "today": "Today", + "@today": {}, + "new_customer": "New Customer", + "@new_customer": {}, + "refund": "Refund", + "@refund": {}, + "void_text": "Void", + "@void_text": {}, + "increase": "Increase", + "@increase": {}, + "today_top_product": "Today's Top Product", + "@today_top_product": {}, + "rank": "Rank", + "@rank": {}, + "quantity_sold": "Quantity Sold", + "@quantity_sold": {}, + "total_orders": "Total Orders", + "@total_orders": {}, + "average_price": "Average Price", + "@average_price": {}, + "perfomance": "Performance", + "@perfomance": {}, + "total_sales": "Total Sales", + "@total_sales": {}, + "total_items": "Total Items", + "@total_items": {}, + "summary": "Summary", + "@summary": {}, + "net_sales": "Net Sales", + "@net_sales": {}, + "daily_breakdown": "Daily Breakdown", + "@daily_breakdown": {}, + "orders": "Orders", + "@orders": {}, + "items": "Items", + "@items": {}, + "tax": "Tax", + "@tax": {}, + "discount": "Discount", + "@discount": {}, + "total_purchase": "Total Purchase", + "@total_purchase": {}, + "pending_order": "Pending Order", + "@pending_order": {}, + "history_purchase": "History Purchase", + "@history_purchase": {}, + "all": "All", + "@all": {}, + "select_date_range": "Select Date Range", + "@select_date_range": {}, + "no_date_selected": "No date has been selected yet", + "@no_date_selected": {}, + "selected_date": "Selected Date", + "@selected_date": {}, + "select": "Select", + "@select": {}, + "cancel": "Cancel", + "@cancel": {}, + "total_revenue": "Total Revenue", + "@total_revenue": {}, + "total_expenditures": "Total Expenditures", + "@total_expenditures": {}, + "net_profit": "Net Profit", + "@net_profit": {}, + "margin_profit": "Margin Profit", + "@margin_profit": {}, + "cash_flow_analysis": "Cash Flow Analysis", + "@cash_flow_analysis": {}, + "cash_in": "Cash In", + "@cash_in": {}, + "cash_out": "Cash Out", + "@cash_out": {}, + "net_flow": "Net Flow", + "@net_flow": {}, + "cash_flow_chart": "Cash Flow Chart for {days} Last Days", + "@cash_flow_chart": { + "placeholders": { + "days": { + "type": "int", + "example": "7" + } + } + }, + "profit_loss_detail": "Profit & Loss Details", + "@profit_loss_detail": {}, + "gross_sales": "Gross Sales", + "@gross_sales": {}, + "return_text": "Return", + "@return_text": {}, + "cogs": "COGS", + "@cogs": {}, + "cost_of_goods_sold": "Cost of goods sold", + "@cost_of_goods_sold": {}, + "gross_profit": "Gross Profit", + "@gross_profit": {}, + "operating_costs": "Operating Costs", + "@operating_costs": {}, + "sales_category": "Sales Category", + "@sales_category": {}, + "unit": "Unit", + "@unit": {}, + "category_no_data": "There are no data categories yet", + "@category_no_data": {}, + "category_no_data_desc": "Sales category data will appear here", + "@category_no_data_desc": {}, + "product_analytic": "Product Analytic", + "@product_analytic": {}, + "view_all": "View All", + "@view_all": {}, + "sold": "Sold", + "@sold": {}, + "revenue": "Revenue", + "@revenue": {}, + "cost": "Cost", + "@cost": {}, + "profit_per_unit": "Profit per unit", + "@profit_per_unit": {}, + "total_sold": "Total Sold", + "@total_sold": {}, + "ingredients": "Ingredients", + "@ingredients": {}, + "low_stock": "Low Stock", + "@low_stock": {}, + "zero_stock": "Zero Stock", + "@zero_stock": {}, + "stock": "Stock", + "@stock": {}, + "price": "Price", + "@price": {}, + "out_of_stock": "Out of stock", + "@out_of_stock": {}, + "out_of_stock_desc": "Product not available for sale", + "@out_of_stock_desc": {}, + "in_text": "In", + "@in_text": {}, + "out_text": "Out", + "@out_text": {}, + "available": "Available", + "@available": {}, + "total_products": "Total Products", + "@total_products": {}, + "total_ingredients": "Total Ingredients", + "@total_ingredients": {}, + "products": "Products", + "@products": {}, + "value_text": "Value", + "@value_text": {}, + "low_stock_desc": "Immediately reorder at least {stock} pcs", + "@low_stock_desc": { + "placeholders": { + "stock": { + "type": "String", + "example": "0" + } + } + }, + "joined": "Joined", + "@joined": {}, + "ago": "ago", + "@ago": {}, + "active": "Active", + "@active": {}, + "inactive": "Inactive", + "@inactive": {}, + "total_amount": "Total Amount", + "@total_amount": {}, + "table": "Table", + "@table": {}, + "remaining": "Remaining", + "@remaining": {}, + "payment": "Payment", + "@payment": {}, + "completed": "Completed", + "@completed": {}, + "pending": "Pending", + "@pending": {}, + "no_order_with_status": "No {status} orders found", + "@no_order_with_status": { + "placeholders": { + "status": { + "type": "String", + "example": "pending" + } + } + }, + "order_details": "Order Details", + "@order_details": {}, + "order_number": "Order Number", + "@order_number": {}, + "order_status": "Order Status", + "@order_status": {}, + "order_information": "Order Information", + "@order_information": {}, + "order_type": "Order Type", + "@order_type": {}, + "payment_status": "Payment Status", + "@payment_status": {}, + "created": "Created", + "@created": {}, + "order_item": "Order Item", + "@order_item": {}, + "item": "Item", + "@item": {}, + "each": "Each", + "@each": {}, + "total_item": "Total Item", + "@total_item": {}, + "payment_summary": "Payment Summary", + "@payment_summary": {}, + "subtotal": "Subtotal", + "@subtotal": {}, + "paid": "Paid", + "@paid": {}, + "total": "Total", + "@total": {}, + "payment_method": "Payment Method", + "@payment_method": {}, + "dine_in": "Dine In", + "@dine_in": {}, + "dine_in_experience": "Dine In Experience", + "@dine_in_experience": {}, + "note": "Note", + "@note": {}, + "sales_chart": "Sales Chart", + "@sales_chart": {}, + "no_data_available": "No Data Avaiable", + "@no_data_available": {}, + "total_days_overview": "{days} days overview", + "@total_days_overview": { + "placeholders": { + "days": { + "type": "int", + "example": "0" + } + } + }, + "sales_data": "Sales Data", + "@sales_data": {}, + "no_sales_data": "No Sales Data", + "@no_sales_data": {}, + "no_sales_data_desc": "Sales data will appear here once transactions are recorded", + "@no_sales_data_desc": {}, + "payment_methods": "Payment Methods", + "@payment_methods": {}, + "payment_methods_desc": "Revenue breakdown by payment method ", + "@payment_methods_desc": {}, + "revenue_share": "Revenue Share", + "@revenue_share": {}, + "no_payment_methods": "No Payment Methods", + "@no_payment_methods": {}, + "no_payment_methods_desc": "Payment method data will appear here once transactions are made", + "@no_payment_methods_desc": {}, + "best_selling_products": "Best Selling Products", + "@best_selling_products": {}, + "highest_sales_ranking": "Highest sales ranking", + "@highest_sales_ranking": {}, + "best_seller": "Best Seller", + "@best_seller": {}, + "top_performer": "Top Performer", + "@top_performer": {}, + "account_information": "Account Information", + "@account_information": {}, + "member_since": "Member Since", + "@member_since": {}, + "edit_profile": "Edit Profile", + "@edit_profile": {}, + "edit_profile_desc": "Update your profile information", + "@edit_profile_desc": {}, + "change_password": "Change Password", + "@change_password": {}, + "change_password_desc": "Update your password", + "@change_password_desc": {}, + "business_settings": "Business Settings", + "@business_settings": {}, + "outlet_information": "Outlet Information", + "@outlet_information": {}, + "outlet_informatio_desc": "Manage your outlet details", + "@outlet_informatio_desc": {}, + "staff_management": "Staff Management", + "@staff_management": {}, + "staff_management_desc": "Manage your staff", + "@staff_management_desc": {}, + "manage_your_products": "Manage Your Products", + "@manage_your_products": {}, + "download_report": "Download Report", + "@download_report": {}, + "download_report_desc": "Download your sales report or inventory report", + "@download_report_desc": {}, + "app_settings": "App Settings", + "@app_settings": {}, + "language_desc": "Select your preferred language", + "@language_desc": {}, + "support": "Support", + "@support": {}, + "help_center": "Help Center", + "@help_center": {}, + "help_center_desc": "Get help from our support team", + "@help_center_desc": {}, + "about": "About", + "@about": {}, + "about_desc": "Learn more about our app", + "@about_desc": {}, + "logout": "Logout", + "@logout": {}, + "logout_desc": "Logout of your account", + "@logout_desc": {}, + "save": "Save", + "@save": {}, + "name": "Name", + "@name": {}, + "name_placeholder": "Please enter your name", + "@name_placeholder": {}, + "password_changed": "Password Changed", + "@password_changed": {}, + "current_password": "Current Password", + "@current_password": {}, + "current_password_placeholder": "Please enter your current password", + "@current_password_placeholder": {}, + "new_password": "New Password", + "@new_password": {}, + "new_password_placeholder": "Please enter your new password", + "@new_password_placeholder": {}, + "new_password_not_same": "New password cannot be same as current password", + "@new_password_not_same": {}, + "general_information": "General Information", + "@general_information": {}, + "address": "Address", + "@address": {}, + "phone_number": "Phone Number", + "@phone_number": {}, + "currency": "Currency", + "@currency": {}, + "tax_rate": "Tax Rate", + "@tax_rate": {}, + "status_text": "Status", + "@status_text": {}, + "coming_soon": "Coming Soon", + "@coming_soon": {}, + "coming_soon_desc": "Something amazing is brewing!\nStay tuned for the big reveal.", + "@coming_soon_desc": {}, + "transaction_report": "Transaction Report", + "@transaction_report": {}, + "transaction_report_desc": "Export all transaction data with detailed analytics", + "@transaction_report_desc": {}, + "invetory_report": "Inventory Report", + "@invetory_report": {}, + "invetory_report_desc": "Export inventory and stock data with trends", + "@invetory_report_desc": {}, + "about_app": "About App", + "@about_app": {}, + "app_information": "App Information", + "@app_information": {}, + "app_name": "App Name", + "@app_name": {}, + "build_number": "Build Number", + "@build_number": {}, + "package_name": "Package Name", + "@package_name": {}, + "device": "Device", + "@device": {}, + "profit_loss": "Laba Rugi", + "@profit_loss": {} +} diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb new file mode 100644 index 0000000..f07c475 --- /dev/null +++ b/lib/l10n/app_id.arb @@ -0,0 +1,435 @@ +{ + "@@locale": "id", + "indonesian": "Indonesia", + "@indonesian": {}, + "english": "Inggris", + "@english": {}, + "language": "Bahasa", + "@language": {}, + "version": "Versi", + "@version": {}, + "select_language": "Pilih Bahasa", + "@select_language": {}, + "login_header": "Selamat Datang kembali", + "@login_header": {}, + "login_desc": "Masuk ke akun Anda", + "@login_desc": {}, + "email": "Email", + "@email": {}, + "email_placeholder": "Masukkan email Anda", + "@email_placeholder": {}, + "password": "Kata Sandi", + "@password": {}, + "password_placeholder": "Masukkan kata sandi Anda", + "@password_placeholder": {}, + "forgot_password": "Lupa Kata Sandi", + "@forgot_password": {}, + "sign_in": "Masuk", + "@sign_in": {}, + "good_morning": "Selamat Pagi", + "@good_morning": {}, + "good_afternoon": "Selamat Siang", + "@good_afternoon": {}, + "good_evening": "Selamat Sore", + "@good_evening": {}, + "good_night": "Selamat Malam", + "@good_night": {}, + "home_header_desc": "Mari tingkatkan performa bisnis Anda hari ini", + "@home_header_desc": {}, + "home": "Beranda", + "@home": {}, + "transaction": "Transaksi", + "@transaction": {}, + "transactions": "Transaksi", + "@transactions": {}, + "report": "Laporan", + "@report": {}, + "reports": "Laporan", + "@reports": {}, + "profile": "Profil", + "@profile": {}, + "sales_today": "Penjualan hari ini", + "@sales_today": {}, + "order": "Pesanan", + "@order": {}, + "sales": "Penjualan", + "@sales": {}, + "finance": "Keuangan", + "@finance": {}, + "product": "Produk", + "@product": {}, + "form": "Form", + "@form": {}, + "schedule": "Jadwal", + "@schedule": {}, + "inventory": "Inventaris", + "@inventory": {}, + "customer": "Pelanggan", + "@customer": {}, + "purchase": "Pembelian", + "@purchase": {}, + "today_summary": "Ringkasan Hari Ini", + "@today_summary": {}, + "today": "Hari ini", + "@today": {}, + "new_customer": "Pelanggan baru", + "@new_customer": {}, + "refund": "Pengembalian dana", + "@refund": {}, + "void_text": "Dibatalkan", + "@void_text": {}, + "increase": "Bertambah", + "@increase": {}, + "today_top_product": "Produk teratas hari ini", + "@today_top_product": {}, + "rank": "Pangkat", + "@rank": {}, + "quantity_sold": "Kuantiti Terjual", + "@quantity_sold": {}, + "total_orders": "Jumlah Pesanan", + "@total_orders": {}, + "average_price": "Harga Rata-rata", + "@average_price": {}, + "perfomance": "Performa", + "@perfomance": {}, + "total_sales": "Jumlah Penjualan", + "@total_sales": {}, + "total_items": "Jumlah Barang", + "@total_items": {}, + "summary": "Ringkasan", + "@summary": {}, + "net_sales": "Penjualan Bersih", + "@net_sales": {}, + "daily_breakdown": "Perincian Harian", + "@daily_breakdown": {}, + "orders": "Pesanan", + "@orders": {}, + "items": "Barang", + "@items": {}, + "tax": "Pajak", + "@tax": {}, + "discount": "Diskon", + "@discount": {}, + "total_purchase": "Jumlah Pembelian", + "@total_purchase": {}, + "pending_order": "Pesanan Menunggu", + "@pending_order": {}, + "history_purchase": "Riwayat Pembelian", + "@history_purchase": {}, + "all": "Semua", + "@all": {}, + "select_date_range": "Pilih Rentang Tanggal", + "@select_date_range": {}, + "no_date_selected": "Belum ada tanggal dipilih", + "@no_date_selected": {}, + "selected_date": "Tanggal Terpilih", + "@selected_date": {}, + "select": "Pilih", + "@select": {}, + "cancel": "Batal", + "@cancel": {}, + "total_revenue": "Jumlah Pendapatan", + "@total_revenue": {}, + "total_expenditures": "Jumlah Pengeluaran", + "@total_expenditures": {}, + "net_profit": "Keuntungan Bersih", + "@net_profit": {}, + "margin_profit": "Keuntungan Margin", + "@margin_profit": {}, + "cash_flow_analysis": "Analisis Arus Kas", + "@cash_flow_analysis": {}, + "cash_in": "Uang Masuk", + "@cash_in": {}, + "cash_out": "Uang Keluar", + "@cash_out": {}, + "net_flow": "Arus Bersih", + "@net_flow": {}, + "cash_flow_chart": "Grafik Cash Flow ${days} Hari Terakhir", + "@cash_flow_chart": { + "placeholders": { + "days": { + "type": "int", + "example": "7" + } + } + }, + "profit_loss_detail": "Detail Untung & Rugi", + "@profit_loss_detail": {}, + "gross_sales": "Penjualan Kotor", + "@gross_sales": {}, + "return_text": "Retur", + "@return_text": {}, + "cogs": "HPP", + "@cogs": {}, + "cost_of_goods_sold": "Harga Pokok Penjualan", + "@cost_of_goods_sold": {}, + "gross_profit": "Keuntungan Kotor", + "@gross_profit": {}, + "operating_costs": "Biaya Operasional", + "@operating_costs": {}, + "sales_category": "Kategori Penjualan", + "@sales_category": {}, + "unit": "Unit", + "@unit": {}, + "category_no_data": "Belum ada data kategori", + "@category_no_data": {}, + "category_no_data_desc": "Data kategori penjualan akan muncul di sini", + "@category_no_data_desc": {}, + "product_analytic": "Analisis Produk", + "@product_analytic": {}, + "view_all": "Lihat Semua", + "@view_all": {}, + "sold": "Terjual", + "@sold": {}, + "revenue": "Pendapatan", + "@revenue": {}, + "cost": "Biaya", + "@cost": {}, + "profit_per_unit": "Keuntungan per unit", + "@profit_per_unit": {}, + "total_sold": "Jumlah Terjual", + "@total_sold": {}, + "ingredients": "Bahan Baku", + "@ingredients": {}, + "low_stock": "Stok Rendah", + "@low_stock": {}, + "zero_stock": "Stok Kosong", + "@zero_stock": {}, + "stock": "Stok", + "@stock": {}, + "price": "Harga", + "@price": {}, + "out_of_stock": "Stok habis", + "@out_of_stock": {}, + "out_of_stock_desc": "Produk tidak tersedia untuk dijual", + "@out_of_stock_desc": {}, + "in_text": "Masuk", + "@in_text": {}, + "out_text": "Keluar", + "@out_text": {}, + "available": "Tersedia", + "@available": {}, + "total_products": "Jumlah Produk", + "@total_products": {}, + "total_ingredients": "Jumlah Bahan Baku", + "@total_ingredients": {}, + "products": "Produk", + "@products": {}, + "value_text": "Nilai", + "@value_text": {}, + "low_stock_desc": "Segera reorder minimal {stock} pcs", + "@low_stock_desc": { + "placeholders": { + "stock": { + "type": "String", + "example": "0" + } + } + }, + "joined": "Bergabung", + "@joined": {}, + "ago": "lalu", + "@ago": {}, + "active": "Aktif", + "@active": {}, + "inactive": "Tidak Aktif", + "@inactive": {}, + "total_amount": "Jumlah Total", + "@total_amount": {}, + "table": "Meja", + "@table": {}, + "remaining": "Sisa", + "@remaining": {}, + "payment": "Pembayaran", + "@payment": {}, + "completed": "Selesai", + "@completed": {}, + "pending": "Menunggu", + "@pending": {}, + "no_order_with_status": "Tidak ada pesanan {status} yang ditemukan", + "@no_order_with_status": { + "placeholders": { + "status": { + "type": "String", + "example": "pending" + } + } + }, + "order_details": "Detail Pesanan", + "@order_details": {}, + "order_number": "Nomor Pesanan", + "@order_number": {}, + "order_status": "Status Pesanan", + "@order_status": {}, + "order_information": "Informasi Pesanan", + "@order_information": {}, + "order_type": "Tipe Pesanan", + "@order_type": {}, + "payment_status": "Status Pembayaran", + "@payment_status": {}, + "created": "Dibuat", + "@created": {}, + "order_item": "Item Pesanan", + "@order_item": {}, + "item": "Item", + "@item": {}, + "each": "Setiap", + "@each": {}, + "total_item": "Jumlah Item", + "@total_item": {}, + "payment_summary": "Ringkasan Pembayaran", + "@payment_summary": {}, + "subtotal": "Subtotal", + "@subtotal": {}, + "paid": "Dibayar", + "@paid": {}, + "total": "Jumlah", + "@total": {}, + "payment_method": "Metode Pembayaran", + "@payment_method": {}, + "dine_in": "Makan di Tempat", + "@dine_in": {}, + "dine_in_experience": "Pengalaman Bersantap Di Tempat", + "@dine_in_experience": {}, + "note": "Catatan", + "@note": {}, + "sales_chart": "Bagan Penjualan", + "@sales_chart": {}, + "no_data_available": "Tidak Ada Data Tersedia", + "@no_data_available": {}, + "total_days_overview": "ikhtisar {days} hari", + "@total_days_overview": { + "placeholders": { + "days": { + "type": "int", + "example": "0" + } + } + }, + "sales_data": "Data Penjualan", + "@sales_data": {}, + "no_sales_data": "Tidak ada data penjualan", + "@no_sales_data": {}, + "no_sales_data_desc": "Data penjualan akan muncul di sini setelah transaksi dicatat", + "@no_sales_data_desc": {}, + "payment_methods": "Metode Pembayaran", + "@payment_methods": {}, + "payment_methods_desc": "Rincian pendapatan berdasarkan metode pembayaran ", + "@payment_methods_desc": {}, + "revenue_share": "Bagi Hasil", + "@revenue_share": {}, + "no_payment_methods": "Tidak Ada Metode Pembayaran", + "@no_payment_methods": {}, + "no_payment_methods_desc": "Data metode pembayaran akan muncul di sini setelah transaksi dilakukan", + "@no_payment_methods_desc": {}, + "best_selling_products": "Produk Terlaris", + "@best_selling_products": {}, + "highest_sales_ranking": "Ranking penjualan tertinggi", + "@highest_sales_ranking": {}, + "best_seller": "Penjual Terbaik", + "@best_seller": {}, + "top_performer": "Berkinerja Terbaik", + "@top_performer": {}, + "account_information": "Informasi Akun", + "@account_information": {}, + "member_since": "Member Sejak", + "@member_since": {}, + "edit_profile": "Ubah Profil", + "@edit_profile": {}, + "edit_profile_desc": "Update informasi profil Anda", + "@edit_profile_desc": {}, + "change_password": "Ubah Kata Sandi", + "@change_password": {}, + "change_password_desc": "Update kata sandi Anda", + "@change_password_desc": {}, + "business_settings": "Pengaturan Bisnis", + "@business_settings": {}, + "outlet_information": "Informasi Outlet", + "@outlet_information": {}, + "outlet_informatio_desc": "Kelola informasi outlet Anda", + "@outlet_informatio_desc": {}, + "staff_management": "Manajemen Staff", + "@staff_management": {}, + "staff_management_desc": "Kelola staff Anda", + "@staff_management_desc": {}, + "manage_your_products": "Kelola Produk Anda", + "@manage_your_products": {}, + "download_report": "Unduh Laporan", + "@download_report": {}, + "download_report_desc": "Unduh laporan penjualan atau stok", + "@download_report_desc": {}, + "app_settings": "Pengaturan Aplikasi", + "@app_settings": {}, + "language_desc": "Pilih bahasa aplikasi Anda", + "@language_desc": {}, + "support": "Dukungan", + "@support": {}, + "help_center": "Pusat Bantuan", + "@help_center": {}, + "help_center_desc": "Hubungi tim dukungan kami", + "@help_center_desc": {}, + "about": "Tentang", + "@about": {}, + "about_desc": "Tentang Aplikasi", + "@about_desc": {}, + "logout": "Keluar", + "@logout": {}, + "logout_desc": "Keluar dari akun Anda", + "@logout_desc": {}, + "save": "Simpan", + "@save": {}, + "name": "Nama", + "@name": {}, + "name_placeholder": "Masukkan nama Anda", + "@name_placeholder": {}, + "password_changed": "Kata Sandi Berubah", + "@password_changed": {}, + "current_password": "Kata Sandi Saat Ini", + "@current_password": {}, + "current_password_placeholder": "Masukkan kata sandi saat ini", + "@current_password_placeholder": {}, + "new_password": "Kata Sandi Baru", + "@new_password": {}, + "new_password_placeholder": "Masukkan kata sandi baru", + "@new_password_placeholder": {}, + "new_password_not_same": "Kata Sandi Baru Tidak Sama Dengan Kata Sandi Saat Ini", + "@new_password_not_same": {}, + "general_information": "Informasi Umum", + "@general_information": {}, + "address": "Alamat", + "@address": {}, + "phone_number": "Nomor Telepon", + "@phone_number": {}, + "currency": "Mata Uang", + "@currency": {}, + "tax_rate": "Tarif Pajak", + "@tax_rate": {}, + "status_text": "Status", + "@status_text": {}, + "coming_soon": "Segera Hadir", + "@coming_soon": {}, + "coming_soon_desc": "Sesuatu yang menakjubkan sedang terjadi!\nNantikan pengungkapan besarnya.", + "@coming_soon_desc": {}, + "transaction_report": "Laporan Transaksi", + "@transaction_report": {}, + "transaction_report_desc": "Ekspor semua data transaksi dengan analitik terperinci", + "@transaction_report_desc": {}, + "invetory_report": "Laporan Inventaris", + "@invetory_report": {}, + "invetory_report_desc": "Ekspor inventaris dan data stok dengan tren", + "@invetory_report_desc": {}, + "about_app": "Tentang Aplikasi", + "@about_app": {}, + "app_information": "Informasi Aplikasi", + "@app_information": {}, + "app_name": "Nama Aplikasi", + "@app_name": {}, + "build_number": "Nomor Build", + "@build_number": {}, + "package_name": "Nama Paket", + "@package_name": {}, + "device": "Perangkat", + "@device": {}, + "profit_loss": "Laba Rugi", + "@profit_loss": {} +} diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart new file mode 100644 index 0000000..91ab6c4 --- /dev/null +++ b/lib/l10n/app_localizations.dart @@ -0,0 +1,1341 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart' as intl; + +import 'app_localizations_en.dart'; +import 'app_localizations_id.dart'; + +// ignore_for_file: type=lint + +/// Callers can lookup localized strings with an instance of AppLocalizations +/// returned by `AppLocalizations.of(context)`. +/// +/// Applications need to include `AppLocalizations.delegate()` in their app's +/// `localizationDelegates` list, and the locales they support in the app's +/// `supportedLocales` list. For example: +/// +/// ```dart +/// import 'l10n/app_localizations.dart'; +/// +/// return MaterialApp( +/// localizationsDelegates: AppLocalizations.localizationsDelegates, +/// supportedLocales: AppLocalizations.supportedLocales, +/// home: MyApplicationHome(), +/// ); +/// ``` +/// +/// ## Update pubspec.yaml +/// +/// Please make sure to update your pubspec.yaml to include the following +/// packages: +/// +/// ```yaml +/// dependencies: +/// # Internationalization support. +/// flutter_localizations: +/// sdk: flutter +/// intl: any # Use the pinned version from flutter_localizations +/// +/// # Rest of dependencies +/// ``` +/// +/// ## iOS Applications +/// +/// iOS applications define key application metadata, including supported +/// locales, in an Info.plist file that is built into the application bundle. +/// To configure the locales supported by your app, you’ll need to edit this +/// file. +/// +/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. +/// Then, in the Project Navigator, open the Info.plist file under the Runner +/// project’s Runner folder. +/// +/// Next, select the Information Property List item, select Add Item from the +/// Editor menu, then select Localizations from the pop-up menu. +/// +/// Select and expand the newly-created Localizations item then, for each +/// locale your application supports, add a new item and select the locale +/// you wish to add from the pop-up menu in the Value field. This list should +/// be consistent with the languages listed in the AppLocalizations.supportedLocales +/// property. +abstract class AppLocalizations { + AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + + final String localeName; + + static AppLocalizations? of(BuildContext context) { + return Localizations.of(context, AppLocalizations); + } + + static const LocalizationsDelegate delegate = _AppLocalizationsDelegate(); + + /// A list of this localizations delegate along with the default localizations + /// delegates. + /// + /// Returns a list of localizations delegates containing this delegate along with + /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, + /// and GlobalWidgetsLocalizations.delegate. + /// + /// Additional delegates can be added by appending to this list in + /// MaterialApp. This list does not have to be used at all if a custom list + /// of delegates is preferred or required. + static const List> localizationsDelegates = >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; + + /// A list of this localizations delegate's supported locales. + static const List supportedLocales = [ + Locale('en'), + Locale('id') + ]; + + /// No description provided for @indonesian. + /// + /// In en, this message translates to: + /// **'Indonesian'** + String get indonesian; + + /// No description provided for @english. + /// + /// In en, this message translates to: + /// **'English'** + String get english; + + /// No description provided for @language. + /// + /// In en, this message translates to: + /// **'Language'** + String get language; + + /// No description provided for @version. + /// + /// In en, this message translates to: + /// **'Version'** + String get version; + + /// No description provided for @select_language. + /// + /// In en, this message translates to: + /// **'Select Language'** + String get select_language; + + /// No description provided for @login_header. + /// + /// In en, this message translates to: + /// **'Welcome back'** + String get login_header; + + /// No description provided for @login_desc. + /// + /// In en, this message translates to: + /// **'Sign in to your account'** + String get login_desc; + + /// No description provided for @email. + /// + /// In en, this message translates to: + /// **'Email'** + String get email; + + /// No description provided for @email_placeholder. + /// + /// In en, this message translates to: + /// **'Enter your email'** + String get email_placeholder; + + /// No description provided for @password. + /// + /// In en, this message translates to: + /// **'Password'** + String get password; + + /// No description provided for @password_placeholder. + /// + /// In en, this message translates to: + /// **'Enter your password'** + String get password_placeholder; + + /// No description provided for @forgot_password. + /// + /// In en, this message translates to: + /// **'Forgot Password'** + String get forgot_password; + + /// No description provided for @sign_in. + /// + /// In en, this message translates to: + /// **'Sign In'** + String get sign_in; + + /// No description provided for @good_morning. + /// + /// In en, this message translates to: + /// **'Good Morning'** + String get good_morning; + + /// No description provided for @good_afternoon. + /// + /// In en, this message translates to: + /// **'Good Afternoon'** + String get good_afternoon; + + /// No description provided for @good_evening. + /// + /// In en, this message translates to: + /// **'Good Evening'** + String get good_evening; + + /// No description provided for @good_night. + /// + /// In en, this message translates to: + /// **'Good Night'** + String get good_night; + + /// No description provided for @home_header_desc. + /// + /// In en, this message translates to: + /// **'Let\'s improve your business performance today'** + String get home_header_desc; + + /// No description provided for @home. + /// + /// In en, this message translates to: + /// **'Home'** + String get home; + + /// No description provided for @transaction. + /// + /// In en, this message translates to: + /// **'Transaction'** + String get transaction; + + /// No description provided for @transactions. + /// + /// In en, this message translates to: + /// **'Transactions'** + String get transactions; + + /// No description provided for @report. + /// + /// In en, this message translates to: + /// **'Report'** + String get report; + + /// No description provided for @reports. + /// + /// In en, this message translates to: + /// **'Reports'** + String get reports; + + /// No description provided for @profile. + /// + /// In en, this message translates to: + /// **'Profile'** + String get profile; + + /// No description provided for @sales_today. + /// + /// In en, this message translates to: + /// **'Sales today'** + String get sales_today; + + /// No description provided for @order. + /// + /// In en, this message translates to: + /// **'Order'** + String get order; + + /// No description provided for @sales. + /// + /// In en, this message translates to: + /// **'Sales'** + String get sales; + + /// No description provided for @finance. + /// + /// In en, this message translates to: + /// **'Finance'** + String get finance; + + /// No description provided for @product. + /// + /// In en, this message translates to: + /// **'Product'** + String get product; + + /// No description provided for @form. + /// + /// In en, this message translates to: + /// **'Form'** + String get form; + + /// No description provided for @schedule. + /// + /// In en, this message translates to: + /// **'Schedule'** + String get schedule; + + /// No description provided for @inventory. + /// + /// In en, this message translates to: + /// **'Inventory'** + String get inventory; + + /// No description provided for @customer. + /// + /// In en, this message translates to: + /// **'Customer'** + String get customer; + + /// No description provided for @purchase. + /// + /// In en, this message translates to: + /// **'Purchase'** + String get purchase; + + /// No description provided for @today_summary. + /// + /// In en, this message translates to: + /// **'Today\'s Summary'** + String get today_summary; + + /// No description provided for @today. + /// + /// In en, this message translates to: + /// **'Today'** + String get today; + + /// No description provided for @new_customer. + /// + /// In en, this message translates to: + /// **'New Customer'** + String get new_customer; + + /// No description provided for @refund. + /// + /// In en, this message translates to: + /// **'Refund'** + String get refund; + + /// No description provided for @void_text. + /// + /// In en, this message translates to: + /// **'Void'** + String get void_text; + + /// No description provided for @increase. + /// + /// In en, this message translates to: + /// **'Increase'** + String get increase; + + /// No description provided for @today_top_product. + /// + /// In en, this message translates to: + /// **'Today\'s Top Product'** + String get today_top_product; + + /// No description provided for @rank. + /// + /// In en, this message translates to: + /// **'Rank'** + String get rank; + + /// No description provided for @quantity_sold. + /// + /// In en, this message translates to: + /// **'Quantity Sold'** + String get quantity_sold; + + /// No description provided for @total_orders. + /// + /// In en, this message translates to: + /// **'Total Orders'** + String get total_orders; + + /// No description provided for @average_price. + /// + /// In en, this message translates to: + /// **'Average Price'** + String get average_price; + + /// No description provided for @perfomance. + /// + /// In en, this message translates to: + /// **'Performance'** + String get perfomance; + + /// No description provided for @total_sales. + /// + /// In en, this message translates to: + /// **'Total Sales'** + String get total_sales; + + /// No description provided for @total_items. + /// + /// In en, this message translates to: + /// **'Total Items'** + String get total_items; + + /// No description provided for @summary. + /// + /// In en, this message translates to: + /// **'Summary'** + String get summary; + + /// No description provided for @net_sales. + /// + /// In en, this message translates to: + /// **'Net Sales'** + String get net_sales; + + /// No description provided for @daily_breakdown. + /// + /// In en, this message translates to: + /// **'Daily Breakdown'** + String get daily_breakdown; + + /// No description provided for @orders. + /// + /// In en, this message translates to: + /// **'Orders'** + String get orders; + + /// No description provided for @items. + /// + /// In en, this message translates to: + /// **'Items'** + String get items; + + /// No description provided for @tax. + /// + /// In en, this message translates to: + /// **'Tax'** + String get tax; + + /// No description provided for @discount. + /// + /// In en, this message translates to: + /// **'Discount'** + String get discount; + + /// No description provided for @total_purchase. + /// + /// In en, this message translates to: + /// **'Total Purchase'** + String get total_purchase; + + /// No description provided for @pending_order. + /// + /// In en, this message translates to: + /// **'Pending Order'** + String get pending_order; + + /// No description provided for @history_purchase. + /// + /// In en, this message translates to: + /// **'History Purchase'** + String get history_purchase; + + /// No description provided for @all. + /// + /// In en, this message translates to: + /// **'All'** + String get all; + + /// No description provided for @select_date_range. + /// + /// In en, this message translates to: + /// **'Select Date Range'** + String get select_date_range; + + /// No description provided for @no_date_selected. + /// + /// In en, this message translates to: + /// **'No date has been selected yet'** + String get no_date_selected; + + /// No description provided for @selected_date. + /// + /// In en, this message translates to: + /// **'Selected Date'** + String get selected_date; + + /// No description provided for @select. + /// + /// In en, this message translates to: + /// **'Select'** + String get select; + + /// No description provided for @cancel. + /// + /// In en, this message translates to: + /// **'Cancel'** + String get cancel; + + /// No description provided for @total_revenue. + /// + /// In en, this message translates to: + /// **'Total Revenue'** + String get total_revenue; + + /// No description provided for @total_expenditures. + /// + /// In en, this message translates to: + /// **'Total Expenditures'** + String get total_expenditures; + + /// No description provided for @net_profit. + /// + /// In en, this message translates to: + /// **'Net Profit'** + String get net_profit; + + /// No description provided for @margin_profit. + /// + /// In en, this message translates to: + /// **'Margin Profit'** + String get margin_profit; + + /// No description provided for @cash_flow_analysis. + /// + /// In en, this message translates to: + /// **'Cash Flow Analysis'** + String get cash_flow_analysis; + + /// No description provided for @cash_in. + /// + /// In en, this message translates to: + /// **'Cash In'** + String get cash_in; + + /// No description provided for @cash_out. + /// + /// In en, this message translates to: + /// **'Cash Out'** + String get cash_out; + + /// No description provided for @net_flow. + /// + /// In en, this message translates to: + /// **'Net Flow'** + String get net_flow; + + /// No description provided for @cash_flow_chart. + /// + /// In en, this message translates to: + /// **'Cash Flow Chart for {days} Last Days'** + String cash_flow_chart(int days); + + /// No description provided for @profit_loss_detail. + /// + /// In en, this message translates to: + /// **'Profit & Loss Details'** + String get profit_loss_detail; + + /// No description provided for @gross_sales. + /// + /// In en, this message translates to: + /// **'Gross Sales'** + String get gross_sales; + + /// No description provided for @return_text. + /// + /// In en, this message translates to: + /// **'Return'** + String get return_text; + + /// No description provided for @cogs. + /// + /// In en, this message translates to: + /// **'COGS'** + String get cogs; + + /// No description provided for @cost_of_goods_sold. + /// + /// In en, this message translates to: + /// **'Cost of goods sold'** + String get cost_of_goods_sold; + + /// No description provided for @gross_profit. + /// + /// In en, this message translates to: + /// **'Gross Profit'** + String get gross_profit; + + /// No description provided for @operating_costs. + /// + /// In en, this message translates to: + /// **'Operating Costs'** + String get operating_costs; + + /// No description provided for @sales_category. + /// + /// In en, this message translates to: + /// **'Sales Category'** + String get sales_category; + + /// No description provided for @unit. + /// + /// In en, this message translates to: + /// **'Unit'** + String get unit; + + /// No description provided for @category_no_data. + /// + /// In en, this message translates to: + /// **'There are no data categories yet'** + String get category_no_data; + + /// No description provided for @category_no_data_desc. + /// + /// In en, this message translates to: + /// **'Sales category data will appear here'** + String get category_no_data_desc; + + /// No description provided for @product_analytic. + /// + /// In en, this message translates to: + /// **'Product Analytic'** + String get product_analytic; + + /// No description provided for @view_all. + /// + /// In en, this message translates to: + /// **'View All'** + String get view_all; + + /// No description provided for @sold. + /// + /// In en, this message translates to: + /// **'Sold'** + String get sold; + + /// No description provided for @revenue. + /// + /// In en, this message translates to: + /// **'Revenue'** + String get revenue; + + /// No description provided for @cost. + /// + /// In en, this message translates to: + /// **'Cost'** + String get cost; + + /// No description provided for @profit_per_unit. + /// + /// In en, this message translates to: + /// **'Profit per unit'** + String get profit_per_unit; + + /// No description provided for @total_sold. + /// + /// In en, this message translates to: + /// **'Total Sold'** + String get total_sold; + + /// No description provided for @ingredients. + /// + /// In en, this message translates to: + /// **'Ingredients'** + String get ingredients; + + /// No description provided for @low_stock. + /// + /// In en, this message translates to: + /// **'Low Stock'** + String get low_stock; + + /// No description provided for @zero_stock. + /// + /// In en, this message translates to: + /// **'Zero Stock'** + String get zero_stock; + + /// No description provided for @stock. + /// + /// In en, this message translates to: + /// **'Stock'** + String get stock; + + /// No description provided for @price. + /// + /// In en, this message translates to: + /// **'Price'** + String get price; + + /// No description provided for @out_of_stock. + /// + /// In en, this message translates to: + /// **'Out of stock'** + String get out_of_stock; + + /// No description provided for @out_of_stock_desc. + /// + /// In en, this message translates to: + /// **'Product not available for sale'** + String get out_of_stock_desc; + + /// No description provided for @in_text. + /// + /// In en, this message translates to: + /// **'In'** + String get in_text; + + /// No description provided for @out_text. + /// + /// In en, this message translates to: + /// **'Out'** + String get out_text; + + /// No description provided for @available. + /// + /// In en, this message translates to: + /// **'Available'** + String get available; + + /// No description provided for @total_products. + /// + /// In en, this message translates to: + /// **'Total Products'** + String get total_products; + + /// No description provided for @total_ingredients. + /// + /// In en, this message translates to: + /// **'Total Ingredients'** + String get total_ingredients; + + /// No description provided for @products. + /// + /// In en, this message translates to: + /// **'Products'** + String get products; + + /// No description provided for @value_text. + /// + /// In en, this message translates to: + /// **'Value'** + String get value_text; + + /// No description provided for @low_stock_desc. + /// + /// In en, this message translates to: + /// **'Immediately reorder at least {stock} pcs'** + String low_stock_desc(String stock); + + /// No description provided for @joined. + /// + /// In en, this message translates to: + /// **'Joined'** + String get joined; + + /// No description provided for @ago. + /// + /// In en, this message translates to: + /// **'ago'** + String get ago; + + /// No description provided for @active. + /// + /// In en, this message translates to: + /// **'Active'** + String get active; + + /// No description provided for @inactive. + /// + /// In en, this message translates to: + /// **'Inactive'** + String get inactive; + + /// No description provided for @total_amount. + /// + /// In en, this message translates to: + /// **'Total Amount'** + String get total_amount; + + /// No description provided for @table. + /// + /// In en, this message translates to: + /// **'Table'** + String get table; + + /// No description provided for @remaining. + /// + /// In en, this message translates to: + /// **'Remaining'** + String get remaining; + + /// No description provided for @payment. + /// + /// In en, this message translates to: + /// **'Payment'** + String get payment; + + /// No description provided for @completed. + /// + /// In en, this message translates to: + /// **'Completed'** + String get completed; + + /// No description provided for @pending. + /// + /// In en, this message translates to: + /// **'Pending'** + String get pending; + + /// No description provided for @no_order_with_status. + /// + /// In en, this message translates to: + /// **'No {status} orders found'** + String no_order_with_status(String status); + + /// No description provided for @order_details. + /// + /// In en, this message translates to: + /// **'Order Details'** + String get order_details; + + /// No description provided for @order_number. + /// + /// In en, this message translates to: + /// **'Order Number'** + String get order_number; + + /// No description provided for @order_status. + /// + /// In en, this message translates to: + /// **'Order Status'** + String get order_status; + + /// No description provided for @order_information. + /// + /// In en, this message translates to: + /// **'Order Information'** + String get order_information; + + /// No description provided for @order_type. + /// + /// In en, this message translates to: + /// **'Order Type'** + String get order_type; + + /// No description provided for @payment_status. + /// + /// In en, this message translates to: + /// **'Payment Status'** + String get payment_status; + + /// No description provided for @created. + /// + /// In en, this message translates to: + /// **'Created'** + String get created; + + /// No description provided for @order_item. + /// + /// In en, this message translates to: + /// **'Order Item'** + String get order_item; + + /// No description provided for @item. + /// + /// In en, this message translates to: + /// **'Item'** + String get item; + + /// No description provided for @each. + /// + /// In en, this message translates to: + /// **'Each'** + String get each; + + /// No description provided for @total_item. + /// + /// In en, this message translates to: + /// **'Total Item'** + String get total_item; + + /// No description provided for @payment_summary. + /// + /// In en, this message translates to: + /// **'Payment Summary'** + String get payment_summary; + + /// No description provided for @subtotal. + /// + /// In en, this message translates to: + /// **'Subtotal'** + String get subtotal; + + /// No description provided for @paid. + /// + /// In en, this message translates to: + /// **'Paid'** + String get paid; + + /// No description provided for @total. + /// + /// In en, this message translates to: + /// **'Total'** + String get total; + + /// No description provided for @payment_method. + /// + /// In en, this message translates to: + /// **'Payment Method'** + String get payment_method; + + /// No description provided for @dine_in. + /// + /// In en, this message translates to: + /// **'Dine In'** + String get dine_in; + + /// No description provided for @dine_in_experience. + /// + /// In en, this message translates to: + /// **'Dine In Experience'** + String get dine_in_experience; + + /// No description provided for @note. + /// + /// In en, this message translates to: + /// **'Note'** + String get note; + + /// No description provided for @sales_chart. + /// + /// In en, this message translates to: + /// **'Sales Chart'** + String get sales_chart; + + /// No description provided for @no_data_available. + /// + /// In en, this message translates to: + /// **'No Data Avaiable'** + String get no_data_available; + + /// No description provided for @total_days_overview. + /// + /// In en, this message translates to: + /// **'{days} days overview'** + String total_days_overview(int days); + + /// No description provided for @sales_data. + /// + /// In en, this message translates to: + /// **'Sales Data'** + String get sales_data; + + /// No description provided for @no_sales_data. + /// + /// In en, this message translates to: + /// **'No Sales Data'** + String get no_sales_data; + + /// No description provided for @no_sales_data_desc. + /// + /// In en, this message translates to: + /// **'Sales data will appear here once transactions are recorded'** + String get no_sales_data_desc; + + /// No description provided for @payment_methods. + /// + /// In en, this message translates to: + /// **'Payment Methods'** + String get payment_methods; + + /// No description provided for @payment_methods_desc. + /// + /// In en, this message translates to: + /// **'Revenue breakdown by payment method '** + String get payment_methods_desc; + + /// No description provided for @revenue_share. + /// + /// In en, this message translates to: + /// **'Revenue Share'** + String get revenue_share; + + /// No description provided for @no_payment_methods. + /// + /// In en, this message translates to: + /// **'No Payment Methods'** + String get no_payment_methods; + + /// No description provided for @no_payment_methods_desc. + /// + /// In en, this message translates to: + /// **'Payment method data will appear here once transactions are made'** + String get no_payment_methods_desc; + + /// No description provided for @best_selling_products. + /// + /// In en, this message translates to: + /// **'Best Selling Products'** + String get best_selling_products; + + /// No description provided for @highest_sales_ranking. + /// + /// In en, this message translates to: + /// **'Highest sales ranking'** + String get highest_sales_ranking; + + /// No description provided for @best_seller. + /// + /// In en, this message translates to: + /// **'Best Seller'** + String get best_seller; + + /// No description provided for @top_performer. + /// + /// In en, this message translates to: + /// **'Top Performer'** + String get top_performer; + + /// No description provided for @account_information. + /// + /// In en, this message translates to: + /// **'Account Information'** + String get account_information; + + /// No description provided for @member_since. + /// + /// In en, this message translates to: + /// **'Member Since'** + String get member_since; + + /// No description provided for @edit_profile. + /// + /// In en, this message translates to: + /// **'Edit Profile'** + String get edit_profile; + + /// No description provided for @edit_profile_desc. + /// + /// In en, this message translates to: + /// **'Update your profile information'** + String get edit_profile_desc; + + /// No description provided for @change_password. + /// + /// In en, this message translates to: + /// **'Change Password'** + String get change_password; + + /// No description provided for @change_password_desc. + /// + /// In en, this message translates to: + /// **'Update your password'** + String get change_password_desc; + + /// No description provided for @business_settings. + /// + /// In en, this message translates to: + /// **'Business Settings'** + String get business_settings; + + /// No description provided for @outlet_information. + /// + /// In en, this message translates to: + /// **'Outlet Information'** + String get outlet_information; + + /// No description provided for @outlet_informatio_desc. + /// + /// In en, this message translates to: + /// **'Manage your outlet details'** + String get outlet_informatio_desc; + + /// No description provided for @staff_management. + /// + /// In en, this message translates to: + /// **'Staff Management'** + String get staff_management; + + /// No description provided for @staff_management_desc. + /// + /// In en, this message translates to: + /// **'Manage your staff'** + String get staff_management_desc; + + /// No description provided for @manage_your_products. + /// + /// In en, this message translates to: + /// **'Manage Your Products'** + String get manage_your_products; + + /// No description provided for @download_report. + /// + /// In en, this message translates to: + /// **'Download Report'** + String get download_report; + + /// No description provided for @download_report_desc. + /// + /// In en, this message translates to: + /// **'Download your sales report or inventory report'** + String get download_report_desc; + + /// No description provided for @app_settings. + /// + /// In en, this message translates to: + /// **'App Settings'** + String get app_settings; + + /// No description provided for @language_desc. + /// + /// In en, this message translates to: + /// **'Select your preferred language'** + String get language_desc; + + /// No description provided for @support. + /// + /// In en, this message translates to: + /// **'Support'** + String get support; + + /// No description provided for @help_center. + /// + /// In en, this message translates to: + /// **'Help Center'** + String get help_center; + + /// No description provided for @help_center_desc. + /// + /// In en, this message translates to: + /// **'Get help from our support team'** + String get help_center_desc; + + /// No description provided for @about. + /// + /// In en, this message translates to: + /// **'About'** + String get about; + + /// No description provided for @about_desc. + /// + /// In en, this message translates to: + /// **'Learn more about our app'** + String get about_desc; + + /// No description provided for @logout. + /// + /// In en, this message translates to: + /// **'Logout'** + String get logout; + + /// No description provided for @logout_desc. + /// + /// In en, this message translates to: + /// **'Logout of your account'** + String get logout_desc; + + /// No description provided for @save. + /// + /// In en, this message translates to: + /// **'Save'** + String get save; + + /// No description provided for @name. + /// + /// In en, this message translates to: + /// **'Name'** + String get name; + + /// No description provided for @name_placeholder. + /// + /// In en, this message translates to: + /// **'Please enter your name'** + String get name_placeholder; + + /// No description provided for @password_changed. + /// + /// In en, this message translates to: + /// **'Password Changed'** + String get password_changed; + + /// No description provided for @current_password. + /// + /// In en, this message translates to: + /// **'Current Password'** + String get current_password; + + /// No description provided for @current_password_placeholder. + /// + /// In en, this message translates to: + /// **'Please enter your current password'** + String get current_password_placeholder; + + /// No description provided for @new_password. + /// + /// In en, this message translates to: + /// **'New Password'** + String get new_password; + + /// No description provided for @new_password_placeholder. + /// + /// In en, this message translates to: + /// **'Please enter your new password'** + String get new_password_placeholder; + + /// No description provided for @new_password_not_same. + /// + /// In en, this message translates to: + /// **'New password cannot be same as current password'** + String get new_password_not_same; + + /// No description provided for @general_information. + /// + /// In en, this message translates to: + /// **'General Information'** + String get general_information; + + /// No description provided for @address. + /// + /// In en, this message translates to: + /// **'Address'** + String get address; + + /// No description provided for @phone_number. + /// + /// In en, this message translates to: + /// **'Phone Number'** + String get phone_number; + + /// No description provided for @currency. + /// + /// In en, this message translates to: + /// **'Currency'** + String get currency; + + /// No description provided for @tax_rate. + /// + /// In en, this message translates to: + /// **'Tax Rate'** + String get tax_rate; + + /// No description provided for @status_text. + /// + /// In en, this message translates to: + /// **'Status'** + String get status_text; + + /// No description provided for @coming_soon. + /// + /// In en, this message translates to: + /// **'Coming Soon'** + String get coming_soon; + + /// No description provided for @coming_soon_desc. + /// + /// In en, this message translates to: + /// **'Something amazing is brewing!\nStay tuned for the big reveal.'** + String get coming_soon_desc; + + /// No description provided for @transaction_report. + /// + /// In en, this message translates to: + /// **'Transaction Report'** + String get transaction_report; + + /// No description provided for @transaction_report_desc. + /// + /// In en, this message translates to: + /// **'Export all transaction data with detailed analytics'** + String get transaction_report_desc; + + /// No description provided for @invetory_report. + /// + /// In en, this message translates to: + /// **'Inventory Report'** + String get invetory_report; + + /// No description provided for @invetory_report_desc. + /// + /// In en, this message translates to: + /// **'Export inventory and stock data with trends'** + String get invetory_report_desc; + + /// No description provided for @about_app. + /// + /// In en, this message translates to: + /// **'About App'** + String get about_app; + + /// No description provided for @app_information. + /// + /// In en, this message translates to: + /// **'App Information'** + String get app_information; + + /// No description provided for @app_name. + /// + /// In en, this message translates to: + /// **'App Name'** + String get app_name; + + /// No description provided for @build_number. + /// + /// In en, this message translates to: + /// **'Build Number'** + String get build_number; + + /// No description provided for @package_name. + /// + /// In en, this message translates to: + /// **'Package Name'** + String get package_name; + + /// No description provided for @device. + /// + /// In en, this message translates to: + /// **'Device'** + String get device; + + /// No description provided for @profit_loss. + /// + /// In en, this message translates to: + /// **'Laba Rugi'** + String get profit_loss; +} + +class _AppLocalizationsDelegate extends LocalizationsDelegate { + const _AppLocalizationsDelegate(); + + @override + Future load(Locale locale) { + return SynchronousFuture(lookupAppLocalizations(locale)); + } + + @override + bool isSupported(Locale locale) => ['en', 'id'].contains(locale.languageCode); + + @override + bool shouldReload(_AppLocalizationsDelegate old) => false; +} + +AppLocalizations lookupAppLocalizations(Locale locale) { + + + // Lookup logic when only language code is specified. + switch (locale.languageCode) { + case 'en': return AppLocalizationsEn(); + case 'id': return AppLocalizationsId(); + } + + throw FlutterError( + 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' + 'an issue with the localizations generation tool. Please file an issue ' + 'on GitHub with a reproducible sample app and the gen-l10n configuration ' + 'that was used.' + ); +} diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart new file mode 100644 index 0000000..4f371d7 --- /dev/null +++ b/lib/l10n/app_localizations_en.dart @@ -0,0 +1,624 @@ +// ignore: unused_import +import 'package:intl/intl.dart' as intl; +import 'app_localizations.dart'; + +// ignore_for_file: type=lint + +/// The translations for English (`en`). +class AppLocalizationsEn extends AppLocalizations { + AppLocalizationsEn([String locale = 'en']) : super(locale); + + @override + String get indonesian => 'Indonesian'; + + @override + String get english => 'English'; + + @override + String get language => 'Language'; + + @override + String get version => 'Version'; + + @override + String get select_language => 'Select Language'; + + @override + String get login_header => 'Welcome back'; + + @override + String get login_desc => 'Sign in to your account'; + + @override + String get email => 'Email'; + + @override + String get email_placeholder => 'Enter your email'; + + @override + String get password => 'Password'; + + @override + String get password_placeholder => 'Enter your password'; + + @override + String get forgot_password => 'Forgot Password'; + + @override + String get sign_in => 'Sign In'; + + @override + String get good_morning => 'Good Morning'; + + @override + String get good_afternoon => 'Good Afternoon'; + + @override + String get good_evening => 'Good Evening'; + + @override + String get good_night => 'Good Night'; + + @override + String get home_header_desc => 'Let\'s improve your business performance today'; + + @override + String get home => 'Home'; + + @override + String get transaction => 'Transaction'; + + @override + String get transactions => 'Transactions'; + + @override + String get report => 'Report'; + + @override + String get reports => 'Reports'; + + @override + String get profile => 'Profile'; + + @override + String get sales_today => 'Sales today'; + + @override + String get order => 'Order'; + + @override + String get sales => 'Sales'; + + @override + String get finance => 'Finance'; + + @override + String get product => 'Product'; + + @override + String get form => 'Form'; + + @override + String get schedule => 'Schedule'; + + @override + String get inventory => 'Inventory'; + + @override + String get customer => 'Customer'; + + @override + String get purchase => 'Purchase'; + + @override + String get today_summary => 'Today\'s Summary'; + + @override + String get today => 'Today'; + + @override + String get new_customer => 'New Customer'; + + @override + String get refund => 'Refund'; + + @override + String get void_text => 'Void'; + + @override + String get increase => 'Increase'; + + @override + String get today_top_product => 'Today\'s Top Product'; + + @override + String get rank => 'Rank'; + + @override + String get quantity_sold => 'Quantity Sold'; + + @override + String get total_orders => 'Total Orders'; + + @override + String get average_price => 'Average Price'; + + @override + String get perfomance => 'Performance'; + + @override + String get total_sales => 'Total Sales'; + + @override + String get total_items => 'Total Items'; + + @override + String get summary => 'Summary'; + + @override + String get net_sales => 'Net Sales'; + + @override + String get daily_breakdown => 'Daily Breakdown'; + + @override + String get orders => 'Orders'; + + @override + String get items => 'Items'; + + @override + String get tax => 'Tax'; + + @override + String get discount => 'Discount'; + + @override + String get total_purchase => 'Total Purchase'; + + @override + String get pending_order => 'Pending Order'; + + @override + String get history_purchase => 'History Purchase'; + + @override + String get all => 'All'; + + @override + String get select_date_range => 'Select Date Range'; + + @override + String get no_date_selected => 'No date has been selected yet'; + + @override + String get selected_date => 'Selected Date'; + + @override + String get select => 'Select'; + + @override + String get cancel => 'Cancel'; + + @override + String get total_revenue => 'Total Revenue'; + + @override + String get total_expenditures => 'Total Expenditures'; + + @override + String get net_profit => 'Net Profit'; + + @override + String get margin_profit => 'Margin Profit'; + + @override + String get cash_flow_analysis => 'Cash Flow Analysis'; + + @override + String get cash_in => 'Cash In'; + + @override + String get cash_out => 'Cash Out'; + + @override + String get net_flow => 'Net Flow'; + + @override + String cash_flow_chart(int days) { + return 'Cash Flow Chart for $days Last Days'; + } + + @override + String get profit_loss_detail => 'Profit & Loss Details'; + + @override + String get gross_sales => 'Gross Sales'; + + @override + String get return_text => 'Return'; + + @override + String get cogs => 'COGS'; + + @override + String get cost_of_goods_sold => 'Cost of goods sold'; + + @override + String get gross_profit => 'Gross Profit'; + + @override + String get operating_costs => 'Operating Costs'; + + @override + String get sales_category => 'Sales Category'; + + @override + String get unit => 'Unit'; + + @override + String get category_no_data => 'There are no data categories yet'; + + @override + String get category_no_data_desc => 'Sales category data will appear here'; + + @override + String get product_analytic => 'Product Analytic'; + + @override + String get view_all => 'View All'; + + @override + String get sold => 'Sold'; + + @override + String get revenue => 'Revenue'; + + @override + String get cost => 'Cost'; + + @override + String get profit_per_unit => 'Profit per unit'; + + @override + String get total_sold => 'Total Sold'; + + @override + String get ingredients => 'Ingredients'; + + @override + String get low_stock => 'Low Stock'; + + @override + String get zero_stock => 'Zero Stock'; + + @override + String get stock => 'Stock'; + + @override + String get price => 'Price'; + + @override + String get out_of_stock => 'Out of stock'; + + @override + String get out_of_stock_desc => 'Product not available for sale'; + + @override + String get in_text => 'In'; + + @override + String get out_text => 'Out'; + + @override + String get available => 'Available'; + + @override + String get total_products => 'Total Products'; + + @override + String get total_ingredients => 'Total Ingredients'; + + @override + String get products => 'Products'; + + @override + String get value_text => 'Value'; + + @override + String low_stock_desc(String stock) { + return 'Immediately reorder at least $stock pcs'; + } + + @override + String get joined => 'Joined'; + + @override + String get ago => 'ago'; + + @override + String get active => 'Active'; + + @override + String get inactive => 'Inactive'; + + @override + String get total_amount => 'Total Amount'; + + @override + String get table => 'Table'; + + @override + String get remaining => 'Remaining'; + + @override + String get payment => 'Payment'; + + @override + String get completed => 'Completed'; + + @override + String get pending => 'Pending'; + + @override + String no_order_with_status(String status) { + return 'No $status orders found'; + } + + @override + String get order_details => 'Order Details'; + + @override + String get order_number => 'Order Number'; + + @override + String get order_status => 'Order Status'; + + @override + String get order_information => 'Order Information'; + + @override + String get order_type => 'Order Type'; + + @override + String get payment_status => 'Payment Status'; + + @override + String get created => 'Created'; + + @override + String get order_item => 'Order Item'; + + @override + String get item => 'Item'; + + @override + String get each => 'Each'; + + @override + String get total_item => 'Total Item'; + + @override + String get payment_summary => 'Payment Summary'; + + @override + String get subtotal => 'Subtotal'; + + @override + String get paid => 'Paid'; + + @override + String get total => 'Total'; + + @override + String get payment_method => 'Payment Method'; + + @override + String get dine_in => 'Dine In'; + + @override + String get dine_in_experience => 'Dine In Experience'; + + @override + String get note => 'Note'; + + @override + String get sales_chart => 'Sales Chart'; + + @override + String get no_data_available => 'No Data Avaiable'; + + @override + String total_days_overview(int days) { + return '$days days overview'; + } + + @override + String get sales_data => 'Sales Data'; + + @override + String get no_sales_data => 'No Sales Data'; + + @override + String get no_sales_data_desc => 'Sales data will appear here once transactions are recorded'; + + @override + String get payment_methods => 'Payment Methods'; + + @override + String get payment_methods_desc => 'Revenue breakdown by payment method '; + + @override + String get revenue_share => 'Revenue Share'; + + @override + String get no_payment_methods => 'No Payment Methods'; + + @override + String get no_payment_methods_desc => 'Payment method data will appear here once transactions are made'; + + @override + String get best_selling_products => 'Best Selling Products'; + + @override + String get highest_sales_ranking => 'Highest sales ranking'; + + @override + String get best_seller => 'Best Seller'; + + @override + String get top_performer => 'Top Performer'; + + @override + String get account_information => 'Account Information'; + + @override + String get member_since => 'Member Since'; + + @override + String get edit_profile => 'Edit Profile'; + + @override + String get edit_profile_desc => 'Update your profile information'; + + @override + String get change_password => 'Change Password'; + + @override + String get change_password_desc => 'Update your password'; + + @override + String get business_settings => 'Business Settings'; + + @override + String get outlet_information => 'Outlet Information'; + + @override + String get outlet_informatio_desc => 'Manage your outlet details'; + + @override + String get staff_management => 'Staff Management'; + + @override + String get staff_management_desc => 'Manage your staff'; + + @override + String get manage_your_products => 'Manage Your Products'; + + @override + String get download_report => 'Download Report'; + + @override + String get download_report_desc => 'Download your sales report or inventory report'; + + @override + String get app_settings => 'App Settings'; + + @override + String get language_desc => 'Select your preferred language'; + + @override + String get support => 'Support'; + + @override + String get help_center => 'Help Center'; + + @override + String get help_center_desc => 'Get help from our support team'; + + @override + String get about => 'About'; + + @override + String get about_desc => 'Learn more about our app'; + + @override + String get logout => 'Logout'; + + @override + String get logout_desc => 'Logout of your account'; + + @override + String get save => 'Save'; + + @override + String get name => 'Name'; + + @override + String get name_placeholder => 'Please enter your name'; + + @override + String get password_changed => 'Password Changed'; + + @override + String get current_password => 'Current Password'; + + @override + String get current_password_placeholder => 'Please enter your current password'; + + @override + String get new_password => 'New Password'; + + @override + String get new_password_placeholder => 'Please enter your new password'; + + @override + String get new_password_not_same => 'New password cannot be same as current password'; + + @override + String get general_information => 'General Information'; + + @override + String get address => 'Address'; + + @override + String get phone_number => 'Phone Number'; + + @override + String get currency => 'Currency'; + + @override + String get tax_rate => 'Tax Rate'; + + @override + String get status_text => 'Status'; + + @override + String get coming_soon => 'Coming Soon'; + + @override + String get coming_soon_desc => 'Something amazing is brewing!\nStay tuned for the big reveal.'; + + @override + String get transaction_report => 'Transaction Report'; + + @override + String get transaction_report_desc => 'Export all transaction data with detailed analytics'; + + @override + String get invetory_report => 'Inventory Report'; + + @override + String get invetory_report_desc => 'Export inventory and stock data with trends'; + + @override + String get about_app => 'About App'; + + @override + String get app_information => 'App Information'; + + @override + String get app_name => 'App Name'; + + @override + String get build_number => 'Build Number'; + + @override + String get package_name => 'Package Name'; + + @override + String get device => 'Device'; + + @override + String get profit_loss => 'Laba Rugi'; +} diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart new file mode 100644 index 0000000..2c66dcf --- /dev/null +++ b/lib/l10n/app_localizations_id.dart @@ -0,0 +1,624 @@ +// ignore: unused_import +import 'package:intl/intl.dart' as intl; +import 'app_localizations.dart'; + +// ignore_for_file: type=lint + +/// The translations for Indonesian (`id`). +class AppLocalizationsId extends AppLocalizations { + AppLocalizationsId([String locale = 'id']) : super(locale); + + @override + String get indonesian => 'Indonesia'; + + @override + String get english => 'Inggris'; + + @override + String get language => 'Bahasa'; + + @override + String get version => 'Versi'; + + @override + String get select_language => 'Pilih Bahasa'; + + @override + String get login_header => 'Selamat Datang kembali'; + + @override + String get login_desc => 'Masuk ke akun Anda'; + + @override + String get email => 'Email'; + + @override + String get email_placeholder => 'Masukkan email Anda'; + + @override + String get password => 'Kata Sandi'; + + @override + String get password_placeholder => 'Masukkan kata sandi Anda'; + + @override + String get forgot_password => 'Lupa Kata Sandi'; + + @override + String get sign_in => 'Masuk'; + + @override + String get good_morning => 'Selamat Pagi'; + + @override + String get good_afternoon => 'Selamat Siang'; + + @override + String get good_evening => 'Selamat Sore'; + + @override + String get good_night => 'Selamat Malam'; + + @override + String get home_header_desc => 'Mari tingkatkan performa bisnis Anda hari ini'; + + @override + String get home => 'Beranda'; + + @override + String get transaction => 'Transaksi'; + + @override + String get transactions => 'Transaksi'; + + @override + String get report => 'Laporan'; + + @override + String get reports => 'Laporan'; + + @override + String get profile => 'Profil'; + + @override + String get sales_today => 'Penjualan hari ini'; + + @override + String get order => 'Pesanan'; + + @override + String get sales => 'Penjualan'; + + @override + String get finance => 'Keuangan'; + + @override + String get product => 'Produk'; + + @override + String get form => 'Form'; + + @override + String get schedule => 'Jadwal'; + + @override + String get inventory => 'Inventaris'; + + @override + String get customer => 'Pelanggan'; + + @override + String get purchase => 'Pembelian'; + + @override + String get today_summary => 'Ringkasan Hari Ini'; + + @override + String get today => 'Hari ini'; + + @override + String get new_customer => 'Pelanggan baru'; + + @override + String get refund => 'Pengembalian dana'; + + @override + String get void_text => 'Dibatalkan'; + + @override + String get increase => 'Bertambah'; + + @override + String get today_top_product => 'Produk teratas hari ini'; + + @override + String get rank => 'Pangkat'; + + @override + String get quantity_sold => 'Kuantiti Terjual'; + + @override + String get total_orders => 'Jumlah Pesanan'; + + @override + String get average_price => 'Harga Rata-rata'; + + @override + String get perfomance => 'Performa'; + + @override + String get total_sales => 'Jumlah Penjualan'; + + @override + String get total_items => 'Jumlah Barang'; + + @override + String get summary => 'Ringkasan'; + + @override + String get net_sales => 'Penjualan Bersih'; + + @override + String get daily_breakdown => 'Perincian Harian'; + + @override + String get orders => 'Pesanan'; + + @override + String get items => 'Barang'; + + @override + String get tax => 'Pajak'; + + @override + String get discount => 'Diskon'; + + @override + String get total_purchase => 'Jumlah Pembelian'; + + @override + String get pending_order => 'Pesanan Menunggu'; + + @override + String get history_purchase => 'Riwayat Pembelian'; + + @override + String get all => 'Semua'; + + @override + String get select_date_range => 'Pilih Rentang Tanggal'; + + @override + String get no_date_selected => 'Belum ada tanggal dipilih'; + + @override + String get selected_date => 'Tanggal Terpilih'; + + @override + String get select => 'Pilih'; + + @override + String get cancel => 'Batal'; + + @override + String get total_revenue => 'Jumlah Pendapatan'; + + @override + String get total_expenditures => 'Jumlah Pengeluaran'; + + @override + String get net_profit => 'Keuntungan Bersih'; + + @override + String get margin_profit => 'Keuntungan Margin'; + + @override + String get cash_flow_analysis => 'Analisis Arus Kas'; + + @override + String get cash_in => 'Uang Masuk'; + + @override + String get cash_out => 'Uang Keluar'; + + @override + String get net_flow => 'Arus Bersih'; + + @override + String cash_flow_chart(int days) { + return 'Grafik Cash Flow \$$days Hari Terakhir'; + } + + @override + String get profit_loss_detail => 'Detail Untung & Rugi'; + + @override + String get gross_sales => 'Penjualan Kotor'; + + @override + String get return_text => 'Retur'; + + @override + String get cogs => 'HPP'; + + @override + String get cost_of_goods_sold => 'Harga Pokok Penjualan'; + + @override + String get gross_profit => 'Keuntungan Kotor'; + + @override + String get operating_costs => 'Biaya Operasional'; + + @override + String get sales_category => 'Kategori Penjualan'; + + @override + String get unit => 'Unit'; + + @override + String get category_no_data => 'Belum ada data kategori'; + + @override + String get category_no_data_desc => 'Data kategori penjualan akan muncul di sini'; + + @override + String get product_analytic => 'Analisis Produk'; + + @override + String get view_all => 'Lihat Semua'; + + @override + String get sold => 'Terjual'; + + @override + String get revenue => 'Pendapatan'; + + @override + String get cost => 'Biaya'; + + @override + String get profit_per_unit => 'Keuntungan per unit'; + + @override + String get total_sold => 'Jumlah Terjual'; + + @override + String get ingredients => 'Bahan Baku'; + + @override + String get low_stock => 'Stok Rendah'; + + @override + String get zero_stock => 'Stok Kosong'; + + @override + String get stock => 'Stok'; + + @override + String get price => 'Harga'; + + @override + String get out_of_stock => 'Stok habis'; + + @override + String get out_of_stock_desc => 'Produk tidak tersedia untuk dijual'; + + @override + String get in_text => 'Masuk'; + + @override + String get out_text => 'Keluar'; + + @override + String get available => 'Tersedia'; + + @override + String get total_products => 'Jumlah Produk'; + + @override + String get total_ingredients => 'Jumlah Bahan Baku'; + + @override + String get products => 'Produk'; + + @override + String get value_text => 'Nilai'; + + @override + String low_stock_desc(String stock) { + return 'Segera reorder minimal $stock pcs'; + } + + @override + String get joined => 'Bergabung'; + + @override + String get ago => 'lalu'; + + @override + String get active => 'Aktif'; + + @override + String get inactive => 'Tidak Aktif'; + + @override + String get total_amount => 'Jumlah Total'; + + @override + String get table => 'Meja'; + + @override + String get remaining => 'Sisa'; + + @override + String get payment => 'Pembayaran'; + + @override + String get completed => 'Selesai'; + + @override + String get pending => 'Menunggu'; + + @override + String no_order_with_status(String status) { + return 'Tidak ada pesanan $status yang ditemukan'; + } + + @override + String get order_details => 'Detail Pesanan'; + + @override + String get order_number => 'Nomor Pesanan'; + + @override + String get order_status => 'Status Pesanan'; + + @override + String get order_information => 'Informasi Pesanan'; + + @override + String get order_type => 'Tipe Pesanan'; + + @override + String get payment_status => 'Status Pembayaran'; + + @override + String get created => 'Dibuat'; + + @override + String get order_item => 'Item Pesanan'; + + @override + String get item => 'Item'; + + @override + String get each => 'Setiap'; + + @override + String get total_item => 'Jumlah Item'; + + @override + String get payment_summary => 'Ringkasan Pembayaran'; + + @override + String get subtotal => 'Subtotal'; + + @override + String get paid => 'Dibayar'; + + @override + String get total => 'Jumlah'; + + @override + String get payment_method => 'Metode Pembayaran'; + + @override + String get dine_in => 'Makan di Tempat'; + + @override + String get dine_in_experience => 'Pengalaman Bersantap Di Tempat'; + + @override + String get note => 'Catatan'; + + @override + String get sales_chart => 'Bagan Penjualan'; + + @override + String get no_data_available => 'Tidak Ada Data Tersedia'; + + @override + String total_days_overview(int days) { + return 'ikhtisar $days hari'; + } + + @override + String get sales_data => 'Data Penjualan'; + + @override + String get no_sales_data => 'Tidak ada data penjualan'; + + @override + String get no_sales_data_desc => 'Data penjualan akan muncul di sini setelah transaksi dicatat'; + + @override + String get payment_methods => 'Metode Pembayaran'; + + @override + String get payment_methods_desc => 'Rincian pendapatan berdasarkan metode pembayaran '; + + @override + String get revenue_share => 'Bagi Hasil'; + + @override + String get no_payment_methods => 'Tidak Ada Metode Pembayaran'; + + @override + String get no_payment_methods_desc => 'Data metode pembayaran akan muncul di sini setelah transaksi dilakukan'; + + @override + String get best_selling_products => 'Produk Terlaris'; + + @override + String get highest_sales_ranking => 'Ranking penjualan tertinggi'; + + @override + String get best_seller => 'Penjual Terbaik'; + + @override + String get top_performer => 'Berkinerja Terbaik'; + + @override + String get account_information => 'Informasi Akun'; + + @override + String get member_since => 'Member Sejak'; + + @override + String get edit_profile => 'Ubah Profil'; + + @override + String get edit_profile_desc => 'Update informasi profil Anda'; + + @override + String get change_password => 'Ubah Kata Sandi'; + + @override + String get change_password_desc => 'Update kata sandi Anda'; + + @override + String get business_settings => 'Pengaturan Bisnis'; + + @override + String get outlet_information => 'Informasi Outlet'; + + @override + String get outlet_informatio_desc => 'Kelola informasi outlet Anda'; + + @override + String get staff_management => 'Manajemen Staff'; + + @override + String get staff_management_desc => 'Kelola staff Anda'; + + @override + String get manage_your_products => 'Kelola Produk Anda'; + + @override + String get download_report => 'Unduh Laporan'; + + @override + String get download_report_desc => 'Unduh laporan penjualan atau stok'; + + @override + String get app_settings => 'Pengaturan Aplikasi'; + + @override + String get language_desc => 'Pilih bahasa aplikasi Anda'; + + @override + String get support => 'Dukungan'; + + @override + String get help_center => 'Pusat Bantuan'; + + @override + String get help_center_desc => 'Hubungi tim dukungan kami'; + + @override + String get about => 'Tentang'; + + @override + String get about_desc => 'Tentang Aplikasi'; + + @override + String get logout => 'Keluar'; + + @override + String get logout_desc => 'Keluar dari akun Anda'; + + @override + String get save => 'Simpan'; + + @override + String get name => 'Nama'; + + @override + String get name_placeholder => 'Masukkan nama Anda'; + + @override + String get password_changed => 'Kata Sandi Berubah'; + + @override + String get current_password => 'Kata Sandi Saat Ini'; + + @override + String get current_password_placeholder => 'Masukkan kata sandi saat ini'; + + @override + String get new_password => 'Kata Sandi Baru'; + + @override + String get new_password_placeholder => 'Masukkan kata sandi baru'; + + @override + String get new_password_not_same => 'Kata Sandi Baru Tidak Sama Dengan Kata Sandi Saat Ini'; + + @override + String get general_information => 'Informasi Umum'; + + @override + String get address => 'Alamat'; + + @override + String get phone_number => 'Nomor Telepon'; + + @override + String get currency => 'Mata Uang'; + + @override + String get tax_rate => 'Tarif Pajak'; + + @override + String get status_text => 'Status'; + + @override + String get coming_soon => 'Segera Hadir'; + + @override + String get coming_soon_desc => 'Sesuatu yang menakjubkan sedang terjadi!\nNantikan pengungkapan besarnya.'; + + @override + String get transaction_report => 'Laporan Transaksi'; + + @override + String get transaction_report_desc => 'Ekspor semua data transaksi dengan analitik terperinci'; + + @override + String get invetory_report => 'Laporan Inventaris'; + + @override + String get invetory_report_desc => 'Ekspor inventaris dan data stok dengan tren'; + + @override + String get about_app => 'Tentang Aplikasi'; + + @override + String get app_information => 'Informasi Aplikasi'; + + @override + String get app_name => 'Nama Aplikasi'; + + @override + String get build_number => 'Nomor Build'; + + @override + String get package_name => 'Nama Paket'; + + @override + String get device => 'Perangkat'; + + @override + String get profit_loss => 'Laba Rugi'; +} diff --git a/lib/main.dart b/lib/main.dart index 826ecd4..25f0646 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:injectable/injectable.dart'; +import 'common/utils/fcm_service.dart'; import 'injection.dart'; import 'presentation/app_widget.dart'; @@ -24,5 +25,12 @@ void main() async { kReleaseMode ? Environment.prod : Environment.dev, ); + // Initialize FCM after dependencies are ready + await getIt().initialize( + onMessageTap: (message) { + debugPrint('[FCM] Navigate based on: ${message.data}'); + }, + ); + runApp(const AppWidget()); } diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index 38ae400..b43f852 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -1,8 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:loader_overlay/loader_overlay.dart'; +import '../application/auth/auth_bloc.dart'; +import '../application/language/language_bloc.dart'; import '../common/theme/theme.dart'; import '../common/constant/app_constant.dart'; import '../injection.dart'; +import '../l10n/app_localizations.dart'; +import 'components/loading/loading_overlay.dart'; import 'router/app_router.dart'; import 'router/app_router_observer.dart'; @@ -18,12 +24,32 @@ class _AppWidgetState extends State { @override Widget build(BuildContext context) { - return MaterialApp.router( - debugShowCheckedModeBanner: false, - title: AppConstant.appName, - theme: ThemeApp.theme, - routerConfig: _appRouter.config( - navigatorObservers: () => [AppRouteObserver()], + return MultiBlocProvider( + providers: [ + BlocProvider(create: (context) => getIt()), + BlocProvider(create: (context) => getIt()), + ], + child: GlobalLoaderOverlay( + useDefaultLoading: false, + overlayWidgetBuilder: (progress) => LoadingOverlay(), + overlayColor: AppColor.black.withOpacity(0.35), + child: BlocBuilder( + builder: (context, state) { + return MaterialApp.router( + debugShowCheckedModeBanner: false, + title: AppConstant.appName, + locale: state.language.locale, + supportedLocales: AppLocalizations.supportedLocales, + localizationsDelegates: AppLocalizations.localizationsDelegates, + theme: ThemeApp.theme, + routerConfig: _appRouter.config( + navigatorObservers: () => [ + AppRouteObserver(), + ], + ), + ); + }, + ), ), ); } diff --git a/lib/presentation/components/appbar/appbar.dart b/lib/presentation/components/appbar/appbar.dart new file mode 100644 index 0000000..afe8f0d --- /dev/null +++ b/lib/presentation/components/appbar/appbar.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; + +import '../../../common/painter/wave_painter.dart'; +import '../../../common/theme/theme.dart'; + +class CustomAppBar extends StatelessWidget { + final String title; + final bool isBack; + const CustomAppBar({super.key, required this.title, this.isBack = true}); + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + + return FlexibleSpaceBar( + titlePadding: EdgeInsets.only(left: isBack ? 50 : 20, bottom: 16), + title: Text( + title, + style: AppStyle.xl.copyWith( + color: AppColor.textWhite, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + background: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: Stack( + children: [ + // Static decorative circles (right side) + Positioned( + top: -20, + right: -30, + child: Container( + width: 120, + height: 120, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.textWhite.withOpacity(0.08), + ), + ), + ), + Positioned( + top: 30, + right: 20, + child: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.textWhite.withOpacity(0.05), + ), + ), + ), + + // Static decorative circles (left side) + Positioned( + top: 10, + left: -20, + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.textWhite.withOpacity(0.04), + ), + ), + ), + + // Static sparkle icons + ...List.generate(4, (index) { + return Positioned( + left: (index * 90.0) % size.width, + top: 20 + (index * 25.0), + child: Icon( + Icons.auto_awesome, + size: 10 + (index % 3) * 3, + color: AppColor.textWhite.withOpacity(0.2), + ), + ); + }), + + // Wave pattern (static) + Positioned.fill( + child: CustomPaint( + painter: WavePainter( + animation: 0.0, + color: AppColor.textWhite.withOpacity(0.1), + ), + ), + ), + + // Gradient overlay for depth + Container( + decoration: BoxDecoration( + gradient: RadialGradient( + center: const Alignment(0.3, -0.2), + radius: 1.2, + colors: [ + Colors.transparent, + AppColor.primaryGradient.first.withOpacity(0.1), + Colors.transparent, + ], + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/components/assets/assets.gen.dart b/lib/presentation/components/assets/assets.gen.dart index c528e32..84d22e0 100644 --- a/lib/presentation/components/assets/assets.gen.dart +++ b/lib/presentation/components/assets/assets.gen.dart @@ -11,19 +11,52 @@ import 'package:flutter/widgets.dart'; +class $AssetsIconsGen { + const $AssetsIconsGen(); + + /// File path: assets/icons/ic-report-product.png + AssetGenImage get icReportProduct => + const AssetGenImage('assets/icons/ic-report-product.png'); + + /// File path: assets/icons/ic-report-profit-loss.png + AssetGenImage get icReportProfitLoss => + const AssetGenImage('assets/icons/ic-report-profit-loss.png'); + + /// File path: assets/icons/ic-report-purchase.png + AssetGenImage get icReportPurchase => + const AssetGenImage('assets/icons/ic-report-purchase.png'); + + /// File path: assets/icons/ic-report-sales.png + AssetGenImage get icReportSales => + const AssetGenImage('assets/icons/ic-report-sales.png'); + + /// List of all assets + List get values => [ + icReportProduct, + icReportProfitLoss, + icReportPurchase, + icReportSales, + ]; +} + class $AssetsImagesGen { const $AssetsImagesGen(); + /// File path: assets/images/ic_notification.png + AssetGenImage get icNotification => + const AssetGenImage('assets/images/ic_notification.png'); + /// File path: assets/images/logo.png AssetGenImage get logo => const AssetGenImage('assets/images/logo.png'); /// List of all assets - List get values => [logo]; + List get values => [icNotification, logo]; } class Assets { const Assets._(); + static const $AssetsIconsGen icons = $AssetsIconsGen(); static const $AssetsImagesGen images = $AssetsImagesGen(); } diff --git a/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart b/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart new file mode 100644 index 0000000..4db02b2 --- /dev/null +++ b/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart @@ -0,0 +1,365 @@ +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datepicker/datepicker.dart'; + +import '../../../common/extension/extension.dart'; + +class DateRangePickerBottomSheet { + static Future show({ + required BuildContext context, + String title = 'Pilih Rentang Tanggal', + DateTime? initialStartDate, + DateTime? initialEndDate, + DateTime? minDate, + DateTime? maxDate, + String? confirmText, + String? cancelText, + Color primaryColor = Colors.blue, + Function(DateTime? startDate, DateTime? endDate)? onChanged, + }) async { + return await showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + isDismissible: false, + enableDrag: false, + builder: (BuildContext context) => _DateRangePickerBottomSheet( + title: title, + initialStartDate: initialStartDate, + initialEndDate: initialEndDate, + minDate: minDate, + maxDate: maxDate, + confirmText: confirmText ?? context.lang.select, + cancelText: cancelText ?? context.lang.cancel, + primaryColor: primaryColor, + onChanged: onChanged, + ), + ); + } +} + +class _DateRangePickerBottomSheet extends StatefulWidget { + final String title; + final DateTime? initialStartDate; + final DateTime? initialEndDate; + final DateTime? minDate; + final DateTime? maxDate; + final String confirmText; + final String cancelText; + final Color primaryColor; + final Function(DateTime? startDate, DateTime? endDate)? onChanged; + + const _DateRangePickerBottomSheet({ + required this.title, + this.initialStartDate, + this.initialEndDate, + this.minDate, + this.maxDate, + required this.confirmText, + required this.cancelText, + required this.primaryColor, + this.onChanged, + }); + + @override + State<_DateRangePickerBottomSheet> createState() => + _DateRangePickerBottomSheetState(); +} + +class _DateRangePickerBottomSheetState + extends State<_DateRangePickerBottomSheet> + with TickerProviderStateMixin { + DateRangePickerSelectionChangedArgs? _selectionChangedArgs; + late AnimationController _animationController; + late Animation _slideAnimation; + + @override + void initState() { + super.initState(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 300), + vsync: this, + ); + _slideAnimation = Tween(begin: 1.0, end: 0.0).animate( + CurvedAnimation(parent: _animationController, curve: Curves.easeOutCubic), + ); + _animationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + void _onSelectionChanged(DateRangePickerSelectionChangedArgs args) { + setState(() { + _selectionChangedArgs = args; + }); + } + + String _getSelectionText() { + if (_selectionChangedArgs?.value is PickerDateRange) { + final PickerDateRange range = _selectionChangedArgs!.value; + if (range.startDate != null && range.endDate != null) { + return '${_formatDate(range.startDate!)} - ${_formatDate(range.endDate!)}'; + } else if (range.startDate != null) { + return _formatDate(range.startDate!); + } + } + return context.lang.no_date_selected; + } + + String _formatDate(DateTime date) { + final months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'Mei', + 'Jun', + 'Jul', + 'Agu', + 'Sep', + 'Okt', + 'Nov', + 'Des', + ]; + return '${date.day} ${months[date.month - 1]} ${date.year}'; + } + + bool get _isValidSelection { + if (_selectionChangedArgs?.value is PickerDateRange) { + final PickerDateRange range = _selectionChangedArgs!.value; + return range.startDate != null && range.endDate != null; + } + return false; + } + + @override + Widget build(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height; + final bottomSheetHeight = screenHeight * 0.75; + + return AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return Transform.translate( + offset: Offset(0, _slideAnimation.value * bottomSheetHeight), + child: Container( + height: bottomSheetHeight, + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Drag Handle + Container( + margin: const EdgeInsets.only(top: 12, bottom: 8), + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + + // Content + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + // Selection Info + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: widget.primaryColor.withOpacity(0.08), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: widget.primaryColor.withOpacity(0.2), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${context.lang.selected_date}:', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: widget.primaryColor, + ), + ), + const SizedBox(height: 6), + Text( + _getSelectionText(), + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Colors.black87, + ), + ), + ], + ), + ), + + const SizedBox(height: 20), + + // Date Picker + Container( + height: 320, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Colors.grey.withOpacity(0.2), + ), + ), + child: SfDateRangePicker( + onSelectionChanged: _onSelectionChanged, + selectionMode: DateRangePickerSelectionMode.range, + initialSelectedRange: + (widget.initialStartDate != null && + widget.initialEndDate != null) + ? PickerDateRange( + widget.initialStartDate, + widget.initialEndDate, + ) + : null, + minDate: widget.minDate, + maxDate: widget.maxDate, + startRangeSelectionColor: widget.primaryColor, + endRangeSelectionColor: widget.primaryColor, + rangeSelectionColor: widget.primaryColor + .withOpacity(0.2), + todayHighlightColor: widget.primaryColor, + headerStyle: DateRangePickerHeaderStyle( + backgroundColor: Colors.transparent, + textAlign: TextAlign.center, + textStyle: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + monthViewSettings: DateRangePickerMonthViewSettings( + viewHeaderStyle: DateRangePickerViewHeaderStyle( + backgroundColor: Colors.grey.withOpacity(0.1), + textStyle: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: widget.primaryColor, + ), + ), + ), + selectionTextStyle: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + rangeTextStyle: TextStyle( + color: widget.primaryColor, + fontWeight: FontWeight.w500, + fontSize: 14, + ), + ), + ), + ], + ), + ), + ), + + // Bottom Fixed Action Buttons + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + border: Border( + top: BorderSide( + color: Colors.grey.withOpacity(0.2), + width: 1, + ), + ), + ), + child: SafeArea( + child: Row( + children: [ + Expanded( + child: OutlinedButton( + onPressed: () => Navigator.of(context).pop(), + style: OutlinedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 16), + side: BorderSide(color: Colors.grey.shade400), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: Text( + widget.cancelText, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Colors.grey, + ), + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: ElevatedButton( + onPressed: _isValidSelection + ? () { + // Call onChanged when confirm button is pressed + if (widget.onChanged != null && + _selectionChangedArgs?.value + is PickerDateRange) { + final PickerDateRange range = + _selectionChangedArgs!.value; + widget.onChanged!( + range.startDate, + range.endDate, + ); + } + Navigator.of( + context, + ).pop(_selectionChangedArgs); + } + : null, + style: ElevatedButton.styleFrom( + backgroundColor: widget.primaryColor, + padding: const EdgeInsets.symmetric(vertical: 16), + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + disabledBackgroundColor: Colors.grey.shade300, + ), + child: Text( + widget.confirmText, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: _isValidSelection + ? Colors.white + : Colors.grey.shade600, + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/presentation/components/button/action_icon_button.dart b/lib/presentation/components/button/action_icon_button.dart new file mode 100644 index 0000000..deeac78 --- /dev/null +++ b/lib/presentation/components/button/action_icon_button.dart @@ -0,0 +1,30 @@ +part of 'button.dart'; + +class ActionIconButton extends StatelessWidget { + const ActionIconButton({super.key, required this.onTap, required this.icon}); + + final Function()? onTap; + final IconData icon; + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(right: 8), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(12), + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(icon, color: AppColor.textWhite, size: 20), + ), + ), + ), + ); + } +} diff --git a/lib/presentation/components/button/button.dart b/lib/presentation/components/button/button.dart new file mode 100644 index 0000000..ebbf30f --- /dev/null +++ b/lib/presentation/components/button/button.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import '../../../common/theme/theme.dart'; +import '../spacer/spacer.dart'; + +part 'elevated_button.dart'; +part 'action_icon_button.dart'; diff --git a/lib/presentation/components/button/elevated_button.dart b/lib/presentation/components/button/elevated_button.dart new file mode 100644 index 0000000..c4bd484 --- /dev/null +++ b/lib/presentation/components/button/elevated_button.dart @@ -0,0 +1,70 @@ +part of 'button.dart'; + +class AppElevatedButton extends StatelessWidget { + const AppElevatedButton({ + super.key, + required this.text, + required this.isLoading, + required this.onPressed, + this.height = 50, + this.width = double.infinity, + }); + + final String text; + final bool isLoading; + final Function()? onPressed; + final double height; + final double width; + + @override + Widget build(BuildContext context) { + return Container( + height: height, + width: width, + decoration: BoxDecoration( + gradient: const LinearGradient(colors: AppColor.primaryGradient), + borderRadius: BorderRadius.circular(AppValue.radius), + boxShadow: [ + BoxShadow( + color: AppColor.primaryWithOpacity(0.3), + blurRadius: 15, + offset: const Offset(0, 8), + ), + ], + ), + child: ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: isLoading + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + 'Loading', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.white, + ), + ), + SpaceWidth(8), + SpinKitCircle(color: AppColor.white, size: 24.0), + ], + ) + : Text( + text, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.white, + ), + ), + ), + ); + } +} diff --git a/lib/presentation/components/field/date_range_picker_field.dart b/lib/presentation/components/field/date_range_picker_field.dart new file mode 100644 index 0000000..9450368 --- /dev/null +++ b/lib/presentation/components/field/date_range_picker_field.dart @@ -0,0 +1,415 @@ +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datepicker/datepicker.dart'; + +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../bottom_sheet/date_range_bottom_sheet.dart'; + +class DateRangePickerField extends StatefulWidget { + final String? label; + final String placeholder; + final DateTime? startDate; + final DateTime? endDate; + final DateTime? minDate; + final DateTime? maxDate; + final Function(DateTime? startDate, DateTime? endDate)? onChanged; + final Color primaryColor; + final bool enabled; + final String? errorText; + final EdgeInsetsGeometry? padding; + final TextStyle? textStyle; + final TextStyle? placeholderStyle; + final BoxDecoration? decoration; + final double height; + + const DateRangePickerField({ + super.key, + this.label, + this.placeholder = 'Pilih rentang tanggal', + this.startDate, + this.endDate, + this.minDate, + this.maxDate, + this.onChanged, + this.primaryColor = AppColor.primary, + this.enabled = true, + this.errorText, + this.padding, + this.textStyle, + this.placeholderStyle, + this.decoration, + this.height = 52.0, + }); + + @override + State createState() => _DateRangePickerFieldState(); +} + +class _DateRangePickerFieldState extends State { + bool _isPressed = false; + + String get _displayText { + if (widget.startDate != null && widget.endDate != null) { + return '${_formatDate(widget.startDate!)} - ${_formatDate(widget.endDate!)}'; + } else if (widget.startDate != null) { + return _formatDate(widget.startDate!); + } + return widget.placeholder; + } + + bool get _hasValue { + return widget.startDate != null || widget.endDate != null; + } + + String _formatDate(DateTime date) { + final months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'Mei', + 'Jun', + 'Jul', + 'Agu', + 'Sep', + 'Okt', + 'Nov', + 'Des', + ]; + return '${date.day} ${months[date.month - 1]} ${date.year}'; + } + + Future _showDateRangePicker() async { + if (!widget.enabled) return; + + final result = await DateRangePickerBottomSheet.show( + context: context, + title: widget.label ?? context.lang.select_date_range, + initialStartDate: widget.startDate, + initialEndDate: widget.endDate, + minDate: widget.minDate, + maxDate: widget.maxDate, + primaryColor: widget.primaryColor, + onChanged: widget.onChanged, + ); + + if (result != null && widget.onChanged != null) { + if (result.value is PickerDateRange) { + final PickerDateRange range = result.value; + widget.onChanged!(range.startDate, range.endDate); + } + } + } + + @override + Widget build(BuildContext context) { + final hasError = widget.errorText != null && widget.errorText!.isNotEmpty; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + // Label + if (widget.label != null) ...[ + Text( + widget.label!, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: hasError ? AppColor.error : AppColor.textSecondary, + ), + ), + const SizedBox(height: 8), + ], + + // Input Field + GestureDetector( + onTap: _showDateRangePicker, + onTapDown: widget.enabled + ? (_) => setState(() => _isPressed = true) + : null, + onTapUp: widget.enabled + ? (_) => setState(() => _isPressed = false) + : null, + onTapCancel: widget.enabled + ? () => setState(() => _isPressed = false) + : null, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + height: widget.height, + padding: + widget.padding ?? const EdgeInsets.symmetric(horizontal: 16), + decoration: + widget.decoration ?? + BoxDecoration( + color: widget.enabled + ? (_isPressed ? AppColor.backgroundLight : AppColor.white) + : AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: hasError + ? AppColor.error + : (_isPressed ? widget.primaryColor : AppColor.border), + width: _isPressed ? 2 : 1, + ), + boxShadow: _isPressed && widget.enabled + ? [ + BoxShadow( + color: widget.primaryColor.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ] + : null, + ), + child: Row( + children: [ + // Date Text + Expanded( + child: Text( + _displayText, + style: + widget.textStyle ?? + TextStyle( + fontSize: 15, + fontWeight: _hasValue + ? FontWeight.w500 + : FontWeight.w400, + color: widget.enabled + ? (_hasValue + ? AppColor.textPrimary + : AppColor.textSecondary) + : AppColor.textLight, + ), + ), + ), + + // Calendar Icon + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: widget.primaryColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + Icons.calendar_today_rounded, + size: 20, + color: widget.enabled + ? widget.primaryColor + : AppColor.textLight, + ), + ), + ], + ), + ), + ), + + // Error Text + if (hasError) ...[ + const SizedBox(height: 6), + Text( + widget.errorText!, + style: TextStyle( + fontSize: 12, + color: AppColor.error, + fontWeight: FontWeight.w400, + ), + ), + ], + ], + ); + } +} + +// Variasi dengan style yang berbeda +class DateRangePickerFieldOutlined extends StatefulWidget { + final String? label; + final String placeholder; + final DateTime? startDate; + final DateTime? endDate; + final DateTime? minDate; + final DateTime? maxDate; + final Function(DateTime? startDate, DateTime? endDate)? onChanged; + final Color primaryColor; + final bool enabled; + final String? errorText; + + const DateRangePickerFieldOutlined({ + Key? key, + this.label, + this.placeholder = 'Pilih rentang tanggal', + this.startDate, + this.endDate, + this.minDate, + this.maxDate, + this.onChanged, + this.primaryColor = AppColor.primary, + this.enabled = true, + this.errorText, + }) : super(key: key); + + @override + State createState() => + _DateRangePickerFieldOutlinedState(); +} + +class _DateRangePickerFieldOutlinedState + extends State { + bool _isFocused = false; + + String get _displayText { + if (widget.startDate != null && widget.endDate != null) { + return '${_formatDate(widget.startDate!)} - ${_formatDate(widget.endDate!)}'; + } else if (widget.startDate != null) { + return _formatDate(widget.startDate!); + } + return widget.placeholder; + } + + bool get _hasValue { + return widget.startDate != null || widget.endDate != null; + } + + String _formatDate(DateTime date) { + final months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'Mei', + 'Jun', + 'Jul', + 'Agu', + 'Sep', + 'Okt', + 'Nov', + 'Des', + ]; + return '${date.day} ${months[date.month - 1]} ${date.year}'; + } + + Future _showDateRangePicker() async { + if (!widget.enabled) return; + + setState(() => _isFocused = true); + + final result = await DateRangePickerBottomSheet.show( + context: context, + title: widget.label ?? context.lang.select_date_range, + initialStartDate: widget.startDate, + initialEndDate: widget.endDate, + minDate: widget.minDate, + maxDate: widget.maxDate, + primaryColor: widget.primaryColor, + onChanged: widget.onChanged, + ); + + setState(() => _isFocused = false); + + if (result != null && widget.onChanged != null) { + if (result.value is PickerDateRange) { + final PickerDateRange range = result.value; + widget.onChanged!(range.startDate, range.endDate); + } + } + } + + @override + Widget build(BuildContext context) { + final hasError = widget.errorText != null && widget.errorText!.isNotEmpty; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: _showDateRangePicker, + child: Container( + height: 56, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: hasError + ? AppColor.error + : (_isFocused || _hasValue + ? widget.primaryColor + : AppColor.border), + width: _isFocused ? 2 : 1, + ), + ), + child: Row( + children: [ + const SizedBox(width: 16), + + // Date Text + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (widget.label != null && (_isFocused || _hasValue)) + Text( + widget.label!, + style: TextStyle( + fontSize: 12, + color: hasError + ? AppColor.error + : widget.primaryColor, + fontWeight: FontWeight.w500, + ), + ), + Text( + _hasValue + ? _displayText + : (widget.label ?? widget.placeholder), + style: TextStyle( + fontSize: _hasValue ? 16 : 16, + fontWeight: FontWeight.w400, + color: widget.enabled + ? (_hasValue + ? AppColor.textPrimary + : AppColor.textSecondary) + : AppColor.textLight, + ), + ), + ], + ), + ), + + // Calendar Icon + Padding( + padding: const EdgeInsets.only(right: 16), + child: Icon( + Icons.calendar_today_rounded, + size: 24, + color: widget.enabled + ? (_isFocused + ? widget.primaryColor + : AppColor.textSecondary) + : AppColor.textLight, + ), + ), + ], + ), + ), + ), + + // Error Text + if (hasError) ...[ + const SizedBox(height: 6), + Padding( + padding: const EdgeInsets.only(left: 16), + child: Text( + widget.errorText!, + style: TextStyle( + fontSize: 12, + color: AppColor.error, + fontWeight: FontWeight.w400, + ), + ), + ), + ], + ], + ); + } +} diff --git a/lib/presentation/components/field/field.dart b/lib/presentation/components/field/field.dart new file mode 100644 index 0000000..ed5287d --- /dev/null +++ b/lib/presentation/components/field/field.dart @@ -0,0 +1,9 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icon.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../common/theme/theme.dart'; +import '../spacer/spacer.dart'; + +part 'password_text_form_field.dart'; +part 'text_form_field.dart'; diff --git a/lib/presentation/components/field/password_text_form_field.dart b/lib/presentation/components/field/password_text_form_field.dart new file mode 100644 index 0000000..ef285eb --- /dev/null +++ b/lib/presentation/components/field/password_text_form_field.dart @@ -0,0 +1,72 @@ +part of 'field.dart'; + +class AppPasswordTextFormField extends StatefulWidget { + const AppPasswordTextFormField({ + super.key, + this.controller, + required this.title, + this.hintText, + required this.prefixIcon, + this.validator, + this.onChanged, + }); + + final TextEditingController? controller; + final String title; + final String? hintText; + final IconData prefixIcon; + final String? Function(String?)? validator; + final Function(String)? onChanged; + + @override + State createState() => + _AppPasswordTextFormFieldState(); +} + +class _AppPasswordTextFormFieldState extends State { + bool _obscurePassword = true; + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.title, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + const SpaceHeight(8), + TextFormField( + controller: widget.controller, + keyboardType: TextInputType.emailAddress, + cursorColor: AppColor.primary, + obscureText: _obscurePassword, + style: AppStyle.md.copyWith(color: AppColor.textPrimary), + onChanged: widget.onChanged, + decoration: InputDecoration( + hintText: widget.hintText, + prefixIcon: LineIcon( + widget.prefixIcon, + color: AppColor.textSecondary, + ), + suffixIcon: IconButton( + padding: EdgeInsets.zero, + icon: Icon( + _obscurePassword ? LineIcons.eye : LineIcons.eyeSlash, + color: AppColor.textSecondary, + ), + onPressed: () { + setState(() { + _obscurePassword = !_obscurePassword; + }); + }, + ), + ), + validator: widget.validator, + ), + ], + ); + } +} diff --git a/lib/presentation/components/field/text_form_field.dart b/lib/presentation/components/field/text_form_field.dart new file mode 100644 index 0000000..869879c --- /dev/null +++ b/lib/presentation/components/field/text_form_field.dart @@ -0,0 +1,51 @@ +part of 'field.dart'; + +class AppTextFormField extends StatelessWidget { + const AppTextFormField({ + super.key, + this.controller, + required this.title, + this.hintText, + required this.prefixIcon, + this.validator, + this.onChanged, + this.keyboardType = TextInputType.text, + }); + + final TextEditingController? controller; + final String title; + final String? hintText; + final IconData prefixIcon; + final String? Function(String?)? validator; + final Function(String)? onChanged; + final TextInputType keyboardType; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + const SpaceHeight(8), + TextFormField( + controller: controller, + keyboardType: keyboardType, + cursorColor: AppColor.primary, + onChanged: onChanged, + style: AppStyle.md.copyWith(color: AppColor.textPrimary), + decoration: InputDecoration( + hintText: hintText, + prefixIcon: LineIcon(prefixIcon, color: AppColor.textSecondary), + ), + validator: validator, + ), + ], + ); + } +} diff --git a/lib/presentation/components/image/image.dart b/lib/presentation/components/image/image.dart new file mode 100644 index 0000000..edfb521 --- /dev/null +++ b/lib/presentation/components/image/image.dart @@ -0,0 +1,5 @@ +import 'package:flutter/material.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:shimmer/shimmer.dart'; + +part 'network_image.dart'; diff --git a/lib/presentation/components/image/network_image.dart b/lib/presentation/components/image/network_image.dart new file mode 100644 index 0000000..3f5f65b --- /dev/null +++ b/lib/presentation/components/image/network_image.dart @@ -0,0 +1,68 @@ +part of 'image.dart'; + +class AppNetworkImage extends StatelessWidget { + final String? url; + final double? height; + final double? width; + final double? borderRadius; + final BoxFit? fit; + final bool? isCanZoom; + final VoidCallback? onTap; + + const AppNetworkImage({ + super.key, + this.url, + this.height, + this.width, + this.borderRadius = 0, + this.fit = BoxFit.cover, + this.isCanZoom = false, + this.onTap, + }); + + @override + Widget build(BuildContext context) { + Widget customPhoto( + double? heightx, + double? widthx, + BoxFit? fitx, + double? radius, + ) { + return CachedNetworkImage( + imageUrl: url.toString(), + placeholder: (context, url) => Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Container( + height: height, + width: width, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(radius ?? 0), + ), + ), + ), + errorWidget: (context, url, error) => Container( + height: height, + width: width, + decoration: BoxDecoration( + color: Colors.grey.shade200, + borderRadius: BorderRadius.circular(radius ?? 0), + ), + child: Icon(Icons.image_outlined, color: Colors.grey.shade400), + ), + height: heightx, + width: widthx, + fit: fitx, + ); + } + + return GestureDetector( + onTap: onTap, + child: ClipRRect( + borderRadius: BorderRadius.circular(borderRadius!), + child: customPhoto(height, width, BoxFit.fill, borderRadius), + ), + ); + } +} diff --git a/lib/presentation/components/loading/loading_overlay.dart b/lib/presentation/components/loading/loading_overlay.dart new file mode 100644 index 0000000..a711771 --- /dev/null +++ b/lib/presentation/components/loading/loading_overlay.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import '../../../common/theme/theme.dart'; + +class LoadingOverlay extends StatelessWidget { + const LoadingOverlay({super.key}); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 64, + height: 64, + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(AppValue.radius), + ), + child: SpinKitCircle(color: AppColor.primary, size: 32.0), + ), + ); + } +} diff --git a/lib/presentation/components/report/inventory_report.dart b/lib/presentation/components/report/inventory_report.dart new file mode 100644 index 0000000..3ad5771 --- /dev/null +++ b/lib/presentation/components/report/inventory_report.dart @@ -0,0 +1,547 @@ +import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; + +import '../../../common/utils/pdf_service.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../domain/outlet/outlet.dart'; + +class InventoryReport { + static final primaryColor = PdfColor.fromHex("36175e"); + + static Future previewPdf({ + required String searchDateFormatted, + required InventoryAnalytic inventory, + required Outlet outlet, + }) async { + final pdf = pw.Document(); + final ByteData dataImage = await rootBundle.load('assets/images/logo.png'); + final Uint8List bytes = dataImage.buffer.asUint8List(); + + final image = pw.MemoryImage(bytes); + pdf.addPage( + pw.MultiPage( + pageFormat: PdfPageFormat.a4, + margin: pw.EdgeInsets.zero, + build: (pw.Context context) { + return [ + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + // Bagian kiri - Logo dan Info Perusahaan + pw.Row( + crossAxisAlignment: pw.CrossAxisAlignment.center, + children: [ + // Icon/Logo placeholder (bisa diganti dengan gambar logo) + pw.Container( + width: 40, + height: 40, + child: pw.Image(image), + ), + pw.SizedBox(width: 15), + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + pw.Text( + 'Apskel', + style: pw.TextStyle( + fontSize: 28, + fontWeight: pw.FontWeight.bold, + color: primaryColor, + ), + ), + pw.SizedBox(height: 4), + pw.Text( + outlet.name, + style: pw.TextStyle( + fontSize: 16, + color: PdfColors.grey700, + ), + ), + pw.SizedBox(height: 2), + pw.Text( + outlet.address, + style: pw.TextStyle( + fontSize: 12, + color: PdfColors.grey600, + ), + ), + ], + ), + ], + ), + // Bagian kanan - Info Laporan + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.end, + children: [ + pw.Text( + 'Laporan Transaksi', + style: pw.TextStyle( + fontSize: 24, + fontWeight: pw.FontWeight.bold, + color: PdfColors.grey800, + ), + ), + pw.SizedBox(height: 8), + pw.Text( + searchDateFormatted, + style: pw.TextStyle( + fontSize: 14, + color: PdfColors.grey600, + ), + ), + pw.SizedBox(height: 4), + pw.Text( + 'Laporan', + style: pw.TextStyle( + fontSize: 12, + color: PdfColors.grey500, + ), + ), + ], + ), + ], + ), + ), + pw.Container( + width: double.infinity, + height: 3, + color: primaryColor, + ), + + // Summary + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('1. Ringkasan'), + pw.SizedBox(height: 30), + pw.Row( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + pw.Expanded( + flex: 1, + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSummaryItem( + 'Total Item', + (inventory.summary.totalProducts).toString(), + ), + _buildSummaryItem( + 'Total Item Masuk', + (inventory.products.fold( + 0, + (sum, item) => sum + (item.totalIn), + )).toString(), + ), + _buildSummaryItem( + 'Total Item Keluar', + (inventory.products.fold( + 0, + (sum, item) => sum + (item.totalOut), + )).toString(), + ), + ], + ), + ), + pw.SizedBox(width: 20), + pw.Expanded( + flex: 1, + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSummaryItem( + 'Total Ingredient', + (inventory.summary.totalIngredients).toString(), + ), + _buildSummaryItem( + 'Total Ingredient Masuk', + (inventory.ingredients.fold( + 0, + (sum, item) => sum + (item.totalIn), + )).toString(), + ), + _buildSummaryItem( + 'Total Ingredient Keluar', + (inventory.ingredients.fold( + 0, + (sum, item) => sum + (item.totalOut), + )).toString(), + ), + ], + ), + ), + ], + ), + ], + ), + ), + + // Summary Item + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + children: [ + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('2. Item'), + pw.SizedBox(height: 30), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + topLeft: pw.Radius.circular(8), + topRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(2), // Kategori + 2: pw.FlexColumnWidth(1), // Stock + 3: pw.FlexColumnWidth(2), // Masuk + 4: pw.FlexColumnWidth(2), // Keluar + }, + children: [ + pw.TableRow( + children: [ + _buildHeaderCell('Nama'), + _buildHeaderCell('Kategori'), + _buildHeaderCell('Stock'), + _buildHeaderCell('Masuk'), + _buildHeaderCell('Keluar'), + ], + ), + ], + ), + ), + pw.Container( + decoration: pw.BoxDecoration(color: PdfColors.white), + child: pw.Table( + columnWidths: { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(2), // Kategori + 2: pw.FlexColumnWidth(1), // Stock + 3: pw.FlexColumnWidth(2), // Masuk + 4: pw.FlexColumnWidth(2), // Keluar + }, + children: inventory.products + .map( + (item) => _buildProductDataRow( + item, + inventory.products.indexOf(item) % 2 == 0, + ), + ) + .toList(), + ), + ), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + bottomLeft: pw.Radius.circular(8), + bottomRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(2), // Kategori + 2: pw.FlexColumnWidth(1), // Stock + 3: pw.FlexColumnWidth(2), // Masuk + 4: pw.FlexColumnWidth(2), // Keluar + }, + children: [ + pw.TableRow( + children: [ + _buildTotalCell('TOTAL'), + _buildTotalCell(''), + _buildTotalCell( + (inventory.products.fold( + 0, + (sum, item) => sum + (item.quantity), + )).toString(), + ), + _buildTotalCell( + (inventory.products.fold( + 0, + (sum, item) => sum + (item.totalIn), + )).toString(), + ), + _buildTotalCell( + (inventory.products.fold( + 0, + (sum, item) => sum + (item.totalOut), + )).toString(), + ), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + + // Summary Ingredient + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + children: [ + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('3. Ingredient'), + pw.SizedBox(height: 30), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + topLeft: pw.Radius.circular(8), + topRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Name + 1: pw.FlexColumnWidth(1), // Stock + 2: pw.FlexColumnWidth(2), // Masuk + 3: pw.FlexColumnWidth(2), // Keluar + }, + children: [ + pw.TableRow( + children: [ + _buildHeaderCell('Nama'), + _buildHeaderCell('Stock'), + _buildHeaderCell('Masuk'), + _buildHeaderCell('Keluar'), + ], + ), + ], + ), + ), + pw.Container( + decoration: pw.BoxDecoration(color: PdfColors.white), + child: pw.Table( + columnWidths: { + 0: pw.FlexColumnWidth(2.5), // Name + 1: pw.FlexColumnWidth(1), // Stock + 2: pw.FlexColumnWidth(2), // Masuk + 3: pw.FlexColumnWidth(2), // Keluar + }, + children: inventory.ingredients + .map( + (item) => _buildIngredientsDataRow( + item, + inventory.ingredients.indexOf(item) % 2 == 0, + ), + ) + .toList(), + ), + ), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + bottomLeft: pw.Radius.circular(8), + bottomRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Name + 1: pw.FlexColumnWidth(1), // Stock + 2: pw.FlexColumnWidth(2), // Masuk + 3: pw.FlexColumnWidth(2), // Keluar + }, + children: [ + pw.TableRow( + children: [ + _buildTotalCell('TOTAL'), + _buildTotalCell( + (inventory.ingredients.fold( + 0, + (sum, item) => sum + (item.quantity), + )).toString(), + ), + _buildTotalCell( + (inventory.ingredients.fold( + 0, + (sum, item) => sum + (item.totalIn), + )).toString(), + ), + _buildTotalCell( + (inventory.ingredients.fold( + 0, + (sum, item) => sum + (item.totalOut), + )).toString(), + ), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + ]; + }, + ), + ); + + return HelperPdfService.saveDocument( + name: + 'Apskel POS | Inventory Report | ${DateTime.now().millisecondsSinceEpoch}.pdf', + pdf: pdf, + ); + } + + static pw.Widget _buildSectionWidget(String title) { + return pw.Text( + title, + style: pw.TextStyle( + fontSize: 20, + fontWeight: pw.FontWeight.bold, + color: primaryColor, + ), + ); + } + + static pw.Widget _buildSummaryItem( + String label, + String value, { + pw.TextStyle? valueStyle, + pw.TextStyle? labelStyle, + }) { + return pw.Container( + padding: pw.EdgeInsets.only(bottom: 8), + margin: pw.EdgeInsets.only(bottom: 16), + decoration: pw.BoxDecoration( + border: pw.Border(bottom: pw.BorderSide(color: PdfColors.grey300)), + ), + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text(label, style: labelStyle), + pw.Text( + value, + style: valueStyle ?? pw.TextStyle(fontWeight: pw.FontWeight.bold), + ), + ], + ), + ); + } + + static pw.Widget _buildHeaderCell(String text) { + return pw.Container( + padding: pw.EdgeInsets.symmetric(horizontal: 12, vertical: 16), + child: pw.Text( + text, + style: pw.TextStyle( + color: PdfColors.white, + fontWeight: pw.FontWeight.bold, + fontSize: 12, + ), + textAlign: pw.TextAlign.center, + ), + ); + } + + static pw.Widget _buildDataCell( + String text, { + pw.Alignment alignment = pw.Alignment.center, + PdfColor? textColor, + }) { + return pw.Container( + padding: pw.EdgeInsets.symmetric(horizontal: 12, vertical: 16), + alignment: alignment, + child: pw.Text( + text, + style: pw.TextStyle( + fontSize: 12, + color: textColor ?? PdfColors.black, + fontWeight: pw.FontWeight.normal, + ), + textAlign: alignment == pw.Alignment.centerLeft + ? pw.TextAlign.left + : pw.TextAlign.center, + ), + ); + } + + static pw.Widget _buildTotalCell(String text) { + return pw.Container( + padding: pw.EdgeInsets.symmetric(horizontal: 12, vertical: 16), + child: pw.Text( + text, + style: pw.TextStyle( + color: PdfColors.white, + fontWeight: pw.FontWeight.bold, + fontSize: 12, + ), + textAlign: pw.TextAlign.center, + ), + ); + } + + static pw.TableRow _buildProductDataRow( + InventoryProduct product, + bool isEven, + ) { + return pw.TableRow( + decoration: pw.BoxDecoration( + color: product.isZeroStock + ? PdfColors.red100 + : product.isLowStock + ? PdfColors.yellow100 + : isEven + ? PdfColors.grey50 + : PdfColors.white, + ), + children: [ + _buildDataCell(product.productName, alignment: pw.Alignment.centerLeft), + _buildDataCell( + product.categoryName, + alignment: pw.Alignment.centerLeft, + ), + _buildDataCell(product.quantity.toString()), + _buildDataCell(product.totalIn.toString()), + _buildDataCell(product.totalOut.toString()), + ], + ); + } + + static pw.TableRow _buildIngredientsDataRow( + InventoryIngredient item, + bool isEven, + ) { + return pw.TableRow( + decoration: pw.BoxDecoration( + color: item.isZeroStock + ? PdfColors.red100 + : item.isLowStock + ? PdfColors.yellow100 + : isEven + ? PdfColors.grey50 + : PdfColors.white, + ), + children: [ + _buildDataCell(item.ingredientName, alignment: pw.Alignment.centerLeft), + _buildDataCell(item.quantity.toString()), + _buildDataCell(item.totalIn.toString()), + _buildDataCell(item.totalOut.toString()), + ], + ); + } +} diff --git a/lib/presentation/components/report/transaction_report.dart b/lib/presentation/components/report/transaction_report.dart new file mode 100644 index 0000000..fcc3e82 --- /dev/null +++ b/lib/presentation/components/report/transaction_report.dart @@ -0,0 +1,956 @@ +import 'dart:io'; + +import 'package:flutter/services.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pw; + +import '../../../common/extension/extension.dart'; +import '../../../common/utils/pdf_service.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../domain/outlet/outlet.dart'; + +class TransactionReport { + static final primaryColor = PdfColor.fromHex("36175e"); + + static Future previewPdf({ + required Outlet outlet, + required String searchDateFormatted, + required CategoryAnalytic categoryAnalyticData, + required ProfitLossAnalytic profitLossData, + required PaymentMethodAnalytic paymentMethodAnalyticData, + required ProductAnalytic productAnalyticData, + }) async { + final pdf = pw.Document(); + final ByteData dataImage = await rootBundle.load('assets/images/logo.png'); + final Uint8List bytes = dataImage.buffer.asUint8List(); + + final profitLossProductSummary = { + 'totalRevenue': profitLossData.productData.fold( + 0, + (sum, item) => sum + (item.revenue), + ), + 'totalCost': profitLossData.productData.fold( + 0, + (sum, item) => sum + (item.cost), + ), + 'totalGrossProfit': profitLossData.productData.fold( + 0, + (sum, item) => sum + (item.grossProfit), + ), + 'totalQuantity': profitLossData.productData.fold( + 0, + (sum, item) => sum + (item.quantitySold), + ), + }; + + final categorySummary = { + 'totalRevenue': categoryAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.totalRevenue), + ), + 'orderCount': categoryAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.orderCount), + ), + 'productCount': categoryAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.productCount), + ), + 'totalQuantity': categoryAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.totalQuantity), + ), + }; + + final productItemSummary = { + 'totalRevenue': productAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.revenue), + ), + 'orderCount': productAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.orderCount), + ), + 'totalQuantitySold': productAnalyticData.data.fold( + 0, + (sum, item) => sum + (item.quantitySold), + ), + }; + + // Membuat objek Image dari gambar + final image = pw.MemoryImage(bytes); + pdf.addPage( + pw.MultiPage( + pageFormat: PdfPageFormat.a4, + margin: pw.EdgeInsets.zero, + build: (pw.Context context) { + return [ + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + // Bagian kiri - Logo dan Info Perusahaan + pw.Row( + crossAxisAlignment: pw.CrossAxisAlignment.center, + children: [ + // Icon/Logo placeholder (bisa diganti dengan gambar logo) + pw.Container( + width: 40, + height: 40, + child: pw.Image(image), + ), + pw.SizedBox(width: 15), + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + pw.Text( + 'Apskel', + style: pw.TextStyle( + fontSize: 28, + fontWeight: pw.FontWeight.bold, + color: primaryColor, + ), + ), + pw.SizedBox(height: 4), + pw.Text( + outlet.name, + style: pw.TextStyle( + fontSize: 16, + color: PdfColors.grey700, + ), + ), + pw.SizedBox(height: 2), + pw.Text( + outlet.address, + style: pw.TextStyle( + fontSize: 12, + color: PdfColors.grey600, + ), + ), + ], + ), + ], + ), + // Bagian kanan - Info Laporan + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.end, + children: [ + pw.Text( + 'Laporan Transaksi', + style: pw.TextStyle( + fontSize: 24, + fontWeight: pw.FontWeight.bold, + color: PdfColors.grey800, + ), + ), + pw.SizedBox(height: 8), + pw.Text( + searchDateFormatted, + style: pw.TextStyle( + fontSize: 14, + color: PdfColors.grey600, + ), + ), + pw.SizedBox(height: 4), + pw.Text( + 'Laporan', + style: pw.TextStyle( + fontSize: 12, + color: PdfColors.grey500, + ), + ), + ], + ), + ], + ), + ), + pw.Container( + width: double.infinity, + height: 3, + color: primaryColor, + ), + + // Summary + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('1. Ringkasan'), + pw.SizedBox(height: 30), + pw.Row( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + pw.Expanded( + flex: 1, + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSummaryItem( + 'Total Penjualan (termasuk rasik)', + (profitLossData.summary.totalRevenue) + .toString() + .currencyFormatRpV2, + ), + _buildSummaryItem( + 'Total Terjual', + (profitLossData.summary.totalOrders).toString(), + ), + _buildSummaryItem( + 'HPP', + '${safeCurrency(profitLossData.summary.totalCost)} | ${safePercentage(profitLossData.summary.totalCost, profitLossData.summary.totalRevenue)}', + ), + _buildSummaryItem( + 'Laba Kotor', + '${safeCurrency(profitLossData.summary.grossProfit)} | ${safeRound(profitLossData.summary.grossProfitMargin)}%', + valueStyle: pw.TextStyle( + color: PdfColors.green800, + fontWeight: pw.FontWeight.bold, + fontSize: 16, + ), + labelStyle: pw.TextStyle( + color: PdfColors.green800, + fontWeight: pw.FontWeight.bold, + fontSize: 16, + ), + ), + ], + ), + ), + pw.SizedBox(width: 20), + pw.Expanded( + flex: 1, + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSummaryItem( + 'Biaya Lain lain', + '${safeCurrency(profitLossData.summary.totalTax)} | ${safePercentage(profitLossData.summary.totalTax, profitLossData.summary.totalRevenue)}', + ), + _buildSummaryItem( + 'Laba/Rugi', + '${safeCurrency(profitLossData.summary.netProfit)} | ${safeRound(profitLossData.summary.netProfitMargin)}%', + valueStyle: pw.TextStyle( + color: PdfColors.blue800, + fontWeight: pw.FontWeight.bold, + fontSize: 16, + ), + labelStyle: pw.TextStyle( + color: PdfColors.blue800, + fontWeight: pw.FontWeight.bold, + fontSize: 16, + ), + ), + ], + ), + ), + ], + ), + pw.SizedBox(height: 16), + pw.Text( + "Laba Rugi Perproduk", + style: pw.TextStyle( + fontSize: 16, + fontWeight: pw.FontWeight.bold, + color: primaryColor, + ), + ), + pw.SizedBox(height: 20), + pw.Column( + children: [ + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + topLeft: pw.Radius.circular(8), + topRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(1), // Qty + 2: pw.FlexColumnWidth(2.5), // Pendapatan + 3: pw.FlexColumnWidth(2), // HPP + 4: pw.FlexColumnWidth(2), // Laba Kotor + 5: pw.FlexColumnWidth(2), // Margin (%) + }, + children: [ + pw.TableRow( + children: [ + _buildHeaderCell('Produk'), + _buildHeaderCell('Qty'), + _buildHeaderCell('Pendapatan'), + _buildHeaderCell('HPP'), + _buildHeaderCell('Laba Kotor'), + _buildHeaderCell('Margin (%)'), + ], + ), + ], + ), + ), + pw.Container( + decoration: pw.BoxDecoration(color: PdfColors.white), + child: pw.Table( + columnWidths: { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(1), // Qty + 2: pw.FlexColumnWidth(2.5), // Pendapatan + 3: pw.FlexColumnWidth(2), // HPP + 4: pw.FlexColumnWidth(2), // Laba Kotor + 5: pw.FlexColumnWidth(2), // Margin (%) + }, + children: profitLossData.productData + .map( + (profitLoss) => _buildPerProductDataRow( + product: profitLoss.productName, + qty: profitLoss.quantitySold.toString(), + pendapatan: profitLoss.revenue + .toString() + .currencyFormatRpV2, + hpp: profitLoss.cost + .toString() + .currencyFormatRpV2, + labaKotor: profitLoss.grossProfit + .toString() + .currencyFormatRpV2, + margin: + '${safeRound(profitLoss.grossProfitMargin)}%', + isEven: + profitLossData.productData.indexOf( + profitLoss, + ) % + 2 == + 0, + ), + ) + .toList(), + ), + ), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + bottomLeft: pw.Radius.circular(8), + bottomRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(1), // Qty + 2: pw.FlexColumnWidth(2.5), // Pendapatan + 3: pw.FlexColumnWidth(2), // HPP + 4: pw.FlexColumnWidth(2), // Laba Kotor + 5: pw.FlexColumnWidth(2), // Margin (%) + }, + children: [ + pw.TableRow( + children: [ + _buildTotalCell('TOTAL'), + _buildTotalCell( + profitLossProductSummary['totalQuantity'] + .toString(), + ), + _buildTotalCell( + profitLossProductSummary['totalRevenue'] + .toString() + .currencyFormatRpV2, + ), + _buildTotalCell( + profitLossProductSummary['totalCost'] + .toString() + .currencyFormatRpV2, + ), + _buildTotalCell( + profitLossProductSummary['totalGrossProfit'] + .toString() + .currencyFormatRpV2, + ), + _buildTotalCell(''), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + + // Summary Payment Method + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + children: [ + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('2. Ringkasan Metode Pembayaran'), + pw.SizedBox(height: 30), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + topLeft: pw.Radius.circular(8), + topRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Nama + 1: pw.FlexColumnWidth(1), // Tipe + 2: pw.FlexColumnWidth(2.5), // Jumlah Order + 3: pw.FlexColumnWidth(2), // Total Amount + 4: pw.FlexColumnWidth(2), // Presentase + }, + children: [ + pw.TableRow( + children: [ + _buildHeaderCell('Nama'), + _buildHeaderCell('Tipe'), + _buildHeaderCell('Jumlah Order'), + _buildHeaderCell('Total Amount'), + _buildHeaderCell('Presentase'), + ], + ), + ], + ), + ), + pw.Container( + decoration: pw.BoxDecoration(color: PdfColors.white), + child: pw.Table( + columnWidths: { + 0: pw.FlexColumnWidth(2.5), // Nama + 1: pw.FlexColumnWidth(1), // Tipe + 2: pw.FlexColumnWidth(2.5), // Jumlah Order + 3: pw.FlexColumnWidth(2), // Total Amount + 4: pw.FlexColumnWidth(2), // Presentase + }, + children: paymentMethodAnalyticData.data + .map( + (payment) => _buildPaymentMethodDataRow( + name: payment.paymentMethodName, + tipe: payment.paymentMethodType.toTitleCase, + jumlahOrder: payment.orderCount.toString(), + totalAmount: payment.totalAmount + .toString() + .currencyFormatRpV2, + presentase: + '${safeRound(payment.percentage)}%', + isEven: + paymentMethodAnalyticData.data.indexOf( + payment, + ) % + 2 == + 0, + ), + ) + .toList(), + ), + ), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + bottomLeft: pw.Radius.circular(8), + bottomRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(1), // Qty + 2: pw.FlexColumnWidth(2.5), // Pendapatan + 3: pw.FlexColumnWidth(2), // HPP + 4: pw.FlexColumnWidth(2), // Laba Kotor + 5: pw.FlexColumnWidth(2), // Margin (%) + }, + children: [ + pw.TableRow( + children: [ + _buildTotalCell('TOTAL'), + _buildTotalCell(''), + _buildTotalCell( + (paymentMethodAnalyticData + .summary + .totalOrders) + .toString(), + ), + _buildTotalCell( + (paymentMethodAnalyticData + .summary + .totalAmount) + .toString() + .currencyFormatRpV2, + ), + _buildTotalCell(''), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + + // Summary Category + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('3. Ringkasan Kategori'), + pw.SizedBox(height: 30), + pw.Column( + children: [ + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + topLeft: pw.Radius.circular(8), + topRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Nama + 1: pw.FlexColumnWidth(2), // Total Product + 2: pw.FlexColumnWidth(1), // qty + 3: pw.FlexColumnWidth(2), // Jumlah Order + 4: pw.FlexColumnWidth(2.5), // Presentase + }, + children: [ + pw.TableRow( + children: [ + _buildHeaderCell('Nama'), + _buildHeaderCell('Total Produk'), + _buildHeaderCell('Qty'), + _buildHeaderCell('Jumlah Order'), + _buildHeaderCell('Pendapatan'), + ], + ), + ], + ), + ), + pw.Container( + decoration: pw.BoxDecoration(color: PdfColors.white), + child: pw.Table( + columnWidths: { + 0: pw.FlexColumnWidth(2.5), // Nama + 1: pw.FlexColumnWidth(2), // Total Product + 2: pw.FlexColumnWidth(1), // qty + 3: pw.FlexColumnWidth(2), // Jumlah Order + 4: pw.FlexColumnWidth(2.5), // Presentase + }, + children: categoryAnalyticData.data + .map( + (category) => _buildCategoryDataRow( + name: category.categoryName, + totalProduct: category.productCount + .toString(), + qty: category.totalQuantity.toString(), + jumlahOrder: category.orderCount.toString(), + pendapatan: category.totalRevenue + .toString() + .currencyFormatRpV2, + isEven: + categoryAnalyticData.data.indexOf( + category, + ) % + 2 == + 0, + ), + ) + .toList(), + ), + ), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + bottomLeft: pw.Radius.circular(8), + bottomRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Nama + 1: pw.FlexColumnWidth(2), // Total Product + 2: pw.FlexColumnWidth(1), // qty + 3: pw.FlexColumnWidth(2), // Jumlah Order + 4: pw.FlexColumnWidth(2.5), // Presentase + }, + children: [ + pw.TableRow( + children: [ + _buildTotalCell('TOTAL'), + _buildTotalCell( + categorySummary['productCount'].toString(), + ), + _buildTotalCell( + categorySummary['totalQuantity'].toString(), + ), + _buildTotalCell( + categorySummary['orderCount'].toString(), + ), + _buildTotalCell( + categorySummary['totalRevenue'] + .toString() + .currencyFormatRpV2, + ), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + + // Summary Item + pw.Container( + padding: pw.EdgeInsets.all(20), + child: pw.Column( + children: [ + pw.Column( + crossAxisAlignment: pw.CrossAxisAlignment.start, + children: [ + _buildSectionWidget('4. Ringkasan Item'), + pw.SizedBox(height: 30), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + topLeft: pw.Radius.circular(8), + topRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(2), // Kategori + 2: pw.FlexColumnWidth(1), // qty + 3: pw.FlexColumnWidth(2), // Order + 4: pw.FlexColumnWidth(2), // Pendapatan + 5: pw.FlexColumnWidth(2), // Average + }, + children: [ + pw.TableRow( + children: [ + _buildHeaderCell('Produk'), + _buildHeaderCell('Kategori'), + _buildHeaderCell('Qty'), + _buildHeaderCell('Order'), + _buildHeaderCell('Pendapatan'), + _buildHeaderCell('Rata Rata'), + ], + ), + ], + ), + ), + pw.Container( + decoration: pw.BoxDecoration(color: PdfColors.white), + child: pw.Table( + columnWidths: { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(2), // Kategori + 2: pw.FlexColumnWidth(1), // qty + 3: pw.FlexColumnWidth(2), // Order + 4: pw.FlexColumnWidth(2), // Pendapatan + 5: pw.FlexColumnWidth(2), // Average + }, + children: productAnalyticData.data + .map( + (item) => _buildItemDataRow( + product: item.productName, + category: item.categoryName, + qty: item.quantitySold.toString(), + order: item.orderCount.toString(), + pendapatan: item.revenue + .toString() + .currencyFormatRpV2, + average: safeCurrency( + item.averagePrice.round(), + ), + isEven: + productAnalyticData.data.indexOf(item) % + 2 == + 0, + ), + ) + .toList(), + ), + ), + pw.Container( + decoration: pw.BoxDecoration( + color: primaryColor, // Purple color + borderRadius: pw.BorderRadius.only( + bottomLeft: pw.Radius.circular(8), + bottomRight: pw.Radius.circular(8), + ), + ), + child: pw.Table( + columnWidths: const { + 0: pw.FlexColumnWidth(2.5), // Produk + 1: pw.FlexColumnWidth(2), // Kategori + 2: pw.FlexColumnWidth(1), // qty + 3: pw.FlexColumnWidth(2), // Order + 4: pw.FlexColumnWidth(2), // Pendapatan + 5: pw.FlexColumnWidth(2), // Average + }, + children: [ + pw.TableRow( + children: [ + _buildTotalCell('TOTAL'), + _buildTotalCell(''), + _buildTotalCell( + productItemSummary['totalQuantitySold'] + .toString(), + ), + _buildTotalCell( + productItemSummary['orderCount'].toString(), + ), + _buildTotalCell( + productItemSummary['totalRevenue'] + .toString() + .currencyFormatRpV2, + ), + _buildTotalCell(''), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + ]; + }, + ), + ); + + return HelperPdfService.saveDocument( + name: 'Laporan Transaksi | $searchDateFormatted.pdf', + pdf: pdf, + ); + } + + static String safePercentage(num numerator, num denominator) { + if (denominator == 0 || + numerator.isInfinite || + numerator.isNaN || + denominator.isInfinite || + denominator.isNaN) { + return '0%'; + } + final result = (numerator / denominator) * 100; + if (result.isInfinite || result.isNaN) { + return '0%'; + } + return '${result.round()}%'; + } + + static String safeRound(num value) { + if (value.isInfinite || value.isNaN) { + return '0'; + } + return value.round().toString(); + } + + static String safeCurrency(num value) { + if (value.isInfinite || value.isNaN) { + return '0'.currencyFormatRpV2; + } + return value.toString().currencyFormatRpV2; + } + + static pw.Widget _buildSectionWidget(String title) { + return pw.Text( + title, + style: pw.TextStyle( + fontSize: 20, + fontWeight: pw.FontWeight.bold, + color: primaryColor, + ), + ); + } + + static pw.Widget _buildSummaryItem( + String label, + String value, { + pw.TextStyle? valueStyle, + pw.TextStyle? labelStyle, + }) { + return pw.Container( + padding: pw.EdgeInsets.only(bottom: 8), + margin: pw.EdgeInsets.only(bottom: 16), + decoration: pw.BoxDecoration( + border: pw.Border(bottom: pw.BorderSide(color: PdfColors.grey300)), + ), + child: pw.Row( + mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, + children: [ + pw.Text(label, style: labelStyle), + pw.Text( + value, + style: valueStyle ?? pw.TextStyle(fontWeight: pw.FontWeight.bold), + ), + ], + ), + ); + } + + static pw.Widget _buildHeaderCell(String text) { + return pw.Container( + padding: pw.EdgeInsets.symmetric(horizontal: 12, vertical: 16), + child: pw.Text( + text, + style: pw.TextStyle( + color: PdfColors.white, + fontWeight: pw.FontWeight.bold, + fontSize: 12, + ), + textAlign: pw.TextAlign.center, + ), + ); + } + + static pw.Widget _buildDataCell( + String text, { + pw.Alignment alignment = pw.Alignment.center, + PdfColor? textColor, + }) { + return pw.Container( + padding: pw.EdgeInsets.symmetric(horizontal: 12, vertical: 16), + alignment: alignment, + child: pw.Text( + text, + style: pw.TextStyle( + fontSize: 12, + color: textColor ?? PdfColors.black, + fontWeight: pw.FontWeight.normal, + ), + textAlign: alignment == pw.Alignment.centerLeft + ? pw.TextAlign.left + : pw.TextAlign.center, + ), + ); + } + + static pw.Widget _buildTotalCell(String text) { + return pw.Container( + padding: pw.EdgeInsets.symmetric(horizontal: 12, vertical: 16), + child: pw.Text( + text, + style: pw.TextStyle( + color: PdfColors.white, + fontWeight: pw.FontWeight.bold, + fontSize: 12, + ), + textAlign: pw.TextAlign.center, + ), + ); + } + + static pw.TableRow _buildPerProductDataRow({ + required String product, + required String qty, + required String pendapatan, + required String hpp, + required String labaKotor, + required String margin, + required bool isEven, + }) { + return pw.TableRow( + decoration: pw.BoxDecoration( + color: isEven ? PdfColors.grey50 : PdfColors.white, + ), + children: [ + _buildDataCell(product, alignment: pw.Alignment.centerLeft), + _buildDataCell(qty), + _buildDataCell(pendapatan), + _buildDataCell(hpp, textColor: PdfColors.red600), + _buildDataCell(labaKotor, textColor: PdfColors.green600), + _buildDataCell(margin), + ], + ); + } + + static pw.TableRow _buildPaymentMethodDataRow({ + required String name, + required String tipe, + required String jumlahOrder, + required String totalAmount, + required String presentase, + required bool isEven, + }) { + return pw.TableRow( + decoration: pw.BoxDecoration( + color: isEven ? PdfColors.grey50 : PdfColors.white, + ), + children: [ + _buildDataCell(name, alignment: pw.Alignment.centerLeft), + _buildDataCell(tipe), + _buildDataCell(jumlahOrder), + _buildDataCell(totalAmount), + _buildDataCell(presentase), + ], + ); + } + + static pw.TableRow _buildCategoryDataRow({ + required String name, + required String totalProduct, + required String qty, + required String jumlahOrder, + required String pendapatan, + required bool isEven, + }) { + return pw.TableRow( + decoration: pw.BoxDecoration( + color: isEven ? PdfColors.grey50 : PdfColors.white, + ), + children: [ + _buildDataCell(name, alignment: pw.Alignment.centerLeft), + _buildDataCell(totalProduct), + _buildDataCell(qty), + _buildDataCell(jumlahOrder), + _buildDataCell(pendapatan), + ], + ); + } + + static pw.TableRow _buildItemDataRow({ + required String product, + required String category, + required String qty, + required String order, + required String pendapatan, + required String average, + required bool isEven, + }) { + return pw.TableRow( + decoration: pw.BoxDecoration( + color: isEven ? PdfColors.grey50 : PdfColors.white, + ), + children: [ + _buildDataCell(product, alignment: pw.Alignment.centerLeft), + _buildDataCell(category, alignment: pw.Alignment.centerLeft), + _buildDataCell(qty), + _buildDataCell(order), + _buildDataCell(pendapatan), + _buildDataCell(average), + ], + ); + } +} diff --git a/lib/presentation/components/spacer/spacer.dart b/lib/presentation/components/spacer/spacer.dart new file mode 100644 index 0000000..3732df0 --- /dev/null +++ b/lib/presentation/components/spacer/spacer.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +class SpaceHeight extends StatelessWidget { + const SpaceHeight(this.height, {super.key}); + + final double height; + + @override + Widget build(BuildContext context) { + return SizedBox(height: height); + } +} + +class SpaceWidth extends StatelessWidget { + const SpaceWidth(this.width, {super.key}); + + final double width; + + @override + Widget build(BuildContext context) { + return SizedBox(width: width); + } +} diff --git a/lib/presentation/components/toast/flushbar.dart b/lib/presentation/components/toast/flushbar.dart new file mode 100644 index 0000000..1f8ff86 --- /dev/null +++ b/lib/presentation/components/toast/flushbar.dart @@ -0,0 +1,66 @@ +import 'package:another_flushbar/flushbar.dart'; +import 'package:flutter/material.dart'; + +import '../../../common/theme/theme.dart'; +import '../../../domain/auth/auth.dart'; +import '../../../domain/user/user.dart'; + +class AppFlushbar { + static void showSuccess(BuildContext context, String message) { + Flushbar( + messageText: Text( + message, + style: AppStyle.lg.copyWith( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + icon: const Icon(Icons.check_circle, color: Colors.white), + duration: const Duration(seconds: 2), + flushbarPosition: FlushbarPosition.BOTTOM, + backgroundColor: AppColor.secondary, + borderRadius: BorderRadius.circular(12), + margin: const EdgeInsets.all(12), + ).show(context); + } + + static void showError(BuildContext context, String message) { + Flushbar( + messageText: Text( + message, + style: AppStyle.lg.copyWith( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + icon: const Icon(Icons.error, color: Colors.white), + duration: const Duration(seconds: 3), + flushbarPosition: FlushbarPosition.BOTTOM, + backgroundColor: AppColor.error, + borderRadius: BorderRadius.circular(12), + margin: const EdgeInsets.all(12), + ).show(context); + } + + static void showAuthFailureToast(BuildContext context, AuthFailure failure) => + showError( + context, + failure.map( + serverError: (value) => value.failure.toStringFormatted(context), + dynamicErrorMessage: (value) => value.erroMessage, + unexpectedError: (value) => 'Error has eccoured', + ), + ); + + static void showUserFailureToast(BuildContext context, UserFailure failure) => + showError( + context, + failure.map( + serverError: (value) => value.failure.toStringFormatted(context), + dynamicErrorMessage: (value) => value.erroMessage, + unexpectedError: (value) => 'Error has eccoured', + empty: (value) => 'Data not found', + ), + ); +} diff --git a/lib/presentation/components/widgets/empty_search_widget.dart b/lib/presentation/components/widgets/empty_search_widget.dart new file mode 100644 index 0000000..298cc7b --- /dev/null +++ b/lib/presentation/components/widgets/empty_search_widget.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +import '../../../common/theme/theme.dart'; +import 'empty_widget.dart'; + +class EmptySearchWidget extends StatelessWidget { + final String? searchQuery; + final VoidCallback? onClear; + + const EmptySearchWidget({Key? key, this.searchQuery, this.onClear}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return EmptyWidget( + title: 'Pencarian Tidak Ditemukan', + message: searchQuery != null + ? 'Tidak ada hasil untuk "$searchQuery"\nCoba kata kunci lain' + : 'Coba gunakan kata kunci yang berbeda', + emptyIcon: Icons.search_off_rounded, + iconColor: AppColor.warning, + buttonText: 'Hapus Filter', + onRefresh: onClear, + showButton: onClear != null, + ); + } +} diff --git a/lib/presentation/components/widgets/empty_widget.dart b/lib/presentation/components/widgets/empty_widget.dart new file mode 100644 index 0000000..6d9a997 --- /dev/null +++ b/lib/presentation/components/widgets/empty_widget.dart @@ -0,0 +1,179 @@ +// ==================== EMPTY WIDGET ==================== +import 'package:flutter/material.dart'; + +import '../../../common/theme/theme.dart'; + +class EmptyWidget extends StatefulWidget { + final String? title; + final String? message; + final VoidCallback? onRefresh; + final IconData? emptyIcon; + final String? buttonText; + final double? width; + final double? height; + final bool showButton; + final EdgeInsets? padding; + final Color? iconColor; + + const EmptyWidget({ + super.key, + this.title, + this.message, + this.onRefresh, + this.emptyIcon, + this.buttonText, + this.width, + this.height, + this.showButton = true, + this.padding, + this.iconColor, + }); + + @override + State createState() => _EmptyWidgetState(); +} + +class _EmptyWidgetState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + + @override + void initState() { + super.initState(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0.0, 0.3), end: Offset.zero).animate( + CurvedAnimation( + parent: _animationController, + curve: Curves.easeOutCubic, + ), + ); + + _animationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: widget.width, + height: widget.height, + padding: widget.padding ?? const EdgeInsets.all(24), + child: FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + // Empty Illustration + Stack( + alignment: Alignment.center, + children: [ + // Background Circle + Container( + width: 120, + height: 120, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.05), + AppColor.secondary.withOpacity(0.05), + ], + ), + ), + ), + + // Icon Container + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.surface, + border: Border.all(color: AppColor.border, width: 2), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.08), + blurRadius: 20, + offset: const Offset(0, 4), + ), + ], + ), + child: Icon( + widget.emptyIcon ?? Icons.inbox_outlined, + size: 40, + color: widget.iconColor ?? AppColor.textLight, + ), + ), + ], + ), + + const SizedBox(height: 24), + + // Title + Text( + widget.title ?? 'Tidak Ada Data', + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + textAlign: TextAlign.center, + ), + + const SizedBox(height: 8), + + // Message + Text( + widget.message ?? 'Belum ada data untuk ditampilkan', + style: AppStyle.md.copyWith( + color: AppColor.textSecondary, + height: 1.4, + ), + textAlign: TextAlign.center, + ), + + // Action Button + if (widget.showButton && widget.onRefresh != null) ...[ + const SizedBox(height: 24), + OutlinedButton.icon( + onPressed: widget.onRefresh, + icon: const Icon(Icons.refresh_rounded, size: 18), + label: Text(widget.buttonText ?? 'Muat Ulang'), + style: OutlinedButton.styleFrom( + foregroundColor: AppColor.primary, + side: BorderSide(color: AppColor.primary, width: 1.5), + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ], + ], + ), + ), + ), + ); + } +} diff --git a/lib/presentation/components/widgets/error_widget.dart b/lib/presentation/components/widgets/error_widget.dart new file mode 100644 index 0000000..8a2ee20 --- /dev/null +++ b/lib/presentation/components/widgets/error_widget.dart @@ -0,0 +1,176 @@ +import 'package:flutter/material.dart'; + +import '../../../common/theme/theme.dart'; + +class ErrorWidget extends StatefulWidget { + final String? title; + final String? message; + final VoidCallback? onRetry; + final String? errorCode; + final IconData? errorIcon; + final double? width; + final double? height; + final bool showRetryButton; + final EdgeInsets? padding; + + const ErrorWidget({ + super.key, + this.title, + this.message, + this.onRetry, + this.errorCode, + this.errorIcon, + this.width, + this.height, + this.showRetryButton = true, + this.padding, + }); + + @override + State createState() => _ErrorWidgetState(); +} + +class _ErrorWidgetState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _fadeAnimation; + late Animation _scaleAnimation; + + @override + void initState() { + super.initState(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 600), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), + ); + + _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( + CurvedAnimation(parent: _animationController, curve: Curves.elasticOut), + ); + + _animationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + width: widget.width, + height: widget.height, + padding: widget.padding ?? const EdgeInsets.all(24), + child: FadeTransition( + opacity: _fadeAnimation, + child: ScaleTransition( + scale: _scaleAnimation, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + // Error Icon + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + colors: [ + AppColor.error.withOpacity(0.1), + AppColor.warning.withOpacity(0.1), + ], + ), + border: Border.all( + color: AppColor.error.withOpacity(0.2), + width: 2, + ), + ), + child: Icon( + widget.errorIcon ?? Icons.error_outline_rounded, + size: 40, + color: AppColor.error, + ), + ), + + const SizedBox(height: 16), + + // Title + if (widget.title != null) + Text( + widget.title!, + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + textAlign: TextAlign.center, + ), + + const SizedBox(height: 8), + + // Message + Text( + widget.message ?? 'Terjadi kesalahan tidak terduga', + style: AppStyle.md.copyWith( + color: AppColor.textSecondary, + height: 1.4, + ), + textAlign: TextAlign.center, + ), + + // Error Code + if (widget.errorCode != null) ...[ + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.error.withOpacity(0.2)), + ), + child: Text( + 'Error: ${widget.errorCode}', + style: AppStyle.xs.copyWith( + color: AppColor.error, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + + // Retry Button + if (widget.showRetryButton && widget.onRetry != null) ...[ + const SizedBox(height: 20), + ElevatedButton.icon( + onPressed: widget.onRetry, + icon: const Icon(Icons.refresh_rounded, size: 18), + label: const Text('Coba Lagi'), + style: ElevatedButton.styleFrom( + backgroundColor: AppColor.primary, + foregroundColor: AppColor.textWhite, + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 12, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ], + ], + ), + ), + ), + ); + } +} diff --git a/lib/presentation/components/widgets/particle_card.dart b/lib/presentation/components/widgets/particle_card.dart new file mode 100644 index 0000000..fd810f5 --- /dev/null +++ b/lib/presentation/components/widgets/particle_card.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; + +import '../../../common/painter/wave_painter.dart'; +import '../../../common/theme/theme.dart'; + +class ParticleCard extends StatelessWidget { + /// Content yang ditampilkan di atas particle background + final Widget child; + + /// Gradient background card. Default pakai primaryGradient + final List? gradientColors; + + /// Arah gradient. Default topLeft → bottomRight + final AlignmentGeometry gradientBegin; + final AlignmentGeometry gradientEnd; + + /// Border radius card. Default 16 + final double borderRadius; + + /// Padding konten. Default 16 semua sisi + final EdgeInsetsGeometry? padding; + + /// Height card. Null = wrap content + final double? height; + + /// Opacity particle & wave. Default 1.0 + final double decorationOpacity; + + const ParticleCard({ + super.key, + required this.child, + this.gradientColors, + this.gradientBegin = Alignment.topLeft, + this.gradientEnd = Alignment.bottomRight, + this.borderRadius = 16, + this.padding, + this.height, + this.decorationOpacity = 1.0, + }); + + @override + Widget build(BuildContext context) { + final colors = gradientColors ?? AppColor.primaryGradient; + + return ClipRRect( + borderRadius: BorderRadius.circular(borderRadius), + child: Container( + height: height, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(borderRadius), + gradient: LinearGradient( + colors: colors, + begin: gradientBegin, + end: gradientEnd, + ), + boxShadow: [ + BoxShadow( + color: colors.first.withOpacity(0.35), + blurRadius: 16, + offset: const Offset(0, 6), + ), + ], + ), + child: Stack( + children: [ + // --- Decorative background --- + Opacity( + opacity: decorationOpacity, + child: Stack( + children: [ + // Circles kanan atas + Positioned( + top: -24, + right: -24, + child: _circle(120, AppColor.white, 0.10), + ), + Positioned( + top: 28, + right: 16, + child: _circle(60, AppColor.white, 0.06), + ), + Positioned( + top: 70, + right: -10, + child: _circle(36, AppColor.white, 0.08), + ), + + // Circles kiri bawah + Positioned( + bottom: -20, + left: -20, + child: _circle(90, AppColor.white, 0.06), + ), + Positioned( + bottom: 20, + left: 40, + child: _circle(40, AppColor.white, 0.04), + ), + + // Sparkle icons + ..._sparkles(context), + + // Wave pattern + Positioned.fill( + child: CustomPaint( + painter: WavePainter( + animation: 0.0, + color: AppColor.white.withOpacity(0.08), + ), + ), + ), + + // Radial gradient overlay + Container( + decoration: BoxDecoration( + gradient: RadialGradient( + center: const Alignment(0.7, -0.5), + radius: 1.4, + colors: [ + Colors.white.withOpacity(0.06), + Colors.transparent, + ], + ), + ), + ), + ], + ), + ), + + // --- Content --- + Padding( + padding: padding ?? const EdgeInsets.all(16), + child: child, + ), + ], + ), + ), + ); + } + + Widget _circle(double size, Color color, double opacity) { + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: color.withOpacity(opacity), + ), + ); + } + + List _sparkles(BuildContext context) { + final width = MediaQuery.of(context).size.width; + return List.generate(5, (i) { + return Positioned( + left: (i * 70.0) % (width - 20), + top: 10 + (i * 18.0), + child: Icon( + Icons.auto_awesome, + size: 8 + (i % 3) * 3.0, + color: AppColor.white.withOpacity(0.18), + ), + ); + }); + } +} diff --git a/lib/presentation/pages/about_app/about_app_page.dart b/lib/presentation/pages/about_app/about_app_page.dart new file mode 100644 index 0000000..9b42104 --- /dev/null +++ b/lib/presentation/pages/about_app/about_app_page.dart @@ -0,0 +1,337 @@ +import 'package:flutter/material.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:device_info_plus/device_info_plus.dart'; + +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../components/assets/assets.gen.dart'; + +@RoutePage() +class AboutAppPage extends StatefulWidget { + const AboutAppPage({super.key}); + + @override + State createState() => _AboutAppPageState(); +} + +class _AboutAppPageState extends State + with TickerProviderStateMixin { + PackageInfo? packageInfo; + String deviceInfo = ''; + late AnimationController _fadeController; + late AnimationController _slideController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + + @override + void initState() { + super.initState(); + _initAnimations(); + _loadAppInfo(); + } + + void _initAnimations() { + _fadeController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + _slideController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.elasticOut), + ); + + _fadeController.forward(); + Future.delayed(const Duration(milliseconds: 300), () { + _slideController.forward(); + }); + } + + Future _loadAppInfo() async { + try { + final info = await PackageInfo.fromPlatform(); + final deviceInfoPlugin = DeviceInfoPlugin(); + String device = ''; + + if (Theme.of(context).platform == TargetPlatform.android) { + final androidInfo = await deviceInfoPlugin.androidInfo; + device = '${androidInfo.brand} ${androidInfo.model}'; + } else if (Theme.of(context).platform == TargetPlatform.iOS) { + final iosInfo = await deviceInfoPlugin.iosInfo; + device = '${iosInfo.name} ${iosInfo.model}'; + } + + setState(() { + packageInfo = info; + deviceInfo = device; + }); + } catch (e) { + print('Error loading app info: $e'); + } + } + + @override + void dispose() { + _fadeController.dispose(); + _slideController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [_buildSliverAppBar(), _buildContent()], + ), + ); + } + + Widget _buildSliverAppBar() { + return SliverAppBar( + expandedHeight: 280.0, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + flexibleSpace: FlexibleSpaceBar( + title: AnimatedBuilder( + animation: _fadeAnimation, + builder: (context, child) { + return Opacity( + opacity: _fadeAnimation.value, + child: Text( + context.lang.about_app, + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ); + }, + ), + background: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: AppColor.primaryGradient, + ), + ), + child: Stack( + children: [ + // Background pattern + Positioned.fill(child: CustomPaint(painter: _PatternPainter())), + // App icon and version + Center( + child: FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 100, + height: 100, + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.2), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Assets.images.logo.image(), + ), + ), + const SizedBox(height: 16), + Text( + packageInfo?.appName ?? 'My App', + style: AppStyle.h4.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(20), + ), + child: Text( + 'v${packageInfo?.version ?? '1.0.0'}', + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: AppColor.white), + onPressed: () => context.router.back(), + ), + ); + } + + Widget _buildContent() { + return SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: Container( + color: AppColor.background, + child: Column( + children: [_buildAppInfoSection(), const SizedBox(height: 40)], + ), + ), + ), + ); + } + + Widget _buildAppInfoSection() { + return Container( + margin: const EdgeInsets.all(20), + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + Icons.info_outline, + color: AppColor.primary, + size: 24, + ), + ), + const SizedBox(width: 16), + Text( + context.lang.app_information, + style: AppStyle.h6.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + ], + ), + const SizedBox(height: 20), + _buildInfoRow( + context.lang.app_name, + packageInfo?.appName ?? 'Loading...', + ), + _buildInfoRow( + context.lang.version, + packageInfo?.version ?? 'Loading...', + ), + _buildInfoRow( + context.lang.build_number, + packageInfo?.buildNumber ?? 'Loading...', + ), + _buildInfoRow( + context.lang.package_name, + packageInfo?.packageName ?? 'Loading...', + ), + _buildInfoRow( + context.lang.device, + deviceInfo.isEmpty ? 'Loading...' : deviceInfo, + ), + ], + ), + ); + } + + Widget _buildInfoRow(String label, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 120, + child: Text( + label, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textSecondary, + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: Text( + value, + style: AppStyle.md.copyWith(color: AppColor.textPrimary), + ), + ), + ], + ), + ); + } +} + +class _PatternPainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = AppColor.white.withOpacity(0.1) + ..strokeWidth = 1 + ..style = PaintingStyle.stroke; + + // Create geometric pattern + for (int i = 0; i < 20; i++) { + for (int j = 0; j < 20; j++) { + final x = (size.width / 20) * i; + final y = (size.height / 20) * j; + + if ((i + j) % 3 == 0) { + canvas.drawCircle(Offset(x, y), 3, paint); + } + } + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/lib/presentation/pages/auth/login/login_page.dart b/lib/presentation/pages/auth/login/login_page.dart new file mode 100644 index 0000000..76b5e2a --- /dev/null +++ b/lib/presentation/pages/auth/login/login_page.dart @@ -0,0 +1,396 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'dart:math' as math; + +import '../../../../application/auth/auth_bloc.dart'; +import '../../../../application/auth/login_form/login_form_bloc.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../injection.dart'; +import '../../../components/button/button.dart'; +import '../../../components/spacer/spacer.dart'; +import '../../../components/toast/flushbar.dart'; +import '../../../router/app_router.gr.dart'; +import 'widgets/email_field.dart'; +import 'widgets/password_field.dart'; + +@RoutePage() +class LoginPage extends StatefulWidget implements AutoRouteWrapper { + const LoginPage({super.key}); + + @override + State createState() => _LoginPageState(); + + @override + Widget wrappedRoute(BuildContext context) => + BlocProvider(create: (_) => getIt(), child: this); +} + +class _LoginPageState extends State with TickerProviderStateMixin { + late AnimationController _fadeController; + late AnimationController _slideController; + late AnimationController _backgroundController; + late AnimationController _floatingController; + + late Animation _fadeAnimation; + late Animation _slideAnimation; + late Animation _backgroundAnimation; + late Animation _floatingAnimation; + + @override + void initState() { + super.initState(); + + _fadeController = AnimationController( + duration: const Duration(milliseconds: 1500), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _backgroundController = AnimationController( + duration: const Duration(seconds: 10), + vsync: this, + )..repeat(); + + _floatingController = AnimationController( + duration: const Duration(seconds: 6), + vsync: this, + )..repeat(reverse: true); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), + ); + + _backgroundAnimation = Tween( + begin: 0.0, + end: 2 * math.pi, + ).animate(_backgroundController); + + _floatingAnimation = Tween(begin: -20.0, end: 20.0).animate( + CurvedAnimation(parent: _floatingController, curve: Curves.easeInOut), + ); + + _fadeController.forward(); + _slideController.forward(); + } + + @override + void dispose() { + _fadeController.dispose(); + _slideController.dispose(); + _backgroundController.dispose(); + _floatingController.dispose(); + super.dispose(); + } + + Future _handleLogin() async { + context.read().add(LoginFormEvent.submitted()); + } + + @override + Widget build(BuildContext context) { + return BlocListener( + listenWhen: (previous, current) => + previous.failureOrAuthOption != current.failureOrAuthOption, + listener: (context, state) { + state.failureOrAuthOption.fold( + () => null, + (either) => either.fold( + (f) => AppFlushbar.showAuthFailureToast(context, f), + (user) { + if (context.mounted) { + context.read().add(AuthEvent.fetchCurrentUser()); + context.router.replace(const MainRoute()); + } + }, + ), + ); + }, + child: Scaffold( + body: AnimatedBuilder( + animation: Listenable.merge([ + _backgroundController, + _floatingController, + ]), + builder: (context, child) { + return Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: AppColor.primaryGradient, + ), + ), + child: Stack( + children: [ + // Animated background elements + _buildAnimatedBackground(), + + // Main content + SafeArea( + child: Center( + child: SingleChildScrollView( + padding: EdgeInsets.symmetric( + horizontal: AppValue.padding, + ), + child: FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: BlocBuilder( + builder: (context, state) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildLogo(context), + SpaceHeight(48), + _buildLoginCard( + context, + state.isSubmitting, + state.showErrorMessages, + ), + ], + ); + }, + ), + ), + ), + ), + ), + ), + ], + ), + ); + }, + ), + ), + ); + } + + Widget _buildAnimatedBackground() { + return Stack( + children: [ + // Floating circles + ...List.generate(6, (index) { + final double size = 80 + (index * 40); + final double left = + (index * 60.0) % MediaQuery.of(context).size.width; + final double top = + (index * 120.0) % MediaQuery.of(context).size.height; + + return Positioned( + left: left + math.sin(_backgroundAnimation.value + index) * 30, + top: top + _floatingAnimation.value + (index * 10), + child: Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white.withOpacity(0.1), + border: Border.all( + color: Colors.white.withOpacity(0.2), + width: 2, + ), + ), + ), + ); + }), + + // Rotating geometric shapes + Positioned( + top: 100, + right: 50, + child: Transform.rotate( + angle: _backgroundAnimation.value, + child: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.08), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: Colors.white.withOpacity(0.15), + width: 1, + ), + ), + ), + ), + ), + + Positioned( + bottom: 150, + left: 30, + child: Transform.rotate( + angle: -_backgroundAnimation.value * 0.5, + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.06), + shape: BoxShape.circle, + border: Border.all( + color: Colors.white.withOpacity(0.12), + width: 1, + ), + ), + ), + ), + ), + + // Floating particles + ...List.generate(8, (index) { + return Positioned( + left: (index * 45.0) % MediaQuery.of(context).size.width, + top: (index * 80.0) % MediaQuery.of(context).size.height, + child: Transform.translate( + offset: Offset( + math.sin(_backgroundAnimation.value + index * 0.5) * 20, + math.cos(_backgroundAnimation.value + index * 0.3) * 15, + ), + child: Container( + width: 4 + (index % 3) * 2, + height: 4 + (index % 3) * 2, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white.withOpacity(0.3), + ), + ), + ), + ); + }), + + // Gradient overlay for better text readability + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + Colors.black.withOpacity(0.1), + Colors.transparent, + ], + ), + ), + ), + ], + ); + } + + Widget _buildLogo(BuildContext context) { + return Column( + children: [ + Text( + context.lang.login_header, + style: AppStyle.h1.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.white, + shadows: [ + Shadow( + offset: const Offset(0, 2), + blurRadius: 10, + color: Colors.black.withOpacity(0.3), + ), + ], + ), + textAlign: TextAlign.center, + ), + const SpaceHeight(8), + Text( + context.lang.login_desc, + style: AppStyle.lg.copyWith( + color: AppColor.textLight, + shadows: [ + Shadow( + offset: const Offset(0, 1), + blurRadius: 5, + color: Colors.black.withOpacity(0.2), + ), + ], + ), + ), + ], + ); + } + + Widget _buildLoginCard( + BuildContext context, + bool isLoading, + bool showErrorMessages, + ) { + return Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 24), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.15), + blurRadius: 40, + offset: const Offset(0, 20), + spreadRadius: 0, + ), + BoxShadow( + color: AppColor.black.withOpacity(0.1), + blurRadius: 10, + offset: const Offset(0, 5), + spreadRadius: 0, + ), + ], + ), + child: Form( + autovalidateMode: showErrorMessages + ? AutovalidateMode.always + : AutovalidateMode.disabled, + + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + LoginEmailField(), + const SpaceHeight(24), + LoginPasswordField(), + const SpaceHeight(16), + _buildForgetPassword(context), + const SpaceHeight(32), + _buildLoginButton(isLoading), + ], + ), + ), + ); + } + + Widget _buildForgetPassword(BuildContext context) { + return Align( + alignment: Alignment.centerRight, + child: GestureDetector( + onTap: () {}, + child: Text( + '${context.lang.forgot_password}?', + style: AppStyle.md.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w600, + ), + ), + ), + ); + } + + Widget _buildLoginButton(bool isLoading) { + return AppElevatedButton( + text: context.lang.sign_in, + isLoading: isLoading, + onPressed: _handleLogin, + ); + } +} diff --git a/lib/presentation/pages/auth/login/widgets/email_field.dart b/lib/presentation/pages/auth/login/widgets/email_field.dart new file mode 100644 index 0000000..0c041b6 --- /dev/null +++ b/lib/presentation/pages/auth/login/widgets/email_field.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../../application/auth/login_form/login_form_bloc.dart'; +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/validator/validator.dart'; +import '../../../../components/field/field.dart'; + +class LoginEmailField extends StatelessWidget { + const LoginEmailField({super.key}); + + @override + Widget build(BuildContext context) { + return AppTextFormField( + title: context.lang.email, + hintText: context.lang.email_placeholder, + prefixIcon: LineIcons.envelope, + validator: (value) => + AppValidator.validateEmail(context.read().state.email), + onChanged: (value) => + context.read().add(LoginFormEvent.emailChanged(value)), + ); + } +} diff --git a/lib/presentation/pages/auth/login/widgets/password_field.dart b/lib/presentation/pages/auth/login/widgets/password_field.dart new file mode 100644 index 0000000..5ddab86 --- /dev/null +++ b/lib/presentation/pages/auth/login/widgets/password_field.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../../application/auth/login_form/login_form_bloc.dart'; +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/validator/validator.dart'; +import '../../../../components/field/field.dart'; + +class LoginPasswordField extends StatelessWidget { + const LoginPasswordField({super.key}); + + @override + Widget build(BuildContext context) { + return AppPasswordTextFormField( + title: context.lang.password, + prefixIcon: LineIcons.lock, + hintText: context.lang.password_placeholder, + validator: (value) => AppValidator.validatePassword( + context.read().state.password, + ), + onChanged: (value) => context.read().add( + LoginFormEvent.passwordChanged(value), + ), + ); + } +} diff --git a/lib/presentation/pages/coming_soon/coming_soon_page.dart b/lib/presentation/pages/coming_soon/coming_soon_page.dart new file mode 100644 index 0000000..8e309b1 --- /dev/null +++ b/lib/presentation/pages/coming_soon/coming_soon_page.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; +import 'package:auto_route/auto_route.dart'; + +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; + +@RoutePage() +class ComingSoonPage extends StatefulWidget { + const ComingSoonPage({super.key}); + + @override + State createState() => _ComingSoonPageState(); +} + +class _ComingSoonPageState extends State + with TickerProviderStateMixin { + late AnimationController _fadeController; + late AnimationController _slideController; + late AnimationController _pulseController; + + late Animation _fadeAnimation; + late Animation _slideAnimation; + late Animation _pulseAnimation; + + @override + void initState() { + super.initState(); + + // Initialize animation controllers + _fadeController = AnimationController( + duration: const Duration(milliseconds: 1500), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _pulseController = AnimationController( + duration: const Duration(milliseconds: 2000), + vsync: this, + ); + + // Initialize animations + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.5), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), + ); + + _pulseAnimation = Tween(begin: 1.0, end: 1.1).animate( + CurvedAnimation(parent: _pulseController, curve: Curves.easeInOut), + ); + + // Start animations + _startAnimations(); + } + + void _startAnimations() { + _fadeController.forward(); + _slideController.forward(); + _pulseController.repeat(reverse: true); + } + + @override + void dispose() { + _fadeController.dispose(); + _slideController.dispose(); + _pulseController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppColor.primary, + AppColor.primaryLight, + AppColor.primaryDark, + ], + stops: const [0.0, 0.5, 1.0], + ), + ), + child: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Animated Logo/Icon + FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: _buildAnimatedLogo(), + ), + ), + + const SizedBox(height: 40), + + // Coming Soon Text + FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Text( + context.lang.coming_soon, + style: AppStyle.h1.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + fontSize: 42, + letterSpacing: 2.0, + ), + textAlign: TextAlign.center, + ), + ), + ), + + const SizedBox(height: 16), + + // Subtitle + FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Text( + context.lang.coming_soon_desc, + style: AppStyle.lg.copyWith( + color: AppColor.textWhite.withOpacity(0.9), + height: 1.5, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + Widget _buildAnimatedLogo() { + return AnimatedBuilder( + animation: _pulseAnimation, + builder: (context, child) { + return Transform.scale( + scale: _pulseAnimation.value, + child: Container( + width: 120, + height: 120, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + colors: [AppColor.secondary, AppColor.secondaryLight], + ), + boxShadow: [ + BoxShadow( + color: AppColor.secondary.withOpacity(0.3), + blurRadius: 30, + spreadRadius: 5, + ), + ], + ), + child: Icon( + Icons.rocket_launch, + size: 60, + color: AppColor.textWhite, + ), + ), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/customer/customer_page.dart b/lib/presentation/pages/customer/customer_page.dart new file mode 100644 index 0000000..a1e4e5f --- /dev/null +++ b/lib/presentation/pages/customer/customer_page.dart @@ -0,0 +1,161 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../application/customer/customer_loader/customer_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../domain/customer/customer.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import '../../components/button/button.dart'; +import 'widgets/customer_card.dart'; +import 'widgets/customer_tile.dart'; + +@RoutePage() +class CustomerPage extends StatefulWidget implements AutoRouteWrapper { + const CustomerPage({super.key}); + + @override + State createState() => _CustomerPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (context) => + getIt() + ..add(CustomerLoaderEvent.fetched(isRefresh: true)), + child: this, + ); +} + +class _CustomerPageState extends State + with TickerProviderStateMixin { + final TextEditingController _searchController = TextEditingController(); + final ScrollController _scrollController = ScrollController(); + bool _isGridView = false; + + @override + initState() { + super.initState(); + } + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: BlocBuilder( + builder: (context, state) { + return NotificationListener( + onNotification: (notification) { + if (notification is ScrollEndNotification && + _scrollController.position.extentAfter == 0) { + context.read().add( + CustomerLoaderEvent.fetched(), + ); + return true; + } + + return true; + }, + child: CustomScrollView( + controller: _scrollController, + slivers: [ + // SliverAppBar with gradient + SliverAppBar( + expandedHeight: 120.0, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.customer), + actions: [ + ActionIconButton(onTap: () {}, icon: LineIcons.search), + ], + ), + + // Search and Filter Section + SliverToBoxAdapter( + child: Container( + color: AppColor.white, + child: Column( + children: [ + // View toggle and sort + Padding( + padding: EdgeInsets.only( + left: 16, + right: 16, + bottom: 0, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Row( + children: [ + IconButton( + icon: Icon( + _isGridView + ? Icons.list + : Icons.grid_view, + color: AppColor.primary, + ), + onPressed: () { + setState(() { + _isGridView = !_isGridView; + }); + }, + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + + // Customer List + _isGridView + ? _buildCustomerGrid(state.customers) + : _buildCustomerList(state.customers), + ], + ), + ); + }, + ), + ); + } + + Widget _buildCustomerList(List customers) { + return SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + final customer = customers[index]; + return CustomerTile(customer: customer); + }, childCount: customers.length), + ); + } + + Widget _buildCustomerGrid(List customers) { + return SliverPadding( + padding: EdgeInsets.all(16), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 16, + mainAxisSpacing: 16, + childAspectRatio: 0.65, + ), + delegate: SliverChildBuilderDelegate((context, index) { + final customer = customers[index]; + return CustomerCard(customer: customer); + }, childCount: customers.length), + ), + ); + } +} diff --git a/lib/presentation/pages/customer/widgets/appbar.dart b/lib/presentation/pages/customer/widgets/appbar.dart new file mode 100644 index 0000000..cb95b3c --- /dev/null +++ b/lib/presentation/pages/customer/widgets/appbar.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class CustomerAppbar extends StatelessWidget { + final Animation rotationAnimation; + const CustomerAppbar({super.key, required this.rotationAnimation}); + + @override + Widget build(BuildContext context) { + return FlexibleSpaceBar( + titlePadding: const EdgeInsets.only(left: 50, bottom: 16), + title: Text( + 'Customer', + style: AppStyle.xl.copyWith( + color: AppColor.textWhite, + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + background: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: Stack( + children: [ + Positioned( + right: -20, + top: -20, + child: AnimatedBuilder( + animation: rotationAnimation, + builder: (context, child) { + return Transform.rotate( + angle: rotationAnimation.value, + child: Container( + width: 100, + height: 100, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.1), + ), + ), + ); + }, + ), + ), + Positioned( + left: -30, + bottom: -30, + child: AnimatedBuilder( + animation: rotationAnimation, + builder: (context, child) { + return Transform.rotate( + angle: -rotationAnimation.value * 0.5, + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.05), + ), + ), + ); + }, + ), + ), + Positioned( + right: 80, + bottom: 30, + child: AnimatedBuilder( + animation: rotationAnimation, + builder: (context, child) { + return Transform.rotate( + angle: -rotationAnimation.value * 0.2, + child: Container( + width: 40, + height: 40, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: AppColor.white.withOpacity(0.08), + ), + ), + ); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/pages/customer/widgets/customer_card.dart b/lib/presentation/pages/customer/widgets/customer_card.dart new file mode 100644 index 0000000..cb512ae --- /dev/null +++ b/lib/presentation/pages/customer/widgets/customer_card.dart @@ -0,0 +1,319 @@ +import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/customer/customer.dart'; +import '../../../components/spacer/spacer.dart'; + +class CustomerCard extends StatelessWidget { + final Customer customer; + final VoidCallback? onTap; + final VoidCallback? onLongPress; + + const CustomerCard({ + super.key, + required this.customer, + this.onTap, + this.onLongPress, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.06), + blurRadius: 20, + offset: const Offset(0, 6), + spreadRadius: -4, + ), + ], + border: Border.all( + color: customer.isActive + ? AppColor.primary.withOpacity(0.1) + : Colors.grey.withOpacity(0.08), + width: 1.5, + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + onLongPress: onLongPress, + borderRadius: BorderRadius.circular(20), + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Avatar with status indicator + Stack( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + _getAvatarColor(customer.name), + _getAvatarColor(customer.name).withOpacity(0.8), + ], + ), + boxShadow: [ + BoxShadow( + color: _getAvatarColor( + customer.name, + ).withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: 32, + child: Text( + customer.name.isNotEmpty + ? customer.name[0].toUpperCase() + : '?', + style: AppStyle.xxl.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + + // Status indicator + Positioned( + bottom: 2, + right: 2, + child: Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: customer.isActive + ? AppColor.success + : AppColor.error, + shape: BoxShape.circle, + border: Border.all(color: AppColor.white, width: 3), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + ), + ), + + // Default badge + if (customer.isDefault) + Positioned( + top: -2, + left: -8, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 2, + ), + decoration: BoxDecoration( + color: AppColor.primary, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Text( + '⭐', + style: AppStyle.xs.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + + const SpaceHeight(16), + + // Customer Name + Text( + customer.name.isNotEmpty ? customer.name : 'Unknown Customer', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + + const SpaceHeight(8), + + // Contact Info + if (customer.email.isNotEmpty || customer.phone.isNotEmpty) ...[ + Column( + children: [ + if (customer.email.isNotEmpty) + _buildContactInfo(Icons.email_outlined, customer.email), + if (customer.email.isNotEmpty && + customer.phone.isNotEmpty) + const SpaceHeight(4), + if (customer.phone.isNotEmpty) + _buildContactInfo(Icons.phone_outlined, customer.phone), + ], + ), + const SpaceHeight(12), + ], + + // Metadata info + if (customer.metadata.isNotEmpty && _hasRelevantMetadata()) ...[ + const SpaceHeight(8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.star_outline, + size: 12, + color: AppColor.primary, + ), + const SpaceWidth(4), + Text( + _getMetadataInfo(), + style: AppStyle.xs.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ], + + // Join date + if (customer.createdAt.isNotEmpty) ...[ + const SpaceHeight(8), + Text( + '${context.lang.joined} ${_formatDate(context, customer.createdAt)}', + style: AppStyle.xs.copyWith(color: AppColor.textSecondary), + textAlign: TextAlign.center, + ), + ], + ], + ), + ), + ), + ), + ); + } + + Widget _buildContactInfo(IconData icon, String text) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 14, color: AppColor.textSecondary), + const SpaceWidth(6), + Flexible( + child: Text( + text, + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ); + } + + Color _getAvatarColor(String name) { + final colors = [ + AppColor.primary, + const Color(0xFF9C27B0), // Purple + const Color(0xFFFF9800), // Orange + const Color(0xFF607D8B), // Blue Grey + const Color(0xFF795548), // Brown + const Color(0xFF4CAF50), // Green + const Color(0xFF2196F3), // Blue + const Color(0xFFE91E63), // Pink + const Color(0xFF00BCD4), // Cyan + const Color(0xFFFF5722), // Deep Orange + ]; + + if (name.isEmpty) return AppColor.primary; + final index = name.hashCode.abs() % colors.length; + return colors[index]; + } + + String _formatDate(BuildContext context, String dateStr) { + try { + final date = DateTime.parse(dateStr); + final now = DateTime.now(); + final difference = now.difference(date).inDays; + + if (difference == 0) { + return 'today'; + } else if (difference == 1) { + return 'yesterday'; + } else if (difference < 30) { + return '${difference}d ${context.lang.ago}'; + } else if (difference < 365) { + final months = (difference / 30).floor(); + return '${months}mo ${context.lang.ago}'; + } else { + final years = (difference / 365).floor(); + return '${years}y ${context.lang.ago}'; + } + } catch (e) { + return dateStr; + } + } + + bool _hasRelevantMetadata() { + return customer.metadata.containsKey('notes') || + customer.metadata.containsKey('tags') || + customer.metadata.containsKey('source') || + customer.metadata.containsKey('preferences') || + customer.metadata.containsKey('vip') || + customer.metadata.containsKey('tier'); + } + + String _getMetadataInfo() { + if (customer.metadata.containsKey('vip') && + customer.metadata['vip'] == true) { + return 'VIP'; + } + if (customer.metadata.containsKey('tier')) { + return customer.metadata['tier'].toString(); + } + if (customer.metadata.containsKey('tags')) { + final tags = customer.metadata['tags']; + if (tags is List && tags.isNotEmpty) { + return tags.first.toString(); + } + } + if (customer.metadata.containsKey('source')) { + return customer.metadata['source'].toString(); + } + return 'Special'; + } +} diff --git a/lib/presentation/pages/customer/widgets/customer_tile.dart b/lib/presentation/pages/customer/widgets/customer_tile.dart new file mode 100644 index 0000000..eb7edd8 --- /dev/null +++ b/lib/presentation/pages/customer/widgets/customer_tile.dart @@ -0,0 +1,381 @@ +import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/customer/customer.dart'; +import '../../../components/spacer/spacer.dart'; + +class CustomerTile extends StatelessWidget { + final Customer customer; + final VoidCallback? onTap; + final VoidCallback? onEdit; + final VoidCallback? onDelete; + + const CustomerTile({ + super.key, + required this.customer, + this.onTap, + this.onEdit, + this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.06), + blurRadius: 16, + offset: const Offset(0, 4), + spreadRadius: -2, + ), + ], + border: Border.all( + color: customer.isActive + ? AppColor.primary.withOpacity(0.15) + : Colors.grey.withOpacity(0.1), + width: 1, + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header Row + Row( + children: [ + // Avatar + Stack( + children: [ + CircleAvatar( + radius: 26, + backgroundColor: _getAvatarColor(customer.name), + child: Text( + customer.name.isNotEmpty + ? customer.name[0].toUpperCase() + : '?', + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + // Status indicator + Positioned( + bottom: 2, + right: 2, + child: Container( + width: 16, + height: 16, + decoration: BoxDecoration( + color: customer.isActive + ? AppColor.success + : AppColor.error, + shape: BoxShape.circle, + border: Border.all( + color: AppColor.white, + width: 2, + ), + ), + ), + ), + ], + ), + const SpaceWidth(16), + + // Customer Info + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Name with badges + Row( + children: [ + Expanded( + child: Text( + customer.name.isNotEmpty + ? customer.name + : 'Unknown Customer', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + overflow: TextOverflow.ellipsis, + ), + ), + if (customer.isDefault) + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + 'DEFAULT', + style: AppStyle.xs.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.bold, + letterSpacing: 0.5, + ), + ), + ), + ], + ), + const SpaceHeight(4), + + // Contact info + if (customer.email.isNotEmpty) ...[ + Row( + children: [ + Icon( + Icons.email_outlined, + size: 16, + color: AppColor.textSecondary, + ), + const SpaceWidth(6), + Expanded( + child: Text( + customer.email, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SpaceHeight(4), + ], + + if (customer.phone.isNotEmpty) + Row( + children: [ + Icon( + Icons.phone_outlined, + size: 16, + color: AppColor.textSecondary, + ), + const SpaceWidth(6), + Text( + customer.phone, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + ], + ), + ), + ], + ), + + // Address section + if (customer.address.isNotEmpty) ...[ + const SpaceHeight(16), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + Icon( + Icons.location_on_outlined, + size: 18, + color: AppColor.textSecondary, + ), + const SpaceWidth(8), + Expanded( + child: Text( + customer.address, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ], + + // Footer with status and dates + const SpaceHeight(16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Status badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: customer.isActive + ? AppColor.success.withOpacity(0.1) + : AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: customer.isActive + ? AppColor.success + : AppColor.error, + shape: BoxShape.circle, + ), + ), + const SpaceWidth(6), + Text( + customer.isActive + ? context.lang.active + : context.lang.inactive, + style: AppStyle.sm.copyWith( + color: customer.isActive + ? AppColor.success + : AppColor.error, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + + // Created date + if (customer.createdAt.isNotEmpty) + Text( + '${context.lang.joined} ${_formatDate(context, customer.createdAt)}', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + + // Metadata section (if has any relevant data) + if (customer.metadata.isNotEmpty && _hasRelevantMetadata()) ...[ + const SpaceHeight(12), + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.05), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: AppColor.primary.withOpacity(0.1), + width: 1, + ), + ), + child: Row( + children: [ + Icon( + Icons.info_outline, + size: 16, + color: AppColor.primary, + ), + const SpaceWidth(8), + Expanded( + child: Text( + _getMetadataInfo(), + style: AppStyle.xs.copyWith( + color: AppColor.primary, + ), + ), + ), + ], + ), + ), + ], + ], + ), + ), + ), + ), + ); + } + + Color _getAvatarColor(String name) { + final colors = [ + AppColor.primary, + const Color(0xFF9C27B0), + const Color(0xFFFF9800), + const Color(0xFF607D8B), + const Color(0xFF795548), + const Color(0xFF4CAF50), + const Color(0xFF2196F3), + const Color(0xFFE91E63), + ]; + + final index = name.hashCode.abs() % colors.length; + return colors[index]; + } + + String _formatDate(BuildContext context, String dateStr) { + try { + final date = DateTime.parse(dateStr); + final now = DateTime.now(); + final difference = now.difference(date).inDays; + + if (difference == 0) { + return 'today'; + } else if (difference == 1) { + return 'yesterday'; + } else if (difference < 30) { + return '${difference}d ${context.lang.ago}'; + } else if (difference < 365) { + final months = (difference / 30).floor(); + return '${months}mo ${context.lang.ago}'; + } else { + final years = (difference / 365).floor(); + return '${years}y ${context.lang.ago}'; + } + } catch (e) { + return dateStr; + } + } + + bool _hasRelevantMetadata() { + return customer.metadata.containsKey('notes') || + customer.metadata.containsKey('tags') || + customer.metadata.containsKey('source') || + customer.metadata.containsKey('preferences'); + } + + String _getMetadataInfo() { + final info = []; + + if (customer.metadata.containsKey('notes')) { + info.add('Has notes'); + } + if (customer.metadata.containsKey('tags')) { + final tags = customer.metadata['tags']; + if (tags is List && tags.isNotEmpty) { + info.add('${tags.length} tags'); + } + } + if (customer.metadata.containsKey('source')) { + info.add('Source: ${customer.metadata['source']}'); + } + + return info.join(' • '); + } +} diff --git a/lib/presentation/pages/download/download_report_page.dart b/lib/presentation/pages/download/download_report_page.dart new file mode 100644 index 0000000..cbafb74 --- /dev/null +++ b/lib/presentation/pages/download/download_report_page.dart @@ -0,0 +1,564 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import '../../../application/report/inventory_report/inventory_report_bloc.dart'; +import '../../../application/report/transaction_report/transaction_report_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../common/utils/pdf_service.dart'; +import '../../../common/utils/permission.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import '../../components/field/date_range_picker_field.dart'; +import '../../components/report/inventory_report.dart'; +import '../../components/report/transaction_report.dart'; +import '../../components/toast/flushbar.dart'; + +@RoutePage() +class DownloadReportPage extends StatefulWidget implements AutoRouteWrapper { + const DownloadReportPage({super.key}); + + @override + State createState() => _DownloadReportPageState(); + + @override + Widget wrappedRoute(BuildContext context) => MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => + getIt() + ..add(InventoryReportEvent.fetchedOutlet()), + ), + BlocProvider( + create: (context) => + getIt() + ..add(TransactionReportEvent.fetchedOutlet()), + ), + ], + child: this, + ); +} + +class _DownloadReportPageState extends State + with TickerProviderStateMixin { + late AnimationController _fadeController; + late AnimationController _slideController; + late AnimationController _scaleController; + + late Animation _fadeAnimation; + + // Date range variables for each report type + DateTime? _transactionStartDate; + DateTime? _transactionEndDate; + DateTime? _inventoryStartDate; + DateTime? _inventoryEndDate; + // DateTime? _salesStartDate; + // DateTime? _salesEndDate; + // DateTime? _customerStartDate; + // DateTime? _customerEndDate; + + @override + void initState() { + super.initState(); + + // Initialize animation controllers + _fadeController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + + _scaleController = AnimationController( + duration: const Duration(milliseconds: 600), + vsync: this, + ); + + // Initialize animations + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + // Start animations + _fadeController.forward(); + _slideController.forward(); + _scaleController.forward(); + } + + @override + void dispose() { + _fadeController.dispose(); + _slideController.dispose(); + _scaleController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + slivers: [ + // SliverAppBar with gradient + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.download_report), + ), + + // Content + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + // Report Options + FadeTransition( + opacity: _fadeAnimation, + child: Column( + children: [ + // Transaction Report Card + BlocBuilder< + TransactionReportBloc, + TransactionReportState + >( + builder: (context, state) { + return _ReportOptionCard( + title: context.lang.transaction_report, + subtitle: context.lang.transaction_report_desc, + icon: Icons.receipt_long_outlined, + gradient: const [ + AppColor.primary, + AppColor.primaryLight, + ], + startDate: _transactionStartDate, + endDate: _transactionEndDate, + isLoading: state.isFetching, + onDateRangeChanged: (start, end) { + setState(() { + _transactionStartDate = start; + _transactionEndDate = end; + }); + if (start != null || end != null) { + context.read().add( + TransactionReportEvent.fetchedTransaction( + start!, + end!, + ), + ); + } + }, + onDownload: () async { + try { + final status = await PermessionHelper() + .checkPermission(); + if (status) { + final pdfFile = + await TransactionReport.previewPdf( + searchDateFormatted: + "${_transactionStartDate?.toServerDate} - ${_transactionEndDate?.toServerDate}", + outlet: state.outlet, + categoryAnalyticData: + state.categoryAnalytic, + profitLossData: + state.profitLossAnalytic, + paymentMethodAnalyticData: + state.paymentMethodAnalytic, + productAnalyticData: + state.productAnalytic, + ); + log("pdfFile: $pdfFile"); + await HelperPdfService.openFile(pdfFile); + } else { + AppFlushbar.showError( + context, + 'Storage permission is required to save PDF', + ); + } + } catch (e) { + log("Error generating PDF: $e"); + AppFlushbar.showError( + context, + 'Failed to generate PDF: $e', + ); + } + }, + delay: 200, + ); + }, + ), + + const SizedBox(height: 20), + + // Inventory Report Card + BlocBuilder( + builder: (context, state) { + return _ReportOptionCard( + title: context.lang.invetory_report, + subtitle: context.lang.invetory_report_desc, + icon: Icons.inventory_2_outlined, + gradient: const [ + AppColor.secondary, + AppColor.secondaryLight, + ], + startDate: _inventoryStartDate, + endDate: _inventoryEndDate, + isLoading: state.isFetching, + onDateRangeChanged: (start, end) { + setState(() { + _inventoryStartDate = start; + _inventoryEndDate = end; + }); + if (start != null || end != null) { + context.read().add( + InventoryReportEvent.fetchedInventory( + start!, + end!, + ), + ); + } + }, + onDownload: () async { + try { + final status = await PermessionHelper() + .checkPermission(); + if (status) { + final pdfFile = + await InventoryReport.previewPdf( + searchDateFormatted: + "${_inventoryStartDate?.toServerDate} - ${_inventoryEndDate?.toServerDate}", + inventory: state.inventoryAnalytic, + outlet: state.outlet, + ); + log("pdfFile: $pdfFile"); + await HelperPdfService.openFile(pdfFile); + } else { + AppFlushbar.showError( + context, + 'Storage permission is required to save PDF', + ); + } + } catch (e) { + log("Error generating PDF: $e"); + AppFlushbar.showError( + context, + 'Failed to generate PDF: $e', + ); + } + }, + delay: 400, + ); + }, + ), + + const SizedBox(height: 20), + + // Sales Report Card + // _ReportOptionCard( + // title: 'Sales Report', + // subtitle: 'Export sales performance and revenue data', + // icon: Icons.trending_up_outlined, + // gradient: const [AppColor.info, Color(0xFF64B5F6)], + // startDate: _salesStartDate, + // endDate: _salesEndDate, + // onDateRangeChanged: (start, end) { + // setState(() { + // _salesStartDate = start; + // _salesEndDate = end; + // }); + // }, + // onDownload: () => _downloadReport( + // 'Sales Report', + // _salesStartDate, + // _salesEndDate, + // ), + // delay: 600, + // ), + + // const SizedBox(height: 20), + + // // Customer Report Card + // _ReportOptionCard( + // title: 'Customer Report', + // subtitle: + // 'Export customer data and behavior analytics', + // icon: Icons.people_outline, + // gradient: const [AppColor.warning, Color(0xFFFFB74D)], + // startDate: _customerStartDate, + // endDate: _customerEndDate, + // onDateRangeChanged: (start, end) { + // setState(() { + // _customerStartDate = start; + // _customerEndDate = end; + // }); + // }, + // onDownload: () => _downloadReport( + // 'Customer Report', + // _customerStartDate, + // _customerEndDate, + // ), + // delay: 800, + // ), + ], + ), + ), + + const SizedBox(height: 40), + ], + ), + ), + ), + ], + ), + ); + } +} + +class _ReportOptionCard extends StatefulWidget { + final String title; + final String subtitle; + final IconData icon; + final List gradient; + final DateTime? startDate; + final DateTime? endDate; + final Function(DateTime? startDate, DateTime? endDate) onDateRangeChanged; + final VoidCallback onDownload; + final bool isLoading; + final int delay; + + const _ReportOptionCard({ + required this.title, + required this.subtitle, + required this.icon, + required this.gradient, + required this.startDate, + required this.endDate, + required this.onDateRangeChanged, + required this.onDownload, + required this.delay, + required this.isLoading, + }); + + @override + State<_ReportOptionCard> createState() => _ReportOptionCardState(); +} + +class _ReportOptionCardState extends State<_ReportOptionCard> + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _slideAnimation; + bool _isExpanded = false; + + @override + void initState() { + super.initState(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 300), + vsync: this, + ); + _slideAnimation = CurvedAnimation( + parent: _animationController, + curve: Curves.easeInOutCubic, + ); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + void _toggleExpanded() { + setState(() { + _isExpanded = !_isExpanded; + if (_isExpanded) { + _animationController.forward(); + } else { + _animationController.reverse(); + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: widget.gradient, + ), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: widget.gradient.first.withOpacity(0.3), + blurRadius: 15, + offset: const Offset(0, 8), + ), + ], + ), + child: Column( + children: [ + // Header Section + GestureDetector( + onTap: _toggleExpanded, + child: Container( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(16), + ), + child: Icon(widget.icon, color: AppColor.white, size: 32), + ), + const SizedBox(width: 20), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.title, + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + widget.subtitle, + style: AppStyle.sm.copyWith( + color: AppColor.white.withOpacity(0.8), + ), + ), + ], + ), + ), + AnimatedRotation( + turns: _isExpanded ? 0.25 : 0, + duration: const Duration(milliseconds: 300), + child: Icon( + Icons.arrow_forward_ios, + color: AppColor.white.withOpacity(0.8), + size: 20, + ), + ), + ], + ), + ), + ), + + // Expandable Content + SizeTransition( + sizeFactor: _slideAnimation, + child: Container( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 20), + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.select_date_range, + style: AppStyle.md.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 16), + + // Date Range Picker Field Style + DateRangePickerField( + placeholder: context.lang.select_date_range, + startDate: widget.startDate, + endDate: widget.endDate, + onChanged: widget.onDateRangeChanged, + ), + + const SizedBox(height: 20), + + // Download Button + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: + widget.startDate != null && + widget.endDate != null + ? widget.onDownload + : null, + style: ElevatedButton.styleFrom( + backgroundColor: AppColor.white, + foregroundColor: widget.gradient.first, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 0, + ), + child: widget.isLoading + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SpinKitCircle( + color: widget.gradient.first, + size: 24, + ), + const SizedBox(width: 8), + Text( + 'Loading', + style: AppStyle.md.copyWith( + color: widget.gradient.first, + fontWeight: FontWeight.bold, + ), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.download_rounded, + color: widget.gradient.first, + ), + const SizedBox(width: 8), + Text( + context.lang.download_report, + style: AppStyle.md.copyWith( + color: widget.gradient.first, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/error/error_page.dart b/lib/presentation/pages/error/error_page.dart new file mode 100644 index 0000000..0b648da --- /dev/null +++ b/lib/presentation/pages/error/error_page.dart @@ -0,0 +1,509 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../common/theme/theme.dart'; + +@RoutePage() +class ErrorPage extends StatefulWidget { + final String? title; + final String? message; + final VoidCallback? onRetry; + final VoidCallback? onBack; + final String? errorCode; + final IconData? errorIcon; + + const ErrorPage({ + Key? key, + this.title, + this.message, + this.onRetry, + this.onBack, + this.errorCode, + this.errorIcon, + }) : super(key: key); + + @override + State createState() => _ErrorPageState(); +} + +class _ErrorPageState extends State with TickerProviderStateMixin { + late AnimationController _bounceController; + late AnimationController _fadeController; + late AnimationController _slideController; + + late Animation _bounceAnimation; + late Animation _fadeAnimation; + late Animation _slideAnimation; + + @override + void initState() { + super.initState(); + + _bounceController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _fadeController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + + _bounceAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _bounceController, curve: Curves.elasticOut), + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0.0, 0.5), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), + ); + + // Start animations + _bounceController.forward(); + Future.delayed(const Duration(milliseconds: 300), () { + _fadeController.forward(); + }); + Future.delayed(const Duration(milliseconds: 500), () { + _slideController.forward(); + }); + } + + @override + void dispose() { + _bounceController.dispose(); + _fadeController.dispose(); + _slideController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppColor.primary.withOpacity(0.05), + AppColor.background, + AppColor.primaryLight.withOpacity(0.03), + ], + ), + ), + child: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 60), + + // Animated Error Illustration + AnimatedBuilder( + animation: _bounceAnimation, + builder: (context, child) { + return Transform.scale( + scale: _bounceAnimation.value, + child: Stack( + alignment: Alignment.center, + children: [ + // Outer glow circle + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: RadialGradient( + colors: [ + AppColor.error.withOpacity(0.1), + Colors.transparent, + ], + ), + ), + ), + + // Middle circle with gradient + Container( + width: 140, + height: 140, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + AppColor.error.withOpacity(0.15), + AppColor.warning.withOpacity(0.15), + AppColor.primary.withOpacity(0.1), + ], + ), + boxShadow: [ + BoxShadow( + color: AppColor.error.withOpacity(0.2), + blurRadius: 30, + offset: const Offset(0, 10), + ), + ], + ), + ), + + // Inner circle with icon + Container( + width: 100, + height: 100, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + colors: AppColor.primaryGradient, + ), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Icon( + widget.errorIcon ?? Icons.sentiment_dissatisfied, + size: 50, + color: AppColor.textWhite, + ), + ), + + // Decorative floating dots + ...List.generate(6, (index) { + final radius = 120.0; + return Positioned( + left: + 100 + + radius * + 0.8 * + (index.isEven ? 1 : -1) * + (index / 6), + top: + 100 + + radius * + 0.6 * + (index.isOdd ? 1 : -1) * + (index / 6), + child: Container( + width: 8 + (index % 3) * 4, + height: 8 + (index % 3) * 4, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: [ + AppColor.primary, + AppColor.error, + AppColor.warning, + ][index % 3].withOpacity(0.6), + ), + ), + ); + }), + ], + ), + ); + }, + ), + + const SizedBox(height: 40), + + // Animated Title + FadeTransition( + opacity: _fadeAnimation, + child: Text( + widget.title ?? 'Ups! Ada Yang Salah', + style: AppStyle.h2.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, // warna solid + ), + textAlign: TextAlign.center, + ), + ), + + const SizedBox(height: 16), + + // Animated Message + SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeAnimation, + child: Container( + padding: const EdgeInsets.all(20), + margin: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.08), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + border: Border.all( + color: AppColor.border.withOpacity(0.5), + ), + ), + child: Column( + children: [ + Text( + widget.message ?? + 'Sepertinya ada masalah teknis yang tidak terduga. Jangan khawatir, tim kami sedang bekerja keras untuk memperbaikinya!', + style: AppStyle.lg.copyWith( + color: AppColor.textSecondary, + height: 1.6, + ), + textAlign: TextAlign.center, + ), + + if (widget.errorCode != null) ...[ + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.error.withOpacity(0.1), + AppColor.warning.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColor.error.withOpacity(0.3), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.code, + size: 16, + color: AppColor.error, + ), + const SizedBox(width: 8), + Text( + 'Kode Error: ${widget.errorCode}', + style: AppStyle.sm.copyWith( + color: AppColor.error, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ], + ], + ), + ), + ), + ), + + const SizedBox(height: 50), + + // Animated Buttons + SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeAnimation, + child: Column( + children: [ + // Retry Button with gradient + if (widget.onRetry != null) + Container( + width: double.infinity, + height: 60, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.4), + blurRadius: 15, + offset: const Offset(0, 8), + ), + ], + ), + child: ElevatedButton.icon( + onPressed: widget.onRetry, + icon: const Icon( + Icons.refresh_rounded, + color: AppColor.textWhite, + size: 24, + ), + label: Text( + 'Coba Lagi', + style: AppStyle.xl.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + ), + ), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), + ), + ), + + const SizedBox(height: 16), + + // Back Button with modern design + if (widget.onBack != null) + Container( + width: double.infinity, + height: 60, + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + width: 2, + color: AppColor.primary.withOpacity(0.3), + ), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.1), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: OutlinedButton.icon( + onPressed: widget.onBack, + icon: Icon( + Icons.arrow_back_ios_rounded, + color: AppColor.primary, + size: 20, + ), + label: Text( + 'Kembali', + style: AppStyle.xl.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.bold, + ), + ), + style: OutlinedButton.styleFrom( + backgroundColor: Colors.transparent, + side: BorderSide.none, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + ), + ), + ), + ], + ), + ), + ), + + const SizedBox(height: 40), + + // Help text with icon + FadeTransition( + opacity: _fadeAnimation, + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.info.withOpacity(0.05), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.info.withOpacity(0.1)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.help_outline_rounded, + size: 18, + color: AppColor.info, + ), + const SizedBox(width: 8), + Flexible( + child: Text( + 'Butuh bantuan? Hubungi tim support kami', + style: AppStyle.sm.copyWith( + color: AppColor.info, + fontWeight: FontWeight.w500, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} + +// Usage Example dengan berbagai variasi +class ErrorPageExamples extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Column( + children: [ + // Network Error + ElevatedButton( + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ErrorPage( + title: 'Koneksi Terputus', + message: + 'Sepertinya koneksi internet Anda bermasalah. Periksa jaringan dan coba lagi.', + errorCode: 'NET_404', + errorIcon: Icons.wifi_off_rounded, + onRetry: () => Navigator.pop(context), + onBack: () => Navigator.pop(context), + ), + ), + ), + child: Text('Network Error'), + ), + + // Server Error + ElevatedButton( + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ErrorPage( + title: 'Server Sibuk', + message: + 'Server sedang mengalami gangguan. Tim kami sedang memperbaikinya.', + errorCode: 'SRV_500', + errorIcon: Icons.dns_rounded, + onRetry: () => Navigator.pop(context), + onBack: () => Navigator.pop(context), + ), + ), + ), + child: Text('Server Error'), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/finance/finance_page.dart b/lib/presentation/pages/finance/finance_page.dart new file mode 100644 index 0000000..77e9ae7 --- /dev/null +++ b/lib/presentation/pages/finance/finance_page.dart @@ -0,0 +1,336 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../application/analytic/category_analytic_loader/category_analytic_loader_bloc.dart'; +import '../../../application/analytic/profit_loss_loader/profit_loss_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import '../../components/field/date_range_picker_field.dart'; +import 'widgets/cash_flow.dart'; +import 'widgets/category.dart'; +import 'widgets/product.dart'; +import 'widgets/profit_loss.dart'; +import 'widgets/summary_card.dart'; + +@RoutePage() +class FinancePage extends StatefulWidget implements AutoRouteWrapper { + const FinancePage({super.key}); + + @override + State createState() => _FinancePageState(); + + @override + Widget wrappedRoute(BuildContext context) => MultiBlocProvider( + providers: [ + BlocProvider( + create: (_) => + getIt()..add(ProfitLossLoaderEvent.fetched()), + ), + BlocProvider( + create: (context) => + getIt() + ..add(CategoryAnalyticLoaderEvent.fetched()), + ), + ], + child: this, + ); +} + +class _FinancePageState extends State + with TickerProviderStateMixin { + late AnimationController _slideController; + late AnimationController _fadeController; + late AnimationController _scaleController; + + late Animation _slideAnimation; + late Animation _fadeAnimation; + late Animation _scaleAnimation; + + @override + void initState() { + super.initState(); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _fadeController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + + _scaleController = AnimationController( + duration: const Duration(milliseconds: 600), + vsync: this, + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), + ); + + _fadeAnimation = Tween( + begin: 0.0, + end: 1.0, + ).animate(CurvedAnimation(parent: _fadeController, curve: Curves.easeIn)); + + _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( + CurvedAnimation(parent: _scaleController, curve: Curves.elasticOut), + ); + + // Start animations + _fadeController.forward(); + Future.delayed(const Duration(milliseconds: 200), () { + _slideController.forward(); + }); + Future.delayed(const Duration(milliseconds: 400), () { + _scaleController.forward(); + }); + } + + @override + void dispose() { + _slideController.dispose(); + _fadeController.dispose(); + _scaleController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: BlocListener( + listenWhen: (previous, current) => + previous.dateFrom != current.dateFrom || + previous.dateTo != current.dateTo, + listener: (context, state) { + context.read().add( + ProfitLossLoaderEvent.fetched(), + ); + }, + child: BlocBuilder( + builder: (context, state) { + return CustomScrollView( + slivers: [ + // SliverAppBar with animated background + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + elevation: 0, + flexibleSpace: CustomAppBar(title: context.lang.profit_loss), + ), + + // Header dengan filter periode + SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: DateRangePickerField( + maxDate: DateTime.now(), + startDate: state.dateFrom, + endDate: state.dateTo, + onChanged: (startDate, endDate) { + context.read().add( + ProfitLossLoaderEvent.rangeDateChanged( + startDate!, + endDate!, + ), + ); + }, + ), + ), + ), + ), + + // Summary Cards + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: _buildSummaryCards(state.profitLoss.summary), + ), + ), + + // Cash Flow Analysis + SliverToBoxAdapter( + child: ScaleTransition( + scale: _scaleAnimation, + child: FinanceCashFlow(dailyData: state.profitLoss.data), + ), + ), + + // Profit Loss Detail + SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: FinanceProfitLoss(data: state.profitLoss.summary), + ), + ), + + BlocBuilder< + CategoryAnalyticLoaderBloc, + CategoryAnalyticLoaderState + >( + builder: (context, stateCategory) { + return SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: FinanceCategory( + categories: stateCategory.categoryAnalytic.data, + ), + ), + ); + }, + ), + + // Product Analysis Section + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: _buildProductAnalysis(state.profitLoss.productData), + ), + ), + + // Transaction Categories + + // Bottom spacing + const SliverToBoxAdapter(child: SizedBox(height: 100)), + ], + ); + }, + ), + ), + ); + } + + Widget _buildSummaryCards(ProfitLossSummary summary) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: FinanceSummaryCard( + title: context.lang.total_revenue, + amount: summary.totalRevenue.currencyFormatRp, + icon: LineIcons.arrowUp, + color: AppColor.success, + isPositive: true, + ), + ), + const SizedBox(width: 12), + Expanded( + child: FinanceSummaryCard( + title: context.lang.total_expenditures, + amount: summary.totalCost.currencyFormatRp, + icon: LineIcons.arrowDown, + color: AppColor.error, + isPositive: false, + ), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: FinanceSummaryCard( + title: context.lang.net_profit, + amount: summary.netProfit.currencyFormatRp, + icon: LineIcons.lineChart, + color: AppColor.info, + isPositive: true, + ), + ), + const SizedBox(width: 12), + Expanded( + child: FinanceSummaryCard( + title: context.lang.margin_profit, + amount: '${summary.profitabilityRatio.round()}%', + icon: LineIcons.percent, + color: AppColor.warning, + isPositive: true, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildProductAnalysis(List products) { + return Container( + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.textLight.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.info.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: const Icon( + LineIcons.shoppingBag, + color: AppColor.info, + size: 20, + ), + ), + const SizedBox(width: 12), + Text( + context.lang.product_analytic, + style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), + ), + const Spacer(), + TextButton( + onPressed: () {}, + child: Text( + context.lang.view_all, + style: AppStyle.sm.copyWith(color: AppColor.primary), + ), + ), + ], + ), + // Product list + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.only(top: 12), + itemCount: products.length, + separatorBuilder: (context, index) => const SizedBox(height: 12), + itemBuilder: (context, index) { + final product = products[index]; + return ProfitLossProduct(product: product); + }, + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/finance/widgets/cash_flow.dart b/lib/presentation/pages/finance/widgets/cash_flow.dart new file mode 100644 index 0000000..fa6e0cd --- /dev/null +++ b/lib/presentation/pages/finance/widgets/cash_flow.dart @@ -0,0 +1,476 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; + +class FinanceCashFlow extends StatelessWidget { + final List dailyData; + + const FinanceCashFlow({super.key, required this.dailyData}); + + @override + Widget build(BuildContext context) { + // Calculate totals from daily data + final totalCashIn = _calculateTotalCashIn(); + final totalCashOut = _calculateTotalCashOut(); + final netFlow = totalCashIn - totalCashOut; + + return Container( + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.textLight.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + ), + borderRadius: BorderRadius.circular(8), + ), + child: const Icon( + LineIcons.areaChart, + color: AppColor.white, + size: 20, + ), + ), + const SizedBox(width: 12), + Text( + context.lang.cash_flow_analysis, + style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), + ), + ], + ), + IconButton( + onPressed: () {}, + icon: const Icon( + LineIcons.alternateExternalLink, + color: AppColor.primary, + ), + ), + ], + ), + const SizedBox(height: 20), + + // Cash Flow Indicators + Row( + children: [ + Expanded( + child: _buildCashFlowIndicator( + context.lang.cash_in, + _formatCurrency(totalCashIn), + LineIcons.arrowUp, + AppColor.success, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildCashFlowIndicator( + context.lang.cash_out, + _formatCurrency(totalCashOut), + LineIcons.arrowDown, + AppColor.error, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildCashFlowIndicator( + context.lang.net_flow, + _formatCurrency(netFlow), + LineIcons.equals, + AppColor.info, + ), + ), + ], + ), + const SizedBox(height: 20), + + // FL Chart Implementation + Container( + height: 200, + 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: [ + Text( + context.lang.cash_flow_chart(dailyData.length), + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 16), + Expanded( + child: dailyData.isEmpty + ? _buildEmptyChart() + : LineChart(_buildLineChartData()), + ), + const SizedBox(height: 12), + // Legend + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildChartLegend(context.lang.cash_in, AppColor.success), + const SizedBox(width: 20), + _buildChartLegend(context.lang.cash_out, AppColor.error), + const SizedBox(width: 20), + _buildChartLegend(context.lang.net_flow, AppColor.info), + ], + ), + ], + ), + ), + ], + ), + ); + } + + LineChartData _buildLineChartData() { + final maxValue = _getMaxChartValue(); + final minValue = _getMinChartValue(); + + return LineChartData( + gridData: FlGridData( + show: true, + drawVerticalLine: false, + horizontalInterval: (maxValue / 5).roundToDouble(), + getDrawingHorizontalLine: (value) { + return FlLine(color: AppColor.borderLight, strokeWidth: 1); + }, + ), + titlesData: FlTitlesData( + show: true, + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 30, + interval: 1, + getTitlesWidget: (double value, TitleMeta meta) { + final index = value.toInt(); + if (index >= 0 && index < dailyData.length) { + final date = DateTime.parse(dailyData[index].date); + final dayName = _getDayName(date.weekday); + return SideTitleWidget( + meta: meta, + child: Text( + dayName, + style: const TextStyle( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 10, + ), + ), + ); + } + return SideTitleWidget(meta: meta, child: Text('')); + }, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + interval: (maxValue / 3).roundToDouble(), + reservedSize: 42, + getTitlesWidget: (double value, TitleMeta meta) { + return Text( + _formatChartValue(value), + style: const TextStyle( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 10, + ), + textAlign: TextAlign.left, + ); + }, + ), + ), + ), + borderData: FlBorderData( + show: true, + border: Border.all(color: AppColor.borderLight), + ), + minX: 0, + maxX: (dailyData.length - 1).toDouble(), + minY: minValue, + maxY: maxValue, + lineBarsData: [ + // Cash In Line (Revenue) + LineChartBarData( + spots: _buildCashInSpots(), + isCurved: true, + gradient: LinearGradient( + colors: [AppColor.success.withOpacity(0.8), AppColor.success], + ), + barWidth: 3, + isStrokeCapRound: true, + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 4, + color: AppColor.success, + strokeWidth: 2, + strokeColor: AppColor.white, + ); + }, + ), + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + AppColor.success.withOpacity(0.1), + AppColor.success.withOpacity(0.0), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + // Cash Out Line (Total Cost) + LineChartBarData( + spots: _buildCashOutSpots(), + isCurved: true, + gradient: LinearGradient( + colors: [AppColor.error.withOpacity(0.8), AppColor.error], + ), + barWidth: 3, + isStrokeCapRound: true, + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 4, + color: AppColor.error, + strokeWidth: 2, + strokeColor: AppColor.white, + ); + }, + ), + ), + // Net Flow Line (Net Profit) + LineChartBarData( + spots: _buildNetFlowSpots(), + isCurved: true, + gradient: LinearGradient( + colors: [AppColor.info.withOpacity(0.8), AppColor.info], + ), + barWidth: 3, + isStrokeCapRound: true, + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 4, + color: AppColor.info, + strokeWidth: 2, + strokeColor: AppColor.white, + ); + }, + ), + ), + ], + ); + } + + Widget _buildEmptyChart() { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + LineIcons.lineChart, + size: 48, + color: AppColor.textSecondary.withOpacity(0.3), + ), + const SizedBox(height: 12), + Text( + 'Tidak ada data untuk ditampilkan', + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + ], + ), + ); + } + + // Helper methods for calculating data + int _calculateTotalCashIn() { + return dailyData.fold(0, (sum, data) => sum + data.revenue); + } + + int _calculateTotalCashOut() { + return dailyData.fold( + 0, + (sum, data) => sum + data.cost + data.tax + data.discount, + ); + } + + double _getMaxChartValue() { + if (dailyData.isEmpty) return 30000000; + + final maxRevenue = dailyData + .map((e) => e.revenue) + .reduce((a, b) => a > b ? a : b); + final maxCost = dailyData + .map((e) => e.cost + e.tax + e.discount) + .reduce((a, b) => a > b ? a : b); + final maxValue = maxRevenue > maxCost ? maxRevenue : maxCost; + + return (maxValue * 1.2).toDouble(); // Add 20% padding + } + + double _getMinChartValue() { + if (dailyData.isEmpty) return -5000000; + + final minNetProfit = dailyData + .map((e) => e.netProfit) + .reduce((a, b) => a < b ? a : b); + return minNetProfit < 0 ? (minNetProfit * 1.2).toDouble() : 0; + } + + List _buildCashInSpots() { + return dailyData.asMap().entries.map((entry) { + return FlSpot(entry.key.toDouble(), entry.value.revenue.toDouble()); + }).toList(); + } + + List _buildCashOutSpots() { + return dailyData.asMap().entries.map((entry) { + final totalCost = + entry.value.cost + entry.value.tax + entry.value.discount; + return FlSpot(entry.key.toDouble(), totalCost.toDouble()); + }).toList(); + } + + List _buildNetFlowSpots() { + return dailyData.asMap().entries.map((entry) { + return FlSpot(entry.key.toDouble(), entry.value.netProfit.toDouble()); + }).toList(); + } + + String _getDayName(int weekday) { + switch (weekday) { + case 1: + return 'Sen'; + case 2: + return 'Sel'; + case 3: + return 'Rab'; + case 4: + return 'Kam'; + case 5: + return 'Jum'; + case 6: + return 'Sab'; + case 7: + return 'Min'; + default: + return ''; + } + } + + String _formatChartValue(double value) { + if (value.abs() >= 1000000) { + return '${(value / 1000000).toStringAsFixed(0)}M'; + } else if (value.abs() >= 1000) { + return '${(value / 1000).toStringAsFixed(0)}K'; + } else { + return value.toStringAsFixed(0); + } + } + + String _formatCurrency(int amount) { + if (amount.abs() >= 1000000000) { + return 'Rp ${(amount / 1000000000).toStringAsFixed(1)}B'; + } else if (amount.abs() >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; + } else if (amount.abs() >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(1)}K'; + } else { + return 'Rp ${NumberFormat('#,###', 'id_ID').format(amount)}'; + } + } + + Widget _buildChartLegend(String label, Color color) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 12, + height: 12, + decoration: BoxDecoration(color: color, shape: BoxShape.circle), + ), + const SizedBox(width: 6), + Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ); + } + + Widget _buildCashFlowIndicator( + String label, + String amount, + IconData icon, + Color color, + ) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: color.withOpacity(0.05), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: color.withOpacity(0.2)), + ), + child: Column( + children: [ + Icon(icon, color: color, size: 20), + const SizedBox(height: 8), + Text( + label, + style: AppStyle.xs.copyWith(color: AppColor.textSecondary), + ), + const SizedBox(height: 4), + Text( + amount, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: color, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/finance/widgets/category.dart b/lib/presentation/pages/finance/widgets/category.dart new file mode 100644 index 0000000..df21ac6 --- /dev/null +++ b/lib/presentation/pages/finance/widgets/category.dart @@ -0,0 +1,209 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../components/widgets/empty_widget.dart'; + +class FinanceCategory extends StatelessWidget { + final List categories; + + const FinanceCategory({super.key, required this.categories}); + + @override + Widget build(BuildContext context) { + final totalRevenue = _calculateTotalRevenue(); + final sortedCategories = _sortCategoriesByRevenue(); + + return Container( + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.textLight.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.secondary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: const Icon( + LineIcons.pieChart, + color: AppColor.secondary, + size: 20, + ), + ), + const SizedBox(width: 12), + Text( + context.lang.sales_category, + style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), + ), + ], + ), + const SizedBox(height: 20), + + // Show empty state if no categories + if (categories.isEmpty) + _buildEmptyState(context) + else + ...sortedCategories.asMap().entries.map( + (entry) => _buildCategoryItem( + context, + entry.value, + _calculatePercentage(entry.value.totalRevenue, totalRevenue), + _getCategoryColor(entry.key), + ), + ), + ], + ), + ); + } + + Widget _buildCategoryItem( + BuildContext context, + CategoryAnalyticItem category, + double percentage, + Color color, + ) { + return Container( + margin: const EdgeInsets.only(bottom: 16), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + children: [ + Container( + width: 12, + height: 12, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(6), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + category.categoryName, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.w600, + ), + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Text( + '${category.productCount} ${context.lang.product} • ${category.orderCount} ${context.lang.orders}', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + ), + ], + ), + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + category.totalRevenue.currencyFormatRp, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: color, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(category.totalQuantity)} ${context.lang.unit}', + style: AppStyle.xs.copyWith(color: AppColor.textSecondary), + ), + ], + ), + ], + ), + const SizedBox(height: 8), + LinearProgressIndicator( + value: percentage / 100, + backgroundColor: AppColor.borderLight, + valueColor: AlwaysStoppedAnimation(color), + minHeight: 6, + ), + const SizedBox(height: 4), + Align( + alignment: Alignment.centerRight, + child: Text( + '${percentage.toStringAsFixed(1)}%', + style: AppStyle.xs.copyWith(color: AppColor.textSecondary), + ), + ), + ], + ), + ); + } + + Widget _buildEmptyState(BuildContext context) { + return EmptyWidget( + title: context.lang.category_no_data, + message: context.lang.category_no_data_desc, + ); + } + + // Helper methods + int _calculateTotalRevenue() { + return categories.fold(0, (sum, category) => sum + category.totalRevenue); + } + + List _sortCategoriesByRevenue() { + final sorted = List.from(categories); + sorted.sort((a, b) => b.totalRevenue.compareTo(a.totalRevenue)); + return sorted; + } + + double _calculatePercentage(int categoryRevenue, int totalRevenue) { + if (totalRevenue == 0) return 0; + return (categoryRevenue / totalRevenue) * 100; + } + + Color _getCategoryColor(int index) { + // Predefined color palette for categories + const colors = [ + AppColor.primary, + AppColor.secondary, + AppColor.success, + AppColor.warning, + AppColor.error, + AppColor.info, + ]; + + // Generate additional colors if needed + if (index < colors.length) { + return colors[index]; + } else { + // Generate colors based on index for unlimited categories + final hue = (index * 137.5) % 360; // Golden angle approximation + return HSLColor.fromAHSL(1.0, hue, 0.7, 0.5).toColor(); + } + } +} diff --git a/lib/presentation/pages/finance/widgets/product.dart b/lib/presentation/pages/finance/widgets/product.dart new file mode 100644 index 0000000..7f41843 --- /dev/null +++ b/lib/presentation/pages/finance/widgets/product.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; + +class ProfitLossProduct extends StatelessWidget { + final ProfitLossProductData product; + const ProfitLossProduct({super.key, required this.product}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.border.withOpacity(0.5)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Product header + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.productName, + style: AppStyle.md.copyWith(fontWeight: FontWeight.bold), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + product.categoryName, + style: AppStyle.xs.copyWith(color: AppColor.primary), + ), + ), + ], + ), + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + '${product.quantitySold} terjual', + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + Text( + '${product.grossProfitMargin.toStringAsFixed(1)}%', + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: product.grossProfitMargin > 25 + ? AppColor.success + : product.grossProfitMargin > 15 + ? AppColor.warning + : AppColor.error, + ), + ), + ], + ), + ], + ), + const SizedBox(height: 16), + + // Financial metrics + Row( + children: [ + Expanded( + child: _buildMetricColumn( + context.lang.revenue, + product.revenue.currencyFormatRp, + AppColor.success, + ), + ), + Expanded( + child: _buildMetricColumn( + context.lang.cost, + product.cost.currencyFormatRp, + AppColor.error, + ), + ), + Expanded( + child: _buildMetricColumn( + context.lang.gross_profit, + product.grossProfit.currencyFormatRp, + AppColor.info, + ), + ), + ], + ), + const SizedBox(height: 12), + + // Average metrics + Row( + children: [ + Expanded( + child: _buildMetricColumn( + context.lang.average_price, + product.averagePrice.currencyFormatRp, + AppColor.textSecondary, + ), + ), + Expanded( + child: _buildMetricColumn( + context.lang.profit_per_unit, + product.profitPerUnit.currencyFormatRp, + AppColor.primary, + ), + ), + const Expanded(child: SizedBox()), + ], + ), + ], + ), + ); + } + + Widget _buildMetricColumn(String label, String value, Color color) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: AppStyle.xs.copyWith(color: AppColor.textSecondary)), + const SizedBox(height: 2), + Text( + value, + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: color, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/finance/widgets/profit_loss.dart b/lib/presentation/pages/finance/widgets/profit_loss.dart new file mode 100644 index 0000000..929c04e --- /dev/null +++ b/lib/presentation/pages/finance/widgets/profit_loss.dart @@ -0,0 +1,192 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; + +class FinanceProfitLoss extends StatelessWidget { + final ProfitLossSummary data; + + const FinanceProfitLoss({super.key, required this.data}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.textLight.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.info.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: const Icon( + LineIcons.calculator, + color: AppColor.info, + size: 20, + ), + ), + const SizedBox(width: 12), + Text( + context.lang.profit_loss_detail, + style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), + ), + ], + ), + const SizedBox(height: 20), + + // Total Revenue (Penjualan Kotor) + _buildPLItem( + context.lang.gross_sales, + data.totalRevenue.currencyFormatRp, + AppColor.success, + true, + ), + + // Discount (Diskon & Retur) + _buildPLItem( + '${context.lang.discount} & ${context.lang.return_text}', + '- ${data.totalDiscount.currencyFormatRp}', + AppColor.error, + false, + ), + + const Divider(height: 24), + + // Net Sales (Penjualan Bersih = Total Revenue - Discount) + _buildPLItem( + context.lang.net_sales, + (data.totalRevenue - data.totalDiscount).currencyFormatRp, + AppColor.textPrimary, + true, + isHeader: true, + ), + + const SizedBox(height: 12), + + // Cost of Goods Sold (HPP) + _buildPLItem( + '${context.lang.cogs} (${context.lang.cost_of_goods_sold})', + '- ${data.totalCost.currencyFormatRp}', + AppColor.error, + false, + ), + + const Divider(height: 24), + + // Gross Profit (Laba Kotor) + _buildPLItem( + context.lang.gross_profit, + data.grossProfit.currencyFormatRp, + AppColor.success, + true, + isHeader: true, + showPercentage: true, + percentage: '${data.grossProfitMargin.toStringAsFixed(1)}%', + ), + + const SizedBox(height: 12), + + // Operational Cost (Biaya Operasional) - calculated as difference + _buildPLItem( + context.lang.operating_costs, + '- ${_calculateOperationalCost().currencyFormatRp}', + AppColor.error, + false, + ), + + const Divider(height: 24), + + // Net Profit (Laba Bersih) + _buildPLItem( + context.lang.net_profit, + data.netProfit.currencyFormatRp, + AppColor.primary, + true, + isHeader: true, + showPercentage: true, + percentage: '${data.netProfitMargin.round()}%', + ), + ], + ), + ); + } + + Widget _buildPLItem( + String title, + String amount, + Color color, + bool isPositive, { + bool isHeader = false, + bool showPercentage = false, + String? percentage, + }) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + title, + style: isHeader + ? AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: color, + ) + : AppStyle.md.copyWith(color: AppColor.textSecondary), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + amount, + style: isHeader + ? AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: color, + ) + : AppStyle.md.copyWith( + color: color, + fontWeight: FontWeight.w600, + ), + ), + if (showPercentage && percentage != null) + Text( + percentage, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontStyle: FontStyle.italic, + ), + ), + ], + ), + ], + ), + ); + } + + // Calculate operational cost as the difference between gross profit and net profit + int _calculateOperationalCost() { + return data.grossProfit - data.netProfit - data.totalTax; + } +} diff --git a/lib/presentation/pages/finance/widgets/summary_card.dart b/lib/presentation/pages/finance/widgets/summary_card.dart new file mode 100644 index 0000000..26daaf6 --- /dev/null +++ b/lib/presentation/pages/finance/widgets/summary_card.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class FinanceSummaryCard extends StatelessWidget { + const FinanceSummaryCard({ + super.key, + required this.title, + required this.amount, + required this.icon, + required this.color, + required this.isPositive, + }); + + final String title; + final String amount; + final IconData icon; + final Color color; + final bool isPositive; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.textLight.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, color: color, size: 20), + ), + ], + ), + const SizedBox(height: 12), + Text( + title, + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + const SizedBox(height: 4), + Text( + amount, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/form/daily_task_form_page.dart b/lib/presentation/pages/form/daily_task_form_page.dart new file mode 100644 index 0000000..8862ecb --- /dev/null +++ b/lib/presentation/pages/form/daily_task_form_page.dart @@ -0,0 +1,470 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'dart:io'; + +import '../../../common/theme/theme.dart'; + +// Model untuk question item +class TaskQuestion { + final String id; + final String question; + bool? answer; + File? photo; + + TaskQuestion({ + required this.id, + required this.question, + this.answer, + this.photo, + }); +} + +// Model untuk task section +class TaskSection { + final String title; + final List questions; + + TaskSection({required this.title, required this.questions}); +} + +@RoutePage() +class DailyTasksFormPage extends StatefulWidget { + const DailyTasksFormPage({super.key}); + + @override + State createState() => _DailyTasksFormPageState(); +} + +class _DailyTasksFormPageState extends State + with SingleTickerProviderStateMixin { + late TabController _tabController; + final ImagePicker _picker = ImagePicker(); + + // Sample data untuk OPEN dan CLOSING tasks + List taskSections = [ + TaskSection( + title: "OPENING", + questions: [ + TaskQuestion(id: "open_1", question: "Apakah meja sudah dibersihkan?"), + TaskQuestion( + id: "open_2", + question: "Apakah alat kerja sudah disiapkan?", + ), + TaskQuestion( + id: "open_3", + question: "Apakah ruangan sudah dalam kondisi bersih?", + ), + TaskQuestion( + id: "open_4", + question: "Apakah penerangan sudah memadai?", + ), + ], + ), + TaskSection( + title: "CLOSING", + questions: [ + TaskQuestion( + id: "close_1", + question: "Apakah meja sudah dibersihkan kembali?", + ), + TaskQuestion( + id: "close_2", + question: "Apakah alat kerja sudah disimpan dengan rapi?", + ), + TaskQuestion(id: "close_3", question: "Apakah lampu sudah dimatikan?"), + TaskQuestion(id: "close_4", question: "Apakah pintu sudah dikunci?"), + ], + ), + ]; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + Future _pickImage(TaskQuestion question) async { + try { + final XFile? image = await _picker.pickImage( + source: ImageSource.camera, + maxWidth: 1920, + maxHeight: 1080, + imageQuality: 85, + ); + + if (image != null) { + setState(() { + question.photo = File(image.path); + }); + } + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Error mengambil foto: $e'), + backgroundColor: AppColor.error, + ), + ); + } + } + + void _removePhoto(TaskQuestion question) { + setState(() { + question.photo = null; + }); + } + + bool _isFormComplete() { + for (var section in taskSections) { + for (var question in section.questions) { + if (question.answer == null || question.photo == null) { + return false; + } + } + } + return true; + } + + void _submitForm() { + if (!_isFormComplete()) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Mohon lengkapi semua pertanyaan dan foto'), + backgroundColor: AppColor.error, + ), + ); + return; + } + + // Logic untuk submit form + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Daily tasks berhasil disimpan!'), + backgroundColor: AppColor.success, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + appBar: AppBar( + title: const Text( + 'Daily Tasks', + style: TextStyle( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + ), + ), + backgroundColor: AppColor.primary, + elevation: 0, + bottom: TabBar( + controller: _tabController, + indicatorColor: AppColor.textWhite, + labelColor: AppColor.textWhite, + unselectedLabelColor: AppColor.textWhite.withOpacity(0.7), + labelStyle: const TextStyle(fontWeight: FontWeight.bold), + tabs: taskSections + .map((section) => Tab(text: section.title)) + .toList(), + ), + ), + body: Column( + children: [ + Expanded( + child: TabBarView( + controller: _tabController, + children: taskSections.map((section) { + return SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSectionHeader(section.title), + const SizedBox(height: 16), + ...section.questions.map((question) { + return _buildQuestionCard(question); + }).toList(), + ], + ), + ); + }).toList(), + ), + ), + _buildSubmitButton(), + ], + ), + ); + } + + Widget _buildSectionHeader(String title) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [AppColor.primary, AppColor.primaryLight], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + Icon( + title == "OPENING" ? Icons.wb_sunny : Icons.nightlight_round, + color: AppColor.textWhite, + size: 24, + ), + const SizedBox(width: 12), + Text( + '$title CHECKLIST', + style: const TextStyle( + color: AppColor.textWhite, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ); + } + + Widget _buildQuestionCard(TaskQuestion question) { + return Container( + margin: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + question.question, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 16), + + // Yes/No buttons + Row( + children: [ + Expanded( + child: _buildAnswerButton( + question: question, + value: true, + label: "YES", + icon: Icons.check_circle, + color: AppColor.success, + ), + ), + const SizedBox(width: 12), + Expanded( + child: _buildAnswerButton( + question: question, + value: false, + label: "NO", + icon: Icons.cancel, + color: AppColor.error, + ), + ), + ], + ), + + const SizedBox(height: 16), + + // Photo section + _buildPhotoSection(question), + ], + ), + ), + ); + } + + Widget _buildAnswerButton({ + required TaskQuestion question, + required bool value, + required String label, + required IconData icon, + required Color color, + }) { + bool isSelected = question.answer == value; + + return GestureDetector( + onTap: () { + setState(() { + question.answer = value; + }); + }, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + decoration: BoxDecoration( + color: isSelected ? color : AppColor.backgroundLight, + border: Border.all( + color: isSelected ? color : AppColor.border, + width: 1.5, + ), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icon, + color: isSelected ? AppColor.white : AppColor.textSecondary, + size: 20, + ), + const SizedBox(width: 8), + Text( + label, + style: TextStyle( + color: isSelected ? AppColor.white : AppColor.textSecondary, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ); + } + + Widget _buildPhotoSection(TaskQuestion question) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Icon( + Icons.camera_alt, + color: AppColor.textSecondary, + size: 18, + ), + const SizedBox(width: 8), + const Text( + 'Foto Bukti', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: AppColor.textSecondary, + ), + ), + const Text(' *', style: TextStyle(color: AppColor.error)), + ], + ), + const SizedBox(height: 8), + + if (question.photo == null) + GestureDetector( + onTap: () => _pickImage(question), + child: Container( + height: 120, + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.borderLight, + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: AppColor.border, + style: BorderStyle.solid, + ), + ), + child: const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.add_a_photo, size: 32, color: AppColor.textLight), + SizedBox(height: 8), + Text( + 'Tap untuk mengambil foto', + style: TextStyle(color: AppColor.textLight, fontSize: 14), + ), + ], + ), + ), + ) + else + Stack( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.file( + question.photo!, + height: 200, + width: double.infinity, + fit: BoxFit.cover, + ), + ), + Positioned( + top: 8, + right: 8, + child: GestureDetector( + onTap: () => _removePhoto(question), + child: Container( + padding: const EdgeInsets.all(4), + decoration: const BoxDecoration( + color: AppColor.error, + shape: BoxShape.circle, + ), + child: const Icon( + Icons.close, + color: AppColor.white, + size: 16, + ), + ), + ), + ), + ], + ), + ], + ); + } + + Widget _buildSubmitButton() { + return Container( + padding: const EdgeInsets.all(16), + decoration: const BoxDecoration( + color: AppColor.white, + border: Border(top: BorderSide(color: AppColor.border, width: 1)), + ), + child: SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: _submitForm, + style: ElevatedButton.styleFrom( + backgroundColor: AppColor.primary, + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + elevation: 2, + ), + child: const Text( + 'SUBMIT DAILY TASKS', + style: TextStyle( + color: AppColor.textWhite, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ); + } +} diff --git a/lib/presentation/pages/home/home_page.dart b/lib/presentation/pages/home/home_page.dart new file mode 100644 index 0000000..a811baf --- /dev/null +++ b/lib/presentation/pages/home/home_page.dart @@ -0,0 +1,217 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../application/home/home_bloc.dart'; +import '../../../application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart'; +import '../../../application/outlet/selected_outlet/selected_outlet_bloc.dart'; +import '../../../common/constant/app_constant.dart'; +import '../../../common/theme/theme.dart'; +import '../../../injection.dart'; +import '../../components/button/button.dart'; +import '../../components/spacer/spacer.dart'; +import 'widgets/feature.dart'; +import 'widgets/header.dart'; +import 'widgets/promo_banner.dart'; +import 'widgets/stats.dart'; + +@RoutePage() +class HomePage extends StatefulWidget implements AutoRouteWrapper { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); + + @override + Widget wrappedRoute(BuildContext context) => MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => + getIt()..add(HomeEvent.fetchedDashboard()), + ), + BlocProvider( + create: (context) => getIt() + ..add(const OutletListLoaderEvent.fetched()), + ), + BlocProvider( + create: (context) => getIt() + ..add(const SelectedOutletEvent.loaded()), + ), + ], + child: this, + ); +} + +class _HomePageState extends State with TickerProviderStateMixin { + late AnimationController _headerAnimationController; + late AnimationController _contentAnimationController; + + @override + void initState() { + super.initState(); + + _headerAnimationController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _contentAnimationController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _startAnimations(); + } + + void _startAnimations() { + _headerAnimationController.forward(); + Future.delayed(const Duration(milliseconds: 200), () { + _contentAnimationController.forward(); + }); + } + + @override + void dispose() { + _headerAnimationController.dispose(); + _contentAnimationController.dispose(); + super.dispose(); + } + + void _refetchDashboard(BuildContext context) { + context.read().add(HomeEvent.fetchedDashboard()); + } + + @override + Widget build(BuildContext context) { + return BlocListener( + listenWhen: (previous, current) => + previous.selectedOutletId != current.selectedOutletId, + listener: (context, state) => _refetchDashboard(context), + child: Scaffold( + backgroundColor: AppColor.background, + body: RefreshIndicator( + backgroundColor: AppColor.white, + color: AppColor.primary, + onRefresh: () { + _refetchDashboard(context); + return Future.value(); + }, + child: BlocBuilder( + builder: (context, state) { + return CustomScrollView( + physics: const BouncingScrollPhysics( + parent: ClampingScrollPhysics(), + ), + slivers: [ + // SliverAppBar with HomeHeader as background + SliverAppBar( + expandedHeight: 300, // Adjust based on HomeHeader height + floating: false, + pinned: true, + snap: false, + elevation: 0, + scrolledUnderElevation: 8, + backgroundColor: AppColor.primary, + surfaceTintColor: Colors.transparent, + flexibleSpace: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + // Calculate collapse progress (0.0 = expanded, 1.0 = collapsed) + final double expandedHeight = 200; + final double collapsedHeight = + kToolbarHeight + MediaQuery.of(context).padding.top; + final double currentHeight = constraints.maxHeight; + + double collapseProgress = + 1.0 - + ((currentHeight - collapsedHeight) / + (expandedHeight - collapsedHeight)); + collapseProgress = collapseProgress.clamp(0.0, 1.0); + + return FlexibleSpaceBar( + title: Opacity( + opacity: + collapseProgress, // Title muncul saat collapse + child: Row( + children: [ + Expanded( + child: Text( + AppConstant.appName, + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.w700, + fontSize: 18, + letterSpacing: -0.5, + color: AppColor.white, + ), + ), + ), + ActionIconButton( + onTap: () {}, + icon: LineIcons.bell, + ), + ], + ), + ), + titlePadding: const EdgeInsets.only( + left: 20, + right: 12, + bottom: 16, + ), + background: AnimatedBuilder( + animation: _headerAnimationController, + builder: (context, child) { + return Transform.translate( + offset: Offset( + 0, + 50 * (1 - _headerAnimationController.value), + ), + child: Opacity( + opacity: _headerAnimationController.value, + child: HomeHeader( + totalRevenue: + state.dashboard.overview.totalSales, + ), + ), + ); + }, + ), + ); + }, + ), + ), + + // Main Content + SliverToBoxAdapter( + child: AnimatedBuilder( + animation: _contentAnimationController, + builder: (context, child) { + return Transform.translate( + offset: Offset( + 0, + 30 * (1 - _contentAnimationController.value), + ), + child: Opacity( + opacity: _contentAnimationController.value, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const HomePromoBanner(), + HomeFeature(), + HomeStats(overview: state.dashboard.overview), + const SpaceHeight(40), + ], + ), + ), + ); + }, + ), + ), + ], + ); + }, + ), + ), + ), // Scaffold + ); // BlocListener + } +} diff --git a/lib/presentation/pages/home/widgets/feature.dart b/lib/presentation/pages/home/widgets/feature.dart new file mode 100644 index 0000000..796db91 --- /dev/null +++ b/lib/presentation/pages/home/widgets/feature.dart @@ -0,0 +1,95 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../components/assets/assets.gen.dart'; +import '../../../router/app_router.gr.dart'; +import 'feature_tile.dart'; + +class HomeFeature extends StatelessWidget { + const HomeFeature({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric( + vertical: 24, + horizontal: AppValue.padding, + ).copyWith(bottom: 0), + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 10), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(AppValue.radius), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.04), + blurRadius: 10, + offset: const Offset(0, 5), + spreadRadius: 0, + ), + ], + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HomeFeatureTile( + title: context.lang.sales, + iconPath: Assets.icons.icReportSales.path, + onTap: () => context.router.push(SalesRoute()), + ), + HomeFeatureTile( + title: context.lang.purchase, + iconPath: Assets.icons.icReportPurchase.path, + onTap: () => context.router.push(PurchaseRoute()), + ), + HomeFeatureTile( + title: context.lang.profit_loss, + iconPath: Assets.icons.icReportProfitLoss.path, + onTap: () => context.router.push(FinanceRoute()), + ), + HomeFeatureTile( + title: context.lang.product, + iconPath: Assets.icons.icReportProduct.path, + onTap: () => context.router.push(ProductAnalyticRoute()), + ), + ], + ), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceAround, + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // HomeFeatureTile( + // title: context.lang.form, + // color: const Color(0xFFE91E63), + // icon: LineIcons.fileAlt, + // onTap: () => context.router.push(DailyTasksFormRoute()), + // ), + // HomeFeatureTile( + // title: context.lang.schedule, + // color: const Color(0xFF9C27B0), + // icon: LineIcons.calendar, + // onTap: () => context.router.push(ScheduleRoute()), + // ), + // HomeFeatureTile( + // title: context.lang.inventory, + // color: const Color(0xFF00BCD4), + // icon: LineIcons.archive, + // onTap: () => context.router.push(InventoryRoute()), + // ), + // HomeFeatureTile( + // title: context.lang.customer, + // color: const Color(0xFFFF5722), + // icon: LineIcons.userPlus, + // onTap: () => context.router.push(CustomerRoute()), + // ), + // ], + // ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/feature_tile.dart b/lib/presentation/pages/home/widgets/feature_tile.dart new file mode 100644 index 0000000..da66151 --- /dev/null +++ b/lib/presentation/pages/home/widgets/feature_tile.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; +import '../../../components/spacer/spacer.dart'; + +class HomeFeatureTile extends StatelessWidget { + final String title; + final String iconPath; + final Function() onTap; + const HomeFeatureTile({ + super.key, + required this.title, + required this.iconPath, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Expanded( + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(AppValue.radius), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 6), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [AppColor.primary.withOpacity(0.1), AppColor.primary.withOpacity(0.05)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + ), + child: Image.asset(iconPath), + ), + const SpaceHeight(12), + Text( + title, + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + letterSpacing: -0.2, + ), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/header.dart b/lib/presentation/pages/home/widgets/header.dart new file mode 100644 index 0000000..b7ee1f6 --- /dev/null +++ b/lib/presentation/pages/home/widgets/header.dart @@ -0,0 +1,345 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../application/auth/auth_bloc.dart'; +import '../../../../common/constant/app_constant.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/painter/wave_painter.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/user/user.dart'; +import '../../../components/spacer/spacer.dart'; +import 'omset_balance.dart'; + +class HomeHeader extends StatefulWidget { + final int totalRevenue; + const HomeHeader({super.key, required this.totalRevenue}); + + @override + State createState() => _HomeHeaderState(); +} + +class _HomeHeaderState extends State with SingleTickerProviderStateMixin { + late AnimationController _animationController; + + late Animation _fadeInAnimation; + late Animation _slideAnimation; + late Animation _scaleAnimation; + + @override + void initState() { + super.initState(); + + _animationController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _fadeInAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.0, 0.6, curve: Curves.easeOut), + ), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.5), end: Offset.zero).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.2, 0.8, curve: Curves.easeOutCubic), + ), + ); + + _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.0, 0.7, curve: Curves.elasticOut), + ), + ); + + _animationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Container( + height: 280, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primary, + AppColor.primaryLight, + AppColor.primaryLight.withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + stops: const [0.0, 0.7, 1.0], + ), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: Stack( + children: [ + // Static decorative circles (right side) + Positioned( + top: -50, + right: -50, + child: Container( + width: 150, + height: 150, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.10), + ), + ), + ), + Positioned( + top: 80, + right: -20, + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.05), + ), + ), + ), + Positioned( + top: 150, + right: 30, + child: Container( + width: 40, + height: 40, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.07), + ), + ), + ), + + // Static decorative circles (left side) + Positioned( + top: 60, + left: -30, + child: Container( + width: 100, + height: 100, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.03), + ), + ), + ), + Positioned( + bottom: 20, + left: -20, + child: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.04), + ), + ), + ), + + // Static sparkle icons + ...List.generate(8, (index) { + return Positioned( + left: (index * 60.0) % (MediaQuery.of(context).size.width), + top: 30 + (index * 25.0), + child: Icon( + Icons.auto_awesome, + size: 8 + (index % 3) * 3, + color: AppColor.white.withOpacity(0.25), + ), + ); + }), + + // Wave pattern (static) + Positioned.fill( + child: CustomPaint( + painter: WavePainter( + animation: 0.0, + color: AppColor.white.withOpacity(0.08), + ), + ), + ), + + // Gradient overlay for depth + Container( + decoration: BoxDecoration( + gradient: RadialGradient( + center: const Alignment(0.8, -0.3), + radius: 1.5, + colors: [ + Colors.transparent, + AppColor.primary.withOpacity(0.1), + Colors.transparent, + ], + ), + ), + ), + + // Main content + SafeArea(child: _buildContent(context, state.user)), + ], + ), + ); + }, + ); + } + + Widget _buildContent(BuildContext context, User user) { + String greeting(BuildContext context) { + final hour = DateTime.now().hour; + + if (hour >= 4 && hour < 10) { + return context.lang.good_morning; + } else if (hour >= 10 && hour < 15) { + return context.lang.good_afternoon; + } else if (hour >= 15 && hour < 18) { + return context.lang.good_evening; + } else { + return context.lang.good_night; + } + } + + return Padding( + padding: EdgeInsets.all(AppValue.padding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + // Top bar with enhanced animation + SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeInAnimation, + child: Transform.scale( + scale: _scaleAnimation.value, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppConstant.appName, + style: AppStyle.lg.copyWith( + color: AppColor.white.withOpacity(0.9), + fontWeight: FontWeight.w600, + letterSpacing: 0.3, + shadows: [ + Shadow( + color: Colors.black.withOpacity(0.2), + offset: const Offset(0, 1), + blurRadius: 2, + ), + ], + ), + ), + const SpaceHeight(2), + Text( + user.role.toTitleCase, + style: AppStyle.sm.copyWith( + color: AppColor.white.withOpacity(0.7), + fontSize: 11, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + // Notification icon + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.25), + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: AppColor.white.withOpacity(0.3), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: AppColor.white.withOpacity(0.2), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: const Icon( + Icons.notifications_none_rounded, + color: AppColor.white, + size: 20, + ), + ), + ], + ), + ), + ), + ), + + const SpaceHeight(24), + + // Greeting Section with enhanced animations + SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeInAnimation, + child: Transform.scale( + scale: _scaleAnimation.value, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${greeting(context)}, ${user.name}! 👋', + style: AppStyle.md.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w500, + shadows: [ + Shadow( + color: Colors.black.withOpacity(0.2), + offset: const Offset(0, 1), + blurRadius: 2, + ), + ], + ), + ), + ], + ), + ), + ), + ), + + const SpaceHeight(16), + + + // Today's highlight + FadeTransition( + opacity: _fadeInAnimation, + child: SlideTransition( + position: _slideAnimation, + child: HomeOmsetBalance(totalOmset: widget.totalRevenue, user: user), + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/omset_balance.dart b/lib/presentation/pages/home/widgets/omset_balance.dart new file mode 100644 index 0000000..c760e81 --- /dev/null +++ b/lib/presentation/pages/home/widgets/omset_balance.dart @@ -0,0 +1,233 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icon.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../../../common/theme/theme.dart'; +import '../../../../application/outlet/selected_outlet/selected_outlet_bloc.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../domain/user/user.dart'; +import '../../../components/spacer/spacer.dart'; + +class HomeOmsetBalance extends StatefulWidget { + final int totalOmset; + final User user; + const HomeOmsetBalance({super.key, required this.totalOmset, required this.user}); + + @override + State createState() => _HomeOmsetBalanceState(); +} + +class _HomeOmsetBalanceState extends State { + late DateTime _now; + late Timer _timer; + bool _isBalanceVisible = true; + + @override + void initState() { + super.initState(); + _now = DateTime.now(); + _timer = Timer.periodic(const Duration(seconds: 1), (_) { + setState(() => _now = DateTime.now()); + }); + } + + @override + void dispose() { + _timer.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 8), + clipBehavior: Clip.none, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.white.withOpacity(0.3), width: 1), + boxShadow: [ + BoxShadow( + color: AppColor.white.withOpacity(0.1), + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + children: [_top(context), _middle(context), _bottom(context)], + ), + ); + } + + Widget _bottom(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () {}, + child: Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: AppColor.white, + border: Border(top: BorderSide(color: AppColor.border)), + borderRadius: const BorderRadius.vertical( + bottom: Radius.circular(16), + ), + ), + child: Row( + children: [ + LineIcon(LineIcons.calendar, color: AppColor.black, size: 14), + SpaceWidth(6), + Expanded( + child: Text( + _now.toDate, + style: AppStyle.md.copyWith( + color: AppColor.black, + fontWeight: FontWeight.w600, + letterSpacing: 0.3, + ), + ), + ), + LineIcon(LineIcons.clock, color: AppColor.textSecondary, size: 14), + SpaceWidth(4), + Text( + _now.toHourMinuteSecond, + style: AppStyle.md.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontFeatures: [const FontFeature.tabularFigures()], + ), + ), + ], + ), + ), + ); + } + + Container _middle(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + decoration: BoxDecoration(color: AppColor.white), + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () {}, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.sales_today, + style: AppStyle.sm.copyWith( + color: AppColor.black, + fontWeight: FontWeight.w400, + letterSpacing: 0.3, + ), + ), + SpaceHeight(2), + AnimatedSwitcher( + duration: const Duration(milliseconds: 400), + transitionBuilder: (child, animation) { + return FadeTransition( + opacity: animation, + child: SlideTransition( + position: Tween( + begin: const Offset(0, 0.3), + end: Offset.zero, + ).animate(CurvedAnimation( + parent: animation, + curve: Curves.easeOutCubic, + )), + child: child, + ), + ); + }, + child: _isBalanceVisible + ? Text( + widget.totalOmset.currencyFormatRp, + key: const ValueKey('visible'), + style: AppStyle.xxl.copyWith( + color: AppColor.black, + fontWeight: FontWeight.w900, + letterSpacing: 0.3, + ), + ) + : Text( + 'Rp ••••••••', + key: const ValueKey('hidden'), + style: AppStyle.xl.copyWith( + color: AppColor.black, + fontWeight: FontWeight.w900, + letterSpacing: 2, + ), + ), + ), + ], + ), + ), + ), + GestureDetector( + onTap: () => setState(() => _isBalanceVisible = !_isBalanceVisible), + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 200), + child: LineIcon( + _isBalanceVisible ? LineIcons.eye : LineIcons.eyeSlash, + key: ValueKey(_isBalanceVisible), + color: AppColor.primary, + size: 16, + ), + ), + ), + ], + ), + ); + } + + GestureDetector _top(BuildContext context) { + return GestureDetector( + onTap: () {}, + child: BlocBuilder( + builder: (context, state) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + gradient: LinearGradient(colors: AppColor.primaryGradient), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(16), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + state.displayName, + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w600, + letterSpacing: 0.3, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + SpaceWidth(6), + LineIcon( + LineIcons.alternateExchange, + color: AppColor.white, + size: 14, + ), + ], + ), + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/presentation/pages/home/widgets/promo_banner.dart b/lib/presentation/pages/home/widgets/promo_banner.dart new file mode 100644 index 0000000..c302732 --- /dev/null +++ b/lib/presentation/pages/home/widgets/promo_banner.dart @@ -0,0 +1,324 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart'; +import '../../../../application/outlet/selected_outlet/selected_outlet_bloc.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/outlet/outlet.dart'; +import '../../../components/spacer/spacer.dart'; +import '../../../components/widgets/particle_card.dart'; + +class HomePromoBanner extends StatelessWidget { + const HomePromoBanner({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, outletListState) { + if (outletListState.isFetching && outletListState.outlets.isEmpty) { + return const _PromoBannerSkeleton(); + } + + if (outletListState.outlets.isEmpty) { + return const SizedBox.shrink(); + } + + return BlocBuilder( + builder: (context, selectedState) { + return Padding( + padding: const EdgeInsets.fromLTRB( + AppValue.padding, + 24, + AppValue.padding, + 0, + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + // Card "Semua Outlet" di posisi pertama + _AllOutletCard( + isSelected: selectedState.isAllOutlets, + onTap: () { + if (!selectedState.isAllOutlets) { + context + .read() + .add(const SelectedOutletEvent.cleared()); + } + }, + ), + const SpaceWidth(12), + for (int i = 0; i < outletListState.outlets.length; i++) ...[ + _OutletCard( + outlet: outletListState.outlets[i], + isSelected: selectedState.selectedOutletId == + outletListState.outlets[i].id, + onTap: () { + final tapped = outletListState.outlets[i]; + if (selectedState.selectedOutletId == tapped.id) { + // Tap outlet yang sama → deselect (Semua Outlet) + context + .read() + .add(const SelectedOutletEvent.cleared()); + } else { + context + .read() + .add(SelectedOutletEvent.selected(tapped)); + } + }, + ), + if (i < outletListState.outlets.length - 1) + const SpaceWidth(12), + ], + ], + ), + ), + ); + }, + ); + }, + ); + } +} + +class _AllOutletCard extends StatelessWidget { + final bool isSelected; + final VoidCallback onTap; + + const _AllOutletCard({ + required this.isSelected, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + width: 130, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: isSelected ? AppColor.white : Colors.transparent, + width: 2, + ), + boxShadow: isSelected + ? [ + BoxShadow( + color: AppColor.white.withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ] + : [], + ), + child: Opacity( + opacity: isSelected ? 1.0 : 0.55, + child: ParticleCard( + height: 110, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + decorationOpacity: 0.8, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + const Spacer(), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.25), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.store_rounded, + color: AppColor.white, + size: 12, + ), + const SpaceWidth(4), + Text( + 'Semua', + style: AppStyle.xs.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w700, + fontSize: 9, + ), + ), + ], + ), + ), + ], + ), + const SpaceHeight(6), + Text( + 'Semua Outlet', + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w800, + height: 1.25, + ), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ), + ), + ); + } +} + +class _OutletCard extends StatelessWidget { + final Outlet outlet; + final bool isSelected; + final VoidCallback onTap; + + const _OutletCard({ + required this.outlet, + required this.isSelected, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + width: 130, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: isSelected ? AppColor.white : Colors.transparent, + width: 2, + ), + boxShadow: isSelected + ? [ + BoxShadow( + color: AppColor.white.withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ] + : [], + ), + child: Opacity( + opacity: isSelected ? 1.0 : 0.55, + child: ParticleCard( + height: 110, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + decorationOpacity: 0.8, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + const Spacer(), + _buildStatusBadge(outlet.isActive), + ], + ), + const SpaceHeight(6), + Text( + outlet.name, + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w800, + height: 1.25, + ), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ), + ), + ); + } + + Widget _buildStatusBadge(bool isActive) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: isActive + ? AppColor.success.withOpacity(0.9) + : AppColor.error.withOpacity(0.9), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: (isActive ? AppColor.success : AppColor.error) + .withOpacity(0.3), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + isActive ? Icons.check_circle : Icons.warning_rounded, + color: AppColor.white, + size: 12, + ), + const SpaceWidth(4), + Text( + isActive ? 'Sehat' : 'Tidak Sehat', + style: AppStyle.xs.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w700, + fontSize: 9, + ), + ), + ], + ), + ); + } +} + +class _PromoBannerSkeleton extends StatelessWidget { + const _PromoBannerSkeleton(); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB( + AppValue.padding, + 24, + AppValue.padding, + 0, + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + _skeletonCard(), + const SpaceWidth(12), + _skeletonCard(), + const SpaceWidth(12), + _skeletonCard(), + ], + ), + ), + ); + } + + Widget _skeletonCard() { + return Container( + width: 130, + height: 110, + decoration: BoxDecoration( + color: AppColor.border, + borderRadius: BorderRadius.circular(12), + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/stats.dart b/lib/presentation/pages/home/widgets/stats.dart new file mode 100644 index 0000000..1b91665 --- /dev/null +++ b/lib/presentation/pages/home/widgets/stats.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../components/spacer/spacer.dart'; +import 'stats_tile.dart'; +import 'title.dart'; + +class HomeStats extends StatelessWidget { + final DashboardOverview overview; + const HomeStats({super.key, required this.overview}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 24, + horizontal: AppValue.padding, + ).copyWith(bottom: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HomeTitle(title: context.lang.today_summary), + const SpaceHeight(20), + Row( + children: [ + Expanded( + child: HomeStatsTile( + title: context.lang.order, + value: overview.totalOrders.toString(), + icon: Icons.receipt_long_rounded, + color: AppColor.info, + subtitle: context.lang.today, + ), + ), + + const SpaceWidth(16), + Expanded( + child: HomeStatsTile( + title: context.lang.new_customer, + value: overview.totalCustomers.toString(), + icon: Icons.person_add_outlined, + color: AppColor.primary, + subtitle: overview.totalCustomers < 1 + ? context.lang.today + : context.lang.increase, + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: HomeStatsTile( + title: context.lang.refund, + value: overview.refundedOrders.toString(), + icon: LineIcons.alternateExchange, + color: AppColor.warning, + subtitle: context.lang.today, + ), + ), + const SpaceWidth(16), + Expanded( + child: HomeStatsTile( + title: context.lang.void_text, + value: overview.voidedOrders.toString(), + icon: Icons.cancel_rounded, + color: AppColor.error, + subtitle: context.lang.today, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/stats_tile.dart b/lib/presentation/pages/home/widgets/stats_tile.dart new file mode 100644 index 0000000..054163b --- /dev/null +++ b/lib/presentation/pages/home/widgets/stats_tile.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; +import '../../../components/spacer/spacer.dart'; + +class HomeStatsTile extends StatelessWidget { + final String title; + final String value; + final IconData icon; + final Color color; + final String subtitle; + const HomeStatsTile({ + super.key, + required this.title, + required this.value, + required this.icon, + required this.color, + required this.subtitle, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(AppValue.radius), + border: Border.all(color: AppColor.border.withOpacity(0.5)), + boxShadow: [ + BoxShadow( + color: color.withOpacity(0.08), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: 0, + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [color.withOpacity(0.1), color.withOpacity(0.05)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: color.withOpacity(0.2), width: 1), + ), + child: Icon(icon, color: color, size: 20), + ), + ], + ), + const SpaceHeight(16), + FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Text( + value, + style: AppStyle.xxl.copyWith( + fontWeight: FontWeight.w800, + color: AppColor.textPrimary, + letterSpacing: -0.5, + ), + ), + ), + const SpaceHeight(4), + Text( + title, + style: AppStyle.md.copyWith( + fontSize: 13, + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SpaceHeight(2), + Text( + subtitle, + style: AppStyle.xs.copyWith( + color: AppColor.textLight, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/title.dart b/lib/presentation/pages/home/widgets/title.dart new file mode 100644 index 0000000..10cc2e8 --- /dev/null +++ b/lib/presentation/pages/home/widgets/title.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class HomeTitle extends StatelessWidget { + final String title; + const HomeTitle({super.key, required this.title}); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + style: AppStyle.h6.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + letterSpacing: -0.5, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/home/widgets/top_product.dart b/lib/presentation/pages/home/widgets/top_product.dart new file mode 100644 index 0000000..b95b8a1 --- /dev/null +++ b/lib/presentation/pages/home/widgets/top_product.dart @@ -0,0 +1,45 @@ +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 'title.dart'; +import 'top_product_tile.dart'; + +class HomeTopProduct extends StatelessWidget { + final List products; + const HomeTopProduct({super.key, required this.products}); + + @override + Widget build(BuildContext context) { + if (products.isEmpty) { + return const SizedBox.shrink(); + } + + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 24, + horizontal: AppValue.padding, + ).copyWith(bottom: 0), + child: Column( + children: [ + HomeTitle(title: context.lang.today_top_product), + SpaceHeight(20), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: products.length, + padding: EdgeInsets.zero, + itemBuilder: (context, index) { + return HomeTopProductTile( + product: products[index], + ranking: index + 1, + ); + }, + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/home/widgets/top_product_tile.dart b/lib/presentation/pages/home/widgets/top_product_tile.dart new file mode 100644 index 0000000..108163f --- /dev/null +++ b/lib/presentation/pages/home/widgets/top_product_tile.dart @@ -0,0 +1,287 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; + +class HomeTopProductTile extends StatelessWidget { + final DashboardTopProduct product; + final int ranking; + final VoidCallback? onTap; + + const HomeTopProductTile({ + super.key, + required this.product, + required this.ranking, + this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 12), + child: Material( + elevation: 2, + borderRadius: BorderRadius.circular(16), + shadowColor: AppColor.primary.withOpacity(0.1), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(16), + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [AppColor.white, AppColor.backgroundLight], + ), + border: Border.all(color: AppColor.borderLight, width: 1), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header Row - Ranking dan Revenue + Row( + children: [ + _buildRankingBadge(context), + const Spacer(), + _buildRevenueDisplay(), + ], + ), + + const SizedBox(height: 12), + + // Product Name + Text( + product.productName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + + const SizedBox(height: 8), + + // Category + _buildCategoryChip(), + + const SizedBox(height: 12), + + // Metrics dalam Grid 2x2 + _buildMetricsGrid(context), + ], + ), + ), + ), + ), + ); + } + + Widget _buildRankingBadge(BuildContext context) { + Color badgeColor; + IconData icon; + + switch (ranking) { + case 1: + badgeColor = const Color(0xFFFFD700); // Gold + icon = Icons.emoji_events; + break; + case 2: + badgeColor = const Color(0xFFC0C0C0); // Silver + icon = Icons.emoji_events; + break; + case 3: + badgeColor = const Color(0xFFCD7F32); // Bronze + icon = Icons.emoji_events; + break; + default: + badgeColor = AppColor.primary; + icon = Icons.star; + } + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: badgeColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: badgeColor.withOpacity(0.3), width: 1.5), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, color: badgeColor, size: 16), + const SizedBox(width: 6), + Text( + '${context.lang.rank} #$ranking', + style: AppStyle.sm.copyWith( + color: badgeColor, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ); + } + + Widget _buildCategoryChip() { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: AppColor.secondary.withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColor.secondary.withOpacity(0.3), + width: 1, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.category_outlined, size: 14, color: AppColor.secondary), + const SizedBox(width: 6), + Flexible( + child: Text( + product.categoryName, + style: AppStyle.sm.copyWith( + color: AppColor.secondary, + fontWeight: FontWeight.w500, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + } + + Widget _buildMetricsGrid(BuildContext context) { + return Row( + children: [ + Expanded( + child: Column( + children: [ + _buildMetricCard( + icon: Icons.shopping_cart_outlined, + label: context.lang.quantity_sold, + value: product.quantitySold.toString(), + color: AppColor.info, + ), + const SizedBox(height: 8), + _buildMetricCard( + icon: Icons.attach_money, + label: context.lang.average_price, + value: product.averagePrice.round().currencyFormatRp, + color: AppColor.success, + ), + ], + ), + ), + const SizedBox(width: 8), + Expanded( + child: Column( + children: [ + _buildMetricCard( + icon: Icons.receipt_outlined, + label: context.lang.total_orders, + value: product.orderCount.toString(), + color: AppColor.warning, + ), + const SizedBox(height: 8), + _buildMetricCard( + icon: Icons.trending_up, + label: context.lang.perfomance, + value: 'Top $ranking', + color: AppColor.primary, + ), + ], + ), + ), + ], + ); + } + + Widget _buildMetricCard({ + required IconData icon, + required String label, + required String value, + required Color color, + }) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: color.withOpacity(0.05), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: color.withOpacity(0.2), width: 1), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(icon, size: 16, color: color), + const SizedBox(width: 6), + Expanded( + child: Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SizedBox(height: 6), + Text( + value, + style: AppStyle.md.copyWith( + color: color, + fontWeight: FontWeight.bold, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ); + } + + Widget _buildRevenueDisplay() { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + product.revenue.currencyFormatRp, + style: AppStyle.md.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/inventory/inventory_page.dart b/lib/presentation/pages/inventory/inventory_page.dart new file mode 100644 index 0000000..ce2a57c --- /dev/null +++ b/lib/presentation/pages/inventory/inventory_page.dart @@ -0,0 +1,431 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import 'widgets/ingredient_tile.dart'; +import 'widgets/product_tile.dart'; +import 'widgets/stat_card.dart'; +import 'widgets/tabbar_delegate.dart'; + +// Custom SliverPersistentHeaderDelegate untuk TabBar + +@RoutePage() +class InventoryPage extends StatefulWidget implements AutoRouteWrapper { + const InventoryPage({super.key}); + + @override + State createState() => _InventoryPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (_) => + getIt() + ..add(InventoryAnalyticLoaderEvent.fetched()), + child: this, + ); +} + +class _InventoryPageState extends State + with TickerProviderStateMixin { + late AnimationController _fadeAnimationController; + late AnimationController _slideAnimationController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + late TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + + _fadeAnimationController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + _slideAnimationController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _fadeAnimationController, + curve: Curves.easeInOut, + ), + ); + + _slideAnimation = + Tween(begin: const Offset(0.0, 0.3), end: Offset.zero).animate( + CurvedAnimation( + parent: _slideAnimationController, + curve: Curves.easeOutBack, + ), + ); + + _fadeAnimationController.forward(); + _slideAnimationController.forward(); + } + + @override + void dispose() { + _fadeAnimationController.dispose(); + _slideAnimationController.dispose(); + _tabController.dispose(); + super.dispose(); + } + + Color getStatusColor(String status) { + switch (status) { + case 'available': + return AppColor.success; + case 'low_stock': + return AppColor.warning; + case 'out_of_stock': + return AppColor.error; + default: + return AppColor.textSecondary; + } + } + + String getStatusText(String status) { + switch (status) { + case 'available': + return context.lang.available; + case 'low_stock': + return context.lang.low_stock; + case 'out_of_stock': + return context.lang.out_of_stock; + default: + return 'Unknown'; + } + } + + @override + Widget build(BuildContext context) { + return BlocListener< + InventoryAnalyticLoaderBloc, + InventoryAnalyticLoaderState + >( + listenWhen: (previous, current) => + previous.dateFrom != current.dateFrom || + previous.dateTo != current.dateTo, + listener: (context, state) { + context.read().add( + InventoryAnalyticLoaderEvent.fetched(), + ); + }, + child: Scaffold( + backgroundColor: AppColor.background, + body: + BlocBuilder< + InventoryAnalyticLoaderBloc, + InventoryAnalyticLoaderState + >( + builder: (context, state) { + return FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: NestedScrollView( + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + _buildSliverAppBar(), + SliverPersistentHeader( + pinned: true, + delegate: InventorySliverTabBarDelegate( + startDate: state.dateFrom, + endDate: state.dateTo, + onDateRangeChanged: (startDate, endDate) { + context.read().add( + InventoryAnalyticLoaderEvent.rangeDateChanged( + startDate!, + endDate!, + ), + ); + }, + tabBar: TabBar( + controller: _tabController, + indicator: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(25), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + indicatorSize: TabBarIndicatorSize.tab, + indicatorPadding: const EdgeInsets.all(6), + labelColor: AppColor.textWhite, + unselectedLabelColor: AppColor.textSecondary, + labelStyle: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 13, + ), + unselectedLabelStyle: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 13, + ), + dividerColor: Colors.transparent, + splashFactory: NoSplash.splashFactory, + overlayColor: MaterialStateProperty.all( + Colors.transparent, + ), + tabs: [ + Tab( + height: 40, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.inventory_2_rounded, + size: 16, + ), + SizedBox(width: 6), + Text(context.lang.product), + ], + ), + ), + ), + Tab( + height: 40, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Icon( + Icons.restaurant_menu_rounded, + size: 16, + ), + SizedBox(width: 6), + Text(context.lang.ingredients), + ], + ), + ), + ), + ], + ), + ), + ), + ]; + }, + body: TabBarView( + controller: _tabController, + children: [ + _buildProductTab(state.inventoryAnalytic), + _buildIngredientTab(state.inventoryAnalytic), + ], + ), + ), + ), + ); + }, + ), + ), + ); + } + + Widget _buildSliverAppBar() { + return SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.inventory), + ); + } + + Widget _buildProductTab(InventoryAnalytic inventoryAnalytic) { + return CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: _buildProductStats(inventoryAnalytic.summary), + ), + SliverPadding( + padding: const EdgeInsets.all(16), + sliver: SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => + InventoryProductTile(item: inventoryAnalytic.products[index]), + childCount: inventoryAnalytic.products.length, + ), + ), + ), + ], + ); + } + + Widget _buildIngredientTab(InventoryAnalytic inventoryAnalytic) { + return CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: _buildIngredientStats(inventoryAnalytic.summary), + ), + SliverPadding( + padding: const EdgeInsets.all(16), + sliver: SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => InventoryIngredientTile( + item: inventoryAnalytic.ingredients[index], + ), + childCount: inventoryAnalytic.ingredients.length, + ), + ), + ), + ], + ); + } + + Widget _buildProductStats(InventorySummary inventory) { + return Container( + margin: const EdgeInsets.all(16), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: _buildStatCard( + context.lang.total_products, + inventory.totalProducts.toString(), + Icons.inventory_2_rounded, + AppColor.primary, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildStatCard( + context.lang.total_sold, + inventory.totalSoldProducts.toString(), + Icons.check_circle_rounded, + AppColor.success, + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: _buildStatCard( + context.lang.low_stock, + inventory.lowStockProducts.toString(), + Icons.warning_rounded, + AppColor.warning, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildStatCard( + context.lang.zero_stock, + inventory.zeroStockProducts.toString(), + Icons.error_rounded, + AppColor.error, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildIngredientStats(InventorySummary inventory) { + return Container( + margin: const EdgeInsets.all(16), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: _buildStatCard( + context.lang.total_ingredients, + inventory.totalIngredients.toString(), + Icons.restaurant_menu_rounded, + AppColor.primary, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildStatCard( + context.lang.total_sold, + inventory.totalSoldIngredients.toString(), + Icons.check_circle_rounded, + AppColor.success, + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: _buildStatCard( + context.lang.low_stock, + inventory.lowStockIngredients.toString(), + Icons.warning_rounded, + AppColor.warning, + ), + ), + const SizedBox(width: 16), + Expanded( + child: _buildStatCard( + context.lang.zero_stock, + inventory.zeroStockIngredients.toString(), + Icons.error_rounded, + AppColor.error, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildStatCard( + String title, + String value, + IconData icon, + Color color, + ) { + return TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 800), + builder: (context, animationValue, child) { + return Transform.scale( + scale: animationValue, + child: InventoryStatCard( + title: title, + value: value, + icon: icon, + color: color, + ), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/inventory/widgets/ingredient_tile.dart b/lib/presentation/pages/inventory/widgets/ingredient_tile.dart new file mode 100644 index 0000000..8f40077 --- /dev/null +++ b/lib/presentation/pages/inventory/widgets/ingredient_tile.dart @@ -0,0 +1,476 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../components/spacer/spacer.dart'; + +class InventoryIngredientTile extends StatelessWidget { + final InventoryIngredient item; + const InventoryIngredientTile({super.key, required this.item}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _getStatusColor().withOpacity(0.2), + width: 1.5, + ), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.08), + blurRadius: 12, + offset: const Offset(0, 4), + ), + BoxShadow( + color: AppColor.textLight.withOpacity(0.06), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + children: [ + // Main Row + Row( + children: [ + // Enhanced Icon Container + Container( + width: 65, + height: 65, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: _getGradientColors(), + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.2), + blurRadius: 8, + offset: const Offset(0, 3), + ), + ], + ), + child: Stack( + children: [ + Center( + child: Icon( + _getIngredientIcon(), + size: 28, + color: AppColor.white, + ), + ), + // Status indicator dot + Positioned( + top: 6, + right: 6, + child: Container( + width: 12, + height: 12, + decoration: BoxDecoration( + color: AppColor.white, + shape: BoxShape.circle, + border: Border.all( + color: _getStatusColor(), + width: 2, + ), + ), + child: Center( + child: Container( + width: 4, + height: 4, + decoration: BoxDecoration( + color: _getStatusColor(), + shape: BoxShape.circle, + ), + ), + ), + ), + ), + ], + ), + ), + + const SpaceWidth(16), + + // Content Section + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Ingredient Name + Text( + item.ingredientName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + height: 1.2, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + + SpaceHeight(6), + + // Stock Information Row + Row( + children: [ + Icon( + LineIcons.warehouse, + size: 14, + color: AppColor.textSecondary, + ), + const SpaceWidth(4), + Text( + 'Stok: ', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.quantity)} ${item.unitName}', + style: AppStyle.sm.copyWith( + color: _getQuantityColor(), + fontWeight: FontWeight.w700, + ), + ), + ], + ), + + SpaceHeight(4), + + // Reorder Level Information + Row( + children: [ + Icon( + LineIcons.exclamationTriangle, + size: 14, + color: AppColor.warning, + ), + const SpaceWidth(4), + Text( + 'Min: ', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.reorderLevel)} ${item.unitName}', + style: AppStyle.sm.copyWith( + color: AppColor.warning, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + + SpaceHeight(6), + + // Unit Cost + Row( + children: [ + Icon( + LineIcons.dollarSign, + size: 14, + color: AppColor.success, + ), + const SpaceWidth(4), + Text( + item.unitCost.currencyFormatRp, + style: AppStyle.sm.copyWith( + color: AppColor.success, + fontWeight: FontWeight.w700, + ), + ), + Text( + '/${item.unitName}', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ], + ), + ), + + // Status Badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: _getStatusColor(), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + _getStatusText(), + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.white, + fontSize: 11, + ), + ), + ], + ), + ), + ], + ), + + // Additional Information Card (if low stock or has movements) + if (item.isLowStock || item.totalIn > 0 || item.totalOut > 0) ...[ + SpaceHeight(12), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.borderLight, width: 0.5), + ), + child: Column( + children: [ + // Warning message for low stock + if (item.isLowStock && !item.isZeroStock) ...[ + Row( + children: [ + Icon( + LineIcons.exclamationTriangle, + size: 16, + color: AppColor.warning, + ), + const SpaceWidth(6), + Expanded( + child: Text( + 'Stok mendekati batas minimum (${item.reorderLevel} ${item.unitName})', + style: AppStyle.xs.copyWith( + color: AppColor.warning, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + if (item.totalIn > 0 || item.totalOut > 0) SpaceHeight(8), + ], + + // Movement Information + if (item.totalIn > 0 || item.totalOut > 0) + Row( + children: [ + // Stock In + if (item.totalIn > 0) ...[ + Expanded( + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: AppColor.success.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Icon( + LineIcons.arrowUp, + size: 12, + color: AppColor.success, + ), + ), + const SpaceWidth(6), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Masuk', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.totalIn)} ${item.unitName}', + style: AppStyle.xs.copyWith( + color: AppColor.success, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ], + ), + ), + ], + + // Stock Out + if (item.totalOut > 0) ...[ + if (item.totalIn > 0) const SpaceWidth(16), + Expanded( + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Icon( + LineIcons.arrowDown, + size: 12, + color: AppColor.error, + ), + ), + const SpaceWidth(6), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Keluar', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + '${NumberFormat('#,###', 'id_ID').format(item.totalOut)} ${item.unitName}', + style: AppStyle.xs.copyWith( + color: AppColor.error, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ], + ), + ), + ], + + // Total Value + if (item.totalValue > 0) ...[ + const SpaceWidth(16), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Nilai Total', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + _formatCurrencyShort(item.totalValue), + style: AppStyle.xs.copyWith( + color: AppColor.info, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ], + ], + ), + ], + ), + ), + ], + ], + ), + ); + } + + // Helper methods + Color _getStatusColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.success; + } + + List _getGradientColors() { + if (item.isZeroStock) { + return [AppColor.error, AppColor.error.withOpacity(0.7)]; + } + if (item.isLowStock) { + return [AppColor.warning, AppColor.warning.withOpacity(0.7)]; + } + return [AppColor.success, AppColor.success.withOpacity(0.7)]; + } + + Color _getQuantityColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.textPrimary; + } + + String _getStatusText() { + if (item.isZeroStock) return 'HABIS'; + if (item.isLowStock) return 'MINIM'; + return 'TERSEDIA'; + } + + IconData _getIngredientIcon() { + final name = item.ingredientName.toLowerCase(); + + // Food ingredients + if (name.contains('tepung') || name.contains('flour')) { + return LineIcons.breadSlice; + } else if (name.contains('gula') || name.contains('sugar')) { + return LineIcons.cube; + } else if (name.contains('garam') || name.contains('salt')) { + return LineIcons.breadSlice; + } else if (name.contains('minyak') || name.contains('oil')) { + return LineIcons.tint; + } else if (name.contains('susu') || name.contains('milk')) { + return LineIcons.glasses; + } else if (name.contains('telur') || name.contains('egg')) { + return LineIcons.egg; + } else if (name.contains('daging') || name.contains('meat')) { + return LineIcons.hamburger; + } else if (name.contains('sayur') || name.contains('vegetable')) { + return LineIcons.carrot; + } else if (name.contains('bumbu') || name.contains('spice')) { + return LineIcons.leaf; + } else if (name.contains('buah') || name.contains('fruit')) { + return LineIcons.apple; + } else if (name.contains('beras') || name.contains('rice')) { + return LineIcons.seedling; + } else if (name.contains('kopi') || name.contains('coffee')) { + return LineIcons.coffee; + } + + // Default ingredient icon + return LineIcons.utensils; + } + + String _formatCurrencyShort(int amount) { + if (amount.abs() >= 1000000000) { + return 'Rp ${(amount / 1000000000).toStringAsFixed(1)}B'; + } else if (amount.abs() >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; + } else if (amount.abs() >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(0)}K'; + } else { + return 'Rp ${NumberFormat('#,###', 'id_ID').format(amount)}'; + } + } +} diff --git a/lib/presentation/pages/inventory/widgets/product_tile.dart b/lib/presentation/pages/inventory/widgets/product_tile.dart new file mode 100644 index 0000000..916fcf9 --- /dev/null +++ b/lib/presentation/pages/inventory/widgets/product_tile.dart @@ -0,0 +1,517 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:intl/intl.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../components/spacer/spacer.dart'; + +class InventoryProductTile extends StatelessWidget { + final InventoryProduct item; + const InventoryProductTile({super.key, required this.item}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _getStatusColor().withOpacity(0.2), + width: 1.5, + ), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.06), + blurRadius: 16, + offset: const Offset(0, 6), + ), + BoxShadow( + color: AppColor.textLight.withOpacity(0.08), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + children: [ + // Main Content Row + Row( + children: [ + // Enhanced Product Icon + Container( + width: 70, + height: 70, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: _getGradientColors(), + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(18), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.25), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Stack( + children: [ + Center( + child: Icon( + _getCategoryIcon(), + size: 32, + color: AppColor.white, + ), + ), + // Status indicator + Positioned( + top: 6, + right: 6, + child: Container( + width: 14, + height: 14, + decoration: BoxDecoration( + color: AppColor.white, + shape: BoxShape.circle, + border: Border.all( + color: _getStatusColor(), + width: 2.5, + ), + ), + child: Center( + child: Container( + width: 5, + height: 5, + decoration: BoxDecoration( + color: _getStatusColor(), + shape: BoxShape.circle, + ), + ), + ), + ), + ), + ], + ), + ), + + const SpaceWidth(16), + + // Product Information + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Product Name and Category Row + Row( + children: [ + Expanded( + child: Text( + item.productName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + height: 1.2, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + const SpaceWidth(8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), + border: Border.all( + color: AppColor.primary.withOpacity(0.15), + width: 0.5, + ), + ), + child: Text( + item.categoryName, + style: AppStyle.xs.copyWith( + fontSize: 9, + fontWeight: FontWeight.w600, + color: AppColor.primary, + letterSpacing: 0.2, + ), + ), + ), + ], + ), + + SpaceHeight(8), + + // Price and Status Row + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Price + Text( + item.unitCost.currencyFormatRp, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.w800, + color: AppColor.success, + fontSize: 16, + ), + ), + // Status Badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + decoration: BoxDecoration( + color: _getStatusColor(), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: _getStatusColor().withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Text( + item.isZeroStock + ? context.lang.out_of_stock + : item.isLowStock + ? context.lang.low_stock + : context.lang.available, + style: AppStyle.xs.copyWith( + fontSize: 10, + fontWeight: FontWeight.w700, + color: AppColor.white, + ), + ), + ), + ], + ), + + SpaceHeight(10), + + // Stock Information Grid + Row( + children: [ + // Quantity Info + Expanded( + child: _buildInfoItem( + LineIcons.boxes, + context.lang.stock, + '${NumberFormat('#,###', 'id_ID').format(item.quantity)} pcs', + _getQuantityColor(), + ), + ), + const SpaceWidth(16), + // Total Value Info + Expanded( + child: _buildInfoItem( + LineIcons.dollarSign, + context.lang.value_text, + _formatCurrencyShort(item.totalValue), + AppColor.info, + ), + ), + ], + ), + ], + ), + ), + ], + ), + + // Additional Information (conditionally shown) + if (_shouldShowAdditionalInfo()) ...[ + SpaceHeight(12), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.borderLight, width: 0.5), + ), + child: Column( + children: [ + // Low Stock Warning + if (item.isLowStock && !item.isZeroStock) ...[ + Row( + children: [ + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + color: AppColor.warning.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + LineIcons.exclamationTriangle, + size: 16, + color: AppColor.warning, + ), + ), + const SpaceWidth(10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.low_stock, + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.warning, + ), + ), + Text( + context.lang.low_stock_desc( + NumberFormat( + '#,###', + 'id_ID', + ).format(item.reorderLevel), + ), + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ], + ), + ], + + // Zero Stock Warning + if (item.isZeroStock) ...[ + Row( + children: [ + Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration( + color: AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + LineIcons.timesCircle, + size: 16, + color: AppColor.error, + ), + ), + const SpaceWidth(10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.out_of_stock, + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.error, + ), + ), + Text( + context.lang.out_of_stock_desc, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ], + ), + ], + + // Movement Information + if (_hasMovementData()) ...[ + if ((item.isLowStock || item.isZeroStock)) SpaceHeight(12), + Row( + children: [ + if (item.totalIn > 0) + Expanded( + child: _buildMovementInfo( + LineIcons.arrowUp, + context.lang.in_text, + '${NumberFormat('#,###', 'id_ID').format(item.totalIn)} pcs', + AppColor.success, + ), + ), + if (item.totalIn > 0 && item.totalOut > 0) + const SpaceWidth(16), + if (item.totalOut > 0) + Expanded( + child: _buildMovementInfo( + LineIcons.arrowDown, + context.lang.out_text, + '${NumberFormat('#,###', 'id_ID').format(item.totalOut)} pcs', + AppColor.error, + ), + ), + ], + ), + ], + ], + ), + ), + ], + ], + ), + ); + } + + Widget _buildInfoItem( + IconData icon, + String label, + String value, + Color valueColor, + ) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: AppColor.borderLight, width: 0.5), + ), + child: Row( + children: [ + Icon(icon, size: 14, color: AppColor.textSecondary), + const SpaceWidth(6), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: AppStyle.xs.copyWith( + fontSize: 10, + fontWeight: FontWeight.w500, + color: AppColor.textSecondary, + ), + ), + SpaceHeight(1), + Text( + value, + style: AppStyle.xs.copyWith( + fontSize: 11, + fontWeight: FontWeight.w700, + color: valueColor, + ), + ), + ], + ), + ), + ], + ), + ); + } + + Widget _buildMovementInfo( + IconData icon, + String label, + String value, + Color color, + ) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Icon(icon, size: 12, color: color), + ), + const SpaceWidth(8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Text( + value, + style: AppStyle.xs.copyWith( + color: color, + fontWeight: FontWeight.w700, + fontSize: 11, + ), + ), + ], + ), + ], + ); + } + + // Helper methods + bool _shouldShowAdditionalInfo() { + return item.isLowStock || item.isZeroStock || _hasMovementData(); + } + + bool _hasMovementData() { + return item.totalIn > 0 || item.totalOut > 0; + } + + Color _getStatusColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.success; + } + + List _getGradientColors() { + if (item.isZeroStock) { + return [AppColor.error, AppColor.error.withOpacity(0.7)]; + } + if (item.isLowStock) { + return [AppColor.warning, AppColor.warning.withOpacity(0.7)]; + } + return [AppColor.primary, AppColor.primary.withOpacity(0.7)]; + } + + Color _getQuantityColor() { + if (item.isZeroStock) return AppColor.error; + if (item.isLowStock) return AppColor.warning; + return AppColor.textPrimary; + } + + IconData _getCategoryIcon() { + final category = item.categoryName.toLowerCase(); + if (category.contains('elektronik') || category.contains('gadget')) { + return LineIcons.mobilePhone; + } else if (category.contains('fashion') || category.contains('pakaian')) { + return LineIcons.tShirt; + } else if (category.contains('makanan') || category.contains('food')) { + return LineIcons.utensils; + } else if (category.contains('kesehatan') || category.contains('health')) { + return LineIcons.medkit; + } else if (category.contains('rumah') || category.contains('home')) { + return LineIcons.home; + } else if (category.contains('olahraga') || category.contains('sport')) { + return LineIcons.dumbbell; + } + return LineIcons.box; + } + + String _formatCurrencyShort(int amount) { + if (amount.abs() >= 1000000000) { + return 'Rp ${(amount / 1000000000).toStringAsFixed(1)}B'; + } else if (amount.abs() >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}M'; + } else if (amount.abs() >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(0)}K'; + } else { + return 'Rp ${NumberFormat('#,###', 'id_ID').format(amount)}'; + } + } +} diff --git a/lib/presentation/pages/inventory/widgets/stat_card.dart b/lib/presentation/pages/inventory/widgets/stat_card.dart new file mode 100644 index 0000000..c418b06 --- /dev/null +++ b/lib/presentation/pages/inventory/widgets/stat_card.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; +import '../../../components/spacer/spacer.dart'; + +class InventoryStatCard extends StatelessWidget { + final String title; + final String value; + final IconData icon; + final Color color; + const InventoryStatCard({ + super.key, + required this.title, + required this.value, + required this.icon, + required this.color, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: color.withOpacity(0.1), + blurRadius: 15, + offset: const Offset(0, 5), + ), + ], + border: Border.all(color: color.withOpacity(0.2), width: 1.5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [color.withOpacity(0.2), color.withOpacity(0.1)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(icon, color: color, size: 24), + ), + const Spacer(), + ], + ), + SpaceHeight(16), + Text( + title, + style: AppStyle.md.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + SpaceHeight(4), + Text( + value, + style: AppStyle.h3.copyWith( + color: color, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/inventory/widgets/tabbar_delegate.dart b/lib/presentation/pages/inventory/widgets/tabbar_delegate.dart new file mode 100644 index 0000000..8814d96 --- /dev/null +++ b/lib/presentation/pages/inventory/widgets/tabbar_delegate.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; +import '../../../components/field/date_range_picker_field.dart'; + +class InventorySliverTabBarDelegate extends SliverPersistentHeaderDelegate { + final TabBar tabBar; + final DateTime? startDate; + final DateTime? endDate; + final Function(DateTime?, DateTime?)? onDateRangeChanged; + + InventorySliverTabBarDelegate({ + required this.tabBar, + this.startDate, + this.endDate, + this.onDateRangeChanged, + }); + + @override + double get minExtent => 120; // Increased height to accommodate date picker + + @override + double get maxExtent => 120; + + @override + Widget build( + BuildContext context, + double shrinkOffset, + bool overlapsContent, + ) { + return Container( + decoration: BoxDecoration( + color: AppColor.surface, + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), + child: Column( + children: [ + // Date Range Picker Section + if (onDateRangeChanged != null) + Expanded( + child: DateRangePickerField( + maxDate: DateTime.now(), + startDate: startDate, + endDate: endDate, + onChanged: onDateRangeChanged!, + ), + ), + const SizedBox(height: 8), + // Tab Bar Section + Container( + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: AppColor.primary.withOpacity(0.1), + width: 1, + ), + ), + child: tabBar, + ), + ], + ), + ); + } + + @override + bool shouldRebuild(InventorySliverTabBarDelegate oldDelegate) { + return oldDelegate.startDate != startDate || + oldDelegate.endDate != endDate || + oldDelegate.tabBar != tabBar; + } +} diff --git a/lib/presentation/pages/language/language_page.dart b/lib/presentation/pages/language/language_page.dart new file mode 100644 index 0000000..34993b0 --- /dev/null +++ b/lib/presentation/pages/language/language_page.dart @@ -0,0 +1,53 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../application/language/language_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../infrastructure/language/language.dart'; +import 'widgets/language_tile.dart'; + +@RoutePage() +class LanguagePage extends StatelessWidget { + const LanguagePage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + appBar: AppBar( + title: Text(context.lang.select_language), + elevation: 0, + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + onPressed: () => context.router.back(), + ), + ), + body: BlocBuilder( + builder: (context, state) { + return ListView.builder( + padding: const EdgeInsets.all(16), + itemCount: languages.length, + itemBuilder: (context, index) { + final language = languages[index]; + final isSelected = + state.language.locale.languageCode == + language.locale.languageCode + ? true + : false; + + return LanguageTile( + isSelected: isSelected, + language: language, + onTap: () => context.read().add( + LanguageEvent.changeLanguage(language), + ), + ); + }, + ); + }, + ), + ); + } +} diff --git a/lib/presentation/pages/language/widgets/language_tile.dart b/lib/presentation/pages/language/widgets/language_tile.dart new file mode 100644 index 0000000..82721d8 --- /dev/null +++ b/lib/presentation/pages/language/widgets/language_tile.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; +import '../../../../domain/language/language.dart'; + +class LanguageTile extends StatelessWidget { + final bool isSelected; + final Language language; + final Function() onTap; + const LanguageTile({ + super.key, + required this.isSelected, + required this.language, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: isSelected ? AppColor.primary : AppColor.borderLight, + width: isSelected ? 2 : 1, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + leading: Container( + width: 48, + height: 48, + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(24), + ), + child: Center( + child: Text(language.path, style: const TextStyle(fontSize: 24)), + ), + ), + title: Text( + language.name, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + + color: isSelected ? AppColor.primary : AppColor.textPrimary, + ), + ), + subtitle: Text( + language.nativeName, + style: AppStyle.md.copyWith( + color: isSelected ? AppColor.primary : AppColor.textPrimary, + ), + ), + trailing: isSelected + ? Icon(Icons.check_circle, color: AppColor.primary, size: 24) + : Icon( + Icons.radio_button_unchecked, + color: AppColor.textLight, + size: 24, + ), + onTap: onTap, + ), + ); + } +} diff --git a/lib/presentation/pages/main/main_page.dart b/lib/presentation/pages/main/main_page.dart new file mode 100644 index 0000000..f180061 --- /dev/null +++ b/lib/presentation/pages/main/main_page.dart @@ -0,0 +1,27 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../router/app_router.gr.dart'; +import 'widgets/bottom_navbar.dart'; + +@RoutePage() +class MainPage extends StatelessWidget { + const MainPage({super.key}); + + @override + Widget build(BuildContext context) { + return AutoTabsRouter.pageView( + routes: [HomeRoute(), OrderRoute(), ReportRoute(), ProfileRoute()], + physics: const NeverScrollableScrollPhysics(), + builder: (context, child, pageController) { + final tabsRouter = AutoTabsRouter.of(context); + + return Scaffold( + resizeToAvoidBottomInset: false, + body: child, + bottomNavigationBar: MainBottomNavbar(tabsRouter: tabsRouter), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/main/widgets/bottom_navbar.dart b/lib/presentation/pages/main/widgets/bottom_navbar.dart new file mode 100644 index 0000000..c9d19bb --- /dev/null +++ b/lib/presentation/pages/main/widgets/bottom_navbar.dart @@ -0,0 +1,51 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hugeicons/hugeicons.dart'; + +import '../../../../common/extension/extension.dart'; + +class MainBottomNavbar extends StatefulWidget { + final TabsRouter tabsRouter; + + const MainBottomNavbar({super.key, required this.tabsRouter}); + + @override + State createState() => _MainBottomNavbarState(); +} + +class _MainBottomNavbarState extends State { + @override + Widget build(BuildContext context) { + return BottomNavigationBar( + currentIndex: widget.tabsRouter.activeIndex, + onTap: (index) { + setState(() { + widget.tabsRouter.setActiveIndex(index); + }); + }, + type: BottomNavigationBarType.fixed, + items: [ + BottomNavigationBarItem( + icon: HugeIcon(icon: HugeIcons.strokeRoundedHome01), + label: context.lang.home, + tooltip: context.lang.home, + ), + BottomNavigationBarItem( + icon: HugeIcon(icon: HugeIcons.strokeRoundedBorderFull), + label: context.lang.order, + tooltip: context.lang.order, + ), + BottomNavigationBarItem( + icon: HugeIcon(icon: HugeIcons.strokeRoundedChart03), + label: context.lang.report, + tooltip: context.lang.report, + ), + BottomNavigationBarItem( + icon: HugeIcon(icon: HugeIcons.strokeRoundedUser), + label: context.lang.profile, + tooltip: context.lang.profile, + ), + ], + ); + } +} diff --git a/lib/presentation/pages/order/order_detail/order_detail_page.dart b/lib/presentation/pages/order/order_detail/order_detail_page.dart new file mode 100644 index 0000000..4fb774e --- /dev/null +++ b/lib/presentation/pages/order/order_detail/order_detail_page.dart @@ -0,0 +1,1243 @@ +import 'package:flutter/material.dart'; +import 'package:auto_route/auto_route.dart'; +import 'dart:math' show cos, sin; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/order/order.dart'; +import '../../../components/appbar/appbar.dart'; + +@RoutePage() +class OrderDetailPage extends StatelessWidget { + final Order order; + + const OrderDetailPage({super.key, required this.order}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + slivers: [ + SliverAppBar( + expandedHeight: 120, + pinned: true, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.order_details), + elevation: 0, + ), + SliverToBoxAdapter( + child: Column( + children: [ + // Order Status Card + _buildOrderStatusCard(context), + const SizedBox(height: 16), + + // Table Visual Card (for dine-in) + if (_isDineIn()) _buildTableVisualCard(context), + + // Order Info Card + _buildOrderInfoCard(context), + const SizedBox(height: 16), + + // Order Items Section + _buildOrderItemsSection(context), + const SizedBox(height: 16), + + // Payment Summary Card + _buildPaymentSummaryCard(context), + const SizedBox(height: 16), + + // Payment Methods Section + _buildPaymentMethodsSection(context), + const SizedBox(height: 24), + ], + ), + ), + ], + ), + ); + } + + Widget _buildOrderStatusCard(BuildContext context) { + Color statusColor = _getStatusColor(order.status); + return Container( + margin: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + statusColor.withOpacity(0.15), + statusColor.withOpacity(0.08), + Colors.white, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + stops: const [0.0, 0.5, 1.0], + ), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: statusColor.withOpacity(0.3), width: 1.5), + boxShadow: [ + BoxShadow( + color: statusColor.withOpacity(0.2), + blurRadius: 15, + offset: const Offset(0, 5), + ), + BoxShadow( + color: Colors.white, + blurRadius: 8, + offset: const Offset(-2, -2), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [statusColor, statusColor.withOpacity(0.8)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: statusColor.withOpacity(0.4), + blurRadius: 8, + offset: const Offset(0, 3), + ), + ], + ), + child: Icon( + _getStatusIcon(order.status), + color: Colors.white, + size: 28, + ), + ), + const SizedBox(width: 20), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.order_number, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + order.orderNumber, + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 20), + Container( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.7), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: statusColor.withOpacity(0.2)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.order_status, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [statusColor, statusColor.withOpacity(0.8)], + ), + borderRadius: BorderRadius.circular(25), + boxShadow: [ + BoxShadow( + color: statusColor.withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Text( + order.status.toUpperCase(), + style: AppStyle.sm.copyWith( + color: Colors.white, + fontWeight: FontWeight.bold, + letterSpacing: 0.5, + ), + ), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + context.lang.total_amount, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + 'Rp ${_formatCurrency(order.totalAmount)}', + style: AppStyle.xxl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildTableVisualCard(BuildContext context) { + return Container( + margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), + height: 220, // Increased height + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primary, + AppColor.primaryLight, + AppColor.primary.withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + stops: const [0.0, 0.5, 1.0], + ), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: ClipRRect( + // Prevent overflow + borderRadius: BorderRadius.circular(20), + child: Stack( + children: [ + // Background Pattern + Positioned.fill(child: CustomPaint(painter: TablePatternPainter())), + + // Content with proper spacing + Padding( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + // Header + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + border: Border.all( + color: AppColor.white.withOpacity(0.3), + width: 1, + ), + ), + child: const Icon( + Icons.restaurant, + color: AppColor.white, + size: 24, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.dine_in, + style: AppStyle.sm.copyWith( + color: AppColor.white.withOpacity(0.9), + fontWeight: FontWeight.w500, + ), + ), + Text( + context.lang.dine_in_experience, + style: AppStyle.lg.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + + const SizedBox(height: 20), // Fixed spacing + // Table Number Visual + Expanded( + child: Center( + child: Container( + width: 90, + height: 90, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: RadialGradient( + colors: [ + AppColor.white, + AppColor.white.withOpacity(0.9), + AppColor.white.withOpacity(0.7), + ], + stops: const [0.0, 0.7, 1.0], + ), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.2), + blurRadius: 15, + offset: const Offset(0, 5), + ), + ], + ), + child: Stack( + children: [ + // Table surface + Center( + child: Container( + width: 70, + height: 70, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white, + border: Border.all( + color: AppColor.primary.withOpacity(0.3), + width: 2, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + context.lang.table, + style: AppStyle.xs.copyWith( + color: AppColor.primary.withOpacity( + 0.7, + ), + fontWeight: FontWeight.w600, + letterSpacing: 1, + ), + ), + Text( + order.tableNumber, + style: AppStyle.xl.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + // Table legs (decorative) + ...List.generate(4, (index) { + final angle = (index * 90.0) * (3.14159 / 180); + return Positioned( + left: 45 + 30 * cos(angle) - 2, + top: 45 + 30 * sin(angle) - 8, + child: Container( + width: 4, + height: 16, + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.3), + borderRadius: BorderRadius.circular(2), + ), + ), + ); + }), + ], + ), + ), + ), + ), + + const SizedBox(height: 16), // Fixed spacing + // Bottom Info with flexible layout + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColor.white.withOpacity(0.3), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.people, + size: 16, + color: AppColor.white.withOpacity(0.9), + ), + const SizedBox(width: 6), + Text( + '${order.orderItems.length} ${context.lang.items}', + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + const SizedBox(width: 12), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppColor.success.withOpacity(0.2), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColor.success.withOpacity(0.3), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.schedule, + size: 16, + color: AppColor.white.withOpacity(0.9), + ), + const SizedBox(width: 6), + Text( + _formatDateTime(order.createdAt), + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildOrderInfoCard(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [Colors.white, Color(0xFFFAFBFF)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: AppColor.primary.withOpacity(0.1)), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.08), + blurRadius: 20, + offset: const Offset(0, 5), + ), + const BoxShadow( + color: Colors.white, + blurRadius: 6, + offset: Offset(-3, -3), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: AppColor.primaryGradient, + ), + borderRadius: BorderRadius.circular(12), + ), + child: const Icon( + Icons.info_outline, + color: Colors.white, + size: 24, + ), + ), + const SizedBox(width: 16), + Text( + context.lang.order_information, + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + ], + ), + const SizedBox(height: 24), + if (_shouldShowTableNumber()) + _buildInfoRow( + Icons.table_restaurant, + context.lang.table, + order.tableNumber, + ), + _buildInfoRow( + Icons.delivery_dining, + context.lang.order_type, + order.orderType, + ), + _buildInfoRow( + Icons.payment, + context.lang.payment_status, + order.paymentStatus, + ), + _buildInfoRow( + Icons.access_time, + context.lang.created, + _formatDateTime(order.createdAt), + ), + if (order.notes.isNotEmpty) + _buildInfoRow(Icons.note, context.lang.note, order.notes), + ], + ), + ), + ); + } + + Widget _buildInfoRow(IconData icon, String label, String value) { + return Padding( + padding: const EdgeInsets.only(bottom: 12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, size: 16, color: AppColor.primary), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + const SizedBox(height: 2), + Text( + value, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + ], + ), + ), + ], + ), + ); + } + + Widget _buildOrderItemsSection(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 0), + child: Row( + children: [ + Text( + context.lang.order_item, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + const Spacer(), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + '${order.orderItems.length} ${context.lang.item}', + style: AppStyle.sm.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(20), + itemCount: order.orderItems.length, + separatorBuilder: (context, index) => const Divider(height: 24), + itemBuilder: (context, index) { + final item = order.orderItems[index]; + return _buildOrderItemCard(context, item); + }, + ), + ], + ), + ); + } + + Widget _buildOrderItemCard(BuildContext context, OrderItem item) { + // Assume we add status to OrderItem model or determine from order status + String itemStatus = _getItemStatus(context, item); + Color itemStatusColor = _getItemStatusColor(itemStatus); + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + itemStatusColor.withOpacity(0.05), + itemStatusColor.withOpacity(0.02), + Colors.white, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: itemStatusColor.withOpacity(0.3)), + boxShadow: [ + BoxShadow( + color: itemStatusColor.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + children: [ + Row( + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [itemStatusColor, itemStatusColor.withOpacity(0.8)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: itemStatusColor.withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: const Icon( + Icons.fastfood, + color: Colors.white, + size: 28, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + item.productName, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: itemStatusColor.withOpacity(0.2), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + itemStatus, + style: AppStyle.xs.copyWith( + color: itemStatusColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + 'Qty: ${item.quantity}', + style: AppStyle.xs.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w600, + ), + ), + ), + const SizedBox(width: 8), + Text( + 'Rp ${_formatCurrency(item.price)} each', + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + if (item.discountAmount > 0) ...[ + const SizedBox(height: 4), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), + decoration: BoxDecoration( + color: AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(6), + ), + child: Text( + '${context.lang.discount}: -Rp ${_formatCurrency(item.discountAmount)}', + style: AppStyle.xs.copyWith( + color: AppColor.error, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ], + ), + ), + ], + ), + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.7), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: itemStatusColor.withOpacity(0.2)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.lang.total_item, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Rp ${_formatCurrency(item.total)}', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + if (item.discountAmount > 0) + Text( + 'Rp ${_formatCurrency(item.subtotal)}', + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + decoration: TextDecoration.lineThrough, + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + Widget _buildPaymentSummaryCard(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.05), + AppColor.primary.withOpacity(0.02), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.primary.withOpacity(0.2)), + ), + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.payment_summary, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + const SizedBox(height: 16), + _buildSummaryRow(context.lang.subtotal, order.subtotal), + if (order.discountAmount > 0) + _buildSummaryRow( + context.lang.discount, + -order.discountAmount, + isDiscount: true, + ), + _buildSummaryRow(context.lang.tax, order.taxAmount), + const Divider(height: 24), + _buildSummaryRow( + context.lang.total, + order.totalAmount, + isTotal: true, + ), + _buildSummaryRow( + context.lang.paid, + order.totalPaid, + isSuccess: true, + ), + if (order.remainingAmount > 0) + _buildSummaryRow( + context.lang.remaining, + order.remainingAmount, + isError: true, + ), + ], + ), + ), + ); + } + + Widget _buildSummaryRow( + String label, + int amount, { + bool isTotal = false, + bool isDiscount = false, + bool isSuccess = false, + bool isError = false, + }) { + Color textColor = AppColor.textPrimary; + if (isTotal) textColor = AppColor.primary; + if (isDiscount) textColor = AppColor.error; + if (isSuccess) textColor = AppColor.success; + if (isError) textColor = AppColor.error; + + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + label, + style: AppStyle.md.copyWith( + color: isTotal ? AppColor.primary : AppColor.textSecondary, + fontWeight: isTotal ? FontWeight.bold : FontWeight.normal, + ), + ), + Text( + '${amount < 0 ? '-' : ''}Rp ${_formatCurrency(amount.abs())}', + style: AppStyle.md.copyWith( + color: textColor, + fontWeight: isTotal ? FontWeight.bold : FontWeight.w600, + ), + ), + ], + ), + ); + } + + Widget _buildPaymentMethodsSection(BuildContext context) { + if (order.payments.isEmpty) return const SizedBox(); + + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 0), + child: Text( + context.lang.payment_method, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(20), + itemCount: order.payments.length, + separatorBuilder: (context, index) => const SizedBox(height: 12), + itemBuilder: (context, index) { + final payment = order.payments[index]; + return _buildPaymentMethodCard(payment); + }, + ), + ], + ), + ); + } + + Widget _buildPaymentMethodCard(OrderPayment payment) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.success.withOpacity(0.05), + AppColor.success.withOpacity(0.02), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.success.withOpacity(0.3)), + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.success.withOpacity(0.2), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + _getPaymentIcon(payment.paymentMethodType), + color: AppColor.success, + size: 20, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + payment.paymentMethodName, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 4), + Text( + payment.paymentMethodType, + style: AppStyle.sm.copyWith(color: AppColor.textSecondary), + ), + if (payment.splitType.isNotEmpty && payment.splitTotal > 1) ...[ + const SizedBox(height: 4), + Text( + 'Split ${payment.splitNumber}/${payment.splitTotal}', + style: AppStyle.xs.copyWith(color: AppColor.info), + ), + ], + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + 'Rp ${_formatCurrency(payment.amount)}', + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.success, + ), + ), + Container( + margin: const EdgeInsets.only(top: 4), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: _getPaymentStatusColor( + payment.status, + ).withOpacity(0.2), + borderRadius: BorderRadius.circular(10), + ), + child: Text( + payment.status, + style: AppStyle.xs.copyWith( + color: _getPaymentStatusColor(payment.status), + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ], + ), + ); + } + + bool _isDineIn() { + final orderType = order.orderType + .toLowerCase() + .replaceAll('-', '') + .replaceAll('_', ''); + return orderType == 'dinein' || + orderType == 'dine' || + orderType.contains('dinein'); + } + + bool _shouldShowTableNumber() { + final orderType = order.orderType + .toLowerCase() + .replaceAll('-', '') + .replaceAll('_', '') + .replaceAll(' ', ''); + + // Don't show table number for these order types + final noTableTypes = [ + 'takeaway', + 'takeout', + 'pickup', + 'delivery', + 'dinein', + ]; + + return !noTableTypes.any((type) => orderType.contains(type)) && + order.tableNumber.isNotEmpty; + } + + String _formatCurrency(int amount) { + return amount.toString().replaceAllMapped( + RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), + (Match m) => '${m[1]}.', + ); + } + + String _formatDateTime(String dateTime) { + // Simple date formatting - you might want to use intl package for better formatting + return dateTime.split('T')[0]; + } + + Color _getStatusColor(String status) { + switch (status.toLowerCase()) { + case 'completed': + return AppColor.success; + case 'pending': + return AppColor.warning; + case 'cancelled': + return AppColor.error; + default: + return AppColor.info; + } + } + + IconData _getStatusIcon(String status) { + switch (status.toLowerCase()) { + case 'completed': + return Icons.check_circle; + case 'pending': + return Icons.access_time; + case 'cancelled': + return Icons.cancel; + default: + return Icons.info; + } + } + + IconData _getPaymentIcon(String type) { + switch (type.toLowerCase()) { + case 'cash': + return Icons.money; + case 'card': + return Icons.credit_card; + case 'digital': + return Icons.qr_code; + default: + return Icons.payment; + } + } + + Color _getPaymentStatusColor(String status) { + switch (status.toLowerCase()) { + case 'success': + return AppColor.success; + case 'pending': + return AppColor.warning; + case 'failed': + return AppColor.error; + default: + return AppColor.info; + } + } + + String _getItemStatus(BuildContext context, OrderItem item) { + // Logic untuk menentukan status item berdasarkan: + // 1. Status order secara keseluruhan + // 2. Jika ada field status di OrderItem model + // 3. Waktu pembuatan vs waktu sekarang + + switch (order.status.toLowerCase()) { + case 'completed': + return context.lang.completed; + case 'pending': + return context.lang.pending; + case 'cancelled': + return context.lang.void_text; + default: + return context.lang.pending; + } + } + + Color _getItemStatusColor(String status) { + switch (status.toLowerCase()) { + case 'completed': + return AppColor.success; + case 'pending': + return AppColor.warning; + case 'cancelled': + return AppColor.error; + default: + return AppColor.primary; + } + } +} + +class TablePatternPainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = AppColor.white.withOpacity(0.1) + ..strokeWidth = 1 + ..style = PaintingStyle.stroke; + + // Draw decorative pattern + for (int i = 0; i < 8; i++) { + final offset = i * 20.0; + canvas.drawLine( + Offset(offset, 0), + Offset(offset + size.height * 0.3, size.height), + paint, + ); + } + + // Draw subtle dots pattern + final dotPaint = Paint() + ..color = AppColor.white.withOpacity(0.05) + ..style = PaintingStyle.fill; + + for (int x = 0; x < size.width; x += 30) { + for (int y = 0; y < size.height; y += 30) { + canvas.drawCircle(Offset(x.toDouble(), y.toDouble()), 2, dotPaint); + } + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/lib/presentation/pages/order/order_list/order_page.dart b/lib/presentation/pages/order/order_list/order_page.dart new file mode 100644 index 0000000..66bce4e --- /dev/null +++ b/lib/presentation/pages/order/order_list/order_page.dart @@ -0,0 +1,370 @@ +import 'dart:developer'; + +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/order/order_loader/order_loader_bloc.dart'; +import '../../../../application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../injection.dart'; +import '../../../components/appbar/appbar.dart'; +import '../../../components/widgets/empty_widget.dart'; +import '../../../router/app_router.gr.dart'; +import 'widgets/filter_header_delegate.dart'; +import 'widgets/order_tile.dart'; + +@RoutePage() +class OrderPage extends StatefulWidget implements AutoRouteWrapper { + const OrderPage({super.key}); + + @override + State createState() => _OrderPageState(); + + @override + Widget wrappedRoute(BuildContext context) => MultiBlocProvider( + providers: [ + BlocProvider( + create: (_) => + getIt() + ..add(OrderLoaderEvent.fetched(isRefresh: true)), + ), + BlocProvider( + create: (_) => + getIt() + ..add(const OutletListLoaderEvent.fetched()), + ), + ], + child: this, + ); +} + +class _OrderPageState extends State with TickerProviderStateMixin { + late AnimationController _fadeController; + late AnimationController _slideController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + final ScrollController _scrollController = ScrollController(); + + // Filter state + final List filterOptions = ['All', 'Completed', 'Pending']; + + @override + void initState() { + super.initState(); + + _fadeController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.elasticOut), + ); + + _fadeController.forward(); + _slideController.forward(); + } + + @override + void dispose() { + _fadeController.dispose(); + _slideController.dispose(); + super.dispose(); + } + + Widget _buildShimmerOrderCard() { + return Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 120, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + Container( + width: 60, + height: 20, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + ), + ), + ], + ), + const SizedBox(height: 8), + Container( + width: double.infinity, + height: 14, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + const SizedBox(height: 6), + Container( + width: 200, + height: 14, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 80, + height: 14, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + Container( + width: 100, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildShimmerList() { + return ListView.builder( + itemCount: 5, // Show 5 shimmer cards + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemBuilder: (context, index) => _buildShimmerOrderCard(), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: MultiBlocListener( + listeners: [ + BlocListener( + listenWhen: (p, c) => p.outletId != c.outletId, + listener: (context, state) { + context.read().add( + OrderLoaderEvent.fetched(isRefresh: true), + ); + }, + ), + BlocListener( + listenWhen: (p, c) => p.status != c.status, + listener: (context, state) { + context.read().add( + OrderLoaderEvent.fetched(isRefresh: true), + ); + }, + ), + BlocListener( + listenWhen: (previous, current) => + previous.dateFrom != current.dateFrom || + previous.dateTo != current.dateTo, + listener: (context, state) { + context.read().add( + OrderLoaderEvent.fetched(isRefresh: true), + ); + }, + ), + ], + child: BlocBuilder( + builder: (context, outletListState) { + return BlocBuilder( + builder: (context, state) { + return NotificationListener( + onNotification: (notification) { + if (notification is ScrollEndNotification && + _scrollController.position.extentAfter == 0) { + context.read().add( + OrderLoaderEvent.fetched(), + ); + return true; + } + + return true; + }, + child: CustomScrollView( + controller: _scrollController, + slivers: [ + // Custom App Bar with Hero Effect + SliverAppBar( + expandedHeight: 120, + floating: true, + pinned: true, + backgroundColor: AppColor.primary, + centerTitle: false, + flexibleSpace: CustomAppBar( + title: context.lang.orders, + isBack: false, + ), + ), + + // Pinned Filter Section + SliverPersistentHeader( + pinned: true, + delegate: FilterHeaderDelegate( + backgroundColor: AppColor.background, + padding: EdgeInsets.fromLTRB( + AppValue.padding, + 10, + AppValue.padding, + 10, + ), + startDate: state.dateFrom, + endDate: state.dateTo, + filterOptions: filterOptions, + selectedFilter: state.status, + selectedOutletId: state.outletId, + outletListState: outletListState, + onDateChanged: (startDate, endDate) { + if (startDate != null && endDate != null) { + log('Date changed'); + context.read().add( + OrderLoaderEvent.rangeDateChanged( + startDate, + endDate, + ), + ); + } + }, + onFilterChanged: (filter) { + final status = filter.toLowerCase(); + context.read().add( + OrderLoaderEvent.statusChanged(status), + ); + }, + onOutletChanged: (outletId) { + context.read().add( + OrderLoaderEvent.outletChanged(outletId), + ); + }, + ), + ), + + // Content + SliverPadding( + padding: EdgeInsets.all(AppValue.padding), + sliver: SliverList( + delegate: SliverChildListDelegate([ + FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Column( + children: [ + // Show filtered transaction count + if (state.status != 'all' && + !state.isFetching) + Padding( + padding: const EdgeInsets.only( + bottom: 16, + ), + child: Row( + children: [ + Text( + '${state.orders.length} ${state.status.toLowerCase()} ${context.lang.orders}', + style: TextStyle( + color: AppColor.textSecondary, + fontSize: 14, + ), + ), + ], + ), + ), + + // Order List with Shimmer Loading + if (state.isFetching) + _buildShimmerList() + else if (state.orders.isEmpty) + EmptyWidget( + title: context.lang.order, + message: + context.lang.no_order_with_status( + state.status.toLowerCase(), + ), + ) + else + ListView.builder( + itemCount: state.orders.length, + shrinkWrap: true, + physics: + const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + itemBuilder: (context, index) { + return OrderTile( + onTap: () => context.router.push( + OrderDetailRoute( + order: state.orders[index], + ), + ), + order: state.orders[index], + ); + }, + ), + ], + ), + ), + ), + ]), + ), + ), + ], + ), + ); + }, + ); + }, + ), + ), + ); + } +} diff --git a/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart b/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart new file mode 100644 index 0000000..0afb502 --- /dev/null +++ b/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart @@ -0,0 +1,359 @@ +import 'package:flutter/material.dart'; + +import '../../../../../application/outlet/outlet_list_loader/outlet_list_loader_bloc.dart'; +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/outlet/outlet.dart'; +import '../../../../components/field/date_range_picker_field.dart'; +import 'status_tile.dart'; + +class FilterHeaderDelegate extends SliverPersistentHeaderDelegate { + final Color backgroundColor; + final EdgeInsets padding; + final DateTime? startDate; + final DateTime? endDate; + final List filterOptions; + final String selectedFilter; + final String? selectedOutletId; + final OutletListLoaderState outletListState; + final Function(DateTime?, DateTime?) onDateChanged; + final Function(String) onFilterChanged; + final Function(String?) onOutletChanged; + + FilterHeaderDelegate({ + required this.backgroundColor, + required this.padding, + required this.startDate, + required this.endDate, + required this.filterOptions, + required this.selectedFilter, + required this.selectedOutletId, + required this.outletListState, + required this.onDateChanged, + required this.onFilterChanged, + required this.onOutletChanged, + }); + + @override + double get minExtent => 190; + + @override + double get maxExtent => 190; + + @override + Widget build( + BuildContext context, + double shrinkOffset, + bool overlapsContent, + ) { + final selectedOutlet = outletListState.outlets + .where((o) => o.id == selectedOutletId) + .firstOrNull; + + return Container( + color: backgroundColor, + padding: padding, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Date range picker + DateRangePickerField( + maxDate: DateTime.now(), + startDate: startDate, + endDate: endDate, + onChanged: (start, end) => onDateChanged(start, end), + ), + const SizedBox(height: 8), + // Outlet selector + status chips + _OutletSelectorField( + selectedOutlet: selectedOutlet, + isLoading: outletListState.isFetching, + onTap: () => _showOutletSheet(context), + ), + const SizedBox(height: 8), + // Status chips + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: filterOptions.asMap().entries.map((entry) { + final index = entry.key; + final option = entry.value; + return Padding( + padding: EdgeInsets.only( + right: index < filterOptions.length - 1 ? 8 : 0, + ), + child: OrderStatusTile( + label: option == 'All' + ? context.lang.all + : option == 'Completed' + ? context.lang.completed + : context.lang.pending, + isSelected: option.toLowerCase() == selectedFilter, + onSelected: (isSelected) { + if (isSelected) onFilterChanged(option); + }, + ), + ); + }).toList(), + ), + ), + ], + ), + ); + } + + void _showOutletSheet(BuildContext context) { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + builder: (_) => _OutletBottomSheet( + outlets: outletListState.outlets, + selectedOutletId: selectedOutletId, + onSelected: (outletId) { + Navigator.pop(context); + onOutletChanged(outletId); + }, + ), + ); + } + + @override + bool shouldRebuild(covariant FilterHeaderDelegate oldDelegate) { + return oldDelegate.startDate != startDate || + oldDelegate.endDate != endDate || + oldDelegate.selectedFilter != selectedFilter || + oldDelegate.selectedOutletId != selectedOutletId || + oldDelegate.outletListState.outlets.length != + outletListState.outlets.length || + oldDelegate.outletListState.isFetching != outletListState.isFetching || + oldDelegate.filterOptions.length != filterOptions.length || + oldDelegate.backgroundColor != backgroundColor; + } +} + +// Field outlet — ikut style DateRangePickerField +class _OutletSelectorField extends StatefulWidget { + final Outlet? selectedOutlet; + final bool isLoading; + final VoidCallback onTap; + + const _OutletSelectorField({ + required this.selectedOutlet, + required this.isLoading, + required this.onTap, + }); + + @override + State<_OutletSelectorField> createState() => _OutletSelectorFieldState(); +} + +class _OutletSelectorFieldState extends State<_OutletSelectorField> { + bool _isPressed = false; + + @override + Widget build(BuildContext context) { + final hasValue = widget.selectedOutlet != null; + final label = widget.selectedOutlet?.name ?? 'Semua Outlet'; + + return GestureDetector( + onTap: widget.isLoading ? null : widget.onTap, + onTapDown: (_) => setState(() => _isPressed = true), + onTapUp: (_) => setState(() => _isPressed = false), + onTapCancel: () => setState(() => _isPressed = false), + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: _isPressed ? AppColor.backgroundLight : AppColor.white, + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: _isPressed ? AppColor.primary : AppColor.border, + width: _isPressed ? 2 : 1, + ), + boxShadow: _isPressed + ? [ + BoxShadow( + color: AppColor.primary.withOpacity(0.1), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ] + : null, + ), + child: Row( + children: [ + Expanded( + child: Text( + label, + style: TextStyle( + fontSize: 15, + fontWeight: hasValue ? FontWeight.w500 : FontWeight.w400, + color: hasValue + ? AppColor.textPrimary + : AppColor.textSecondary, + ), + overflow: TextOverflow.ellipsis, + ), + ), + Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: widget.isLoading + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + color: AppColor.primary, + ), + ) + : const Icon( + Icons.store_rounded, + size: 20, + color: AppColor.primary, + ), + ), + ], + ), + ), + ); + } +} + +// Bottom sheet pilih outlet +class _OutletBottomSheet extends StatelessWidget { + final List outlets; + final String? selectedOutletId; + final Function(String?) onSelected; + + const _OutletBottomSheet({ + required this.outlets, + required this.selectedOutletId, + required this.onSelected, + }); + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 20, 20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + const SizedBox(height: 16), + Text( + 'Pilih Outlet', + style: AppStyle.lg.copyWith(fontWeight: FontWeight.w700), + ), + const SizedBox(height: 12), + _OutletItem( + label: 'Semua Outlet', + icon: Icons.store_rounded, + isSelected: selectedOutletId == null, + onTap: () => onSelected(null), + ), + const Divider(height: 1), + ...outlets.map( + (outlet) => Column( + children: [ + _OutletItem( + label: outlet.name, + icon: Icons.storefront_rounded, + isSelected: selectedOutletId == outlet.id, + isActive: outlet.isActive, + onTap: () => onSelected(outlet.id), + ), + if (outlet != outlets.last) const Divider(height: 1), + ], + ), + ), + ], + ), + ), + ); + } +} + +class _OutletItem extends StatelessWidget { + final String label; + final IconData icon; + final bool isSelected; + final bool? isActive; + final VoidCallback onTap; + + const _OutletItem({ + required this.label, + required this.icon, + required this.isSelected, + required this.onTap, + this.isActive, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + onTap: onTap, + contentPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), + leading: Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: isSelected + ? AppColor.primary.withOpacity(0.1) + : AppColor.background, + borderRadius: BorderRadius.circular(10), + ), + child: Icon( + icon, + size: 18, + color: isSelected ? AppColor.primary : AppColor.textSecondary, + ), + ), + title: Text( + label, + style: AppStyle.md.copyWith( + fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500, + color: isSelected ? AppColor.primary : AppColor.textPrimary, + ), + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (isActive != null) + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: isActive! ? AppColor.success : AppColor.error, + ), + ), + if (isActive != null) const SizedBox(width: 8), + if (isSelected) + const Icon( + Icons.check_rounded, + color: AppColor.primary, + size: 20, + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/order/order_list/widgets/order_tile.dart b/lib/presentation/pages/order/order_list/widgets/order_tile.dart new file mode 100644 index 0000000..c9ecbfd --- /dev/null +++ b/lib/presentation/pages/order/order_list/widgets/order_tile.dart @@ -0,0 +1,438 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/order/order.dart'; + +class OrderTile extends StatelessWidget { + final Order order; + final VoidCallback? onTap; + final VoidCallback? onPrint; + final VoidCallback? onRefund; + + const OrderTile({ + super.key, + required this.order, + this.onTap, + this.onPrint, + this.onRefund, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 16), + child: Card( + elevation: 4, + shadowColor: AppColor.primaryWithOpacity(0.1), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide(color: AppColor.border, width: 0.5), + ), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(16), + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [AppColor.backgroundLight, AppColor.background], + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header Row + _buildHeaderRow(context), + const SizedBox(height: 12), + + // Order Info + _buildOrderInfo(context), + const SizedBox(height: 16), + + // Amount Section + _buildAmountSection(context), + const SizedBox(height: 16), + + // Footer with Actions + _buildFooterActions(context), + ], + ), + ), + ), + ), + ); + } + + Widget _buildHeaderRow(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + order.orderNumber.isNotEmpty + ? order.orderNumber + : 'ORD-${order.id}', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 2), + Text( + _formatDate(order.createdAt), + style: const TextStyle( + fontSize: 12, + color: AppColor.textSecondary, + ), + ), + ], + ), + _buildStatusChip(context), + ], + ); + } + + Widget _buildStatusChip(BuildContext context) { + Color statusColor; + String statusText; + IconData statusIcon; + + // Check isVoid and isRefund first for display + if (order.isVoid) { + statusColor = AppColor.error; + statusText = context.lang.void_text; + statusIcon = Icons.block; + } else if (order.isRefund) { + statusColor = AppColor.info; + statusText = context.lang.refund; + statusIcon = Icons.undo; + } else { + // Handle status values (only pending and completed) + switch (order.status.toLowerCase()) { + case 'completed': + statusColor = AppColor.success; + statusText = context.lang.completed; + statusIcon = Icons.check_circle; + case 'paid': + case 'finished': + statusColor = AppColor.success; + statusText = context.lang.completed; + statusIcon = Icons.check_circle; + break; + case 'pending': + statusColor = AppColor.warning; + statusText = context.lang.pending; + statusIcon = Icons.schedule; + break; + case 'waiting': + case 'processing': + statusColor = AppColor.warning; + statusText = context.lang.pending; + statusIcon = Icons.schedule; + break; + default: + statusColor = AppColor.textSecondary; + statusText = order.status; + statusIcon = Icons.info; + break; + } + } + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: statusColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: statusColor.withOpacity(0.3), width: 1), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(statusIcon, size: 14, color: statusColor), + const SizedBox(width: 4), + Text( + statusText, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: statusColor, + ), + ), + ], + ), + ); + } + + Widget _buildOrderInfo(BuildContext context) { + return Row( + children: [ + Expanded( + flex: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(_getOrderInfoIcon(), size: 16, color: AppColor.primary), + const SizedBox(width: 6), + Expanded( + child: Text( + _getOrderInfoText(context), + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SizedBox(height: 8), + Row( + children: [ + Icon( + Icons.shopping_bag_outlined, + size: 16, + color: AppColor.primary, + ), + const SizedBox(width: 6), + Text( + '${order.orderItems.length} ${context.lang.items}', + style: const TextStyle( + fontSize: 13, + color: AppColor.textSecondary, + ), + ), + ], + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: AppColor.primaryWithOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + _getOrderTypeIcon(order.orderType), + size: 16, + color: AppColor.primary, + ), + const SizedBox(width: 6), + Text( + order.orderType.isNotEmpty ? order.orderType : 'Dine In', + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: AppColor.primary, + ), + ), + ], + ), + ), + ], + ); + } + + Widget _buildAmountSection(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: AppColor.primaryGradient, + ), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.2), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.total_amount, + style: TextStyle( + fontSize: 14, + color: AppColor.textWhite, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + order.totalAmount.currencyFormatRp, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: AppColor.textWhite, + ), + ), + if (order.remainingAmount > 0) ...[ + const SizedBox(height: 4), + Text( + '${context.lang.remaining}: ${order.remainingAmount.currencyFormatRp}', + style: const TextStyle( + fontSize: 12, + color: AppColor.textWhite, + fontWeight: FontWeight.w400, + ), + ), + ], + ], + ), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.backgroundLight.withOpacity(0.2), + shape: BoxShape.circle, + ), + child: Icon( + _getPaymentStatusIcon(order.paymentStatus), + color: AppColor.textWhite, + size: 24, + ), + ), + ], + ), + ); + } + + Widget _buildFooterActions(BuildContext context) { + // Don't show anything if order is void or refunded + if (order.isVoid || order.isRefund) { + return const SizedBox.shrink(); + } + + return Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (order.payments.isNotEmpty) ...[ + const SizedBox(height: 2), + Text( + '${context.lang.payment}: ${_getPaymentMethods()}', + style: const TextStyle( + fontSize: 11, + color: AppColor.textLight, + fontWeight: FontWeight.w400, + ), + ), + ], + ], + ), + ), + ], + ); + } + + IconData _getOrderInfoIcon() { + switch (order.orderType.toLowerCase()) { + case 'dine in': + case 'dine_in': + return Icons.table_restaurant_outlined; + case 'takeaway': + case 'take_away': + case 'pickup': + return Icons.person_outline; + case 'delivery': + return Icons.location_on_outlined; + default: + return Icons.receipt_outlined; + } + } + + String _getOrderInfoText(BuildContext context) { + switch (order.orderType.toLowerCase()) { + case 'dine in': + case 'dine_in': + return '${context.lang.table} ${order.tableNumber.isNotEmpty ? order.tableNumber : 'N/A'}'; + case 'takeaway': + case 'take_away': + case 'pickup': + return 'Pickup Order'; + case 'delivery': + return 'Delivery Order'; + default: + return order.tableNumber.isNotEmpty + ? '${context.lang.table} ${order.tableNumber}' + : context.lang.order; + } + } + + IconData _getOrderTypeIcon(String orderType) { + switch (orderType.toLowerCase()) { + case 'dine in': + case 'dine_in': + return Icons.restaurant; + case 'takeaway': + case 'take_away': + case 'pickup': + return Icons.shopping_bag; + case 'delivery': + return Icons.delivery_dining; + default: + return Icons.restaurant_menu; + } + } + + IconData _getPaymentStatusIcon(String paymentStatus) { + switch (paymentStatus.toLowerCase()) { + case 'paid': + case 'completed': + return Icons.check_circle; + case 'pending': + case 'partial': + return Icons.schedule; + case 'failed': + case 'cancelled': + return Icons.error; + default: + return Icons.attach_money; + } + } + + String _getPaymentMethods() { + if (order.payments.isEmpty) return 'N/A'; + + // Get unique payment methods from payments + final methods = order.payments + .map((payment) => payment.paymentMethodName) + .toSet() + .join(', '); + + return methods.isEmpty ? 'N/A' : methods; + } + + String _formatDate(String dateString) { + try { + final date = DateTime.parse(dateString); + return DateFormat('dd MMM yyyy, HH:mm').format(date); + } catch (e) { + return dateString; + } + } +} diff --git a/lib/presentation/pages/order/order_list/widgets/status_tile.dart b/lib/presentation/pages/order/order_list/widgets/status_tile.dart new file mode 100644 index 0000000..10f627e --- /dev/null +++ b/lib/presentation/pages/order/order_list/widgets/status_tile.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +import '../../../../../common/theme/theme.dart'; + +class OrderStatusTile extends StatelessWidget { + final String label; + final bool isSelected; + final void Function(bool)? onSelected; + const OrderStatusTile({ + super.key, + required this.label, + this.isSelected = false, + this.onSelected, + }); + + @override + Widget build(BuildContext context) { + return FilterChip( + label: Text( + label, + style: TextStyle( + color: isSelected ? Colors.white : AppColor.primary, + fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, + ), + ), + selected: isSelected, + onSelected: onSelected, + backgroundColor: Colors.white, + selectedColor: AppColor.primary, + checkmarkColor: Colors.white, + side: BorderSide( + color: isSelected ? AppColor.primary : Colors.grey.shade300, + width: 1, + ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + ); + } +} diff --git a/lib/presentation/pages/outlet/outlet_information_page.dart b/lib/presentation/pages/outlet/outlet_information_page.dart new file mode 100644 index 0000000..b33f925 --- /dev/null +++ b/lib/presentation/pages/outlet/outlet_information_page.dart @@ -0,0 +1,377 @@ +import 'package:flutter/material.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../application/outlet/current_outlet_loader/current_outlet_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../domain/outlet/outlet.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import '../../components/spacer/spacer.dart'; + +// Outlet Information Page +@RoutePage() +class OutletInformationPage extends StatefulWidget implements AutoRouteWrapper { + const OutletInformationPage({super.key}); + + @override + State createState() => _OutletInformationPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (_) => + getIt() + ..add(CurrentOutletLoaderEvent.fetched()), + child: this, + ); +} + +class _OutletInformationPageState extends State + with TickerProviderStateMixin { + late ScrollController _scrollController; + late AnimationController _fadeController; + late AnimationController _slideController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + + @override + void initState() { + super.initState(); + _scrollController = ScrollController(); + _fadeController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + _slideController = AnimationController( + duration: const Duration(milliseconds: 600), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutBack), + ); + + // Start animations + _fadeController.forward(); + _slideController.forward(); + } + + @override + void dispose() { + _scrollController.dispose(); + _fadeController.dispose(); + _slideController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + controller: _scrollController, + slivers: [ + SliverAppBar( + expandedHeight: 120.0, + floating: false, + pinned: true, + flexibleSpace: CustomAppBar(title: context.lang.outlet_information), + ), + SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: _buildContent(context), + ), + ), + ), + ], + ), + ); + } + + Widget _buildContent(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildHeaderCard(state.outlet), + const SizedBox(height: 20), + _buildInfoSection(context, state.outlet), + const SizedBox(height: 20), + _buildBusinessSection(context, state.outlet), + const SizedBox(height: 20), + _buildStatusSection(context, state.outlet), + ], + ), + ); + }, + ); + } + + Widget _buildHeaderCard(Outlet outlet) { + return TweenAnimationBuilder( + duration: const Duration(milliseconds: 800), + tween: Tween(begin: 0.0, end: 1.0), + builder: (context, value, child) { + return Transform.scale( + scale: 0.8 + (0.2 * value), + child: Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: AppColor.primaryGradient, + ), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(Icons.store, color: AppColor.white, size: 24), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + outlet.name, + style: AppStyle.h5.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + outlet.businessType, + style: AppStyle.md.copyWith( + color: AppColor.white.withOpacity(0.9), + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } + + Widget _buildInfoSection(BuildContext context, Outlet outlet) { + return _buildAnimatedCard( + delay: 200, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSectionTitle( + context.lang.outlet_information, + Icons.info_outline, + ), + SpaceHeight(20), + _buildInfoRow( + context.lang.address, + outlet.address, + Icons.location_on, + ), + _buildInfoRow( + context.lang.phone_number, + outlet.phoneNumber, + Icons.phone, + ), + ], + ), + ); + } + + Widget _buildBusinessSection(BuildContext context, Outlet outlet) { + return _buildAnimatedCard( + delay: 600, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSectionTitle( + context.lang.business_settings, + Icons.settings_applications, + ), + const SizedBox(height: 16), + _buildInfoRow( + context.lang.currency, + outlet.currency, + Icons.monetization_on, + ), + _buildInfoRow( + context.lang.tax_rate, + '${outlet.taxRate}%', + Icons.percent, + ), + ], + ), + ); + } + + Widget _buildStatusSection(BuildContext context, Outlet outlet) { + return _buildAnimatedCard( + delay: 800, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSectionTitle(context.lang.status_text, Icons.toggle_on), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: outlet.isActive + ? AppColor.success.withOpacity(0.1) + : AppColor.error.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: outlet.isActive + ? AppColor.success.withOpacity(0.3) + : AppColor.error.withOpacity(0.3), + ), + ), + child: Row( + children: [ + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: outlet.isActive ? AppColor.success : AppColor.error, + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 12), + Text( + outlet.isActive ? context.lang.active : context.lang.inactive, + style: AppStyle.md.copyWith( + color: outlet.isActive ? AppColor.success : AppColor.error, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ], + ), + ); + } + + Widget _buildAnimatedCard({required Widget child, required int delay}) { + return TweenAnimationBuilder( + duration: Duration(milliseconds: 600 + delay), + tween: Tween(begin: 0.0, end: 1.0), + builder: (context, value, _) { + return Transform.translate( + offset: Offset(0, 30 * (1 - value)), + child: Opacity( + opacity: value, + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 5), + ), + ], + ), + child: child, + ), + ), + ); + }, + ); + } + + Widget _buildSectionTitle(String title, IconData icon) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, color: AppColor.primary, size: 20), + ), + const SizedBox(width: 12), + Text( + title, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ], + ); + } + + Widget _buildInfoRow(String label, String value, IconData icon) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(icon, color: AppColor.textSecondary, size: 20), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + value, + style: AppStyle.md.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/product/product_analytic/product_analytic_page.dart b/lib/presentation/pages/product/product_analytic/product_analytic_page.dart new file mode 100644 index 0000000..33b0683 --- /dev/null +++ b/lib/presentation/pages/product/product_analytic/product_analytic_page.dart @@ -0,0 +1,762 @@ +import 'package:flutter/material.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../../injection.dart'; +import '../../../components/appbar/appbar.dart'; +import '../../../components/field/date_range_picker_field.dart'; + +@RoutePage() +class ProductAnalyticPage extends StatefulWidget implements AutoRouteWrapper { + const ProductAnalyticPage({super.key}); + + @override + State createState() => _ProductAnalyticPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (context) => + getIt() + ..add(ProductAnalyticLoaderEvent.fetched()), + child: this, + ); +} + +class _ProductAnalyticPageState extends State + with TickerProviderStateMixin { + late AnimationController _animationController; + late AnimationController _cardAnimationController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + + @override + void initState() { + super.initState(); + _initializeAnimations(); + } + + void _initializeAnimations() { + _animationController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + _cardAnimationController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.0, 0.6, curve: Curves.easeOut), + ), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.2, 1.0, curve: Curves.easeOutCubic), + ), + ); + + _animationController.forward(); + _cardAnimationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + _cardAnimationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: BlocListener( + listenWhen: (previous, current) => + previous.dateFrom != current.dateFrom || + previous.dateTo != current.dateTo, + listener: (context, state) { + context.read().add( + ProductAnalyticLoaderEvent.fetched(), + ); + }, + child: + BlocBuilder( + builder: (context, state) { + return CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + _buildSliverAppBar(), + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeAnimation, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: DateRangePickerField( + maxDate: DateTime.now(), + startDate: state.dateFrom, + endDate: state.dateTo, + onChanged: (startDate, endDate) { + context.read().add( + ProductAnalyticLoaderEvent.rangeDateChanged( + startDate!, + endDate!, + ), + ); + }, + ), + ), + ), + ), + ), + _buildSummarySection(state.productAnalytic), + _buildProductsList(state.productAnalytic), + ], + ); + }, + ), + ), + ); + } + + // SLIVER APP BAR + Widget _buildSliverAppBar() { + return SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.product_analytic), + ); + } + + // SUMMARY SECTION + Widget _buildSummarySection(ProductAnalytic productAnalytic) { + return SliverToBoxAdapter( + child: FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Container( + margin: const EdgeInsets.all(16), + child: _buildSummaryCards(productAnalytic.data), + ), + ), + ), + ); + } + + // PRODUCTS LIST + Widget _buildProductsList(ProductAnalytic productAnalytic) { + return SliverPadding( + padding: const EdgeInsets.all(16), + sliver: SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + return AnimatedBuilder( + animation: _cardAnimationController, + builder: (context, child) { + final delay = index * 0.1; + final progress = (_cardAnimationController.value - delay).clamp( + 0.0, + 1.0, + ); + final animValue = Curves.easeOutCubic + .transform(progress) + .clamp(0.0, 1.0); + + return Transform.translate( + offset: Offset(0, 50 * (1 - animValue)), + child: Opacity( + opacity: animValue, + child: _buildProductCard( + productAnalytic, + productAnalytic.data[index], + index, + ), + ), + ); + }, + ); + }, childCount: productAnalytic.data.length), + ), + ); + } + + // SUMMARY CARDS + Widget _buildSummaryCards(List data) { + final stats = _calculateSummaryStats(data); + + return Column( + children: [ + Row( + children: [ + Expanded( + child: _buildSummaryCard( + icon: Icons.monetization_on, + title: context.lang.total_revenue, + value: _formatCurrency(stats.totalRevenue), + color: AppColor.success, + ), + ), + const SizedBox(width: 12), + Expanded( + child: _buildSummaryCard( + icon: Icons.shopping_cart, + title: context.lang.total_sold, + value: _formatNumber(stats.totalQuantity), + color: AppColor.info, + ), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: _buildSummaryCard( + icon: Icons.receipt_long, + title: context.lang.total_orders, + value: _formatNumber(stats.totalOrders), + color: AppColor.warning, + ), + ), + const SizedBox(width: 12), + Expanded( + child: _buildSummaryCard( + icon: Icons.trending_up, + title: context.lang.average_price, + value: _formatCurrency(stats.averageOrderValue), + color: AppColor.primary, + ), + ), + ], + ), + ], + ); + } + + Widget _buildSummaryCard({ + required IconData icon, + required String title, + required String value, + required Color color, + }) { + return TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 800), + curve: Curves.elasticOut, + builder: (context, animationValue, child) { + return Transform.scale( + scale: animationValue, + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: color.withOpacity(0.1), + blurRadius: 15, + offset: const Offset(0, 5), + ), + ], + border: Border.all(color: color.withOpacity(0.2), width: 1.5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [color.withOpacity(0.2), color.withOpacity(0.1)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(icon, color: color, size: 24), + ), + const SizedBox(height: 16), + Text( + title, + style: _getTextStyle( + AppStyle.md, + color: AppColor.textSecondary, + weight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + value, + style: _getTextStyle( + AppStyle.xxl, + color: color, + weight: FontWeight.bold, + ), + ), + ], + ), + ), + ); + }, + ); + } + + // PRODUCT CARD - NEW CLEAN LAYOUT + Widget _buildProductCard( + ProductAnalytic productAnalytic, + ProductAnalyticData product, + int index, + ) { + return TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: Duration(milliseconds: 600 + (index * 100)), + curve: Curves.easeOutBack, + builder: (context, animationValue, child) { + final clampedValue = animationValue.clamp(0.0, 1.0); + + return Transform.translate( + offset: Offset(0, 30 * (1 - clampedValue)), + child: Opacity( + opacity: clampedValue, + child: Container( + margin: EdgeInsets.only( + bottom: index == productAnalytic.data.length - 1 ? 0 : 16, + ), + child: _buildCardContent(productAnalytic, product, index), + ), + ), + ); + }, + ); + } + + Widget _buildCardContent( + ProductAnalytic productAnalytic, + ProductAnalyticData product, + int index, + ) { + return Container( + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(8), + bottomRight: Radius.circular(8), + ), + boxShadow: [ + BoxShadow( + color: _getCategoryColor(product.categoryName).withOpacity(0.08), + blurRadius: 24, + offset: const Offset(0, 12), + ), + BoxShadow( + color: Colors.black.withOpacity(0.04), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(8), + onTap: () => _onProductTap(product), + child: Column( + children: [ + _buildCardHeader(product, index), + _buildCardBody(productAnalytic, product), + ], + ), + ), + ), + ); + } + + Widget _buildCardHeader(ProductAnalyticData product, int index) { + return Container( + width: double.infinity, + height: 4, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getCategoryColor(product.categoryName), + _getCategoryColor(product.categoryName).withOpacity(0.6), + ], + ), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + ), + ); + } + + Widget _buildCardBody( + ProductAnalytic productAnalytic, + ProductAnalyticData product, + ) { + final index = productAnalytic.data.indexOf(product); + + return Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildProductHeader(product, index), + const SizedBox(height: 20), + _buildStatsSection(product), + const SizedBox(height: 16), + _buildAveragePriceSection(product), + ], + ), + ); + } + + Widget _buildProductHeader(ProductAnalyticData product, int index) { + return Row( + children: [ + _buildCategoryIcon(product.categoryName), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.productName, + style: _getTextStyle(AppStyle.lg, weight: FontWeight.bold), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Text( + product.categoryName, + style: _getTextStyle( + AppStyle.sm, + color: _getCategoryColor(product.categoryName), + weight: FontWeight.w600, + ), + ), + ], + ), + ), + _buildRankingBadge(index), + ], + ); + } + + Widget _buildCategoryIcon(String categoryName) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getCategoryColor(categoryName).withOpacity(0.1), + _getCategoryColor(categoryName).withOpacity(0.05), + ], + ), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _getCategoryColor(categoryName).withOpacity(0.2), + width: 1.5, + ), + ), + child: Icon( + _getCategoryIcon(categoryName), + color: _getCategoryColor(categoryName), + size: 28, + ), + ); + } + + Widget _buildRankingBadge(int index) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: _getRankingColor(index), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + '#${index + 1}', + style: _getTextStyle( + AppStyle.xs, + color: AppColor.white, + weight: FontWeight.bold, + ), + ), + ); + } + + Widget _buildStatsSection(ProductAnalyticData product) { + return Row( + children: [ + Expanded(flex: 3, child: _buildRevenueCard(product)), + const SizedBox(width: 12), + Expanded(flex: 2, child: _buildSecondaryStats(product)), + ], + ); + } + + Widget _buildRevenueCard(ProductAnalyticData product) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.success.withOpacity(0.1), + AppColor.success.withOpacity(0.05), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.success.withOpacity(0.2)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(Icons.trending_up, color: AppColor.success, size: 20), + const SizedBox(width: 8), + Text( + context.lang.revenue, + style: _getTextStyle( + AppStyle.sm, + color: AppColor.success, + weight: FontWeight.w600, + ), + ), + ], + ), + const SizedBox(height: 8), + Text( + product.revenue.currencyFormatRp, + style: _getTextStyle( + AppStyle.xl, + color: AppColor.success, + weight: FontWeight.bold, + ), + ), + ], + ), + ); + } + + Widget _buildSecondaryStats(ProductAnalyticData product) { + return Column( + children: [ + _buildStatCard( + icon: Icons.shopping_cart_outlined, + value: '${product.quantitySold}', + label: context.lang.sold, + color: AppColor.info, + ), + const SizedBox(height: 8), + _buildStatCard( + icon: Icons.receipt_outlined, + value: '${product.orderCount}', + label: context.lang.orders, + color: AppColor.warning, + ), + ], + ); + } + + Widget _buildStatCard({ + required IconData icon, + required String value, + required String label, + required Color color, + }) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background.withOpacity(0.5), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.border.withOpacity(0.1)), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(icon, color: color, size: 16), + const SizedBox(width: 4), + Text( + value, + style: _getTextStyle( + AppStyle.md, + color: color, + weight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 2), + Text( + label, + style: _getTextStyle( + AppStyle.xs, + color: AppColor.textSecondary, + weight: FontWeight.w500, + ), + ), + ], + ), + ); + } + + Widget _buildAveragePriceSection(ProductAnalyticData product) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getCategoryColor(product.categoryName).withOpacity(0.05), + _getCategoryColor(product.categoryName).withOpacity(0.02), + ], + ), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.lang.average_price, + style: _getTextStyle( + AppStyle.sm, + color: AppColor.textSecondary, + weight: FontWeight.w500, + ), + ), + Text( + product.averagePrice.round().currencyFormatRp, + style: _getTextStyle( + AppStyle.sm, + color: _getCategoryColor(product.categoryName), + weight: FontWeight.bold, + ), + ), + ], + ), + ); + } + + // HELPER METHODS + SummaryStats _calculateSummaryStats(List data) { + final totalRevenue = data.fold( + 0, + (sum, item) => sum + item.revenue, + ); + final totalQuantity = data.fold( + 0, + (sum, item) => sum + item.quantitySold, + ); + final totalOrders = data.fold(0, (sum, item) => sum + item.orderCount); + final averageOrderValue = totalOrders > 0 ? totalRevenue / totalOrders : 0; + + return SummaryStats( + totalRevenue: totalRevenue, + totalQuantity: totalQuantity, + totalOrders: totalOrders, + averageOrderValue: averageOrderValue.roundToDouble(), + ); + } + + TextStyle _getTextStyle( + TextStyle? baseStyle, { + Color? color, + FontWeight? weight, + }) { + return baseStyle?.copyWith(color: color, fontWeight: weight) ?? + TextStyle(color: color, fontWeight: weight); + } + + void _onProductTap(ProductAnalyticData product) { + // Handle product detail navigation + } + + Color _getCategoryColor(String categoryName) { + switch (categoryName) { + case 'Makanan Utama': + return AppColor.primary; + case 'Minuman': + return AppColor.info; + case 'Snack': + return AppColor.warning; + default: + return AppColor.secondary; + } + } + + Color _getRankingColor(int index) { + switch (index) { + case 0: + return const Color(0xFFFFD700); // Gold + case 1: + return const Color(0xFFC0C0C0); // Silver + case 2: + return const Color(0xFFCD7F32); // Bronze + default: + return AppColor.primary; + } + } + + IconData _getCategoryIcon(String categoryName) { + switch (categoryName) { + case 'Makanan Utama': + return Icons.restaurant; + case 'Minuman': + return Icons.local_cafe; + case 'Snack': + return Icons.fastfood; + default: + return Icons.category; + } + } + + String _formatCurrency(double amount) { + if (amount >= 1000000) { + return 'Rp ${(amount / 1000000).toStringAsFixed(1)}jt'; + } else if (amount >= 1000) { + return 'Rp ${(amount / 1000).toStringAsFixed(0)}rb'; + } else { + return 'Rp ${amount.toStringAsFixed(0)}'; + } + } + + String _formatNumber(int number) { + if (number >= 1000) { + return '${(number / 1000).toStringAsFixed(1)}k'; + } + return number.toString(); + } +} + +// HELPER CLASS +class SummaryStats { + final double totalRevenue; + final int totalQuantity; + final int totalOrders; + final double averageOrderValue; + + SummaryStats({ + required this.totalRevenue, + required this.totalQuantity, + required this.totalOrders, + required this.averageOrderValue, + }); +} diff --git a/lib/presentation/pages/product/product_list/product_page.dart b/lib/presentation/pages/product/product_list/product_page.dart new file mode 100644 index 0000000..0c4aa78 --- /dev/null +++ b/lib/presentation/pages/product/product_list/product_page.dart @@ -0,0 +1,385 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:shimmer/shimmer.dart'; + +import '../../../../application/category/category_loader/category_loader_bloc.dart'; +import '../../../../application/product/product_loader/product_loader_bloc.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/category/category.dart'; +import '../../../../domain/product/product.dart'; +import '../../../../injection.dart'; +import '../../../components/appbar/appbar.dart'; +import '../../../components/button/button.dart'; +import '../../../components/widgets/empty_widget.dart'; +import 'widgets/category_delegate.dart'; +import 'widgets/product_card.dart'; +import 'widgets/product_tile.dart'; + +@RoutePage() +class ProductPage extends StatefulWidget implements AutoRouteWrapper { + const ProductPage({super.key}); + + @override + State createState() => _ProductPageState(); + + @override + Widget wrappedRoute(BuildContext context) => MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => + getIt()..add(CategoryLoaderEvent.fetched()), + ), + BlocProvider( + create: (context) => + getIt() + ..add(ProductLoaderEvent.fetched(isRefresh: true)), + ), + ], + child: this, + ); +} + +enum ViewType { grid, list } + +class _ProductPageState extends State + with TickerProviderStateMixin { + Category selectedCategory = Category.addAllData(); + ViewType currentViewType = ViewType.grid; + ScrollController scrollController = ScrollController(); + + @override + initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BlocListener( + listenWhen: (previous, current) => + previous.categoryId != current.categoryId, + listener: (context, state) { + context.read().add( + ProductLoaderEvent.fetched(isRefresh: true), + ); + }, + child: BlocBuilder( + builder: (context, state) { + return Scaffold( + backgroundColor: AppColor.background, + body: NotificationListener( + onNotification: (notification) { + if (notification is ScrollEndNotification && + scrollController.position.extentAfter == 0) { + context.read().add( + ProductLoaderEvent.fetched(), + ); + return true; + } + + return true; + }, + child: CustomScrollView( + controller: scrollController, + slivers: [ + _buildSliverAppBar(context), + _buildCategoryFilter(), + _buildProductContent(state), + ], + ), + ), + ); + }, + ), + ); + } + + Widget _buildSliverAppBar(BuildContext context) { + return SliverAppBar( + expandedHeight: 120.0, + floating: false, + pinned: true, + elevation: 0, + flexibleSpace: CustomAppBar(title: context.lang.product), + actions: [ + ActionIconButton(onTap: () {}, icon: LineIcons.search), + ActionIconButton( + onTap: _toggleViewType, + icon: currentViewType == ViewType.grid + ? LineIcons.list + : LineIcons.thLarge, + ), + ], + ); + } + + Widget _buildCategoryFilter() { + return BlocBuilder( + builder: (context, state) { + if (state.isFetching && state.categories.isEmpty) { + return _buildCategoryShimmer(); + } + + return SliverPersistentHeader( + pinned: true, + delegate: ProductCategoryHeaderDelegate( + categories: state.categories, + selectedCategory: selectedCategory, + onCategoryChanged: (category) { + setState(() { + selectedCategory = category; + }); + if (category.id == Category.addAllData().id) { + context.read().add( + ProductLoaderEvent.categoryIdChanged(''), + ); + } else { + context.read().add( + ProductLoaderEvent.categoryIdChanged(category.id), + ); + } + }, + ), + ); + }, + ); + } + + Widget _buildCategoryShimmer() { + return SliverToBoxAdapter( + child: Container( + height: 60, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Row( + children: List.generate( + 4, + (index) => Container( + margin: EdgeInsets.only(right: index < 3 ? 12 : 0), + width: 80, + height: 35, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + ), + ), + ), + ), + ), + ), + ); + } + + Widget _buildProductContent(ProductLoaderState state) { + if (state.isFetching && state.products.isEmpty) { + return currentViewType == ViewType.grid + ? _buildProductGridShimmer() + : _buildProductListShimmer(); + } + + if (state.products.isEmpty && !state.isFetching) { + return SliverToBoxAdapter( + child: EmptyWidget( + title: 'Tidak ada produk ditemukan', + message: 'Coba ubah filter atau tambah produk baru', + ), + ); + } + + return currentViewType == ViewType.grid + ? _buildProductGrid(state.products) + : _buildProductList(state.products); + } + + Widget _buildProductGridShimmer() { + return SliverPadding( + padding: const EdgeInsets.all(16.0), + sliver: SliverGrid( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 0.85, + crossAxisSpacing: 16.0, + mainAxisSpacing: 16.0, + ), + delegate: SliverChildBuilderDelegate((context, index) { + return _buildProductTileShimmer(); + }, childCount: 6), // Show 6 shimmer items + ), + ); + } + + Widget _buildProductTileShimmer() { + return Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Image shimmer + Expanded( + flex: 3, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + ), + ), + // Content shimmer + Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + height: 16, + color: Colors.white, + ), + const SizedBox(height: 8), + Container(width: 100, height: 12, color: Colors.white), + const Spacer(), + Container(width: 80, height: 14, color: Colors.white), + ], + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildProductListShimmer() { + return SliverPadding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + sliver: SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + return _buildProductListItemShimmer(); + }, childCount: 8), // Show 8 shimmer items + ), + ); + } + + Widget _buildProductListItemShimmer() { + return Container( + margin: const EdgeInsets.only(bottom: 12.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + // Image shimmer + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + ), + const SizedBox(width: 12), + // Content shimmer + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + height: 16, + color: Colors.white, + ), + const SizedBox(height: 8), + Container(width: 120, height: 12, color: Colors.white), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container(width: 100, height: 16, color: Colors.white), + Container( + width: 60, + height: 24, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + ), + ], + ), + ], + ), + ), + const SizedBox(width: 8), + // Action button shimmer + Container(width: 24, height: 24, color: Colors.white), + ], + ), + ), + ), + ); + } + + Widget _buildProductGrid(List products) { + return SliverPadding( + padding: const EdgeInsets.all(16.0), + sliver: SliverGrid( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 0.75, + crossAxisSpacing: 16.0, + mainAxisSpacing: 16.0, + ), + delegate: SliverChildBuilderDelegate((context, index) { + final product = products[index]; + return ProductTile(product: product, onTap: () {}); + }, childCount: products.length), + ), + ); + } + + Widget _buildProductList(List products) { + return SliverPadding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + sliver: SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + final product = products[index]; + return ProductCard(product: product); + }, childCount: products.length), + ), + ); + } + + void _toggleViewType() { + setState(() { + currentViewType = currentViewType == ViewType.grid + ? ViewType.list + : ViewType.grid; + }); + } +} diff --git a/lib/presentation/pages/product/product_list/widgets/category_delegate.dart b/lib/presentation/pages/product/product_list/widgets/category_delegate.dart new file mode 100644 index 0000000..c042683 --- /dev/null +++ b/lib/presentation/pages/product/product_list/widgets/category_delegate.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; + +import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/category/category.dart'; + +class ProductCategoryHeaderDelegate extends SliverPersistentHeaderDelegate { + final List categories; + final Category selectedCategory; + final ValueChanged onCategoryChanged; + + ProductCategoryHeaderDelegate({ + required this.categories, + required this.selectedCategory, + required this.onCategoryChanged, + }); + + @override + Widget build( + BuildContext context, + double shrinkOffset, + bool overlapsContent, + ) { + return Container( + color: AppColor.background, + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Container( + height: 50, + margin: const EdgeInsets.symmetric(horizontal: 16.0), + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: categories.length, + itemBuilder: (context, index) { + final category = categories[index]; + final isSelected = selectedCategory == category; + + return Container( + margin: const EdgeInsets.only(right: 12.0), + child: FilterChip( + label: Text(category.name), + selected: isSelected, + onSelected: (selected) => onCategoryChanged(category), + backgroundColor: AppColor.surface, + selectedColor: AppColor.primary, + checkmarkColor: AppColor.textWhite, + labelStyle: AppStyle.md.copyWith( + color: isSelected ? AppColor.textWhite : AppColor.textPrimary, + fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, + ), + side: BorderSide( + color: isSelected ? AppColor.primary : AppColor.border, + ), + ), + ); + }, + ), + ), + ); + } + + @override + double get maxExtent => 66.0; + + @override + double get minExtent => 66.0; + + @override + bool shouldRebuild(ProductCategoryHeaderDelegate oldDelegate) { + return oldDelegate.categories != categories || + oldDelegate.selectedCategory != selectedCategory; + } +} diff --git a/lib/presentation/pages/product/product_list/widgets/product_card.dart b/lib/presentation/pages/product/product_list/widgets/product_card.dart new file mode 100644 index 0000000..ebb6730 --- /dev/null +++ b/lib/presentation/pages/product/product_list/widgets/product_card.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; + +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/product/product.dart'; +import '../../../../components/image/image.dart'; + +class ProductCard extends StatelessWidget { + const ProductCard({super.key, required this.product, this.onTap}); + + final Product product; + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 12.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 1, + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + // Product Image + _buildProductImage(), + const SizedBox(width: 12), + // Product Info + Expanded(child: _buildProductInfo()), + ], + ), + ), + ), + ); + } + + Widget _buildProductImage() { + return Container( + width: 80, + height: 80, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: AppColor.background, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: AppNetworkImage(url: product.imageUrl, fit: BoxFit.cover), + ), + ); + } + + Widget _buildProductInfo() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.name, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Text( + product.description, + style: TextStyle(fontSize: 12, color: AppColor.textLight), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + product.price.currencyFormatRp, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: AppColor.primary, + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: _getStatusColor().withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + product.isActive ? 'AKTIF' : 'NONAKTIF', + style: TextStyle( + fontSize: 12, + color: _getStatusColor(), + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ], + ); + } + + Color _getStatusColor() { + return product.isActive ? Colors.green : Colors.red; + } +} diff --git a/lib/presentation/pages/product/product_list/widgets/product_tile.dart b/lib/presentation/pages/product/product_list/widgets/product_tile.dart new file mode 100644 index 0000000..fe912bf --- /dev/null +++ b/lib/presentation/pages/product/product_list/widgets/product_tile.dart @@ -0,0 +1,192 @@ +import 'package:flutter/material.dart'; + +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/product/product.dart'; +import '../../../../components/image/image.dart'; +import '../../../../components/spacer/spacer.dart'; + +class ProductTile extends StatelessWidget { + final Product product; + final VoidCallback onTap; + + const ProductTile({super.key, required this.product, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12.0), + border: Border.all( + color: product.isActive + ? AppColor.border + : AppColor.borderLight, + ), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [_buildProductImage(), _buildProductInfo()], + ), + ), + // Overlay gray untuk produk yang tidak aktif + if (!product.isActive) + Container( + decoration: BoxDecoration( + color: AppColor.black.withOpacity(0.4), + borderRadius: BorderRadius.circular(12.0), + ), + child: Center( + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + decoration: BoxDecoration( + color: AppColor.warning, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: AppColor.black.withOpacity(0.2), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.visibility_off, + color: AppColor.textWhite, + size: 16, + ), + SpaceWidth(6), + Text( + 'NONAKTIF', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ); + } + + Widget _buildProductImage() { + return Expanded( + flex: 3, + child: Container( + width: double.infinity, + decoration: const BoxDecoration( + color: AppColor.borderLight, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(12.0), + topRight: Radius.circular(12.0), + ), + ), + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12.0), + topRight: Radius.circular(12.0), + ), + child: AppNetworkImage(url: product.imageUrl, fit: BoxFit.cover), + ), + ), + ); + } + + Widget _buildProductInfo() { + return Expanded( + flex: 2, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + product.name, + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.bold, + color: product.isActive + ? AppColor.textPrimary + : AppColor.textSecondary, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Text( + product.price.currencyFormatRp, + style: AppStyle.xs.copyWith( + color: product.isActive + ? AppColor.primary + : AppColor.textSecondary, + fontWeight: FontWeight.bold, + ), + ), + const Spacer(), + _buildBottomInfo(), + ], + ), + ), + ); + } + + Widget _buildBottomInfo() { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), + decoration: BoxDecoration( + color: _getPrinterTypeColor().withOpacity(0.1), + borderRadius: BorderRadius.circular(3.0), + ), + child: Text( + product.printerType.toUpperCase(), + style: AppStyle.xs.copyWith( + color: product.isActive + ? _getPrinterTypeColor() + : AppColor.textSecondary, + fontSize: 8, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ); + } + + Color _getPrinterTypeColor() { + switch (product.printerType.toLowerCase()) { + case 'kitchen': + return Colors.orange; + case 'bar': + return Colors.blue; + case 'receipt': + return AppColor.primary; + default: + return AppColor.primary; + } + } +} diff --git a/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart b/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart new file mode 100644 index 0000000..9acc80d --- /dev/null +++ b/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart @@ -0,0 +1,107 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../../application/user/change_password_form/change_password_form_bloc.dart'; +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/theme/theme.dart'; +import '../../../../../injection.dart'; +import '../../../../components/appbar/appbar.dart'; +import '../../../../components/button/button.dart'; +import '../../../../components/spacer/spacer.dart'; +import '../../../../components/toast/flushbar.dart'; +import 'widgets/current_password.dart'; +import 'widgets/new_password.dart'; + +@RoutePage() +class ProfileChangePasswordPage extends StatefulWidget + implements AutoRouteWrapper { + const ProfileChangePasswordPage({super.key}); + + @override + State createState() => + _ProfileChangePasswordPageState(); + + @override + Widget wrappedRoute(BuildContext context) => + BlocProvider(create: (_) => getIt(), child: this); +} + +class _ProfileChangePasswordPageState extends State { + @override + Widget build(BuildContext context) { + return BlocListener( + listenWhen: (p, c) => + p.failureOrChangePasswordOption != c.failureOrChangePasswordOption, + listener: (context, state) { + state.failureOrChangePasswordOption.fold( + () => null, + (either) => either.fold( + (f) => AppFlushbar.showUserFailureToast(context, f), + (user) { + if (context.mounted) { + AppFlushbar.showSuccess(context, context.lang.password_changed); + Future.delayed(const Duration(seconds: 2), () { + context.router.back(); + }); + } + }, + ), + ); + }, + child: Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + slivers: [ + // SliverAppBar with gradient + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.change_password), + ), + SliverToBoxAdapter( + child: + BlocBuilder( + builder: (context, state) { + return Container( + margin: EdgeInsets.all(AppValue.margin), + padding: EdgeInsets.all(AppValue.padding), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(AppValue.radius), + ), + child: Form( + autovalidateMode: state.showErrorMessages + ? AutovalidateMode.always + : AutovalidateMode.disabled, + child: Column( + children: [ + ChangePasswordCurrentPassword(), + SpaceHeight(16), + ChangePasswordNewPassword(), + SpaceHeight(24), + AppElevatedButton( + text: context.lang.save, + isLoading: state.isSubmitting, + onPressed: () { + context.read().add( + ChangePasswordFormEvent.submitted(), + ); + }, + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart b/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart new file mode 100644 index 0000000..2422388 --- /dev/null +++ b/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../../../application/user/change_password_form/change_password_form_bloc.dart'; +import '../../../../../../common/extension/extension.dart'; +import '../../../../../components/field/field.dart'; + +class ChangePasswordCurrentPassword extends StatelessWidget { + const ChangePasswordCurrentPassword({super.key}); + + @override + Widget build(BuildContext context) { + return AppPasswordTextFormField( + title: context.lang.current_password, + prefixIcon: LineIcons.lock, + hintText: context.lang.current_password_placeholder, + onChanged: (value) => context.read().add( + ChangePasswordFormEvent.currentPasswordChanged(value), + ), + validator: (value) { + if (context + .read() + .state + .currentPassword + .isEmpty) { + return context.lang.current_password_placeholder; + } + return null; + }, + ); + } +} diff --git a/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart b/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart new file mode 100644 index 0000000..ad133f6 --- /dev/null +++ b/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../../../application/user/change_password_form/change_password_form_bloc.dart'; +import '../../../../../../common/extension/extension.dart'; +import '../../../../../components/field/field.dart'; + +class ChangePasswordNewPassword extends StatelessWidget { + const ChangePasswordNewPassword({super.key}); + + @override + Widget build(BuildContext context) { + return AppPasswordTextFormField( + title: context.lang.new_password, + prefixIcon: LineIcons.lock, + hintText: context.lang.new_password_placeholder, + onChanged: (value) => context.read().add( + ChangePasswordFormEvent.newPasswordChanged(value), + ), + validator: (value) { + if (context.read().state.newPassword.isEmpty) { + return context.lang.new_password_placeholder; + } + + if (context.read().state.newPassword == + context.read().state.currentPassword) { + return context.lang.new_password_not_same; + } + return null; + }, + ); + } +} diff --git a/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart b/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart new file mode 100644 index 0000000..53ff39d --- /dev/null +++ b/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart @@ -0,0 +1,109 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../../application/auth/auth_bloc.dart'; +import '../../../../../application/user/user_edit_form/user_edit_form_bloc.dart'; +import '../../../../../common/extension/extension.dart'; +import '../../../../../common/theme/theme.dart'; +import '../../../../../domain/user/user.dart'; +import '../../../../../injection.dart'; +import '../../../../components/appbar/appbar.dart'; +import '../../../../components/button/button.dart'; +import '../../../../components/spacer/spacer.dart'; +import '../../../../components/toast/flushbar.dart'; +import 'widgets/name_field.dart'; + +@RoutePage() +class ProfileEditPage extends StatefulWidget implements AutoRouteWrapper { + final User user; + const ProfileEditPage({super.key, required this.user}); + + @override + State createState() => _ProfileEditPageState(); + + @override + Widget wrappedRoute(BuildContext context) => + BlocProvider(create: (_) => getIt(), child: this); +} + +class _ProfileEditPageState extends State { + TextEditingController nameController = TextEditingController(); + + @override + void initState() { + super.initState(); + nameController = TextEditingController(text: widget.user.name); + } + + @override + Widget build(BuildContext context) { + return BlocListener( + listenWhen: (p, c) => p.failureOrUserOption != c.failureOrUserOption, + listener: (context, state) { + state.failureOrUserOption.fold( + () => null, + (either) => either.fold( + (f) => AppFlushbar.showUserFailureToast(context, f), + (user) { + if (context.mounted) { + context.read().add(AuthEvent.fetchCurrentUser()); + context.router.back(); + } + }, + ), + ); + }, + child: Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + slivers: [ + // SliverAppBar with gradient + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.edit_profile), + ), + SliverToBoxAdapter( + child: BlocBuilder( + builder: (context, state) { + return Container( + margin: EdgeInsets.all(AppValue.margin), + padding: EdgeInsets.all(AppValue.padding), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(AppValue.radius), + ), + child: Form( + autovalidateMode: state.showErrorMessages + ? AutovalidateMode.always + : AutovalidateMode.disabled, + child: Column( + children: [ + ProfileEditNameField(controller: nameController), + SpaceHeight(24), + AppElevatedButton( + text: context.lang.save, + isLoading: state.isSubmitting, + onPressed: () { + context.read().add( + UserEditFormEvent.submitted(), + ); + }, + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart b/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart new file mode 100644 index 0000000..9adbc51 --- /dev/null +++ b/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../../../application/user/user_edit_form/user_edit_form_bloc.dart'; +import '../../../../../../common/extension/extension.dart'; +import '../../../../../components/field/field.dart'; + +class ProfileEditNameField extends StatelessWidget { + final TextEditingController controller; + const ProfileEditNameField({super.key, required this.controller}); + + @override + Widget build(BuildContext context) { + return AppTextFormField( + title: context.lang.name, + prefixIcon: LineIcons.user, + hintText: context.lang.name_placeholder, + controller: controller, + onChanged: (value) { + context.read().add( + UserEditFormEvent.nameChanged(value), + ); + }, + validator: (value) { + if (context.read().state.name.isEmpty) { + return context.lang.name_placeholder; + } + + return null; + }, + ); + } +} diff --git a/lib/presentation/pages/profile/profile_page.dart b/lib/presentation/pages/profile/profile_page.dart new file mode 100644 index 0000000..1607221 --- /dev/null +++ b/lib/presentation/pages/profile/profile_page.dart @@ -0,0 +1,229 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:line_icons/line_icons.dart'; +import 'package:loader_overlay/loader_overlay.dart'; + +import '../../../application/auth/auth_bloc.dart'; +import '../../../application/auth/logout_form/logout_form_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../common/utils/fcm_service.dart'; +import '../../../injection.dart'; +import '../../components/button/button.dart'; +import '../../components/spacer/spacer.dart'; +import '../../components/toast/flushbar.dart'; +import '../../router/app_router.gr.dart'; +import 'widgets/account_info.dart'; +import 'widgets/app_setting.dart'; +import 'widgets/business_setting.dart'; +import 'widgets/danger_zone.dart'; +import 'widgets/header.dart'; +import 'widgets/support.dart'; + +@RoutePage() +class ProfilePage extends StatelessWidget implements AutoRouteWrapper { + const ProfilePage({super.key}); + + @override + Widget build(BuildContext context) { + return MultiBlocListener( + listeners: [ + BlocListener( + listener: (context, state) { + state.failureOrAuthOption.fold( + () => null, + (either) => either.fold( + (f) => AppFlushbar.showAuthFailureToast(context, f), + (_) => context.router.replace(const LoginRoute()), + ), + ); + }, + ), + BlocListener( + listenWhen: (previous, current) => + previous.isSubmitting != current.isSubmitting, + listener: (context, state) { + if (state.isSubmitting) { + context.loaderOverlay.show(); + } else { + context.loaderOverlay.hide(); + } + }, + ), + ], + child: BlocBuilder( + builder: (context, state) { + return Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + slivers: [ + SliverAppBar( + backgroundColor: AppColor.primary, + elevation: 0, + pinned: true, + expandedHeight: 270.0, + flexibleSpace: LayoutBuilder( + builder: + (BuildContext context, BoxConstraints constraints) { + // Calculate the collapse ratio + final double top = constraints.biggest.height; + final double collapsedHeight = + MediaQuery.of(context).padding.top + + kToolbarHeight; + final double expandedHeight = 270.0; + final double shrinkRatio = + ((expandedHeight - top) / + (expandedHeight - collapsedHeight)) + .clamp(0.0, 1.0); + + return FlexibleSpaceBar( + background: ProfileHeader(user: state.user), + titlePadding: const EdgeInsets.only( + left: 20, + right: 12, + bottom: 16, + ), + title: Opacity( + opacity: shrinkRatio, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + context.lang.profile, + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.w700, + fontSize: 18, + letterSpacing: -0.5, + color: AppColor.white, + ), + ), + ActionIconButton( + onTap: () => context.router.push( + ProfileEditRoute(user: state.user), + ), + icon: LineIcons.userEdit, + ), + ], + ), + ), + ); + }, + ), + ), + SliverToBoxAdapter( + child: Column( + children: [ + const SpaceHeight(20), + ProfileAccountInfo(user: state.user), + const SpaceHeight(12), + ProfileBusinessSetting(), + const SpaceHeight(12), + ProfileAppSetting(), + const SpaceHeight(12), + ProfileSupport(), + const SpaceHeight(12), + ProfileDangerZone(), + const SpaceHeight(30), + // Debug only: FCM Token + if (kDebugMode) const _FcmTokenDebugWidget(), + const SpaceHeight(30), + ], + ), + ), + ], + ), + ); + }, + ), + ); + } + + @override + Widget wrappedRoute(BuildContext context) => + BlocProvider(create: (_) => getIt(), child: this); +} + +class _FcmTokenDebugWidget extends StatefulWidget { + const _FcmTokenDebugWidget(); + + @override + State<_FcmTokenDebugWidget> createState() => _FcmTokenDebugWidgetState(); +} + +class _FcmTokenDebugWidgetState extends State<_FcmTokenDebugWidget> { + String? _token; + + @override + void initState() { + super.initState(); + _loadToken(); + } + + Future _loadToken() async { + final token = await getIt().getToken(); + if (mounted) setState(() => _token = token); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.black.withOpacity(0.05), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColor.black.withOpacity(0.1)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const Icon(Icons.bug_report, size: 14), + const SizedBox(width: 4), + Text( + 'FCM Token (debug only)', + style: AppStyle.sm.copyWith(fontWeight: FontWeight.w700), + ), + const Spacer(), + GestureDetector( + onTap: () async { + if (_token == null) return; + await Clipboard.setData(ClipboardData(text: _token!)); + debugPrint('[FCM] Token copied: $_token'); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('FCM token copied!'), + duration: Duration(seconds: 2), + ), + ); + } + }, + child: Text( + 'Copy', + style: AppStyle.sm.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + const SizedBox(height: 6), + Text( + _token ?? 'Loading...', + style: AppStyle.xs.copyWith(color: AppColor.black.withOpacity(0.6)), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/account_info.dart b/lib/presentation/pages/profile/widgets/account_info.dart new file mode 100644 index 0000000..70e3df1 --- /dev/null +++ b/lib/presentation/pages/profile/widgets/account_info.dart @@ -0,0 +1,80 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/user/user.dart'; +import '../../../router/app_router.gr.dart'; +import 'divider.dart'; +import 'profile_tile.dart'; + +class ProfileAccountInfo extends StatelessWidget { + final User user; + const ProfileAccountInfo({super.key, required this.user}); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: AppValue.margin), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(16), + child: Text( + context.lang.account_information, + style: AppStyle.xl.copyWith( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + + ProfileTile( + icon: LineIcons.envelope, + title: context.lang.email, + subtitle: user.email, + showArrow: false, + ), + + ProfileDivider(), + + ProfileTile( + icon: LineIcons.calendarAlt, + title: context.lang.member_since, + subtitle: user.createdAt.toDate, + showArrow: false, + ), + ProfileDivider(), + + ProfileTile( + icon: LineIcons.userEdit, + title: context.lang.edit_profile, + subtitle: context.lang.edit_profile_desc, + onTap: () => context.router.push(ProfileEditRoute(user: user)), + ), + ProfileDivider(), + ProfileTile( + icon: LineIcons.lock, + title: context.lang.change_password, + subtitle: context.lang.change_password_desc, + onTap: () => context.router.push(ProfileChangePasswordRoute()), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/app_setting.dart b/lib/presentation/pages/profile/widgets/app_setting.dart new file mode 100644 index 0000000..563ef57 --- /dev/null +++ b/lib/presentation/pages/profile/widgets/app_setting.dart @@ -0,0 +1,86 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../router/app_router.gr.dart'; +import 'profile_tile.dart'; + +class ProfileAppSetting extends StatefulWidget { + const ProfileAppSetting({super.key}); + + @override + State createState() => _ProfileAppSettingState(); +} + +class _ProfileAppSettingState extends State { + // bool _notificationsEnabled = true; + // bool _darkModeEnabled = false; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: AppValue.margin), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(16), + child: Text( + context.lang.app_settings, + style: AppStyle.xl.copyWith( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + + // ProfileSwitchTile( + // icon: Icons.notifications_outlined, + // title: 'Notifications', + // subtitle: 'Receive app notifications', + // value: _notificationsEnabled, + // onChanged: (value) { + // setState(() { + // _notificationsEnabled = value; + // }); + // }, + // ), + + // ProfileDivider(), + + // ProfileSwitchTile( + // icon: Icons.dark_mode_outlined, + // title: 'Dark Mode', + // subtitle: 'Switch to dark theme', + // value: _darkModeEnabled, + // onChanged: (value) { + // setState(() { + // _darkModeEnabled = value; + // }); + // }, + // ), + // ProfileDivider(), + ProfileTile( + icon: Icons.language_outlined, + title: context.lang.language, + subtitle: context.lang.language_desc, + onTap: () => context.router.push(LanguageRoute()), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/business_setting.dart b/lib/presentation/pages/profile/widgets/business_setting.dart new file mode 100644 index 0000000..d7789be --- /dev/null +++ b/lib/presentation/pages/profile/widgets/business_setting.dart @@ -0,0 +1,79 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../router/app_router.gr.dart'; +import 'divider.dart'; +import 'profile_tile.dart'; + +class ProfileBusinessSetting extends StatelessWidget { + const ProfileBusinessSetting({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: AppValue.margin), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(16), + child: Text( + context.lang.business_settings, + style: AppStyle.xl.copyWith( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + + ProfileTile( + icon: Icons.business_outlined, + title: context.lang.outlet_information, + subtitle: context.lang.outlet_informatio_desc, + onTap: () => context.router.push(OutletInformationRoute()), + ), + + ProfileDivider(), + + ProfileTile( + icon: Icons.people_outline, + title: context.lang.staff_management, + subtitle: context.lang.staff_management_desc, + onTap: () => context.router.push(ComingSoonRoute()), + ), + + ProfileDivider(), + + ProfileTile( + icon: Icons.inventory_2_outlined, + title: context.lang.products, + subtitle: context.lang.manage_your_products, + onTap: () => context.router.push(ProductRoute()), + ), + ProfileDivider(), + + ProfileTile( + icon: Icons.download_outlined, + title: context.lang.download_report, + subtitle: context.lang.download_report_desc, + onTap: () => context.router.push(DownloadReportRoute()), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/danger_zone.dart b/lib/presentation/pages/profile/widgets/danger_zone.dart new file mode 100644 index 0000000..e9d443c --- /dev/null +++ b/lib/presentation/pages/profile/widgets/danger_zone.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../application/auth/logout_form/logout_form_bloc.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import 'profile_tile.dart'; + +class ProfileDangerZone extends StatelessWidget { + const ProfileDangerZone({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: AppValue.margin), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.error.withOpacity(0.3)), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ProfileTile( + icon: Icons.logout, + title: context.lang.logout, + subtitle: context.lang.logout_desc, + iconColor: AppColor.error, + textColor: AppColor.error, + onTap: () { + context.read().add(LogoutFormEvent.submitted()); + }, + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/divider.dart b/lib/presentation/pages/profile/widgets/divider.dart new file mode 100644 index 0000000..12add2b --- /dev/null +++ b/lib/presentation/pages/profile/widgets/divider.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class ProfileDivider extends StatelessWidget { + const ProfileDivider({super.key}); + + @override + Widget build(BuildContext context) { + return Divider( + height: 1, + thickness: 1, + color: AppColor.border, + indent: 16, + endIndent: 16, + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/header.dart b/lib/presentation/pages/profile/widgets/header.dart new file mode 100644 index 0000000..5f4b074 --- /dev/null +++ b/lib/presentation/pages/profile/widgets/header.dart @@ -0,0 +1,431 @@ +import 'package:flutter/material.dart'; +import 'dart:math' as math; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/painter/wave_painter.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/user/user.dart'; +import '../../../components/spacer/spacer.dart'; + +class ProfileHeader extends StatefulWidget { + final User user; + const ProfileHeader({super.key, required this.user}); + + @override + State createState() => _ProfileHeaderState(); +} + +class _ProfileHeaderState extends State + with TickerProviderStateMixin { + late AnimationController _animationController; + late AnimationController _particleController; + late AnimationController _waveController; + late AnimationController _breathController; + + late Animation _fadeInAnimation; + late Animation _slideAnimation; + late Animation _scaleAnimation; + late Animation _particleAnimation; + late Animation _waveAnimation; + late Animation _breathAnimation; + + @override + void initState() { + super.initState(); + + // Main content animations + _animationController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _particleController = AnimationController( + duration: const Duration(seconds: 8), + vsync: this, + )..repeat(); + + _waveController = AnimationController( + duration: const Duration(seconds: 6), + vsync: this, + )..repeat(); + + _breathController = AnimationController( + duration: const Duration(seconds: 4), + vsync: this, + )..repeat(reverse: true); + + // Content animations + _fadeInAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.0, 0.6, curve: Curves.easeOut), + ), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.5), end: Offset.zero).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.2, 0.8, curve: Curves.easeOutCubic), + ), + ); + + _scaleAnimation = Tween(begin: 0.8, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: const Interval(0.0, 0.7, curve: Curves.elasticOut), + ), + ); + + _particleAnimation = Tween( + begin: 0.0, + end: 2 * math.pi, + ).animate(_particleController); + + _waveAnimation = Tween( + begin: 0.0, + end: 2 * math.pi, + ).animate(_waveController); + + _breathAnimation = Tween(begin: 0.8, end: 1.2).animate( + CurvedAnimation(parent: _breathController, curve: Curves.easeInOut), + ); + + _animationController.forward(); + } + + @override + void dispose() { + _animationController.dispose(); + _particleController.dispose(); + _waveController.dispose(); + _breathController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: Listenable.merge([ + _particleController, + _waveController, + _breathController, + ]), + builder: (context, child) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + ...AppColor.primaryGradient, + AppColor.primaryGradient.last.withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + boxShadow: [ + BoxShadow( + color: AppColor.primaryGradient.first.withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 10), + ), + ], + ), + child: Stack( + alignment: Alignment.center, + children: [ + // Simplified animated background + _buildAnimatedBackground(), + + // Main content + _buildMainContent(), + ], + ), + ); + }, + ); + } + + Widget _buildAnimatedBackground() { + return Stack( + children: [ + // Floating particles with orbital motion + ...List.generate(12, (index) { + final double radius = 80 + (index * 20); + final double angle = _particleAnimation.value + (index * 0.5); + final double centerX = MediaQuery.of(context).size.width * 0.5; + final double centerY = 150; + + return Positioned( + left: centerX + math.cos(angle) * radius - 6, + top: centerY + math.sin(angle) * (radius * 0.6) - 6, + child: Transform.scale( + scale: _breathAnimation.value * 0.5, + child: Container( + width: 3 + (index % 4), + height: 3 + (index % 4), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.textWhite.withOpacity(0.6), + boxShadow: [ + BoxShadow( + color: AppColor.textWhite.withOpacity(0.3), + blurRadius: 8, + spreadRadius: 1, + ), + ], + ), + ), + ), + ); + }), + + // Wave patterns + Positioned.fill( + child: CustomPaint( + painter: WavePainter( + animation: _waveAnimation.value, + color: AppColor.textWhite.withOpacity(0.1), + ), + ), + ), + + // Sparkle effects + ...List.generate(6, (index) { + return Positioned( + left: (index * 80.0) % MediaQuery.of(context).size.width, + top: 50 + (index * 30.0), + child: Transform.rotate( + angle: _particleAnimation.value * 2 + index, + child: Transform.scale( + scale: math.sin(_particleAnimation.value + index) * 0.5 + 1, + child: Icon( + Icons.auto_awesome, + size: 12 + (index % 3) * 4, + color: AppColor.textWhite.withOpacity(0.4), + ), + ), + ), + ); + }), + + // Gradient overlay for depth + Container( + decoration: BoxDecoration( + gradient: RadialGradient( + center: const Alignment(0, -0.3), + radius: 1.2, + colors: [ + Colors.transparent, + AppColor.primaryGradient.first.withOpacity(0.1), + Colors.transparent, + ], + ), + ), + ), + ], + ); + } + + Widget _buildMainContent() { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SpaceHeight(30), + + // Profile Picture with simplified design + AnimatedBuilder( + animation: _scaleAnimation, + builder: (context, child) { + return Transform.scale( + scale: _scaleAnimation.value, + child: Stack( + alignment: Alignment.center, + children: [ + // Outer glow effect with breathing animation + AnimatedBuilder( + animation: _breathAnimation, + builder: (context, child) { + return Transform.scale( + scale: _breathAnimation.value * 0.1 + 1, + child: Container( + width: 120, + height: 120, + decoration: BoxDecoration( + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: AppColor.textWhite.withOpacity(0.3), + blurRadius: 20, + spreadRadius: 5, + ), + ], + ), + ), + ); + }, + ), + // Profile picture container + Container( + width: 110, + height: 110, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all(color: AppColor.textWhite, width: 4), + gradient: LinearGradient( + colors: [ + AppColor.primaryLight, + AppColor.primaryLight.withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + child: ClipOval( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primaryLight, + AppColor.primaryLight.withOpacity(0.7), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: const Icon( + Icons.person, + size: 55, + color: AppColor.textWhite, + ), + ), + ), + ), + // Online status indicator with subtle pulse + Positioned( + bottom: 5, + right: 5, + child: AnimatedBuilder( + animation: _breathController, + builder: (context, child) { + return Transform.scale( + scale: _breathAnimation.value * 0.2 + 1, + child: Container( + width: 24, + height: 24, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.green, + border: Border.all( + color: AppColor.textWhite, + width: 3, + ), + boxShadow: [ + BoxShadow( + color: Colors.green.withOpacity(0.6), + blurRadius: 8, + spreadRadius: 2, + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), + ); + }, + ), + + const SpaceHeight(20), + + // Name with animation + SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeInAnimation, + child: Column( + children: [ + Text( + widget.user.name, + style: AppStyle.h5.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textWhite, + shadows: [ + Shadow( + color: Colors.black.withOpacity(0.3), + offset: const Offset(0, 2), + blurRadius: 4, + ), + ], + ), + ), + const SpaceHeight(4), + Container( + height: 2, + width: 60, + decoration: BoxDecoration( + color: AppColor.textWhite.withOpacity(0.7), + borderRadius: BorderRadius.circular(1), + ), + ), + ], + ), + ), + ), + + const SpaceHeight(12), + + // Enhanced Role Badge + FadeTransition( + opacity: _fadeInAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + decoration: BoxDecoration( + color: AppColor.textWhite.withOpacity(0.25), + borderRadius: BorderRadius.circular(25), + border: Border.all( + color: AppColor.textWhite.withOpacity(0.3), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.business_center, + size: 16, + color: AppColor.textWhite.withOpacity(0.9), + ), + const SpaceWidth(6), + Text( + widget.user.role.toTitleCase, + style: AppStyle.md.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + ), + ), + ], + ), + ), + ), + ), + + const SpaceHeight(30), + ], + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/profile_switch_tile.dart b/lib/presentation/pages/profile/widgets/profile_switch_tile.dart new file mode 100644 index 0000000..a7d8a71 --- /dev/null +++ b/lib/presentation/pages/profile/widgets/profile_switch_tile.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class ProfileSwitchTile extends StatelessWidget { + final IconData icon; + final String title; + final String? subtitle; + final bool value; + final ValueChanged onChanged; + const ProfileSwitchTile({ + super.key, + required this.icon, + required this.title, + this.subtitle, + required this.value, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, color: AppColor.primary, size: 20), + ), + title: Text( + title, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w500, + color: AppColor.textPrimary, + ), + ), + subtitle: subtitle != null + ? Text( + subtitle!, + style: AppStyle.md.copyWith(color: AppColor.textSecondary), + ) + : null, + trailing: Switch( + value: value, + onChanged: onChanged, + activeColor: AppColor.primary, + ), + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/profile_tile.dart b/lib/presentation/pages/profile/widgets/profile_tile.dart new file mode 100644 index 0000000..6f71ef1 --- /dev/null +++ b/lib/presentation/pages/profile/widgets/profile_tile.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class ProfileTile extends StatelessWidget { + final IconData icon; + final String title; + final String? subtitle; + final VoidCallback? onTap; + final bool showArrow; + final Color? iconColor; + final Color? textColor; + const ProfileTile({ + super.key, + required this.icon, + required this.title, + this.subtitle, + this.onTap, + this.showArrow = true, + this.iconColor, + this.textColor, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: (iconColor ?? AppColor.primary).withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, color: iconColor ?? AppColor.primary, size: 20), + ), + title: Text( + title, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w500, + color: textColor ?? AppColor.textPrimary, + ), + ), + subtitle: subtitle != null + ? Text( + subtitle!, + style: AppStyle.md.copyWith(color: AppColor.textSecondary), + ) + : null, + trailing: showArrow + ? Icon(Icons.chevron_right, color: AppColor.textLight, size: 20) + : null, + onTap: onTap, + ); + } +} diff --git a/lib/presentation/pages/profile/widgets/support.dart b/lib/presentation/pages/profile/widgets/support.dart new file mode 100644 index 0000000..6b077a5 --- /dev/null +++ b/lib/presentation/pages/profile/widgets/support.dart @@ -0,0 +1,72 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../router/app_router.gr.dart'; +import 'divider.dart'; +import 'profile_tile.dart'; + +class ProfileSupport extends StatelessWidget { + const ProfileSupport({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(horizontal: AppValue.margin), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.all(16), + child: Text( + context.lang.support, + style: AppStyle.xl.copyWith( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + + ProfileTile( + icon: Icons.help_outline, + title: context.lang.help_center, + subtitle: context.lang.help_center_desc, + onTap: () => context.router.push(ComingSoonRoute()), + ), + + // ProfileDivider(), + + // ProfileTile( + // icon: Icons.feedback_outlined, + // title: 'Send Feedback', + // subtitle: 'Help us improve the app', + // onTap: () { + // // Open feedback form + // }, + // ), + ProfileDivider(), + + ProfileTile( + icon: Icons.info_outline, + title: context.lang.about, + subtitle: context.lang.about_desc, + onTap: () => context.router.push(AboutAppRoute()), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/purchase/purchase_page.dart b/lib/presentation/pages/purchase/purchase_page.dart new file mode 100644 index 0000000..770a38c --- /dev/null +++ b/lib/presentation/pages/purchase/purchase_page.dart @@ -0,0 +1,194 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../components/appbar/appbar.dart'; +import 'widgets/purchase_tile.dart'; +import 'widgets/stat_card.dart'; +import 'widgets/status_chip.dart'; + +@RoutePage() +class PurchasePage extends StatefulWidget { + const PurchasePage({super.key}); + + @override + State createState() => _PurchasePageState(); +} + +class _PurchasePageState extends State + with TickerProviderStateMixin { + late AnimationController cardAnimation; + String selectedFilter = 'Semua'; + final List filterOptions = [ + 'Semua', + 'Pending', + 'Completed', + 'Cancelled', + ]; + + final List> purchaseData = [ + ]; + + @override + void initState() { + super.initState(); + + cardAnimation = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + cardAnimation.forward(); + } + + @override + void dispose() { + cardAnimation.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: CustomScrollView( + slivers: [ + SliverAppBar( + expandedHeight: 120.0, + floating: false, + pinned: true, + elevation: 0, + backgroundColor: AppColor.primary, + + flexibleSpace: CustomAppBar(title: context.lang.purchase), + ), + + // Stats Cards + SliverToBoxAdapter( + child: Container( + color: AppColor.background, + padding: const EdgeInsets.all(16.0), + child: Row( + children: [ + Expanded( + child: PurchaseStatCard( + title: context.lang.total_purchase, + value: 'Rp 0', + icon: LineIcons.shoppingCart, + iconColor: AppColor.success, + cardAnimation: cardAnimation, + ), + ), + const SizedBox(width: 12), + Expanded( + child: PurchaseStatCard( + title: context.lang.pending_order, + value: '0 ${context.lang.orders}', + icon: LineIcons.clock, + iconColor: AppColor.warning, + cardAnimation: cardAnimation, + ), + ), + ], + ), + ), + ), + + // Filter Section + SliverToBoxAdapter( + child: Container( + color: AppColor.surface, + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.lang.history_purchase, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w600, + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: AppColor.primary, + borderRadius: BorderRadius.circular(20), + ), + child: Text( + '${purchaseData.length} ${context.lang.orders}', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + SizedBox( + height: 40, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: filterOptions.length, + itemBuilder: (context, index) { + final isSelected = + selectedFilter == filterOptions[index]; + return PurchaseStatusChip( + isSelected: isSelected, + text: filterOptions[index], + onSelected: (selected) { + setState(() { + selectedFilter = filterOptions[index]; + }); + }, + ); + }, + ), + ), + ], + ), + ), + ), + + // Purchase List + SliverPadding( + padding: const EdgeInsets.all(16), + sliver: SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + final purchase = purchaseData[index]; + return AnimatedBuilder( + animation: cardAnimation, + builder: (context, child) { + final delay = index * 0.1; + final animValue = (cardAnimation.value - delay).clamp( + 0.0, + 1.0, + ); + + return Transform.translate( + offset: Offset(0, 30 * (1 - animValue)), + child: Opacity( + opacity: animValue, + child: PurchaseTile(purchase: purchase, index: index), + ), + ); + }, + ); + }, childCount: purchaseData.length), + ), + ), + + // Bottom spacing for FAB + const SliverToBoxAdapter(child: SizedBox(height: 80)), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/purchase/widgets/purchase_tile.dart b/lib/presentation/pages/purchase/widgets/purchase_tile.dart new file mode 100644 index 0000000..e850031 --- /dev/null +++ b/lib/presentation/pages/purchase/widgets/purchase_tile.dart @@ -0,0 +1,314 @@ +import 'package:flutter/material.dart'; +import 'package:line_icons/line_icons.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; + +class PurchaseTile extends StatelessWidget { + final Map purchase; + final int index; + const PurchaseTile({super.key, required this.purchase, required this.index}); + + @override + Widget build(BuildContext context) { + Color statusColor; + + switch (purchase['status']) { + case 'Completed': + statusColor = AppColor.success; + break; + case 'Pending': + statusColor = AppColor.warning; + break; + case 'Cancelled': + statusColor = AppColor.error; + break; + default: + statusColor = AppColor.textSecondary; + } + return AnimatedContainer( + duration: Duration(milliseconds: 300 + (index * 50)), + curve: Curves.easeOutCubic, + margin: const EdgeInsets.only(bottom: 16), + child: Material( + elevation: 0, + borderRadius: BorderRadius.circular(20), + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [AppColor.surface, AppColor.surface.withOpacity(0.95)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: AppColor.border.withOpacity(0.2), + width: 1, + ), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.08), + blurRadius: 25, + offset: const Offset(0, 10), + spreadRadius: 0, + ), + BoxShadow( + color: AppColor.black.withOpacity(0.04), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Text( + purchase['id'], + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w700, + color: AppColor.textWhite, + ), + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + statusColor.withOpacity(0.15), + statusColor.withOpacity(0.05), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: statusColor.withOpacity(0.2), + width: 1, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: statusColor, + ), + ), + const SizedBox(width: 6), + Text( + purchase['status'], + style: AppStyle.xs.copyWith( + color: statusColor, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: AppColor.background.withOpacity(0.5), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: AppColor.border.withOpacity(0.3), + width: 1, + ), + ), + child: Column( + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + LineIcons.building, + color: AppColor.primary, + size: 16, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + purchase['supplier'], + style: AppStyle.md.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.info.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + LineIcons.calendar, + color: AppColor.info, + size: 16, + ), + ), + const SizedBox(width: 12), + Text( + purchase['date'], + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const Spacer(), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: AppColor.secondary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + LineIcons.shoppingBag, + color: AppColor.secondary, + size: 14, + ), + const SizedBox(width: 4), + Text( + '${purchase['items']} ${context.lang.items}', + style: AppStyle.xs.copyWith( + color: AppColor.secondary, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ], + ), + ], + ), + ), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.total_purchase, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + 'Rp ${purchase['total'].toString().replaceAllMapped(RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]}.')}', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w800, + color: AppColor.primary, + ), + ), + ], + ), + Row( + children: [ + _buildActionButton(LineIcons.eye, AppColor.info, () {}), + const SizedBox(width: 8), + _buildActionButton( + LineIcons.edit, + AppColor.warning, + () {}, + ), + const SizedBox(width: 8), + _buildActionButton( + LineIcons.trash, + AppColor.error, + () {}, + ), + ], + ), + ], + ), + ], + ), + ), + ), + ); + } + + Widget _buildActionButton( + IconData icon, + Color color, + VoidCallback onPressed, + ) { + return Container( + width: 40, + height: 40, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [color.withOpacity(0.15), color.withOpacity(0.05)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: color.withOpacity(0.2), width: 1), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(12), + onTap: onPressed, + child: Center(child: Icon(icon, color: color, size: 18)), + ), + ), + ); + } +} diff --git a/lib/presentation/pages/purchase/widgets/stat_card.dart b/lib/presentation/pages/purchase/widgets/stat_card.dart new file mode 100644 index 0000000..edb17f3 --- /dev/null +++ b/lib/presentation/pages/purchase/widgets/stat_card.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class PurchaseStatCard extends StatelessWidget { + final String title; + final String value; + final IconData icon; + final Color iconColor; + final Animation cardAnimation; + const PurchaseStatCard({ + super.key, + required this.title, + required this.value, + required this.icon, + required this.iconColor, + required this.cardAnimation, + }); + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: cardAnimation, + builder: (context, child) { + return Transform.scale( + scale: 0.8 + (cardAnimation.value * 0.2), + child: Opacity( + opacity: cardAnimation.value, + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [AppColor.surface, AppColor.surface.withOpacity(0.9)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: 0, + ), + BoxShadow( + color: AppColor.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + border: Border.all( + color: AppColor.border.withOpacity(0.3), + width: 1, + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + iconColor.withOpacity(0.15), + iconColor.withOpacity(0.05), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: iconColor.withOpacity(0.2), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Icon(icon, color: iconColor, size: 24), + ), + ], + ), + const SizedBox(height: 16), + Text( + title, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 6), + Text( + value, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.w800, + color: AppColor.textPrimary, + height: 1.2, + ), + ), + ], + ), + ), + ), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/purchase/widgets/status_chip.dart b/lib/presentation/pages/purchase/widgets/status_chip.dart new file mode 100644 index 0000000..91a85ab --- /dev/null +++ b/lib/presentation/pages/purchase/widgets/status_chip.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class PurchaseStatusChip extends StatelessWidget { + final bool isSelected; + final String text; + final Function(bool) onSelected; + const PurchaseStatusChip({ + super.key, + required this.isSelected, + required this.text, + required this.onSelected, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(right: 8), + child: FilterChip( + selected: isSelected, + label: Text( + text, + style: AppStyle.sm.copyWith( + color: isSelected ? AppColor.textWhite : AppColor.textSecondary, + ), + ), + backgroundColor: AppColor.backgroundLight, + selectedColor: AppColor.primary, + onSelected: onSelected, + ), + ); + } +} diff --git a/lib/presentation/pages/report/report_page.dart b/lib/presentation/pages/report/report_page.dart new file mode 100644 index 0000000..1234863 --- /dev/null +++ b/lib/presentation/pages/report/report_page.dart @@ -0,0 +1,220 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'dart:math' as math; + +import '../../../application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import '../../components/field/date_range_picker_field.dart'; +import '../../components/spacer/spacer.dart'; +import 'widgets/payment_method.dart'; +import 'widgets/quick_stats.dart'; +import 'widgets/revenue_summary.dart'; +import 'widgets/sales.dart'; +import 'widgets/top_product.dart'; + +@RoutePage() +class ReportPage extends StatefulWidget implements AutoRouteWrapper { + const ReportPage({super.key}); + + @override + State createState() => _ReportPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (context) => + getIt() + ..add(DashboardAnalyticLoaderEvent.fetched()), + child: this, + ); +} + +class _ReportPageState extends State with TickerProviderStateMixin { + late AnimationController _fadeController; + late AnimationController _slideController; + late AnimationController _rotationController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + late Animation _rotationAnimation; + + @override + void initState() { + super.initState(); + + _fadeController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 1000), + vsync: this, + ); + + _rotationController = AnimationController( + duration: const Duration(seconds: 3), + vsync: this, + )..repeat(); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.elasticOut), + ); + + _rotationAnimation = Tween( + begin: 0, + end: 2 * math.pi, + ).animate(_rotationController); + + _fadeController.forward(); + _slideController.forward(); + } + + @override + void dispose() { + _fadeController.dispose(); + _slideController.dispose(); + _rotationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BlocListener< + DashboardAnalyticLoaderBloc, + DashboardAnalyticLoaderState + >( + listenWhen: (previous, current) => + previous.dateFrom != current.dateFrom || + previous.dateTo != current.dateTo, + listener: (context, state) { + context.read().add( + DashboardAnalyticLoaderEvent.fetched(), + ); + }, + child: Scaffold( + backgroundColor: AppColor.background, + body: + BlocBuilder< + DashboardAnalyticLoaderBloc, + DashboardAnalyticLoaderState + >( + builder: (context, state) { + return RefreshIndicator( + color: AppColor.primary, + onRefresh: () async { + context.read().add( + DashboardAnalyticLoaderEvent.fetched(), + ); + // tunggu sampai fetching selesai + await context + .read() + .stream + .firstWhere((s) => !s.isFetching); + }, + child: CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + centerTitle: false, + flexibleSpace: CustomAppBar( + title: context.lang.report, + isBack: false, + ), + // actions: [ + // ActionIconButton( + // onTap: () {}, + // icon: LineIcons.download, + // ), + // ActionIconButton(onTap: () {}, icon: LineIcons.filter), + // SpaceWidth(8), + // ], + ), + + SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: FadeTransition( + opacity: _fadeAnimation, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: DateRangePickerField( + maxDate: DateTime.now(), + startDate: state.dateFrom, + endDate: state.dateTo, + onChanged: (startDate, endDate) { + context.read().add( + DashboardAnalyticLoaderEvent.rangeDateChanged( + startDate!, + endDate!, + ), + ); + }, + ), + ), + ), + ), + ), + + // Content + SliverPadding( + padding: EdgeInsets.all(AppValue.padding), + sliver: SliverList( + delegate: SliverChildListDelegate([ + FadeTransition( + opacity: _fadeAnimation, + child: SlideTransition( + position: _slideAnimation, + child: Column( + children: [ + ReportRevenueSummary( + overview: state.dashboardAnalytic.overview, + rotationAnimation: _rotationAnimation, + ), + const SpaceHeight(24), + ReportQuickStats( + overview: state.dashboardAnalytic.overview, + ), + const SpaceHeight(24), + ReportSales( + salesData: + state.dashboardAnalytic.recentSales, + ), + const SpaceHeight(24), + ReportPaymentMethod( + paymentMethods: + state.dashboardAnalytic.paymentMethods, + ), + const SpaceHeight(24), + ReportTopProduct( + products: + state.dashboardAnalytic.topProducts, + ), + const SpaceHeight(24), + ], + ), + ), + ), + ]), + ), + ), + ], + ), + ); + }, + ), + ), + ); + } +} diff --git a/lib/presentation/pages/report/widgets/payment_method.dart b/lib/presentation/pages/report/widgets/payment_method.dart new file mode 100644 index 0000000..3a5e676 --- /dev/null +++ b/lib/presentation/pages/report/widgets/payment_method.dart @@ -0,0 +1,622 @@ +import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import '../../../components/widgets/empty_widget.dart'; + +class ReportPaymentMethod extends StatelessWidget { + final List paymentMethods; + + const ReportPaymentMethod({super.key, required this.paymentMethods}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.06), + blurRadius: 20, + offset: const Offset(0, 4), + spreadRadius: -4, + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Icon(Icons.payment, color: AppColor.white, size: 24), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.payment_methods, + style: AppStyle.xl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 4), + Text( + context.lang.payment_methods_desc, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + ), + ), + ], + ), + ), + ], + ), + + const SizedBox(height: 24), + + // Payment Method List + if (paymentMethods.isEmpty) + _buildEmptyState(context) + else + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: paymentMethods.length, + padding: EdgeInsets.zero, + separatorBuilder: (context, index) => + const SizedBox(height: 12), + itemBuilder: (context, index) { + final method = paymentMethods[index]; + return TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: Duration(milliseconds: 600 + (index * 150)), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Transform.translate( + offset: Offset(30 * (1 - value), 0), + child: Opacity( + opacity: value, + child: _buildPaymentMethodTile( + context, + method, + index, + ), + ), + ); + }, + ); + }, + ), + ], + ), + ), + ); + } + + Widget _buildPaymentMethodTile( + BuildContext context, + DashboardPaymentMethod method, + int index, + ) { + final screenWidth = MediaQuery.of(context).size.width; + final isCompact = screenWidth < 400; // For smaller screens + + return Container( + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.1), + width: 1.5, + ), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.08), + blurRadius: 12, + offset: const Offset(0, 4), + spreadRadius: -2, + ), + BoxShadow( + color: Colors.black.withOpacity(0.03), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: Stack( + children: [ + // Subtle background gradient + Positioned.fill( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.03), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.01), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + ), + ), + + // Main content + Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header section with improved responsive layout + if (isCompact) + _buildCompactHeader(method) + else + _buildStandardHeader(context, method), + + const SizedBox(height: 16), + + // Stats row with better spacing + _buildStatsSection(context, method), + + const SizedBox(height: 16), + + // Enhanced progress bar section + _buildProgressSection(context, method, index), + ], + ), + ), + + // Accent line on the left + Positioned( + left: 0, + top: 0, + bottom: 0, + child: Container( + width: 4, + decoration: BoxDecoration( + color: _getPaymentMethodColor(method.paymentMethodType), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + bottomLeft: Radius.circular(16), + ), + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildStandardHeader( + BuildContext context, + DashboardPaymentMethod method, + ) { + return Row( + children: [ + // Enhanced icon container + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor(method.paymentMethodType), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: Icon( + _getPaymentMethodIcon(method.paymentMethodType), + color: AppColor.white, + size: 28, + ), + ), + + const SizedBox(width: 16), + + // Payment method info - improved text handling + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + method.paymentMethodName, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 6), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), + decoration: BoxDecoration( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.2), + width: 1, + ), + ), + child: Text( + method.paymentMethodType.toUpperCase(), + style: AppStyle.xs.copyWith( + color: _getPaymentMethodColor(method.paymentMethodType), + fontWeight: FontWeight.bold, + letterSpacing: 0.8, + ), + ), + ), + ], + ), + ), + + const SizedBox(width: 12), + + // Percentage badge + Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: _getPaymentMethodColor(method.paymentMethodType), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.3), + blurRadius: 6, + offset: const Offset(0, 3), + ), + ], + ), + child: Text( + '${method.percentage.toStringAsFixed(1)}%', + style: AppStyle.sm.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ); + } + + Widget _buildCompactHeader(DashboardPaymentMethod method) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor(method.paymentMethodType), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(14), + ), + child: Icon( + _getPaymentMethodIcon(method.paymentMethodType), + color: AppColor.white, + size: 24, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + method.paymentMethodName, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), + Text( + method.paymentMethodType.toUpperCase(), + style: AppStyle.xs.copyWith( + color: _getPaymentMethodColor(method.paymentMethodType), + fontWeight: FontWeight.bold, + letterSpacing: 0.5, + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: _getPaymentMethodColor(method.paymentMethodType), + borderRadius: BorderRadius.circular(16), + ), + child: Text( + '${method.percentage.toStringAsFixed(1)}%', + style: AppStyle.xs.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ); + } + + Widget _buildStatsSection( + BuildContext context, + DashboardPaymentMethod method, + ) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.background.withOpacity(0.5), + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.border.withOpacity(0.2), width: 1), + ), + child: IntrinsicHeight( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.total_revenue, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + ), + ), + const SizedBox(height: 6), + Text( + method.totalAmount.currencyFormatRp, + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + Container( + width: 1, + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AppColor.border.withOpacity(0.3), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + context.lang.orders, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + letterSpacing: 0.5, + ), + ), + const SizedBox(height: 6), + Text( + '${method.orderCount}', + style: AppStyle.lg.copyWith( + fontWeight: FontWeight.bold, + color: _getPaymentMethodColor(method.paymentMethodType), + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildProgressSection( + BuildContext context, + DashboardPaymentMethod method, + int index, + ) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.lang.revenue_share, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w600, + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + '${method.percentage.toStringAsFixed(1)}%', + style: AppStyle.sm.copyWith( + color: _getPaymentMethodColor(method.paymentMethodType), + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + TweenAnimationBuilder( + tween: Tween(begin: 0, end: method.percentage / 100), + duration: Duration(milliseconds: 1200 + (index * 200)), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Container( + height: 8, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: AppColor.border.withOpacity(0.3), + ), + child: Stack( + children: [ + FractionallySizedBox( + widthFactor: value, + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + _getPaymentMethodColor(method.paymentMethodType), + _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.8), + ], + ), + borderRadius: BorderRadius.circular(4), + boxShadow: [ + BoxShadow( + color: _getPaymentMethodColor( + method.paymentMethodType, + ).withOpacity(0.3), + blurRadius: 4, + offset: const Offset(0, 1), + ), + ], + ), + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + Widget _buildEmptyState(BuildContext context) { + return EmptyWidget( + title: context.lang.no_payment_methods, + message: context.lang.no_payment_methods_desc, + ); + } + + Color _getPaymentMethodColor(String type) { + switch (type.toLowerCase()) { + case 'cash': + return AppColor.success; + case 'card': + case 'credit_card': + case 'debit_card': + return AppColor.info; + case 'bank_transfer': + case 'transfer': + return AppColor.primary; + case 'ewallet': + case 'e_wallet': + case 'digital_wallet': + return AppColor.warning; + case 'qr_code': + case 'qris': + return const Color(0xFF9C27B0); // Purple + default: + return AppColor.textSecondary; + } + } + + IconData _getPaymentMethodIcon(String type) { + switch (type.toLowerCase()) { + case 'cash': + return Icons.payments; + case 'card': + case 'credit_card': + case 'debit_card': + return Icons.credit_card; + case 'bank_transfer': + case 'transfer': + return Icons.account_balance; + case 'ewallet': + case 'e_wallet': + case 'digital_wallet': + return Icons.account_balance_wallet; + case 'qr_code': + case 'qris': + return Icons.qr_code; + default: + return Icons.payment; + } + } +} diff --git a/lib/presentation/pages/report/widgets/quick_stats.dart b/lib/presentation/pages/report/widgets/quick_stats.dart new file mode 100644 index 0000000..b99ac72 --- /dev/null +++ b/lib/presentation/pages/report/widgets/quick_stats.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/extension/extension.dart'; +import '../../../../common/theme/theme.dart'; +import '../../../../domain/analytic/analytic.dart'; +import 'stat_tile.dart'; + +class ReportQuickStats extends StatelessWidget { + final DashboardOverview overview; + + const ReportQuickStats({super.key, required this.overview}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + children: [ + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 800), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: context.lang.total_orders, + value: overview.totalOrders.toString(), + icon: Icons.receipt_long, + color: AppColor.info, + animatedValue: overview.totalOrders * value, + ), + ); + }, + ), + ), + const SizedBox(width: 16), + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 1000), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: context.lang.average_price, + value: overview.averageOrderValue + .round() + .currencyFormatRp, + icon: Icons.trending_up, + color: AppColor.warning, + animatedValue: overview.averageOrderValue * value, + ), + ); + }, + ), + ), + ], + ), + + const SizedBox(height: 16), + + Row( + children: [ + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 1200), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: context.lang.customer, + value: overview.totalCustomers.toString(), + icon: Icons.people, + color: AppColor.success, + animatedValue: overview.totalCustomers * value, + ), + ); + }, + ), + ), + const SizedBox(width: 16), + Expanded( + child: TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), + duration: const Duration(milliseconds: 1400), + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: ReportStatTile( + title: + '${context.lang.void_text} + ${context.lang.refund}', + value: (overview.voidedOrders + overview.refundedOrders) + .toString(), + + icon: Icons.cancel, + color: AppColor.error, + animatedValue: + (overview.voidedOrders + overview.refundedOrders) * + value, + ), + ); + }, + ), + ), + ], + ), + ], + ); + } +} diff --git a/lib/presentation/pages/report/widgets/revenue_summary.dart b/lib/presentation/pages/report/widgets/revenue_summary.dart new file mode 100644 index 0000000..b3a020e --- /dev/null +++ b/lib/presentation/pages/report/widgets/revenue_summary.dart @@ -0,0 +1,130 @@ +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'; + +class ReportRevenueSummary extends StatelessWidget { + final DashboardOverview overview; + final Animation rotationAnimation; + const ReportRevenueSummary({ + super.key, + required this.rotationAnimation, + required this.overview, + }); + + @override + Widget build(BuildContext context) { + return Container( + height: 180, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: AppColor.primaryGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(24), + ), + ), + // Floating elements + Positioned( + right: 20, + top: 20, + child: AnimatedBuilder( + animation: rotationAnimation, + builder: (context, child) { + return Transform.rotate( + angle: rotationAnimation.value * 0.3, + child: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.white.withOpacity(0.1), + ), + ), + ); + }, + ), + ), + Positioned( + right: 60, + bottom: 30, + child: AnimatedBuilder( + animation: rotationAnimation, + builder: (context, child) { + return Transform.rotate( + angle: -rotationAnimation.value * 0.2, + child: Container( + width: 40, + height: 40, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: AppColor.white.withOpacity(0.08), + ), + ), + ); + }, + ), + ), + // Content + Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(10), + ), + child: const Icon( + Icons.account_balance_wallet, + color: AppColor.textWhite, + size: 20, + ), + ), + const SpaceWidth(12), + Text( + context.lang.total_revenue, + style: AppStyle.lg.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + const Spacer(), + Text( + overview.totalSales.currencyFormatRp, + style: AppStyle.h1.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + letterSpacing: -1, + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/report/widgets/sales.dart b/lib/presentation/pages/report/widgets/sales.dart new file mode 100644 index 0000000..09f46c9 --- /dev/null +++ b/lib/presentation/pages/report/widgets/sales.dart @@ -0,0 +1,468 @@ +import 'package:fl_chart/fl_chart.dart'; +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 '../../../components/widgets/empty_widget.dart'; + +class ReportSales extends StatelessWidget { + final List salesData; + + const ReportSales({super.key, required this.salesData}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: AppColor.textSecondary.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header Section + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.sales_chart, + style: AppStyle.xxl.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.bold, + ), + ), + const SpaceHeight(4), + Text( + salesData.isEmpty + ? context.lang.no_data_available + : context.lang.total_days_overview(salesData.length), + style: AppStyle.md.copyWith(color: AppColor.textSecondary), + ), + ], + ), + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: const Icon( + Icons.show_chart, + color: AppColor.primary, + size: 24, + ), + ), + ], + ), + + const SpaceHeight(20), + + // Sales Summary Cards + if (salesData.isNotEmpty) ...[ + _buildSalesSummary(context), + const SpaceHeight(20), + ], + + // Chart Container + salesData.isEmpty + ? _buildEmptyChart(context) + : Container( + height: 300, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.05), + AppColor.backgroundLight, + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: AppColor.primary.withOpacity(0.1), + width: 2, + ), + ), + child: _buildSalesChart(), + ), + + const SpaceHeight(16), + + // Legend + if (salesData.isNotEmpty) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildLegendItem(context.lang.sales_data, AppColor.primary), + ], + ), + ], + ), + ); + } + + Widget _buildSalesSummary(BuildContext context) { + final totalSales = salesData.fold(0, (sum, item) => sum + item.sales); + final totalOrders = salesData.fold( + 0, + (sum, item) => sum + item.orders, + ); + final totalItems = salesData.fold(0, (sum, item) => sum + item.items); + final totalNetSales = salesData.fold( + 0, + (sum, item) => sum + item.netSales, + ); + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.backgroundLight, + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.border.withOpacity(0.3), width: 1), + ), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: _buildSummaryItem( + context.lang.total_sales, + totalSales.currencyFormatRp, + Icons.attach_money, + AppColor.success, + ), + ), + Container( + width: 1, + height: 40, + color: AppColor.border.withOpacity(0.3), + margin: const EdgeInsets.symmetric(horizontal: 16), + ), + Expanded( + child: _buildSummaryItem( + context.lang.net_sales, + totalNetSales.currencyFormatRp, + Icons.trending_up, + AppColor.primary, + ), + ), + ], + ), + const SpaceHeight(16), + Row( + children: [ + Expanded( + child: _buildSummaryItem( + context.lang.total_orders, + totalOrders.toString(), + Icons.shopping_cart, + AppColor.info, + ), + ), + Container( + width: 1, + height: 40, + color: AppColor.border.withOpacity(0.3), + margin: const EdgeInsets.symmetric(horizontal: 16), + ), + Expanded( + child: _buildSummaryItem( + context.lang.total_items, + totalItems.toString(), + Icons.inventory, + AppColor.warning, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildSummaryItem( + String label, + String value, + IconData icon, + Color color, + ) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(icon, size: 16, color: color), + const SpaceWidth(6), + Expanded( + child: Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SpaceHeight(6), + Text( + value, + style: AppStyle.md.copyWith( + color: color, + fontWeight: FontWeight.bold, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ); + } + + Widget _buildSalesChart() { + final maxValue = _getMaxValue(); + final spots = _generateSpots(salesData); + + return LineChart( + LineChartData( + gridData: FlGridData( + show: true, + drawHorizontalLine: true, + drawVerticalLine: false, + horizontalInterval: maxValue / 5, + getDrawingHorizontalLine: (value) { + return FlLine( + color: AppColor.border.withOpacity(0.3), + strokeWidth: 1, + dashArray: [5, 5], + ); + }, + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 70, + getTitlesWidget: (value, meta) { + return Text( + _formatCurrency(value), + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ); + }, + ), + ), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 32, + getTitlesWidget: (value, meta) { + final index = value.toInt(); + if (index >= 0 && index < salesData.length) { + final date = DateTime.parse(salesData[index].date); + final dayName = _getDayName(date.weekday); + return Padding( + padding: const EdgeInsets.only(top: 8), + child: Text( + dayName, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ); + } + return const Text(''); + }, + ), + ), + rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + borderData: FlBorderData(show: false), + minX: 0, + maxX: (salesData.length - 1).toDouble(), + minY: 0, + maxY: maxValue, + lineBarsData: [ + // Main sales line + LineChartBarData( + spots: spots, + isCurved: true, + curveSmoothness: 0.35, + gradient: LinearGradient( + colors: [AppColor.primary, AppColor.primaryLight], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + barWidth: 4, + isStrokeCapRound: true, + belowBarData: BarAreaData( + show: true, + gradient: LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.3), + AppColor.primary.withOpacity(0.1), + Colors.transparent, + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + dotData: FlDotData( + show: true, + getDotPainter: (spot, percent, barData, index) { + return FlDotCirclePainter( + radius: 6, + color: AppColor.surface, + strokeWidth: 3, + strokeColor: AppColor.primary, + ); + }, + ), + ), + ], + lineTouchData: LineTouchData( + enabled: true, + touchTooltipData: LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(12), + getTooltipItems: (List touchedBarSpots) { + return touchedBarSpots + .map((barSpot) { + final index = barSpot.x.toInt(); + + if (index >= 0 && index < salesData.length) { + final sale = salesData[index]; + final date = DateTime.parse(sale.date); + final dayName = _getDayName(date.weekday); + + return LineTooltipItem( + '$dayName\n', + const TextStyle( + color: AppColor.textWhite, + fontWeight: FontWeight.bold, + fontSize: 14, + ), + children: [ + TextSpan( + text: 'Sales: ${sale.sales.currencyFormatRp}\n', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w500, + ), + ), + TextSpan( + text: 'Orders: ${sale.orders}\n', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w400, + ), + ), + TextSpan( + text: 'Net: ${sale.netSales.currencyFormatRp}', + style: AppStyle.sm.copyWith( + color: AppColor.textWhite, + fontWeight: FontWeight.w400, + ), + ), + ], + ); + } + return null; + }) + .where((item) => item != null) + .cast() + .toList(); + }, + ), + touchCallback: + (FlTouchEvent event, LineTouchResponse? touchResponse) { + // Handle touch events here if needed + }, + handleBuiltInTouches: true, + ), + ), + ); + } + + Widget _buildEmptyChart(BuildContext context) { + return EmptyWidget( + title: context.lang.no_sales_data, + message: context.lang.no_sales_data_desc, + emptyIcon: Icons.show_chart, + ); + } + + List _generateSpots(List data) { + return data.asMap().entries.map((entry) { + final index = entry.key; + final sale = entry.value; + return FlSpot(index.toDouble(), sale.sales.toDouble()); + }).toList(); + } + + double _getMaxValue() { + if (salesData.isEmpty) return 1000000; + + double maxValue = salesData + .map((e) => e.sales.toDouble()) + .reduce((a, b) => a > b ? a : b); + + // Add 20% padding to max value + return maxValue * 1.2; + } + + String _formatCurrency(double value) { + if (value >= 1000000) { + return '${(value / 1000000).toStringAsFixed(1)}M'; + } else if (value >= 1000) { + return '${(value / 1000).toStringAsFixed(0)}K'; + } + return value.toStringAsFixed(0); + } + + String _getDayName(int weekday) { + const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + return days[weekday - 1]; + } + + Widget _buildLegendItem(String label, Color color) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 16, + height: 3, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(2), + ), + ), + const SpaceWidth(8), + Text( + label, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + ); + } +} diff --git a/lib/presentation/pages/report/widgets/stat_tile.dart b/lib/presentation/pages/report/widgets/stat_tile.dart new file mode 100644 index 0000000..6452eac --- /dev/null +++ b/lib/presentation/pages/report/widgets/stat_tile.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class ReportStatTile extends StatelessWidget { + final String title; + final String value; + final IconData icon; + final Color color; + final double animatedValue; + const ReportStatTile({ + super.key, + required this.title, + required this.value, + required this.icon, + required this.color, + required this.animatedValue, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: color.withOpacity(0.1), + blurRadius: 15, + offset: const Offset(0, 5), + ), + ], + border: Border.all(color: color.withOpacity(0.2), width: 1.5), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [color.withOpacity(0.2), color.withOpacity(0.1)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(12), + ), + child: Icon(icon, color: color, size: 24), + ), + const Spacer(), + ], + ), + const SizedBox(height: 16), + Text( + title, + style: AppStyle.md.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + Text( + value, + style: AppStyle.xxl.copyWith( + color: color, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/pages/report/widgets/top_product.dart b/lib/presentation/pages/report/widgets/top_product.dart new file mode 100644 index 0000000..0f4bd81 --- /dev/null +++ b/lib/presentation/pages/report/widgets/top_product.dart @@ -0,0 +1,579 @@ +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'; + +class ReportTopProduct extends StatelessWidget { + final List products; + const ReportTopProduct({super.key, required this.products}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(24), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: AppColor.textSecondary.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.best_selling_products, + style: AppStyle.xxl.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.bold, + ), + ), + const SpaceHeight(4), + Text( + context.lang.highest_sales_ranking, + style: AppStyle.md.copyWith(color: AppColor.textSecondary), + ), + ], + ), + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppColor.warning.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: const Icon( + Icons.star, + color: AppColor.warning, + size: 24, + ), + ), + ], + ), + const SpaceHeight(20), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return _buildEnhancedProductItem( + context, + products[index], + index + 1, + ); + }, + itemCount: products.length, + ), + ], + ), + ); + } + + Widget _buildEnhancedProductItem( + BuildContext context, + DashboardTopProduct product, + int rank, + ) { + final isFirst = rank == 1; + final isTopThree = rank <= 3; + + return Container( + margin: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + gradient: isFirst + ? LinearGradient( + colors: [ + AppColor.warning.withOpacity(0.1), + AppColor.warning.withOpacity(0.05), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : isTopThree + ? LinearGradient( + colors: [ + AppColor.primary.withOpacity(0.08), + AppColor.primary.withOpacity(0.03), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : null, + color: isTopThree ? null : AppColor.white, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : isTopThree + ? AppColor.primary.withOpacity(0.2) + : AppColor.border.withOpacity(0.3), + width: isFirst ? 2 : 1, + ), + boxShadow: [ + BoxShadow( + color: isFirst + ? AppColor.warning.withOpacity(0.15) + : isTopThree + ? AppColor.primary.withOpacity(0.1) + : Colors.black.withOpacity(0.04), + blurRadius: isFirst ? 16 : 12, + offset: const Offset(0, 4), + spreadRadius: isFirst ? -2 : -3, + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Stack( + children: [ + // Top accent line for rank 1-3 + if (isTopThree) + Positioned( + top: 0, + left: 0, + right: 0, + child: Container( + height: 4, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: isFirst + ? [ + AppColor.warning, + AppColor.warning.withOpacity(0.7), + ] + : [ + AppColor.primary, + AppColor.primary.withOpacity(0.7), + ], + ), + ), + ), + ), + + // Main content + Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header with rank and product info + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Rank badge + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + gradient: isFirst + ? const LinearGradient( + colors: [AppColor.warning, Color(0xFFFFB74D)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : isTopThree + ? LinearGradient( + colors: [ + AppColor.primary, + AppColor.primary.withOpacity(0.8), + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : LinearGradient( + colors: [ + AppColor.textSecondary.withOpacity(0.8), + AppColor.textSecondary.withOpacity(0.6), + ], + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : isTopThree + ? AppColor.primary.withOpacity(0.3) + : AppColor.textSecondary.withOpacity(0.2), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], + ), + child: Center( + child: isFirst + ? const Icon( + Icons.emoji_events, + color: AppColor.white, + size: 28, + ) + : rank == 2 + ? const Icon( + Icons.workspace_premium, + color: AppColor.white, + size: 26, + ) + : rank == 3 + ? const Icon( + Icons.military_tech, + color: AppColor.white, + size: 26, + ) + : Text( + rank.toString(), + style: AppStyle.xl.copyWith( + color: AppColor.white, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + ), + ), + + const SpaceWidth(16), + + // Product info + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product.productName, + style: AppStyle.lg.copyWith( + color: AppColor.textPrimary, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const SpaceHeight(6), + // Category badge + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 4, + ), + decoration: BoxDecoration( + color: isFirst + ? AppColor.warning.withOpacity(0.1) + : AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : AppColor.primary.withOpacity(0.3), + width: 1, + ), + ), + child: Text( + product.categoryName, + style: AppStyle.xs.copyWith( + color: isFirst + ? AppColor.warning + : AppColor.primary, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ], + ), + + const SpaceHeight(16), + + // Statistics section + Container( + padding: const EdgeInsets.all(14), + decoration: BoxDecoration( + color: AppColor.background.withOpacity(0.5), + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: AppColor.border.withOpacity(0.2), + width: 1, + ), + ), + child: Column( + children: [ + // Revenue and Average Price + IntrinsicHeight( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.attach_money, + size: 14, + color: AppColor.success, + ), + const SpaceWidth(3), + Flexible( + child: Text( + context.lang.revenue, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SpaceHeight(4), + Text( + product.revenue.currencyFormatRp, + style: AppStyle.sm.copyWith( + color: AppColor.success, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + + Container( + width: 1, + margin: const EdgeInsets.symmetric( + horizontal: 10, + ), + color: AppColor.border.withOpacity(0.3), + ), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + context.lang.average_price, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const SpaceWidth(3), + Icon( + Icons.trending_up, + size: 14, + color: AppColor.primary, + ), + ], + ), + const SpaceHeight(4), + Text( + product.averagePrice + .round() + .currencyFormatRp, + style: AppStyle.sm.copyWith( + color: AppColor.primary, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end, + ), + ], + ), + ), + ], + ), + ), + + const SpaceHeight(10), + + // Quantity Sold and Order Count + IntrinsicHeight( + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.inventory, + size: 14, + color: AppColor.warning, + ), + const SpaceWidth(3), + Flexible( + child: Text( + context.lang.sold, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SpaceHeight(4), + Text( + '${product.quantitySold}', + style: AppStyle.sm.copyWith( + color: AppColor.warning, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + ], + ), + ), + + Container( + width: 1, + margin: const EdgeInsets.symmetric( + horizontal: 10, + ), + color: AppColor.border.withOpacity(0.3), + ), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + context.lang.orders, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + const SpaceWidth(3), + Icon( + Icons.shopping_cart, + size: 14, + color: AppColor.info, + ), + ], + ), + const SpaceHeight(4), + Text( + '${product.orderCount}', + style: AppStyle.sm.copyWith( + color: AppColor.info, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ), + + // Performance indicator for top 3 + if (isTopThree) ...[ + const SpaceHeight(10), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 6, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: isFirst + ? [ + AppColor.warning.withOpacity(0.2), + AppColor.warning.withOpacity(0.1), + ] + : [ + AppColor.primary.withOpacity(0.2), + AppColor.primary.withOpacity(0.1), + ], + ), + borderRadius: BorderRadius.circular(10), + border: Border.all( + color: isFirst + ? AppColor.warning.withOpacity(0.3) + : AppColor.primary.withOpacity(0.3), + width: 1, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + isFirst ? Icons.star : Icons.trending_up, + size: 14, + color: isFirst + ? AppColor.warning + : AppColor.primary, + ), + const SpaceWidth(5), + Flexible( + child: Text( + isFirst + ? context.lang.best_seller + : context.lang.top_performer, + style: AppStyle.xs.copyWith( + color: isFirst + ? AppColor.warning + : AppColor.primary, + fontWeight: FontWeight.bold, + fontSize: 11, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ], + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/pages/sales/sales_page.dart b/lib/presentation/pages/sales/sales_page.dart new file mode 100644 index 0000000..d5eed33 --- /dev/null +++ b/lib/presentation/pages/sales/sales_page.dart @@ -0,0 +1,758 @@ +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 'dart:math' as math; + +import '../../../application/analytic/sales_loader/sales_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../domain/analytic/analytic.dart'; +import '../../../injection.dart'; +import '../../components/appbar/appbar.dart'; +import '../../components/field/date_range_picker_field.dart'; +import '../../components/spacer/spacer.dart'; +import 'widgets/summary_card.dart'; + +@RoutePage() +class SalesPage extends StatefulWidget implements AutoRouteWrapper { + const SalesPage({super.key}); + + @override + State createState() => _SalesPageState(); + + @override + Widget wrappedRoute(BuildContext context) => BlocProvider( + create: (context) => + getIt()..add(SalesLoaderEvent.fectched()), + child: this, + ); +} + +class _SalesPageState extends State with TickerProviderStateMixin { + late AnimationController slideAnimationController; + late Animation slideAnimation; + + late AnimationController fadeAnimationController; + late Animation fadeAnimation; + + @override + void initState() { + super.initState(); + + // Slide Animation + slideAnimationController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation( + parent: slideAnimationController, + curve: Curves.easeOutCubic, + ), + ); + + // Fade Animation + fadeAnimationController = AnimationController( + duration: const Duration(milliseconds: 600), + vsync: this, + ); + fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: fadeAnimationController, curve: Curves.easeOut), + ); + + // Start animations + Future.delayed(const Duration(milliseconds: 300), () { + slideAnimationController.forward(); + fadeAnimationController.forward(); + }); + } + + @override + void dispose() { + slideAnimationController.dispose(); + fadeAnimationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: BlocListener( + listenWhen: (previous, current) => + previous.dateFrom != current.dateFrom || + previous.dateTo != current.dateTo, + listener: (context, state) { + context.read().add(SalesLoaderEvent.fectched()); + }, + child: BlocBuilder( + builder: (context, state) { + return CustomScrollView( + slivers: [ + // App Bar + SliverAppBar( + expandedHeight: 120, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.sales), + ), + + // Date Range Header + SliverToBoxAdapter( + child: SlideTransition( + position: slideAnimation, + child: FadeTransition( + opacity: fadeAnimation, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: DateRangePickerField( + maxDate: DateTime.now(), + startDate: state.dateFrom, + endDate: state.dateTo, + onChanged: (startDate, endDate) { + context.read().add( + SalesLoaderEvent.rangeDateChanged( + startDate!, + endDate!, + ), + ); + }, + ), + ), + ), + ), + ), + + // Summary Cards + SliverToBoxAdapter( + child: SlideTransition( + position: slideAnimation, + child: FadeTransition( + opacity: fadeAnimation, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.summary, + style: AppStyle.xxl.copyWith( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + const SpaceHeight(16), + state.isFetching + ? _buildSummaryShimmer() + : _buildSummaryCards(state), + ], + ), + ), + ), + ), + ), + + // Net Sales Card + SliverToBoxAdapter( + child: SlideTransition( + position: slideAnimation, + child: FadeTransition( + opacity: fadeAnimation, + child: state.isFetching + ? _buildNetSalesShimmer() + : _buildNetSalesCard(state), + ), + ), + ), + + // Daily Sales Section Header + SliverToBoxAdapter( + child: SlideTransition( + position: slideAnimation, + child: FadeTransition( + opacity: fadeAnimation, + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: Text( + context.lang.daily_breakdown, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + ), + ), + ), + ), + + // Daily Sales List + state.isFetching + ? _buildDailySalesShimmer() + : _buildDailySalesList(state), + + // Bottom Padding + const SliverToBoxAdapter(child: SpaceHeight(32)), + ], + ); + }, + ), + ), + ); + } + + Widget _buildSummaryShimmer() { + return Column( + children: [ + Row( + children: [ + Expanded(child: _buildSummaryCardShimmer()), + SpaceWidth(12), + Expanded(child: _buildSummaryCardShimmer()), + ], + ), + const SpaceHeight(12), + Row( + children: [ + Expanded(child: _buildSummaryCardShimmer()), + SpaceWidth(12), + Expanded(child: _buildSummaryCardShimmer()), + ], + ), + ], + ); + } + + Widget _buildSummaryCardShimmer() { + return Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(6), + ), + ), + SpaceWidth(8), + Container( + width: 60, + height: 14, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + ], + ), + const SpaceHeight(8), + Container( + width: double.infinity, + height: 20, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + ], + ), + ), + ); + } + + Widget _buildNetSalesShimmer() { + return Container( + margin: const EdgeInsets.all(16), + child: Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + ), + child: Row( + children: [ + Container( + width: 52, + height: 52, + decoration: BoxDecoration( + color: Colors.grey[400], + borderRadius: BorderRadius.circular(12), + ), + ), + SpaceWidth(16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 80, + height: 14, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + const SpaceHeight(8), + Container( + width: 150, + height: 24, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Widget _buildDailySalesShimmer() { + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + child: Shimmer.fromColors( + baseColor: Colors.grey[300]!, + highlightColor: Colors.grey[100]!, + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: Colors.grey[400], + borderRadius: BorderRadius.circular(10), + ), + ), + SpaceWidth(12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 100, + height: 16, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + const SpaceHeight(4), + Container( + width: 80, + height: 14, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + ), + ), + ], + ), + ), + Container( + width: 60, + height: 24, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + ), + ], + ), + ), + ), + ); + }, + childCount: 8, // Show 8 shimmer items while loading + ), + ); + } + + Widget _buildSummaryCards(SalesLoaderState state) { + return Column( + children: [ + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 800), + curve: Curves.elasticOut, + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: Row( + children: [ + Expanded( + child: _buildSummaryCard( + context.lang.total_sales, + state.sales.summary.totalSales.currencyFormatRp, + Icons.trending_up, + AppColor.success, + 0, + ), + ), + SpaceWidth(12), + Expanded( + child: _buildSummaryCard( + context.lang.total_orders, + state.sales.summary.totalOrders.toString(), + Icons.shopping_cart, + AppColor.info, + 100, + ), + ), + ], + ), + ); + }, + ), + const SpaceHeight(12), + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 1000), + curve: Curves.elasticOut, + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: Row( + children: [ + Expanded( + child: _buildSummaryCard( + context.lang.average_price, + state.sales.summary.averageOrderValue + .round() + .currencyFormatRp, + Icons.attach_money, + AppColor.warning, + 200, + ), + ), + SpaceWidth(12), + Expanded( + child: _buildSummaryCard( + context.lang.total_items, + state.sales.summary.totalItems.toString(), + Icons.inventory, + AppColor.primary, + 300, + ), + ), + ], + ), + ); + }, + ), + ], + ); + } + + Widget _buildNetSalesCard(SalesLoaderState state) { + return TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 1200), + curve: Curves.bounceOut, + builder: (context, value, child) { + return Transform.scale( + scale: value, + child: Container( + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: AppColor.successGradient, + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: AppColor.success.withOpacity(0.3), + blurRadius: 15, + offset: const Offset(0, 5), + ), + ], + ), + child: Row( + children: [ + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 1500), + curve: Curves.elasticOut, + builder: (context, iconValue, child) { + return Transform.rotate( + angle: iconValue * 0.1, + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.2), + borderRadius: BorderRadius.circular(12), + ), + child: const Icon( + Icons.account_balance_wallet, + color: AppColor.textWhite, + size: 28, + ), + ), + ); + }, + ), + SpaceWidth(16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + context.lang.net_sales, + style: TextStyle( + color: AppColor.textWhite.withOpacity(0.9), + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + const SpaceHeight(4), + TweenAnimationBuilder( + tween: Tween( + begin: 0.0, + end: state.sales.summary.netSales.toDouble(), + ), + duration: const Duration(milliseconds: 2000), + curve: Curves.easeOutCubic, + builder: (context, countValue, child) { + return Text( + state.sales.summary.netSales.currencyFormatRp, + style: const TextStyle( + color: AppColor.textWhite, + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ); + }, + ), + ], + ), + ), + ], + ), + ), + ); + }, + ); + } + + Widget _buildDailySalesList(SalesLoaderState state) { + return SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + // Calculate intervals ensuring they don't exceed 1.0 + final slideStart = math.min(0.2 + (index * 0.05), 0.7); + final slideEnd = math.min(slideStart + 0.3, 1.0); + final fadeStart = math.min(0.3 + (index * 0.05), 0.8); + final fadeEnd = math.min(fadeStart + 0.2, 1.0); + + return SlideTransition( + position: + Tween( + begin: Offset(index.isEven ? -1.0 : 1.0, 0), + end: Offset.zero, + ).animate( + CurvedAnimation( + parent: slideAnimationController, + curve: Interval( + slideStart, + slideEnd, + curve: Curves.easeOutBack, + ), + ), + ), + child: FadeTransition( + opacity: Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: fadeAnimationController, + curve: Interval(fadeStart, fadeEnd, curve: Curves.easeOut), + ), + ), + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: _buildDailySalesItem(state.sales.data[index]), + ), + ), + ); + }, childCount: state.sales.data.length), + ); + } + + Widget _buildSummaryCard( + String title, + String value, + IconData icon, + Color color, + int delay, + ) { + return SalesSummaryCard( + fadeAnimation: fadeAnimation, + title: title, + value: value, + icon: icon, + color: color, + delay: delay, + ); + } + + Widget _buildDailySalesItem(SalesAnalyticData dailySale) { + return ExpansionTile( + leading: Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + borderRadius: BorderRadius.circular(10), + ), + child: Icon(Icons.calendar_today, color: AppColor.primary, size: 20), + ), + title: Text( + '${dailySale.date.day}/${dailySale.date.month}/${dailySale.date.year}', + style: const TextStyle( + fontWeight: FontWeight.bold, + color: AppColor.textPrimary, + ), + ), + subtitle: Text( + dailySale.sales.currencyFormatRp, + style: TextStyle( + color: AppColor.success, + fontWeight: FontWeight.w600, + fontSize: 16, + ), + ), + trailing: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: AppColor.info.withOpacity(0.1), + borderRadius: BorderRadius.circular(20), + ), + child: Text( + '${dailySale.orders} ${context.lang.orders}', + style: TextStyle( + color: AppColor.info, + fontWeight: FontWeight.w500, + fontSize: 12, + ), + ), + ), + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Expanded( + child: _buildDetailItem( + context.lang.items, + '${dailySale.items}', + Icons.inventory_2, + ), + ), + Expanded( + child: _buildDetailItem( + context.lang.tax, + dailySale.tax.currencyFormatRp, + Icons.receipt, + ), + ), + Expanded( + child: _buildDetailItem( + context.lang.discount, + dailySale.discount.currencyFormatRp, + Icons.local_offer, + ), + ), + ], + ), + ), + ], + ); + } + + Widget _buildDetailItem(String label, String value, IconData icon) { + return TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 600), + curve: Curves.bounceOut, + builder: (context, animValue, child) { + return Transform.scale( + scale: animValue, + child: Column( + children: [ + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: const Duration(milliseconds: 800), + curve: Curves.elasticOut, + builder: (context, iconValue, child) { + return Transform.rotate( + angle: iconValue * 0.1, + child: Icon(icon, color: AppColor.textSecondary, size: 20), + ); + }, + ), + const SpaceHeight(4), + Text( + label, + style: TextStyle(color: AppColor.textSecondary, fontSize: 12), + ), + const SpaceHeight(2), + AnimatedBuilder( + animation: fadeAnimation, + builder: (context, child) { + return Text( + value, + style: TextStyle( + color: AppColor.textPrimary, + fontWeight: FontWeight.w600, + fontSize: 14, + ), + ); + }, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/sales/widgets/summary_card.dart b/lib/presentation/pages/sales/widgets/summary_card.dart new file mode 100644 index 0000000..f8908ce --- /dev/null +++ b/lib/presentation/pages/sales/widgets/summary_card.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; + +import '../../../../common/theme/theme.dart'; + +class SalesSummaryCard extends StatelessWidget { + const SalesSummaryCard({ + super.key, + required this.fadeAnimation, + required this.title, + required this.value, + required this.icon, + required this.color, + required this.delay, + }); + + final Animation fadeAnimation; + final String title; + final String value; + final IconData icon; + final Color color; + final int delay; + + @override + Widget build(BuildContext context) { + return TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: Duration(milliseconds: 800 + delay), + curve: Curves.easeOutBack, + builder: (context, animValue, child) { + return Transform.scale( + scale: animValue, + child: Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppColor.surface, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.05), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: Duration(milliseconds: 1000 + delay), + curve: Curves.bounceOut, + builder: (context, iconValue, child) { + return Transform.scale( + scale: iconValue, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, color: color, size: 20), + ), + ); + }, + ), + const Spacer(), + ], + ), + const SizedBox(height: 12), + Text( + title, + style: AppStyle.sm.copyWith( + color: AppColor.textSecondary, + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 4), + AnimatedBuilder( + animation: fadeAnimation, + builder: (context, child) { + return Text( + value, + style: AppStyle.xl.copyWith( + color: AppColor.textPrimary, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ); + }, + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/presentation/pages/schedule/schedule_page.dart b/lib/presentation/pages/schedule/schedule_page.dart new file mode 100644 index 0000000..7aaeacc --- /dev/null +++ b/lib/presentation/pages/schedule/schedule_page.dart @@ -0,0 +1,892 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:table_calendar/table_calendar.dart'; + +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../components/appbar/appbar.dart'; + +// Schedule model dengan optimasi +class Schedule { + final DateTime date; + final String title; + final String? subtitle; + final String? time; + final Color color; + final IconData? icon; + final String? avatarUrl; + final bool hasDetails; + final String? location; + final String? instructions; + + const Schedule({ + required this.date, + required this.title, + this.subtitle, + this.time, + required this.color, + this.icon, + this.avatarUrl, + this.hasDetails = false, + this.location, + this.instructions, + }); + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Schedule && + runtimeType == other.runtimeType && + date == other.date; + + @override + int get hashCode => date.hashCode; +} + +@RoutePage() +class SchedulePage extends StatefulWidget { + const SchedulePage({super.key}); + + @override + State createState() => _SchedulePageState(); +} + +class _SchedulePageState extends State + with TickerProviderStateMixin { + late DateTime _selectedDay; + late DateTime _focusedDay; + late PageController _pageController; + late AnimationController _fadeController; + late AnimationController _slideController; + late AnimationController _rotationController; + late Animation _fadeAnimation; + late Animation _slideAnimation; + late Animation rotationAnimation; + + final CalendarFormat _calendarFormat = CalendarFormat.week; + + // Optimized schedules with const constructor + static final List _schedules = [ + Schedule( + date: DateTime.now(), + title: 'Morning Shift', + subtitle: '8am - 1pm (5h)', + time: '08:00', + color: AppColor.primary, + icon: Icons.work, + hasDetails: true, + location: 'Office Building A', + instructions: 'Check all equipment before starting', + ), + Schedule( + date: DateTime.now().add(Duration(days: 1)), + title: 'Night Shift', + subtitle: '6pm - 11pm (5h)', + time: '18:00', + color: AppColor.warning, + icon: Icons.nights_stay, + hasDetails: true, + location: 'Warehouse B', + instructions: 'Close all the lights when you exit', + ), + Schedule( + date: DateTime.now().add(Duration(days: 2)), + title: 'Stand up Meeting', + subtitle: '30 minutes', + time: '09:00', + color: AppColor.info, + icon: Icons.group, + hasDetails: true, + location: 'Conference Room', + instructions: 'Prepare weekly report', + ), + Schedule( + date: DateTime.now().add(Duration(days: 3)), + title: 'Training Session', + subtitle: '2 hours', + time: '14:00', + color: AppColor.success, + icon: Icons.school, + hasDetails: true, + location: 'Training Center', + instructions: 'Bring notebook and pen', + ), + Schedule( + date: DateTime.now().add(Duration(days: 4)), + title: 'Client Meeting', + subtitle: '1 hour', + time: '10:00', + color: Color(0xFF9C27B0), + icon: Icons.business, + hasDetails: true, + location: 'Client Office', + instructions: 'Prepare presentation slides', + ), + ]; + + @override + void initState() { + super.initState(); + _selectedDay = DateTime.now(); + _focusedDay = DateTime.now(); + _pageController = PageController(); + + // Animation controllers + _fadeController = AnimationController( + duration: const Duration(milliseconds: 300), + vsync: this, + ); + + _slideController = AnimationController( + duration: const Duration(milliseconds: 400), + vsync: this, + ); + + _rotationController = AnimationController( + duration: const Duration(seconds: 20), + vsync: this, + ); + + _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _fadeController, curve: Curves.easeInOut), + ); + + _slideAnimation = + Tween(begin: const Offset(0, 0.3), end: Offset.zero).animate( + CurvedAnimation(parent: _slideController, curve: Curves.easeOutCubic), + ); + + rotationAnimation = + Tween( + begin: 0.0, + end: 2 * 3.14159, // 360 degrees in radians + ).animate( + CurvedAnimation(parent: _rotationController, curve: Curves.linear), + ); + + // Start animations + _fadeController.forward(); + _slideController.forward(); + _rotationController.repeat(); // Infinite rotation + } + + @override + void dispose() { + _pageController.dispose(); + _fadeController.dispose(); + _slideController.dispose(); + _rotationController.dispose(); + super.dispose(); + } + + List _getEventsForDay(DateTime day) { + return _schedules.where((schedule) { + return isSameDay(schedule.date, day); + }).toList(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.background, + body: AnimatedBuilder( + animation: _fadeAnimation, + builder: (context, child) { + return Opacity( + opacity: _fadeAnimation.value, + child: CustomScrollView( + physics: const BouncingScrollPhysics(), + slivers: [ + _buildSliverAppBar(), + _buildSliverCalendar(), + _buildSliverScheduleList(), + ], + ), + ); + }, + ), + ); + } + + Widget _buildSliverAppBar() { + return SliverAppBar( + expandedHeight: 120.0, + floating: false, + pinned: true, + backgroundColor: AppColor.primary, + flexibleSpace: CustomAppBar(title: context.lang.schedule), + ); + } + + Widget _buildSliverCalendar() { + return SliverToBoxAdapter( + child: SlideTransition( + position: _slideAnimation, + child: Container( + margin: const EdgeInsets.all(20), + padding: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(24), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.04), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: TableCalendar( + firstDay: DateTime.utc(2023, 1, 1), + lastDay: DateTime.utc(2025, 12, 31), + focusedDay: _focusedDay, + selectedDayPredicate: (day) => isSameDay(_selectedDay, day), + calendarFormat: _calendarFormat, + eventLoader: _getEventsForDay, + availableCalendarFormats: const {CalendarFormat.week: 'Week'}, + headerStyle: HeaderStyle( + formatButtonVisible: false, + titleCentered: true, + leftChevronVisible: true, + rightChevronVisible: true, + headerPadding: const EdgeInsets.symmetric(vertical: 16), + titleTextStyle: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + ), + leftChevronIcon: Icon( + Icons.chevron_left, + color: AppColor.textSecondary, + ), + rightChevronIcon: Icon( + Icons.chevron_right, + color: AppColor.textSecondary, + ), + ), + calendarStyle: CalendarStyle( + outsideDaysVisible: false, + weekendTextStyle: TextStyle( + color: AppColor.textLight, + fontWeight: FontWeight.w600, + ), + defaultTextStyle: TextStyle( + color: AppColor.textPrimary, + fontWeight: FontWeight.w600, + ), + selectedTextStyle: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w700, + ), + selectedDecoration: BoxDecoration( + color: AppColor.primary, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: AppColor.primary.withOpacity(0.3), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + todayDecoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.2), + shape: BoxShape.circle, + ), + todayTextStyle: TextStyle( + color: AppColor.primary, + fontWeight: FontWeight.w700, + ), + markerDecoration: BoxDecoration( + color: AppColor.warning, + shape: BoxShape.circle, + ), + markersMaxCount: 1, + markerMargin: const EdgeInsets.only(top: 5), + markerSize: 6, + ), + onDaySelected: (selectedDay, focusedDay) { + if (!isSameDay(_selectedDay, selectedDay)) { + setState(() { + _selectedDay = selectedDay; + _focusedDay = focusedDay; + }); + _animateScheduleChange(); + } + }, + onPageChanged: (focusedDay) { + _focusedDay = focusedDay; + }, + ), + ), + ), + ); + } + + Widget _buildSliverScheduleList() { + final selectedEvents = _getEventsForDay(_selectedDay); + + return selectedEvents.isEmpty + ? SliverFillRemaining( + child: SlideTransition( + position: _slideAnimation, + child: _buildEmptyState(), + ), + ) + : SliverPadding( + padding: const EdgeInsets.only( + top: 8, + left: 20, + right: 20, + bottom: 20, + ), + sliver: SliverList( + delegate: SliverChildBuilderDelegate((context, index) { + return SlideTransition( + position: _slideAnimation, + child: AnimatedContainer( + duration: Duration(milliseconds: 200 + (index * 100)), + curve: Curves.easeOutCubic, + child: _buildModernScheduleItem( + selectedEvents[index], + index, + ), + ), + ); + }, childCount: selectedEvents.length), + ), + ); + } + + Widget _buildEmptyState() { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: const EdgeInsets.all(32), + decoration: BoxDecoration( + color: AppColor.primary.withOpacity(0.1), + shape: BoxShape.circle, + ), + child: Icon( + Icons.event_available, + size: 64, + color: AppColor.primary.withOpacity(0.6), + ), + ), + const SizedBox(height: 24), + Text( + 'No events today', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 8), + Text( + 'Enjoy your free time!', + style: TextStyle(fontSize: 16, color: AppColor.textSecondary), + ), + ], + ), + ); + } + + Widget _buildModernScheduleItem(Schedule schedule, int index) { + return TweenAnimationBuilder( + duration: Duration(milliseconds: 300 + (index * 100)), + tween: Tween(begin: 0.0, end: 1.0), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Transform.translate( + offset: Offset(0, 20 * (1 - value)), + child: Opacity( + opacity: value, + child: Container( + margin: const EdgeInsets.only(bottom: 16), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: schedule.hasDetails + ? () => _showModernScheduleDetails(schedule) + : null, + borderRadius: BorderRadius.circular(20), + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(20), + border: Border.all( + color: schedule.color.withOpacity(0.2), + width: 2, + ), + boxShadow: [ + BoxShadow( + color: schedule.color.withOpacity(0.1), + blurRadius: 20, + offset: const Offset(0, 8), + ), + ], + ), + child: Row( + children: [ + // Time indicator + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + decoration: BoxDecoration( + color: schedule.color.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + schedule.time ?? 'All day', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: schedule.color, + ), + ), + ), + const SizedBox(width: 16), + + // Content + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + schedule.title, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + ), + ), + if (schedule.subtitle != null) ...[ + const SizedBox(height: 4), + Text( + schedule.subtitle!, + style: TextStyle( + fontSize: 14, + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + ), + ], + if (schedule.location != null) ...[ + const SizedBox(height: 4), + Row( + children: [ + Icon( + Icons.location_on, + size: 14, + color: AppColor.textLight, + ), + const SizedBox(width: 4), + Text( + schedule.location!, + style: TextStyle( + fontSize: 12, + color: AppColor.textLight, + ), + ), + ], + ), + ], + ], + ), + ), + + // Icon and arrow + if (schedule.icon != null) ...[ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: schedule.color.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + schedule.icon, + color: schedule.color, + size: 24, + ), + ), + const SizedBox(width: 12), + ], + + if (schedule.hasDetails) + Icon( + Icons.arrow_forward_ios, + size: 16, + color: AppColor.textLight, + ), + ], + ), + ), + ), + ), + ), + ), + ); + }, + ); + } + + void _animateScheduleChange() { + _slideController.reset(); + _slideController.forward(); + } + + void _showModernScheduleDetails(Schedule schedule) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + isScrollControlled: true, + builder: (context) => _buildModernScheduleDetailsModal(schedule), + ); + } + + Widget _buildModernScheduleDetailsModal(Schedule schedule) { + return TweenAnimationBuilder( + duration: const Duration(milliseconds: 400), + tween: Tween(begin: 0.0, end: 1.0), + curve: Curves.easeOutCubic, + builder: (context, value, child) { + return Transform.translate( + offset: Offset(0, 50 * (1 - value)), + child: Opacity( + opacity: value, + child: Container( + height: MediaQuery.of(context).size.height * 0.75, + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), + ), + ), + child: Column( + children: [ + // Handle bar + Container( + margin: const EdgeInsets.only(top: 12), + width: 40, + height: 4, + decoration: BoxDecoration( + color: AppColor.border, + borderRadius: BorderRadius.circular(2), + ), + ), + + // Content + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header with color indicator + Row( + children: [ + Container( + width: 4, + height: 40, + decoration: BoxDecoration( + color: schedule.color, + borderRadius: BorderRadius.circular(2), + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + schedule.title, + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.w800, + color: AppColor.textPrimary, + ), + ), + if (schedule.time != null) + Text( + schedule.time!, + style: TextStyle( + fontSize: 16, + color: schedule.color, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + if (schedule.icon != null) + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: schedule.color.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + ), + child: Icon( + schedule.icon, + color: schedule.color, + size: 32, + ), + ), + ], + ), + + const SizedBox(height: 24), + + // Duration and location info + if (schedule.subtitle != null || + schedule.location != null) ...[ + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(16), + ), + child: Column( + children: [ + if (schedule.subtitle != null) ...[ + Row( + children: [ + Icon( + Icons.access_time, + color: AppColor.textSecondary, + size: 20, + ), + const SizedBox(width: 12), + Text( + schedule.subtitle!, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + ], + ), + if (schedule.location != null) + const SizedBox(height: 16), + ], + if (schedule.location != null) + Row( + children: [ + Icon( + Icons.location_on, + color: AppColor.textSecondary, + size: 20, + ), + const SizedBox(width: 12), + Text( + schedule.location!, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + ], + ), + ], + ), + ), + const SizedBox(height: 24), + ], + + // Map placeholder + Container( + height: 180, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + gradient: LinearGradient( + colors: [ + schedule.color.withOpacity(0.1), + schedule.color.withOpacity(0.05), + ], + ), + ), + child: Stack( + children: [ + // Map grid pattern + CustomPaint( + size: const Size(double.infinity, 180), + painter: MapGridPainter( + color: schedule.color.withOpacity(0.1), + ), + ), + // Location pin + Positioned( + right: 40, + top: 60, + child: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: schedule.color, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: schedule.color.withOpacity( + 0.3, + ), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: const Icon( + Icons.location_on, + color: Colors.white, + size: 24, + ), + ), + ), + ], + ), + ), + + const SizedBox(height: 24), + + // Instructions + if (schedule.instructions != null) ...[ + Text( + 'Instructions', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w700, + color: AppColor.textPrimary, + ), + ), + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: schedule.color.withOpacity(0.2), + ), + ), + child: Text( + schedule.instructions!, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: AppColor.textPrimary, + height: 1.5, + ), + ), + ), + const SizedBox(height: 24), + ], + + // PDF attachment + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + color: AppColor.background, + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.border), + ), + child: Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.red.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: const Icon( + Icons.picture_as_pdf, + color: Colors.red, + size: 24, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + 'Instructions.pdf', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppColor.textPrimary, + ), + ), + Text( + '2.4 MB', + style: TextStyle( + fontSize: 12, + color: AppColor.textSecondary, + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: schedule.color.withOpacity(0.1), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + Icons.download, + color: schedule.color, + size: 20, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + }, + ); + } +} + +// Custom painter for map grid +class MapGridPainter extends CustomPainter { + final Color color; + + MapGridPainter({required this.color}); + + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = color + ..strokeWidth = 1; + + // Draw vertical lines + for (int i = 0; i <= 8; i++) { + final x = (size.width / 8) * i; + canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint); + } + + // Draw horizontal lines + for (int i = 0; i <= 6; i++) { + final y = (size.height / 6) * i; + canvas.drawLine(Offset(0, y), Offset(size.width, y), paint); + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/lib/presentation/pages/splash/splash_page.dart b/lib/presentation/pages/splash/splash_page.dart new file mode 100644 index 0000000..46024f7 --- /dev/null +++ b/lib/presentation/pages/splash/splash_page.dart @@ -0,0 +1,191 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +import '../../../application/auth/auth_bloc.dart'; +import '../../../common/extension/extension.dart'; +import '../../../common/theme/theme.dart'; +import '../../../injection.dart'; +import '../../components/assets/assets.gen.dart'; +import '../../router/app_router.gr.dart'; + +@RoutePage() +class SplashPage extends StatefulWidget { + const SplashPage({super.key}); + + @override + State createState() => _SplashPageState(); +} + +class _SplashPageState extends State with TickerProviderStateMixin { + late AnimationController _logoController; + late AnimationController _versionController; + late AnimationController _backgroundController; + + late Animation _logoAnimation; + late Animation _versionAnimation; + late Animation _backgroundAnimation; + + @override + void initState() { + super.initState(); + + // Initialize animation controllers + _logoController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + + _versionController = AnimationController( + duration: const Duration(milliseconds: 800), + vsync: this, + ); + + _backgroundController = AnimationController( + duration: const Duration(milliseconds: 1500), + vsync: this, + ); + + // Create animations + _logoAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _logoController, curve: Curves.elasticOut), + ); + + _versionAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _versionController, curve: Curves.easeInOut), + ); + + _backgroundAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation(parent: _backgroundController, curve: Curves.easeInOut), + ); + + // Start animations + _startAnimations(); + } + + void _startAnimations() async { + // Start background animation immediately + _backgroundController.forward(); + + // Wait a bit, then start logo animation + await Future.delayed(const Duration(milliseconds: 300)); + if (mounted) _logoController.forward(); + + // Start version animation after logo starts + await Future.delayed(const Duration(milliseconds: 600)); + if (mounted) _versionController.forward(); + + // Navigate to home screen after all animations complete + await Future.delayed(const Duration(milliseconds: 2000)); + if (mounted) { + context.read().add(const AuthEvent.fetchCurrentUser()); + } + } + + @override + void dispose() { + _logoController.dispose(); + _versionController.dispose(); + _backgroundController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final packageInfo = getIt(); + return BlocListener( + listenWhen: (previous, current) => previous.status != current.status, + listener: (context, state) { + if (state.isAuthenticated) { + context.router.replace(const MainRoute()); + } else { + context.router.replace(const LoginRoute()); + } + }, + child: Scaffold( + body: AnimatedBuilder( + animation: Listenable.merge([ + _logoController, + _versionController, + _backgroundController, + ]), + builder: (context, child) { + // Clamp values to prevent opacity errors + final logoOpacity = _logoAnimation.value.clamp(0.0, 1.0); + final versionOpacity = _versionAnimation.value.clamp(0.0, 1.0); + final backgroundOpacity = _backgroundAnimation.value.clamp( + 0.0, + 1.0, + ); + + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + AppColor.primaryWithOpacity(backgroundOpacity), + AppColor.primaryWithOpacity(backgroundOpacity * 0.8), + ], + ), + ), + child: Stack( + children: [ + // Logo di tengah + Center( + child: Transform.scale( + scale: logoOpacity, + child: Opacity( + opacity: logoOpacity, + child: Container( + width: 150, + height: 150, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 30, + offset: const Offset(0, 15), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular( + AppValue.radius, + ), + child: Assets.images.logo.image(fit: BoxFit.cover), + ), + ), + ), + ), + ), + + // Version di bagian bawah + Positioned( + bottom: 60, + left: 0, + right: 0, + child: Transform.translate( + offset: Offset(0, 20 * (1 - versionOpacity)), + child: Opacity( + opacity: versionOpacity, + child: Text( + '${context.lang.version} ${packageInfo.version}+${packageInfo.buildNumber}', + style: AppStyle.md.copyWith( + color: AppColor.textLight, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + ], + ), + ); + }, + ), + ), + ); + } +} diff --git a/lib/presentation/pages/splash_page.dart b/lib/presentation/pages/splash_page.dart deleted file mode 100644 index 12c890a..0000000 --- a/lib/presentation/pages/splash_page.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; - -@RoutePage() -class SplashPage extends StatefulWidget { - const SplashPage({super.key}); - - @override - State createState() => _SplashPageState(); -} - -class _SplashPageState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: Text("Splash Page"), - ), - ); - } -} diff --git a/lib/presentation/router/app_router.dart b/lib/presentation/router/app_router.dart index 4c75faf..3bc5124 100644 --- a/lib/presentation/router/app_router.dart +++ b/lib/presentation/router/app_router.dart @@ -5,7 +5,71 @@ import 'app_router.gr.dart'; class AppRouter extends RootStackRouter { @override List get routes => [ - // Splash - AutoRoute(page: SplashRoute.page, initial: true), - ]; + // Splash + AutoRoute(page: SplashRoute.page, initial: true), + + // Auth + AutoRoute(page: LoginRoute.page), + + // Main + AutoRoute( + page: MainRoute.page, + children: [ + AutoRoute(page: HomeRoute.page), + AutoRoute(page: OrderRoute.page), + AutoRoute(page: ReportRoute.page), + AutoRoute(page: ProfileRoute.page), + ], + ), + + // Language + AutoRoute(page: LanguageRoute.page), + + // Form + AutoRoute(page: DailyTasksFormRoute.page), + + // Schedule + AutoRoute(page: ScheduleRoute.page), + + // Product + AutoRoute(page: ProductRoute.page), + AutoRoute(page: ProductAnalyticRoute.page), + + // Customer + AutoRoute(page: CustomerRoute.page), + + // Inventory + AutoRoute(page: InventoryRoute.page), + + // Sales + AutoRoute(page: SalesRoute.page), + + // Purchase page + AutoRoute(page: PurchaseRoute.page), + + // Finance page + AutoRoute(page: FinanceRoute.page), + + // Order + AutoRoute(page: OrderDetailRoute.page), + + // Outlet + AutoRoute(page: OutletInformationRoute.page), + + // Download Report + AutoRoute(page: DownloadReportRoute.page), + + // Profile + AutoRoute(page: ProfileEditRoute.page), + AutoRoute(page: ProfileChangePasswordRoute.page), + + // About App + AutoRoute(page: AboutAppRoute.page), + + // Error + AutoRoute(page: ErrorRoute.page), + + // Coming Soong + AutoRoute(page: ComingSoonRoute.page), + ]; } diff --git a/lib/presentation/router/app_router.gr.dart b/lib/presentation/router/app_router.gr.dart index 54491c3..00f4aaf 100644 --- a/lib/presentation/router/app_router.gr.dart +++ b/lib/presentation/router/app_router.gr.dart @@ -9,22 +9,563 @@ // coverage:ignore-file // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:apskel_owner_flutter/presentation/pages/splash_page.dart' +import 'package:apskel_owner_flutter/domain/order/order.dart' as _i28; +import 'package:apskel_owner_flutter/domain/user/user.dart' as _i29; +import 'package:apskel_owner_flutter/presentation/pages/about_app/about_app_page.dart' as _i1; -import 'package:auto_route/auto_route.dart' as _i2; +import 'package:apskel_owner_flutter/presentation/pages/auth/login/login_page.dart' + as _i11; +import 'package:apskel_owner_flutter/presentation/pages/coming_soon/coming_soon_page.dart' + as _i2; +import 'package:apskel_owner_flutter/presentation/pages/customer/customer_page.dart' + as _i3; +import 'package:apskel_owner_flutter/presentation/pages/download/download_report_page.dart' + as _i5; +import 'package:apskel_owner_flutter/presentation/pages/error/error_page.dart' + as _i6; +import 'package:apskel_owner_flutter/presentation/pages/finance/finance_page.dart' + as _i7; +import 'package:apskel_owner_flutter/presentation/pages/form/daily_task_form_page.dart' + as _i4; +import 'package:apskel_owner_flutter/presentation/pages/home/home_page.dart' + as _i8; +import 'package:apskel_owner_flutter/presentation/pages/inventory/inventory_page.dart' + as _i9; +import 'package:apskel_owner_flutter/presentation/pages/language/language_page.dart' + as _i10; +import 'package:apskel_owner_flutter/presentation/pages/main/main_page.dart' + as _i12; +import 'package:apskel_owner_flutter/presentation/pages/order/order_detail/order_detail_page.dart' + as _i13; +import 'package:apskel_owner_flutter/presentation/pages/order/order_list/order_page.dart' + as _i14; +import 'package:apskel_owner_flutter/presentation/pages/outlet/outlet_information_page.dart' + as _i15; +import 'package:apskel_owner_flutter/presentation/pages/product/product_analytic/product_analytic_page.dart' + as _i16; +import 'package:apskel_owner_flutter/presentation/pages/product/product_list/product_page.dart' + as _i17; +import 'package:apskel_owner_flutter/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart' + as _i18; +import 'package:apskel_owner_flutter/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart' + as _i19; +import 'package:apskel_owner_flutter/presentation/pages/profile/profile_page.dart' + as _i20; +import 'package:apskel_owner_flutter/presentation/pages/purchase/purchase_page.dart' + as _i21; +import 'package:apskel_owner_flutter/presentation/pages/report/report_page.dart' + as _i22; +import 'package:apskel_owner_flutter/presentation/pages/sales/sales_page.dart' + as _i23; +import 'package:apskel_owner_flutter/presentation/pages/schedule/schedule_page.dart' + as _i24; +import 'package:apskel_owner_flutter/presentation/pages/splash/splash_page.dart' + as _i25; +import 'package:auto_route/auto_route.dart' as _i26; +import 'package:flutter/material.dart' as _i27; /// generated route for -/// [_i1.SplashPage] -class SplashRoute extends _i2.PageRouteInfo { - const SplashRoute({List<_i2.PageRouteInfo>? children}) +/// [_i1.AboutAppPage] +class AboutAppRoute extends _i26.PageRouteInfo { + const AboutAppRoute({List<_i26.PageRouteInfo>? children}) + : super(AboutAppRoute.name, initialChildren: children); + + static const String name = 'AboutAppRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i1.AboutAppPage(); + }, + ); +} + +/// generated route for +/// [_i2.ComingSoonPage] +class ComingSoonRoute extends _i26.PageRouteInfo { + const ComingSoonRoute({List<_i26.PageRouteInfo>? children}) + : super(ComingSoonRoute.name, initialChildren: children); + + static const String name = 'ComingSoonRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i2.ComingSoonPage(); + }, + ); +} + +/// generated route for +/// [_i3.CustomerPage] +class CustomerRoute extends _i26.PageRouteInfo { + const CustomerRoute({List<_i26.PageRouteInfo>? children}) + : super(CustomerRoute.name, initialChildren: children); + + static const String name = 'CustomerRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i3.CustomerPage()); + }, + ); +} + +/// generated route for +/// [_i4.DailyTasksFormPage] +class DailyTasksFormRoute extends _i26.PageRouteInfo { + const DailyTasksFormRoute({List<_i26.PageRouteInfo>? children}) + : super(DailyTasksFormRoute.name, initialChildren: children); + + static const String name = 'DailyTasksFormRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i4.DailyTasksFormPage(); + }, + ); +} + +/// generated route for +/// [_i5.DownloadReportPage] +class DownloadReportRoute extends _i26.PageRouteInfo { + const DownloadReportRoute({List<_i26.PageRouteInfo>? children}) + : super(DownloadReportRoute.name, initialChildren: children); + + static const String name = 'DownloadReportRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i5.DownloadReportPage()); + }, + ); +} + +/// generated route for +/// [_i6.ErrorPage] +class ErrorRoute extends _i26.PageRouteInfo { + ErrorRoute({ + _i27.Key? key, + String? title, + String? message, + _i27.VoidCallback? onRetry, + _i27.VoidCallback? onBack, + String? errorCode, + _i27.IconData? errorIcon, + List<_i26.PageRouteInfo>? children, + }) : super( + ErrorRoute.name, + args: ErrorRouteArgs( + key: key, + title: title, + message: message, + onRetry: onRetry, + onBack: onBack, + errorCode: errorCode, + errorIcon: errorIcon, + ), + initialChildren: children, + ); + + static const String name = 'ErrorRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + final args = data.argsAs( + orElse: () => const ErrorRouteArgs(), + ); + return _i6.ErrorPage( + key: args.key, + title: args.title, + message: args.message, + onRetry: args.onRetry, + onBack: args.onBack, + errorCode: args.errorCode, + errorIcon: args.errorIcon, + ); + }, + ); +} + +class ErrorRouteArgs { + const ErrorRouteArgs({ + this.key, + this.title, + this.message, + this.onRetry, + this.onBack, + this.errorCode, + this.errorIcon, + }); + + final _i27.Key? key; + + final String? title; + + final String? message; + + final _i27.VoidCallback? onRetry; + + final _i27.VoidCallback? onBack; + + final String? errorCode; + + final _i27.IconData? errorIcon; + + @override + String toString() { + return 'ErrorRouteArgs{key: $key, title: $title, message: $message, onRetry: $onRetry, onBack: $onBack, errorCode: $errorCode, errorIcon: $errorIcon}'; + } +} + +/// generated route for +/// [_i7.FinancePage] +class FinanceRoute extends _i26.PageRouteInfo { + const FinanceRoute({List<_i26.PageRouteInfo>? children}) + : super(FinanceRoute.name, initialChildren: children); + + static const String name = 'FinanceRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i7.FinancePage()); + }, + ); +} + +/// generated route for +/// [_i8.HomePage] +class HomeRoute extends _i26.PageRouteInfo { + const HomeRoute({List<_i26.PageRouteInfo>? children}) + : super(HomeRoute.name, initialChildren: children); + + static const String name = 'HomeRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i8.HomePage()); + }, + ); +} + +/// generated route for +/// [_i9.InventoryPage] +class InventoryRoute extends _i26.PageRouteInfo { + const InventoryRoute({List<_i26.PageRouteInfo>? children}) + : super(InventoryRoute.name, initialChildren: children); + + static const String name = 'InventoryRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i9.InventoryPage()); + }, + ); +} + +/// generated route for +/// [_i10.LanguagePage] +class LanguageRoute extends _i26.PageRouteInfo { + const LanguageRoute({List<_i26.PageRouteInfo>? children}) + : super(LanguageRoute.name, initialChildren: children); + + static const String name = 'LanguageRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i10.LanguagePage(); + }, + ); +} + +/// generated route for +/// [_i11.LoginPage] +class LoginRoute extends _i26.PageRouteInfo { + const LoginRoute({List<_i26.PageRouteInfo>? children}) + : super(LoginRoute.name, initialChildren: children); + + static const String name = 'LoginRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i11.LoginPage()); + }, + ); +} + +/// generated route for +/// [_i12.MainPage] +class MainRoute extends _i26.PageRouteInfo { + const MainRoute({List<_i26.PageRouteInfo>? children}) + : super(MainRoute.name, initialChildren: children); + + static const String name = 'MainRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i12.MainPage(); + }, + ); +} + +/// generated route for +/// [_i13.OrderDetailPage] +class OrderDetailRoute extends _i26.PageRouteInfo { + OrderDetailRoute({ + _i27.Key? key, + required _i28.Order order, + List<_i26.PageRouteInfo>? children, + }) : super( + OrderDetailRoute.name, + args: OrderDetailRouteArgs(key: key, order: order), + initialChildren: children, + ); + + static const String name = 'OrderDetailRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + final args = data.argsAs(); + return _i13.OrderDetailPage(key: args.key, order: args.order); + }, + ); +} + +class OrderDetailRouteArgs { + const OrderDetailRouteArgs({this.key, required this.order}); + + final _i27.Key? key; + + final _i28.Order order; + + @override + String toString() { + return 'OrderDetailRouteArgs{key: $key, order: $order}'; + } +} + +/// generated route for +/// [_i14.OrderPage] +class OrderRoute extends _i26.PageRouteInfo { + const OrderRoute({List<_i26.PageRouteInfo>? children}) + : super(OrderRoute.name, initialChildren: children); + + static const String name = 'OrderRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i14.OrderPage()); + }, + ); +} + +/// generated route for +/// [_i15.OutletInformationPage] +class OutletInformationRoute extends _i26.PageRouteInfo { + const OutletInformationRoute({List<_i26.PageRouteInfo>? children}) + : super(OutletInformationRoute.name, initialChildren: children); + + static const String name = 'OutletInformationRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i15.OutletInformationPage()); + }, + ); +} + +/// generated route for +/// [_i16.ProductAnalyticPage] +class ProductAnalyticRoute extends _i26.PageRouteInfo { + const ProductAnalyticRoute({List<_i26.PageRouteInfo>? children}) + : super(ProductAnalyticRoute.name, initialChildren: children); + + static const String name = 'ProductAnalyticRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i16.ProductAnalyticPage()); + }, + ); +} + +/// generated route for +/// [_i17.ProductPage] +class ProductRoute extends _i26.PageRouteInfo { + const ProductRoute({List<_i26.PageRouteInfo>? children}) + : super(ProductRoute.name, initialChildren: children); + + static const String name = 'ProductRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i17.ProductPage()); + }, + ); +} + +/// generated route for +/// [_i18.ProfileChangePasswordPage] +class ProfileChangePasswordRoute extends _i26.PageRouteInfo { + const ProfileChangePasswordRoute({List<_i26.PageRouteInfo>? children}) + : super(ProfileChangePasswordRoute.name, initialChildren: children); + + static const String name = 'ProfileChangePasswordRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i18.ProfileChangePasswordPage()); + }, + ); +} + +/// generated route for +/// [_i19.ProfileEditPage] +class ProfileEditRoute extends _i26.PageRouteInfo { + ProfileEditRoute({ + _i27.Key? key, + required _i29.User user, + List<_i26.PageRouteInfo>? children, + }) : super( + ProfileEditRoute.name, + args: ProfileEditRouteArgs(key: key, user: user), + initialChildren: children, + ); + + static const String name = 'ProfileEditRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + final args = data.argsAs(); + return _i26.WrappedRoute( + child: _i19.ProfileEditPage(key: args.key, user: args.user), + ); + }, + ); +} + +class ProfileEditRouteArgs { + const ProfileEditRouteArgs({this.key, required this.user}); + + final _i27.Key? key; + + final _i29.User user; + + @override + String toString() { + return 'ProfileEditRouteArgs{key: $key, user: $user}'; + } +} + +/// generated route for +/// [_i20.ProfilePage] +class ProfileRoute extends _i26.PageRouteInfo { + const ProfileRoute({List<_i26.PageRouteInfo>? children}) + : super(ProfileRoute.name, initialChildren: children); + + static const String name = 'ProfileRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i20.ProfilePage()); + }, + ); +} + +/// generated route for +/// [_i21.PurchasePage] +class PurchaseRoute extends _i26.PageRouteInfo { + const PurchaseRoute({List<_i26.PageRouteInfo>? children}) + : super(PurchaseRoute.name, initialChildren: children); + + static const String name = 'PurchaseRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i21.PurchasePage(); + }, + ); +} + +/// generated route for +/// [_i22.ReportPage] +class ReportRoute extends _i26.PageRouteInfo { + const ReportRoute({List<_i26.PageRouteInfo>? children}) + : super(ReportRoute.name, initialChildren: children); + + static const String name = 'ReportRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i22.ReportPage()); + }, + ); +} + +/// generated route for +/// [_i23.SalesPage] +class SalesRoute extends _i26.PageRouteInfo { + const SalesRoute({List<_i26.PageRouteInfo>? children}) + : super(SalesRoute.name, initialChildren: children); + + static const String name = 'SalesRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return _i26.WrappedRoute(child: const _i23.SalesPage()); + }, + ); +} + +/// generated route for +/// [_i24.SchedulePage] +class ScheduleRoute extends _i26.PageRouteInfo { + const ScheduleRoute({List<_i26.PageRouteInfo>? children}) + : super(ScheduleRoute.name, initialChildren: children); + + static const String name = 'ScheduleRoute'; + + static _i26.PageInfo page = _i26.PageInfo( + name, + builder: (data) { + return const _i24.SchedulePage(); + }, + ); +} + +/// generated route for +/// [_i25.SplashPage] +class SplashRoute extends _i26.PageRouteInfo { + const SplashRoute({List<_i26.PageRouteInfo>? children}) : super(SplashRoute.name, initialChildren: children); static const String name = 'SplashRoute'; - static _i2.PageInfo page = _i2.PageInfo( + static _i26.PageInfo page = _i26.PageInfo( name, builder: (data) { - return const _i1.SplashPage(); + return const _i25.SplashPage(); }, ); } diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 80ef900..5643091 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -7,7 +7,7 @@ project(runner LANGUAGES CXX) set(BINARY_NAME "apskel_owner_flutter") # The unique GTK application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.apskel_owner_flutter") +set(APPLICATION_ID "com.apskel.enaklo_owner") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..86be7eb 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,18 @@ #include "generated_plugin_registrant.h" +#include +#include +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) open_file_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "OpenFileLinuxPlugin"); + open_file_linux_plugin_register_with_registrar(open_file_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..c842924 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,9 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux + open_file_linux + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 7d12a67..476a6ba 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,11 +6,29 @@ import FlutterMacOS import Foundation import connectivity_plus +import device_info_plus +import file_selector_macos +import firebase_core +import firebase_messaging +import flutter_local_notifications +import open_file_mac +import package_info_plus import path_provider_foundation import shared_preferences_foundation +import sqflite_darwin +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) + OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 01684df..39c7a96 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "85.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7" + url: "https://pub.dev" + source: hosted + version: "1.3.35" analyzer: dependency: transitive description: @@ -17,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.7.1" + another_flushbar: + dependency: "direct main" + description: + name: another_flushbar + sha256: "19bf9520230ec40b300aaf9dd2a8fefcb277b25ecd1c4838f530566965befc2a" + url: "https://pub.dev" + source: hosted + version: "1.12.30" archive: dependency: transitive description: @@ -65,6 +81,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + back_button_interceptor: + dependency: transitive + description: + name: back_button_interceptor + sha256: b85977faabf4aeb95164b3b8bf81784bed4c54ea1aef90a036ab6927ecf80c5a + url: "https://pub.dev" + source: hosted + version: "8.0.4" + barcode: + dependency: transitive + description: + name: barcode + sha256: "7b6729c37e3b7f34233e2318d866e8c48ddb46c1f7ad01ff7bb2a8de1da2b9f4" + url: "https://pub.dev" + source: hosted + version: "2.2.9" + bidi: + dependency: transitive + description: + name: bidi + sha256: "77f475165e94b261745cf1032c751e2032b8ed92ccb2bf5716036db79320637d" + url: "https://pub.dev" + source: hosted + version: "2.0.13" + bloc: + dependency: transitive + description: + name: bloc + sha256: "52c10575f4445c61dd9e0cafcc6356fdd827c4c64dd7945ef3c4105f6b6ac189" + url: "https://pub.dev" + source: hosted + version: "9.0.0" boolean_selector: dependency: transitive description: @@ -137,14 +185,38 @@ packages: url: "https://pub.dev" source: hosted version: "8.11.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + url: "https://pub.dev" + source: hosted + version: "4.1.1" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" + url: "https://pub.dev" + source: hosted + version: "1.3.1" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" checked_yaml: dependency: transitive description: @@ -225,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -281,6 +361,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.11" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" + url: "https://pub.dev" + source: hosted + version: "11.5.0" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f + url: "https://pub.dev" + source: hosted + version: "7.0.3" dio: dependency: "direct main" description: @@ -297,6 +393,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + equatable: + dependency: transitive + description: + name: equatable + sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" + url: "https://pub.dev" + source: hosted + version: "2.0.7" fake_async: dependency: transitive description: @@ -321,6 +425,86 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "8c9250b2bd2d8d4268e39c82543bacbaca0fda7d29e0728c3c4bbb7c820fd711" + url: "https://pub.dev" + source: hosted + version: "0.9.4+3" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c" + url: "https://pub.dev" + source: hosted + version: "2.32.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: "8bcfad6d7033f5ea951d15b867622a824b13812178bfec0c779b9d81de011bbb" + url: "https://pub.dev" + source: hosted + version: "5.4.2" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: eb3afccfc452b2b2075acbe0c4b27de62dd596802b4e5e19869c1e926cbb20b3 + url: "https://pub.dev" + source: hosted + version: "2.24.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + url: "https://pub.dev" + source: hosted + version: "14.7.10" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "87c4a922cb6f811cfb7a889bdbb3622702443c52a0271636cbc90d813ceac147" + url: "https://pub.dev" + source: hosted + version: "4.5.37" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + url: "https://pub.dev" + source: hosted + version: "3.5.18" fixnum: dependency: transitive description: @@ -329,11 +513,35 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "577aeac8ca414c25333334d7c4bb246775234c0e44b38b10a82b559dd4d764e7" + url: "https://pub.dev" + source: hosted + version: "1.0.0" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: "direct main" + description: + name: flutter_bloc + sha256: cf51747952201a455a1c840f8171d273be009b932c75093020f9af64f2123e38 + url: "https://pub.dev" + source: hosted + version: "9.1.1" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + url: "https://pub.dev" + source: hosted + version: "3.4.1" flutter_gen_core: dependency: transitive description: @@ -366,6 +574,51 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: ef41ae901e7529e52934feba19ed82827b11baa67336829564aeab3129460610 + url: "https://pub.dev" + source: hosted + version: "18.0.1" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: "8f685642876742c941b29c32030f6f4f6dacd0e4eaecb3efbb187d6a3812ca01" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "6c5b83c86bf819cdb177a9247a3722067dd8cc6313827ce7c77a4b238a26fd52" + url: "https://pub.dev" + source: hosted + version: "8.0.0" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab" + url: "https://pub.dev" + source: hosted + version: "2.0.29" + flutter_spinkit: + dependency: "direct main" + description: + name: flutter_spinkit + sha256: "77850df57c00dc218bfe96071d576a8babec24cf58b2ed121c83cca4a2fdce7f" + url: "https://pub.dev" + source: hosted + version: "5.2.2" flutter_svg: dependency: "direct main" description: @@ -464,6 +717,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.2" + hugeicons: + dependency: "direct main" + description: + name: hugeicons + sha256: "03845d6fc8fed4a9df27d3710c94499f6f624e2cd343e858be2578a4ec69ad0a" + url: "https://pub.dev" + source: hosted + version: "1.1.6" image: dependency: transitive description: @@ -472,6 +733,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.4" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: b08e9a04d0f8d91f4a6e767a745b9871bfbc585410205c311d0492de20a7ccd6 + url: "https://pub.dev" + source: hosted + version: "0.8.12+25" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100" + url: "https://pub.dev" + source: hosted + version: "0.8.12+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" image_size_getter: dependency: transitive description: @@ -516,10 +841,10 @@ packages: dependency: transitive description: name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.6.7" json_annotation: dependency: "direct main" description: @@ -540,26 +865,34 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" + line_icons: + dependency: "direct main" + description: + name: line_icons + sha256: "249d781d922f5437ac763d9c8f5a02cf5b499a6dc3f85e4b92e074cff0a932ab" + url: "https://pub.dev" + source: hosted + version: "2.0.3" lints: dependency: transitive description: @@ -568,6 +901,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + loader_overlay: + dependency: "direct main" + description: + name: loader_overlay + sha256: "285c9ccab9a42a392ba948bd0b14376fd0ee9ddd7b63e3018bcd54460fd3e021" + url: "https://pub.dev" + source: hosted + version: "5.0.0" logging: dependency: transitive description: @@ -580,26 +921,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -608,6 +949,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" nm: dependency: transitive description: @@ -616,6 +965,78 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + open_file: + dependency: "direct main" + description: + name: open_file + sha256: d17e2bddf5b278cb2ae18393d0496aa4f162142ba97d1a9e0c30d476adf99c0e + url: "https://pub.dev" + source: hosted + version: "3.5.10" + open_file_android: + dependency: transitive + description: + name: open_file_android + sha256: "58141fcaece2f453a9684509a7275f231ac0e3d6ceb9a5e6de310a7dff9084aa" + url: "https://pub.dev" + source: hosted + version: "1.0.6" + open_file_ios: + dependency: transitive + description: + name: open_file_ios + sha256: "02996f01e5f6863832068e97f8f3a5ef9b613516db6897f373b43b79849e4d07" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + open_file_linux: + dependency: transitive + description: + name: open_file_linux + sha256: d189f799eecbb139c97f8bc7d303f9e720954fa4e0fa1b0b7294767e5f2d7550 + url: "https://pub.dev" + source: hosted + version: "0.0.5" + open_file_mac: + dependency: transitive + description: + name: open_file_mac + sha256: "1440b1e37ceb0642208cfeb2c659c6cda27b25187a90635c9d1acb7d0584d324" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + open_file_platform_interface: + dependency: transitive + description: + name: open_file_platform_interface + sha256: "101b424ca359632699a7e1213e83d025722ab668b9fd1412338221bf9b0e5757" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + open_file_web: + dependency: transitive + description: + name: open_file_web + sha256: e3dbc9584856283dcb30aef5720558b90f88036360bd078e494ab80a80130c4f + url: "https://pub.dev" + source: hosted + version: "0.0.4" + open_file_windows: + dependency: transitive + description: + name: open_file_windows + sha256: d26c31ddf935a94a1a3aa43a23f4fff8a5ff4eea395fe7a8cb819cf55431c875 + url: "https://pub.dev" + source: hosted + version: "0.0.3" package_config: dependency: transitive description: @@ -624,6 +1045,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" + url: "https://pub.dev" + source: hosted + version: "8.3.1" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + url: "https://pub.dev" + source: hosted + version: "3.2.1" path: dependency: "direct main" description: @@ -688,6 +1125,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + pdf: + dependency: "direct main" + description: + name: pdf + sha256: "28eacad99bffcce2e05bba24e50153890ad0255294f4dd78a17075a2ba5c8416" + url: "https://pub.dev" + source: hosted + version: "3.11.3" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 + url: "https://pub.dev" + source: hosted + version: "12.0.1" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6" + url: "https://pub.dev" + source: hosted + version: "13.0.1" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 + url: "https://pub.dev" + source: hosted + version: "9.4.7" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" + url: "https://pub.dev" + source: hosted + version: "0.1.3+5" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 + url: "https://pub.dev" + source: hosted + version: "4.3.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" petitparser: dependency: transitive description: @@ -728,6 +1221,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.3" + provider: + dependency: transitive + description: + name: provider + sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + url: "https://pub.dev" + source: hosted + version: "6.1.5" pub_semver: dependency: transitive description: @@ -744,6 +1245,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.0" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" recase: dependency: transitive description: @@ -752,6 +1261,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" shared_preferences: dependency: "direct main" description: @@ -824,6 +1341,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + shimmer: + dependency: "direct main" + description: + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + simple_gesture_detector: + dependency: transitive + description: + name: simple_gesture_detector + sha256: ba2cd5af24ff20a0b8d609cec3f40e5b0744d2a71804a2616ae086b9c19d19a3 + url: "https://pub.dev" + source: hosted + version: "0.2.1" sky_engine: dependency: transitive description: flutter @@ -853,6 +1386,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" stack_trace: dependency: transitive description: @@ -885,6 +1466,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: ce02ce65f51db8e29edc9d2225872d927e001bd2b13c2490d176563bbb046fc7 + url: "https://pub.dev" + source: hosted + version: "30.2.5" + syncfusion_flutter_datepicker: + dependency: "direct main" + description: + name: syncfusion_flutter_datepicker + sha256: e8df9f4777df15db11929f20cbe98e4249fe08208e7107bcb4ad889aa1ba2bbf + url: "https://pub.dev" + source: hosted + version: "30.2.5" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 + url: "https://pub.dev" + source: hosted + version: "3.4.0" + table_calendar: + dependency: "direct main" + description: + name: table_calendar + sha256: "0c0c6219878b363a2d5f40c7afb159d845f253d061dc3c822aa0d5fe0f721982" + url: "https://pub.dev" + source: hosted + version: "3.2.0" term_glyph: dependency: transitive description: @@ -897,10 +1510,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.10" time: dependency: transitive description: @@ -909,6 +1522,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.5" + timezone: + dependency: transitive + description: + name: timezone + sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 + url: "https://pub.dev" + source: hosted + version: "0.10.1" timing: dependency: transitive description: @@ -925,6 +1546,78 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656" + url: "https://pub.dev" + source: hosted + version: "6.3.17" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 + url: "https://pub.dev" + source: hosted + version: "6.3.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f + url: "https://pub.dev" + source: hosted + version: "3.2.3" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_graphics: dependency: transitive description: @@ -953,10 +1646,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -997,6 +1690,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + win32: + dependency: transitive + description: + name: win32 + sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + url: "https://pub.dev" + source: hosted + version: "5.14.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" + url: "https://pub.dev" + source: hosted + version: "2.1.0" xdg_directories: dependency: transitive description: @@ -1022,5 +1731,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.8.1 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.9.0-0 <4.0.0" + flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml index c73810e..e6e3bb2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,6 +12,9 @@ dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter + cupertino_icons: ^1.0.8 auto_route: ^9.3.0 get_it: ^8.0.3 @@ -28,6 +31,27 @@ dependencies: json_annotation: ^4.9.0 shared_preferences: ^2.5.3 awesome_dio_interceptor: ^1.3.0 + line_icons: ^2.0.3 + flutter_spinkit: ^5.2.2 + fl_chart: ^1.0.0 + another_flushbar: ^1.12.30 + flutter_bloc: ^9.1.1 + image_picker: ^1.1.2 + table_calendar: ^3.2.0 + package_info_plus: ^8.3.1 + loader_overlay: ^5.0.0 + shimmer: ^3.0.0 + cached_network_image: ^3.4.1 + syncfusion_flutter_datepicker: ^30.2.5 + url_launcher: ^6.3.2 + device_info_plus: ^11.5.0 + pdf: ^3.11.3 + open_file: ^3.5.10 + permission_handler: ^12.0.1 + firebase_core: 2.32.0 + firebase_messaging: 14.7.10 + flutter_local_notifications: ^18.0.1 + hugeicons: ^1.1.6 dev_dependencies: flutter_test: @@ -43,11 +67,12 @@ dev_dependencies: json_serializable: ^6.9.5 flutter: + generate: true uses-material-design: true assets: - assets/images/ - assets/icons/ - - assets/json/ + # - assets/json/ fonts: - family: Quicksand diff --git a/web/favicon.png b/web/favicon.png index 91b113e..c477ce0 100644 Binary files a/web/favicon.png and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png index 483f22e..ac5b619 100644 Binary files a/web/icons/Icon-192.png and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png index 3d0d42e..d1e12cc 100644 Binary files a/web/icons/Icon-512.png and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png index 483f22e..ac5b619 100644 Binary files a/web/icons/Icon-maskable-192.png and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png index 3d0d42e..d1e12cc 100644 Binary files a/web/icons/Icon-maskable-512.png and b/web/icons/Icon-maskable-512.png differ diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8777c93..281ed4c 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,20 @@ #include "generated_plugin_registrant.h" #include +#include +#include +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index cc1361d..11c0100 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,10 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus + file_selector_windows + firebase_core + permission_handler_windows + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index eba7b0f..53ae5ae 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ