Compare commits

..
21 Commits
Author SHA1 Message Date
efrilm 0c8ca3c51b git push 2026-05-15 12:53:04 +07:00
Efril 96526c1972 update 2026-05-14 15:05:04 +07:00
Efril c4618bbc1b update pesanan 2026-05-14 14:55:49 +07:00
Efril 9f2097a268 add all outlet 2026-05-14 14:11:42 +07:00
efrilm 6fda0f5636 fix home 2026-05-13 15:31:14 +07:00
efrilm d7cd84e130 fix ios 2026-05-13 13:22:06 +07:00
efrilm ba2f0cd265 selected outlet 2026-05-12 17:09:50 +07:00
efrilm 3541fc725c outlet list 2026-05-12 16:47:36 +07:00
efrilm c2727a0995 update outlet card 2026-05-12 16:31:00 +07:00
efrilm 6e4b09f15e update home ui 2026-05-12 15:50:02 +07:00
efrilm 9076c9c66e update home ui 2026-05-12 15:47:38 +07:00
efrilm 86d581f5ea update remove animation 2026-05-12 14:48:53 +07:00
efrilm 411d1274bd add files ios 2026-05-12 02:01:15 +07:00
Efril a4a12c6763 add device info at login 2026-05-12 02:00:38 +07:00
Efril 9b6e9c591d update notification 2026-05-12 01:54:24 +07:00
Efril 3985611a0e update ios 2026-05-12 00:59:56 +07:00
Efril 61dd2bbb2c update api 2026-05-12 00:55:15 +07:00
Efril 91965667ec setup fcm 2026-05-12 00:52:14 +07:00
efrilm 9775e09659 feat: readme 2025-08-22 15:26:16 +07:00
efrilm 3f75bffd09 feat: pull to refresh on home 2025-08-20 13:57:00 +07:00
efrilm 5a83bc4049 feat: lang 2025-08-20 13:52:49 +07:00
163 changed files with 8836 additions and 1711 deletions
+541 -15
View File
@@ -1,39 +1,565 @@
# Apskel Owner App
## Apskel Owner Flutter
A Flutter-based Point of Sale (POS) application designed specifically for business owners.
Helps manage sales, products, inventory, and business reports in real-time with a simple, easy-to-use interface.
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
---
### âś… Prerequisites
### Contents
- [Flutter](https://flutter.dev/docs/get-started/install) 3.32.8 or newer
- Dart 3.8.1 or newer
- 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
### đź›  Installation
---
```bash
git clone https://github.com/efrilm/frl-movie.git
```
## Technical Summary
```bash
cd app-path
```
- 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 <your-repo-url>
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
## 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/
<feature>/ # Entities, repo interfaces, (use-cases if present)
infrastructure/
<feature>/ # 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_<code>.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 <device-id>
```
---
## 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 <repo-url-anda>
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/
<feature>/ # Entity, repo interface, (use-case bila ada)
infrastructure/
<feature>/ # 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_<kode>.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 <device-id>
```
---
## 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.
+1
View File
@@ -14,6 +14,7 @@ analyzer:
invalid_annotation_target: ignore
use_build_context_synchronously: ignore
deprecated_member_use: ignore
depend_on_referenced_packages: ignore
exclude:
- test/generated/**
- "**/**.g.dart"
+8 -2
View File
@@ -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.apskel.apskel_owner"
namespace = "com.apskel.enaklo_owner"
compileSdk = flutter.compileSdkVersion
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.apskel.apskel_owner"
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")
}
+48
View File
@@ -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"
}
+31 -1
View File
@@ -5,9 +5,15 @@
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<!-- FCM: required for POST_NOTIFICATIONS on Android 13+ -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!-- FCM: allow background processing after device reboot -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- FCM: allow wake lock for background message processing -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:label="Apskel Owner"
android:label="Enaklo Owner"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
<activity
@@ -37,6 +43,30 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- FCM: default notification channel for Android 8+ -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="high_importance_channel" />
<!-- FCM: default notification icon -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_notification" />
<!-- FCM: default notification color -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/notification_color" />
<!-- FCM: background message handler service -->
<service
android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false">
<intent-filter android:priority="-500">
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
@@ -1,4 +1,4 @@
package com.apskel.apskel_owner
package com.apskel.enaklo_owner
import io.flutter.embedding.android.FlutterActivity
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 37 KiB

@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#ffffff</color>
<!-- FCM: notification accent color -->
<color name="notification_color">#FF6B35</color>
</resources>
+1
View File
@@ -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")
Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 1.4 MiB

+1 -1
View File
@@ -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'
+181
View File
@@ -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
+145 -6
View File
@@ -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 = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
227E95442FB25185003AAE6C /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -55,13 +66,23 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
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 = "<group>"; };
/* 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 = "<group>";
};
4DBA9259FD070A034AF146BB /* Frameworks */ = {
isa = PBXGroup;
children = (
3B7ABC3D9AD3883EDD2E44FB /* Pods_Runner.framework */,
3A6F295F1D6E4BB0819A8681 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@@ -94,6 +124,8 @@
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
F771B77E516695BE7A4B0AEA /* Pods */,
4DBA9259FD070A034AF146BB /* Frameworks */,
);
sourceTree = "<group>";
};
@@ -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 = "<group>";
};
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 = "<group>";
};
/* 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;
+3
View File
@@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
+22
View File
@@ -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()
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 654 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 678 B

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 14 KiB

+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyCb6teTjGKytZmAZc2aMJrpaW484tm93jY</string>
<key>GCM_SENDER_ID</key>
<string>765730035527</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.apskel.enaklo</string>
<key>PROJECT_ID</key>
<string>apskel-pos-v2</string>
<key>STORAGE_BUCKET</key>
<string>apskel-pos-v2.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:765730035527:ios:c87f91e28b33766e241e62</string>
</dict>
</plist>
+7 -1
View File
@@ -5,7 +5,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Apskel Owner</string>
<string>Enaklo Owner</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@@ -45,5 +45,11 @@
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<!-- FCM: enable background fetch & remote notifications -->
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
</dict>
</plist>
@@ -14,7 +14,7 @@ class DashboardAnalyticLoaderState with _$DashboardAnalyticLoaderState {
DashboardAnalyticLoaderState(
dashboardAnalytic: DashboardAnalytic.empty(),
failureOptionDashboardAnalytic: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateFrom: DateTime.now(),
dateTo: DateTime.now(),
);
}
@@ -4,6 +4,8 @@ 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';
@@ -13,7 +15,11 @@ part 'login_form_bloc.freezed.dart';
@injectable
class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
final IAuthRepository _repository;
LoginFormBloc(this._repository) : super(LoginFormState.initial()) {
final DeviceInfoService _deviceInfoService;
final FcmService _fcmService;
LoginFormBloc(this._repository, this._deviceInfoService, this._fcmService)
: super(LoginFormState.initial()) {
on<LoginFormEvent>(_onLoginFormEvent);
}
@@ -36,9 +42,25 @@ class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
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(
@@ -30,6 +30,9 @@ class OrderLoaderBloc extends Bloc<OrderLoaderEvent, OrderLoaderState> {
searchChanged: (e) async {
emit(state.copyWith(search: e.search));
},
outletChanged: (e) async {
emit(state.copyWith(outletId: e.outletId));
},
fetched: (e) async {
var newState = state;
@@ -69,6 +72,7 @@ class OrderLoaderBloc extends Bloc<OrderLoaderEvent, OrderLoaderState> {
status: state.status == 'all' ? null : state.status,
page: state.page,
search: state.search,
outletId: state.outletId,
dateFrom: state.dateFrom,
dateTo: state.dateTo,
);
@@ -23,6 +23,7 @@ mixin _$OrderLoaderEvent {
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
@@ -30,6 +31,7 @@ mixin _$OrderLoaderEvent {
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
@@ -37,6 +39,7 @@ mixin _$OrderLoaderEvent {
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;
@@ -45,6 +48,7 @@ mixin _$OrderLoaderEvent {
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
@@ -52,6 +56,7 @@ mixin _$OrderLoaderEvent {
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
@@ -59,6 +64,7 @@ mixin _$OrderLoaderEvent {
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;
@@ -171,6 +177,7 @@ class _$RangeDateChangedImpl implements _RangeDateChanged {
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);
@@ -182,6 +189,7 @@ class _$RangeDateChangedImpl implements _RangeDateChanged {
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);
@@ -193,6 +201,7 @@ class _$RangeDateChangedImpl implements _RangeDateChanged {
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(),
}) {
@@ -208,6 +217,7 @@ class _$RangeDateChangedImpl implements _RangeDateChanged {
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);
@@ -219,6 +229,7 @@ class _$RangeDateChangedImpl implements _RangeDateChanged {
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);
@@ -230,6 +241,7 @@ class _$RangeDateChangedImpl implements _RangeDateChanged {
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(),
}) {
@@ -330,6 +342,7 @@ class _$StatusChangedImpl implements _StatusChanged {
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);
@@ -341,6 +354,7 @@ class _$StatusChangedImpl implements _StatusChanged {
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);
@@ -352,6 +366,7 @@ class _$StatusChangedImpl implements _StatusChanged {
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(),
}) {
@@ -367,6 +382,7 @@ class _$StatusChangedImpl implements _StatusChanged {
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);
@@ -378,6 +394,7 @@ class _$StatusChangedImpl implements _StatusChanged {
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);
@@ -389,6 +406,7 @@ class _$StatusChangedImpl implements _StatusChanged {
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(),
}) {
@@ -485,6 +503,7 @@ class _$SearchChangedImpl implements _SearchChanged {
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);
@@ -496,6 +515,7 @@ class _$SearchChangedImpl implements _SearchChanged {
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);
@@ -507,6 +527,7 @@ class _$SearchChangedImpl implements _SearchChanged {
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(),
}) {
@@ -522,6 +543,7 @@ class _$SearchChangedImpl implements _SearchChanged {
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);
@@ -533,6 +555,7 @@ class _$SearchChangedImpl implements _SearchChanged {
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);
@@ -544,6 +567,7 @@ class _$SearchChangedImpl implements _SearchChanged {
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(),
}) {
@@ -566,6 +590,168 @@ abstract class _SearchChanged implements OrderLoaderEvent {
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<TResult extends Object?>({
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 extends Object?>({
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 extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
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 extends Object?>({
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(
@@ -642,6 +828,7 @@ class _$FetchedImpl implements _Fetched {
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);
@@ -653,6 +840,7 @@ class _$FetchedImpl implements _Fetched {
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);
@@ -664,6 +852,7 @@ class _$FetchedImpl implements _Fetched {
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(),
}) {
@@ -679,6 +868,7 @@ class _$FetchedImpl implements _Fetched {
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);
@@ -690,6 +880,7 @@ class _$FetchedImpl implements _Fetched {
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);
@@ -701,6 +892,7 @@ class _$FetchedImpl implements _Fetched {
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(),
}) {
@@ -730,6 +922,7 @@ mixin _$OrderLoaderState {
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;
@@ -755,6 +948,7 @@ abstract class $OrderLoaderStateCopyWith<$Res> {
Option<OrderFailure> failureOptionOrder,
String status,
String? search,
String? outletId,
bool isFetching,
bool hasReachedMax,
int page,
@@ -782,6 +976,7 @@ class _$OrderLoaderStateCopyWithImpl<$Res, $Val extends OrderLoaderState>
Object? failureOptionOrder = null,
Object? status = null,
Object? search = freezed,
Object? outletId = freezed,
Object? isFetching = null,
Object? hasReachedMax = null,
Object? page = null,
@@ -806,6 +1001,10 @@ class _$OrderLoaderStateCopyWithImpl<$Res, $Val extends OrderLoaderState>
? _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
@@ -846,6 +1045,7 @@ abstract class _$$OrderLoaderStateImplCopyWith<$Res>
Option<OrderFailure> failureOptionOrder,
String status,
String? search,
String? outletId,
bool isFetching,
bool hasReachedMax,
int page,
@@ -872,6 +1072,7 @@ class __$$OrderLoaderStateImplCopyWithImpl<$Res>
Object? failureOptionOrder = null,
Object? status = null,
Object? search = freezed,
Object? outletId = freezed,
Object? isFetching = null,
Object? hasReachedMax = null,
Object? page = null,
@@ -896,6 +1097,10 @@ class __$$OrderLoaderStateImplCopyWithImpl<$Res>
? _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
@@ -929,6 +1134,7 @@ class _$OrderLoaderStateImpl implements _OrderLoaderState {
required this.failureOptionOrder,
required this.status,
this.search,
this.outletId,
this.isFetching = false,
this.hasReachedMax = false,
this.page = 1,
@@ -951,6 +1157,8 @@ class _$OrderLoaderStateImpl implements _OrderLoaderState {
@override
final String? search;
@override
final String? outletId;
@override
@JsonKey()
final bool isFetching;
@override
@@ -966,7 +1174,7 @@ class _$OrderLoaderStateImpl implements _OrderLoaderState {
@override
String toString() {
return 'OrderLoaderState(orders: $orders, failureOptionOrder: $failureOptionOrder, status: $status, search: $search, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page, dateFrom: $dateFrom, dateTo: $dateTo)';
return 'OrderLoaderState(orders: $orders, failureOptionOrder: $failureOptionOrder, status: $status, search: $search, outletId: $outletId, isFetching: $isFetching, hasReachedMax: $hasReachedMax, page: $page, dateFrom: $dateFrom, dateTo: $dateTo)';
}
@override
@@ -979,6 +1187,8 @@ class _$OrderLoaderStateImpl implements _OrderLoaderState {
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) ||
@@ -996,6 +1206,7 @@ class _$OrderLoaderStateImpl implements _OrderLoaderState {
failureOptionOrder,
status,
search,
outletId,
isFetching,
hasReachedMax,
page,
@@ -1021,6 +1232,7 @@ abstract class _OrderLoaderState implements OrderLoaderState {
required final Option<OrderFailure> failureOptionOrder,
required final String status,
final String? search,
final String? outletId,
final bool isFetching,
final bool hasReachedMax,
final int page,
@@ -1037,6 +1249,8 @@ abstract class _OrderLoaderState implements OrderLoaderState {
@override
String? get search;
@override
String? get outletId;
@override
bool get isFetching;
@override
bool get hasReachedMax;
@@ -8,6 +8,8 @@ class OrderLoaderEvent with _$OrderLoaderEvent {
) = _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;
}
@@ -7,6 +7,7 @@ class OrderLoaderState with _$OrderLoaderState {
required Option<OrderFailure> failureOptionOrder,
required String status,
String? search,
String? outletId,
@Default(false) bool isFetching,
@Default(false) bool hasReachedMax,
@Default(1) int page,
@@ -17,7 +18,7 @@ class OrderLoaderState with _$OrderLoaderState {
factory OrderLoaderState.initial() => OrderLoaderState(
orders: [],
failureOptionOrder: none(),
dateFrom: DateTime.now().subtract(const Duration(days: 30)),
dateFrom: DateTime.now(),
dateTo: DateTime.now(),
status: 'all',
);
@@ -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<OutletListLoaderEvent, OutletListLoaderState> {
final IOutletRepository _outletRepository;
OutletListLoaderBloc(this._outletRepository)
: super(OutletListLoaderState.initial()) {
on<OutletListLoaderEvent>(_onOutletListLoaderEvent);
}
Future<void> _onOutletListLoaderEvent(
OutletListLoaderEvent event,
Emitter<OutletListLoaderState> 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<OutletListLoaderState> _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;
}
}
@@ -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>(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<TResult extends Object?>({
required TResult Function(String search) searchChanged,
required TResult Function(bool? isActive) isActiveChanged,
required TResult Function(bool isRefresh) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String search)? searchChanged,
TResult? Function(bool? isActive)? isActiveChanged,
TResult? Function(bool isRefresh)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String search)? searchChanged,
TResult Function(bool? isActive)? isActiveChanged,
TResult Function(bool isRefresh)? fetched,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_SearchChanged value) searchChanged,
required TResult Function(_IsActiveChanged value) isActiveChanged,
required TResult Function(_Fetched value) fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_SearchChanged value)? searchChanged,
TResult? Function(_IsActiveChanged value)? isActiveChanged,
TResult? Function(_Fetched value)? fetched,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(String search)? searchChanged,
TResult? Function(bool? isActive)? isActiveChanged,
TResult? Function(bool isRefresh)? fetched,
}) {
return searchChanged?.call(search);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(_SearchChanged value)? searchChanged,
TResult? Function(_IsActiveChanged value)? isActiveChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return searchChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(String search)? searchChanged,
TResult? Function(bool? isActive)? isActiveChanged,
TResult? Function(bool isRefresh)? fetched,
}) {
return isActiveChanged?.call(isActive);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(_SearchChanged value)? searchChanged,
TResult? Function(_IsActiveChanged value)? isActiveChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return isActiveChanged?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(String search)? searchChanged,
TResult? Function(bool? isActive)? isActiveChanged,
TResult? Function(bool isRefresh)? fetched,
}) {
return fetched?.call(isRefresh);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(_SearchChanged value)? searchChanged,
TResult? Function(_IsActiveChanged value)? isActiveChanged,
TResult? Function(_Fetched value)? fetched,
}) {
return fetched?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<Outlet> get outlets => throw _privateConstructorUsedError;
Option<OutletFailure> 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<OutletListLoaderState> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $OutletListLoaderStateCopyWith<$Res> {
factory $OutletListLoaderStateCopyWith(
OutletListLoaderState value,
$Res Function(OutletListLoaderState) then,
) = _$OutletListLoaderStateCopyWithImpl<$Res, OutletListLoaderState>;
@useResult
$Res call({
List<Outlet> outlets,
Option<OutletFailure> 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<Outlet>,
failureOptionOutlet: null == failureOptionOutlet
? _value.failureOptionOutlet
: failureOptionOutlet // ignore: cast_nullable_to_non_nullable
as Option<OutletFailure>,
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<Outlet> outlets,
Option<OutletFailure> 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<Outlet>,
failureOptionOutlet: null == failureOptionOutlet
? _value.failureOptionOutlet
: failureOptionOutlet // ignore: cast_nullable_to_non_nullable
as Option<OutletFailure>,
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<Outlet> outlets,
required this.failureOptionOutlet,
this.search,
this.isActive,
this.isFetching = false,
this.hasReachedMax = false,
this.page = 1,
}) : _outlets = outlets;
final List<Outlet> _outlets;
@override
List<Outlet> get outlets {
if (_outlets is EqualUnmodifiableListView) return _outlets;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_outlets);
}
@override
final Option<OutletFailure> 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<Outlet> outlets,
required final Option<OutletFailure> failureOptionOutlet,
final String? search,
final bool? isActive,
final bool isFetching,
final bool hasReachedMax,
final int page,
}) = _$OutletListLoaderStateImpl;
@override
List<Outlet> get outlets;
@override
Option<OutletFailure> 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;
}
@@ -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;
}
@@ -0,0 +1,17 @@
part of 'outlet_list_loader_bloc.dart';
@freezed
class OutletListLoaderState with _$OutletListLoaderState {
const factory OutletListLoaderState({
required List<Outlet> outlets,
required Option<OutletFailure> 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());
}
@@ -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<SelectedOutletEvent, SelectedOutletState> {
final OutletLocalDataProvider _localDataProvider;
SelectedOutletBloc(this._localDataProvider)
: super(SelectedOutletState.initial()) {
on<SelectedOutletEvent>(_onSelectedOutletEvent);
}
Future<void> _onSelectedOutletEvent(
SelectedOutletEvent event,
Emitter<SelectedOutletState> 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());
},
);
}
}
@@ -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>(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<TResult extends Object?>({
required TResult Function() loaded,
required TResult Function(Outlet outlet) selected,
required TResult Function() cleared,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? loaded,
TResult? Function(Outlet outlet)? selected,
TResult? Function()? cleared,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? loaded,
TResult Function(Outlet outlet)? selected,
TResult Function()? cleared,
required TResult orElse(),
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Loaded value) loaded,
required TResult Function(_Selected value) selected,
required TResult Function(_Cleared value) cleared,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Loaded value)? loaded,
TResult? Function(_Selected value)? selected,
TResult? Function(_Cleared value)? cleared,
}) => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<TResult extends Object?>({
required TResult Function() loaded,
required TResult Function(Outlet outlet) selected,
required TResult Function() cleared,
}) {
return loaded();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? loaded,
TResult? Function(Outlet outlet)? selected,
TResult? Function()? cleared,
}) {
return loaded?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(_Loaded value)? loaded,
TResult? Function(_Selected value)? selected,
TResult? Function(_Cleared value)? cleared,
}) {
return loaded?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<TResult extends Object?>({
required TResult Function() loaded,
required TResult Function(Outlet outlet) selected,
required TResult Function() cleared,
}) {
return selected(outlet);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? loaded,
TResult? Function(Outlet outlet)? selected,
TResult? Function()? cleared,
}) {
return selected?.call(outlet);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(_Loaded value)? loaded,
TResult? Function(_Selected value)? selected,
TResult? Function(_Cleared value)? cleared,
}) {
return selected?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<TResult extends Object?>({
required TResult Function() loaded,
required TResult Function(Outlet outlet) selected,
required TResult Function() cleared,
}) {
return cleared();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? loaded,
TResult? Function(Outlet outlet)? selected,
TResult? Function()? cleared,
}) {
return cleared?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
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<TResult extends Object?>({
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 extends Object?>({
TResult? Function(_Loaded value)? loaded,
TResult? Function(_Selected value)? selected,
TResult? Function(_Cleared value)? cleared,
}) {
return cleared?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
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<SelectedOutletState> 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;
}
@@ -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;
}
@@ -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';
}
+1 -1
View File
@@ -1,3 +1,3 @@
class AppConstant {
static const String appName = "Apskel Owner";
static const String appName = "Enaklo Owner";
}
@@ -2,4 +2,5 @@ class LocalStorageKey {
static const String lang = 'lang';
static const String token = 'token';
static const String user = 'user';
static const String selectedOutletId = 'selected_outlet_id';
}
+8
View File
@@ -0,0 +1,8 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:injectable/injectable.dart';
@module
abstract class FirebaseDi {
@preResolve
Future<FirebaseApp> get firebaseApp => Firebase.initializeApp();
}
+5
View File
@@ -30,4 +30,9 @@ extension DateTimeIndonesia on DateTime {
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);
}
}
+5 -6
View File
@@ -2,9 +2,9 @@ part of 'theme.dart';
class AppColor {
// Primary Colors
static const Color primary = Color(0xFF36175e);
static const Color primaryLight = Color(0xFF5a2d85);
static const Color primaryDark = Color(0xFF1e0d35);
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);
@@ -41,10 +41,9 @@ class AppColor {
// Gradient Colors
static const List<Color> primaryGradient = [
Color(0xFF36175e),
Color(0xFF5a2d85),
Color(0xFFD90000), // primary
Color(0xFF990000), // dark red
];
static const List<Color> successGradient = [
Color(0xFF4CAF50),
Color(0xFF81C784),
+82
View File
@@ -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<String, dynamic> 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<DeviceInfo> 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';
}
}
+200
View File
@@ -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<void> 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<void> _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<void> 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<void> _requestPermission() async {
final settings = await _messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
debugPrint('[FCM] Permission status: ${settings.authorizationStatus}');
}
Future<void> _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<String?> getToken() => _messaging.getToken();
/// Subscribe to a topic (e.g. 'all', 'promo').
Future<void> subscribeToTopic(String topic) =>
_messaging.subscribeToTopic(topic);
/// Unsubscribe from a topic.
Future<void> unsubscribeFromTopic(String topic) =>
_messaging.unsubscribeFromTopic(topic);
/// Listen for token refresh.
Stream<String> get onTokenRefresh => _messaging.onTokenRefresh;
}
@@ -6,35 +6,42 @@ abstract class IAnalyticRepository {
Future<Either<AnalyticFailure, SalesAnalytic>> getSales({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
Future<Either<AnalyticFailure, ProfitLossAnalytic>> getProfitLoss({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
Future<Either<AnalyticFailure, CategoryAnalytic>> getCategory({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
Future<Either<AnalyticFailure, InventoryAnalytic>> getInventory({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
Future<Either<AnalyticFailure, DashboardAnalytic>> getDashboard({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
Future<Either<AnalyticFailure, ProductAnalytic>> getProduct({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
Future<Either<AnalyticFailure, PaymentMethodAnalytic>> getPaymentMethod({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
});
}
@@ -4,6 +4,13 @@ abstract class IAuthRepository {
Future<Either<AuthFailure, Auth>> 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<bool> hasToken();
Future<Either<AuthFailure, User>> currentUser();
@@ -6,6 +6,7 @@ abstract class IOrderRepository {
int limit = 10,
String? status,
String? search,
String? outletId,
required DateTime dateFrom,
required DateTime dateTo,
});
@@ -2,4 +2,11 @@ part of '../outlet.dart';
abstract class IOutletRepository {
Future<Either<OutletFailure, Outlet>> currentOutlet();
Future<Either<OutletFailure, List<Outlet>>> getList({
int page = 1,
int limit = 10,
String? search,
bool? isActive,
});
}
+2 -2
View File
@@ -9,12 +9,12 @@ abstract class Env {
@dev
class DevEnv implements Env {
@override
String get baseUrl => 'https://enaklo-pos-be.altru.id'; // example value
String get baseUrl => 'https://api-pos.apskel.id'; // example value
}
@Injectable(as: Env)
@prod
class ProdEnv implements Env {
@override
String get baseUrl => 'https://enaklo-pos-be.altru.id';
String get baseUrl => 'https://api-pos.apskel.id';
}
@@ -21,14 +21,18 @@ class AnalyticRemoteDataProvider {
Future<DC<AnalyticFailure, SalesAnalyticDto>> fetchSales({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final response = await _apiClient.get(
ApiPath.salesAnalytic,
params: {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
},
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.salesAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
@@ -48,14 +52,18 @@ class AnalyticRemoteDataProvider {
Future<DC<AnalyticFailure, ProfitLossAnalyticDto>> fetchProfitLoss({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final response = await _apiClient.get(
ApiPath.profitLossAnalytic,
params: {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
},
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.profitLossAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
@@ -75,14 +83,18 @@ class AnalyticRemoteDataProvider {
Future<DC<AnalyticFailure, CategoryAnalyticDto>> fetchCategory({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final response = await _apiClient.get(
ApiPath.categoryAnalytic,
params: {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
},
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.categoryAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
@@ -128,17 +140,20 @@ class AnalyticRemoteDataProvider {
}
Future<DC<AnalyticFailure, DashboardAnalyticDto>> fetchDashboard({
required String outletId,
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final response = await _apiClient.get(
ApiPath.dashboardAnalytic,
params: {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
},
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.dashboardAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
@@ -156,17 +171,20 @@ class AnalyticRemoteDataProvider {
}
Future<DC<AnalyticFailure, ProductAnalyticDto>> fetchProduct({
required String outletId,
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final response = await _apiClient.get(
ApiPath.productAnalytic,
params: {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
},
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.productAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
@@ -184,17 +202,20 @@ class AnalyticRemoteDataProvider {
}
Future<DC<AnalyticFailure, PaymentMethodAnalyticDto>> fetchPaymentMethod({
required String outletId,
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
final response = await _apiClient.get(
ApiPath.paymentMethodAnalytic,
params: {
final Map<String, dynamic> params = {
'date_from': dateFrom.toServerDate,
'date_to': dateTo.toServerDate,
},
};
if (outletId != null) params['outlet_id'] = outletId;
final response = await _apiClient.get(
ApiPath.paymentMethodAnalytic,
params: params,
headers: getAuthorizationHeader(),
);
@@ -5,36 +5,43 @@ import 'package:injectable/injectable.dart';
import '../../../domain/analytic/analytic.dart';
import '../../../domain/analytic/repositories/i_analytic_repository.dart';
import '../../../domain/user/user.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);
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<Either<AnalyticFailure, SalesAnalytic>> 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!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -45,20 +52,17 @@ class AnalyticRepository implements IAnalyticRepository {
Future<Either<AnalyticFailure, ProfitLossAnalytic>> 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!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -69,20 +73,17 @@ class AnalyticRepository implements IAnalyticRepository {
Future<Either<AnalyticFailure, CategoryAnalytic>> 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!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -93,23 +94,20 @@ class AnalyticRepository implements IAnalyticRepository {
Future<Either<AnalyticFailure, InventoryAnalytic>> getInventory({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
User currentUser = await _authLocalDataProvider.currentUser();
final currentUser = await _authLocalDataProvider.currentUser();
final resolvedId = _resolveOutletId(outletId) ?? currentUser.outletId;
final result = await _dataProvider.fetchInventory(
outletId: currentUser.outletId,
outletId: resolvedId,
dateFrom: dateFrom,
dateTo: dateTo,
);
if (result.hasError) {
return left(result.error!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -120,23 +118,17 @@ class AnalyticRepository implements IAnalyticRepository {
Future<Either<AnalyticFailure, DashboardAnalytic>> getDashboard({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
User currentUser = await _authLocalDataProvider.currentUser();
final result = await _dataProvider.fetchDashboard(
outletId: currentUser.outletId,
dateFrom: dateFrom,
dateTo: dateTo,
outletId: _resolveOutletId(outletId),
);
if (result.hasError) {
return left(result.error!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -147,23 +139,17 @@ class AnalyticRepository implements IAnalyticRepository {
Future<Either<AnalyticFailure, ProductAnalytic>> getProduct({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
User currentUser = await _authLocalDataProvider.currentUser();
final result = await _dataProvider.fetchProduct(
outletId: currentUser.outletId,
dateFrom: dateFrom,
dateTo: dateTo,
outletId: _resolveOutletId(outletId),
);
if (result.hasError) {
return left(result.error!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -174,23 +160,17 @@ class AnalyticRepository implements IAnalyticRepository {
Future<Either<AnalyticFailure, PaymentMethodAnalytic>> getPaymentMethod({
required DateTime dateFrom,
required DateTime dateTo,
String? outletId,
}) async {
try {
User currentUser = await _authLocalDataProvider.currentUser();
final result = await _dataProvider.fetchPaymentMethod(
outletId: currentUser.outletId,
dateFrom: dateFrom,
dateTo: dateTo,
outletId: _resolveOutletId(outletId),
);
if (result.hasError) {
return left(result.error!);
}
final auth = result.data!.toDomain();
return right(auth);
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());
@@ -21,11 +21,28 @@ class AuthRemoteDataProvider {
Future<DC<AuthFailure, AuthDto>> 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},
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) {
@@ -21,11 +21,25 @@ class AuthRepository implements IAuthRepository {
Future<Either<AuthFailure, Auth>> 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) {
@@ -23,6 +23,7 @@ class OrderRemoteDataProvider {
int limit = 10,
String? status,
String? search,
String? outletId,
required DateTime dateFrom,
required DateTime dateTo,
}) async {
@@ -42,6 +43,10 @@ class OrderRemoteDataProvider {
params['search'] = search;
}
// if (outletId != null) {
// params['outlet_id'] = outletId;
// }
final response = await _apiClient.get(
ApiPath.order,
params: params,
@@ -4,14 +4,16 @@ 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);
OrderRepository(this._dataProvider, this._outletLocalDataProvider);
@override
Future<Either<OrderFailure, List<Order>>> get({
@@ -19,15 +21,20 @@ class OrderRepository implements IOrderRepository {
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,
);
@@ -36,9 +43,9 @@ class OrderRepository implements IOrderRepository {
return left(result.error!);
}
final auth = result.data!.map((e) => e.toDomain()).toList();
final orders = result.data!.map((e) => e.toDomain()).toList();
return right(auth);
return right(orders);
} catch (e, s) {
log('getOrderError', name: _logName, error: e, stackTrace: s);
return left(const OrderFailure.unexpectedError());
@@ -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<void> saveSelectedOutletId(String outletId) async {
await _sharedPreferences.setString(
LocalStorageKey.selectedOutletId,
outletId,
);
}
String? getSelectedOutletId() {
return _sharedPreferences.getString(LocalStorageKey.selectedOutletId);
}
Future<void> deleteSelectedOutletId() async {
await _sharedPreferences.remove(LocalStorageKey.selectedOutletId);
}
}
@@ -36,4 +36,39 @@ class OutletRemoteDataProvider {
return DC.error(OutletFailure.serverError(e));
}
}
Future<DC<OutletFailure, List<OutletDto>>> fetchList({
int page = 1,
int limit = 10,
String? search,
bool? isActive,
}) async {
try {
final Map<String, dynamic> 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));
}
}
}
@@ -33,4 +33,32 @@ class OutletRepository implements IOutletRepository {
return left(const OutletFailure.unexpectedError());
}
}
@override
Future<Either<OutletFailure, List<Outlet>>> 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());
}
}
}
+85 -48
View File
@@ -39,6 +39,10 @@ import 'package:apskel_owner_flutter/application/order/order_loader/order_loader
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'
@@ -53,11 +57,15 @@ 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;
@@ -90,6 +98,8 @@ import 'package:apskel_owner_flutter/infrastructure/order/datasource/remote_data
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'
@@ -106,6 +116,7 @@ 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;
@@ -121,22 +132,29 @@ 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>()),
);
@@ -147,46 +165,49 @@ extension GetItInjectableX on _i174.GetIt {
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<_i130.OrderRemoteDataProvider>(
() => _i130.OrderRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i333.CategoryRemoteDataProvider>(
() => _i333.CategoryRemoteDataProvider(gh<_i115.ApiClient>()),
gh.factory<_i866.AnalyticRemoteDataProvider>(
() => _i866.AnalyticRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i17.AuthRemoteDataProvider>(
() => _i17.AuthRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i785.UserRemoteDataProvider>(
() => _i785.UserRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i823.ProductRemoteDataProvider>(
() => _i823.ProductRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i27.OutletRemoteDataProvider>(
() => _i27.OutletRemoteDataProvider(gh<_i115.ApiClient>()),
);
gh.factory<_i866.AnalyticRemoteDataProvider>(
() => _i866.AnalyticRemoteDataProvider(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<_i219.IOrderRepository>(
() => _i641.OrderRepository(gh<_i130.OrderRemoteDataProvider>()),
);
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>(),
@@ -196,15 +217,15 @@ extension GetItInjectableX on _i174.GetIt {
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<_i477.IAnalyticRepository>(
() => _i393.AnalyticRepository(
gh<_i866.AnalyticRemoteDataProvider>(),
gh<_i991.AuthLocalDataProvider>(),
),
);
gh.factory<_i1020.ICategoryRepository>(
() => _i869.CategoryRepository(gh<_i333.CategoryRemoteDataProvider>()),
);
@@ -220,17 +241,30 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i183.CategoryLoaderBloc>(
() => _i183.CategoryLoaderBloc(gh<_i1020.ICategoryRepository>()),
);
gh.factory<_i473.HomeBloc>(
() => _i473.HomeBloc(gh<_i477.IAnalyticRepository>()),
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<_i221.ProductAnalyticLoaderBloc>(
() => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
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>()),
@@ -240,18 +274,12 @@ extension GetItInjectableX on _i174.GetIt {
gh<_i477.IAnalyticRepository>(),
),
);
gh.factory<_i1038.CategoryAnalyticLoaderBloc>(
() => _i1038.CategoryAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
gh.factory<_i221.ProductAnalyticLoaderBloc>(
() => _i221.ProductAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i11.ProfitLossLoaderBloc>(
() => _i11.ProfitLossLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i516.DashboardAnalyticLoaderBloc>(
() => _i516.DashboardAnalyticLoaderBloc(gh<_i477.IAnalyticRepository>()),
);
gh.factory<_i775.LoginFormBloc>(
() => _i775.LoginFormBloc(gh<_i49.IAuthRepository>()),
);
gh.factory<_i945.AuthBloc>(
() => _i945.AuthBloc(gh<_i49.IAuthRepository>()),
);
@@ -261,16 +289,17 @@ extension GetItInjectableX on _i174.GetIt {
gh.factory<_i1058.OrderLoaderBloc>(
() => _i1058.OrderLoaderBloc(gh<_i219.IOrderRepository>()),
);
gh.factory<_i147.UserEditFormBloc>(
() => _i147.UserEditFormBloc(gh<_i635.IUserRepository>()),
);
gh.factory<_i1030.ChangePasswordFormBloc>(
() => _i1030.ChangePasswordFormBloc(gh<_i635.IUserRepository>()),
);
gh.factory<_i605.TransactionReportBloc>(
() => _i605.TransactionReportBloc(
gh<_i477.IAnalyticRepository>(),
gh<_i197.IOutletRepository>(),
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>(
@@ -279,16 +308,24 @@ extension GetItInjectableX on _i174.GetIt {
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 {}
+383 -1
View File
@@ -49,5 +49,387 @@
"profile": "Profile",
"@profile": {},
"sales_today": "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": {}
}
+383 -1
View File
@@ -49,5 +49,387 @@
"profile": "Profil",
"@profile": {},
"sales_today": "Penjualan hari ini",
"@sales_today": {}
"@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": {}
}
File diff suppressed because it is too large Load Diff
+539
View File
@@ -82,4 +82,543 @@ class AppLocalizationsEn extends AppLocalizations {
@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';
}
+539
View File
@@ -82,4 +82,543 @@ class AppLocalizationsId extends AppLocalizations {
@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';
}
+8
View File
@@ -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<FcmService>().initialize(
onMessageTap: (message) {
debugPrint('[FCM] Navigate based on: ${message.data}');
},
);
runApp(const AppWidget());
}
+51 -123
View File
@@ -1,76 +1,21 @@
import 'package:flutter/material.dart';
import 'dart:math' as math;
import '../../../../common/theme/theme.dart';
import '../../../common/painter/wave_painter.dart';
import '../../../common/theme/theme.dart';
class CustomAppBar extends StatefulWidget {
class CustomAppBar extends StatelessWidget {
final String title;
final bool isBack;
const CustomAppBar({super.key, required this.title, this.isBack = true});
@override
State<CustomAppBar> createState() => _CustomAppBarState();
}
class _CustomAppBarState extends State<CustomAppBar>
with TickerProviderStateMixin {
late AnimationController _particleController;
late AnimationController _waveController;
late AnimationController _breathController;
late Animation<double> _particleAnimation;
late Animation<double> _waveAnimation;
late Animation<double> _breathAnimation;
@override
void initState() {
super.initState();
_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);
_particleAnimation = Tween<double>(
begin: 0.0,
end: 2 * math.pi,
).animate(_particleController);
_waveAnimation = Tween<double>(
begin: 0.0,
end: 2 * math.pi,
).animate(_waveController);
_breathAnimation = Tween<double>(begin: 0.8, end: 1.2).animate(
CurvedAnimation(parent: _breathController, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_particleController.dispose();
_waveController.dispose();
_breathController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return FlexibleSpaceBar(
titlePadding: EdgeInsets.only(left: widget.isBack ? 50 : 20, bottom: 16),
titlePadding: EdgeInsets.only(left: isBack ? 50 : 20, bottom: 16),
title: Text(
widget.title,
title,
style: AppStyle.xl.copyWith(
color: AppColor.textWhite,
fontSize: 18,
@@ -85,90 +30,71 @@ class _CustomAppBarState extends State<CustomAppBar>
end: Alignment.bottomCenter,
),
),
child: AnimatedBuilder(
animation: Listenable.merge([
_particleController,
_waveController,
_breathController,
]),
builder: (context, child) {
return Stack(
child: Stack(
children: [
// Animated background elements
_buildAnimatedBackground(context),
],
);
},
),
),
);
}
Widget _buildAnimatedBackground(BuildContext context) {
final size = MediaQuery.of(context).size;
return Stack(
children: [
// Floating particles with orbital motion
...List.generate(8, (index) {
final double radius = 40 + (index * 15);
final double angle = _particleAnimation.value + (index * 0.8);
final double centerX = size.width * 0.7;
final double centerY = 60;
return Positioned(
left: centerX + math.cos(angle) * radius - 3,
top: centerY + math.sin(angle) * (radius * 0.5) - 3,
child: Transform.scale(
scale: _breathAnimation.value * 0.5,
// Static decorative circles (right side)
Positioned(
top: -20,
right: -30,
child: Container(
width: 4 + (index % 3),
height: 4 + (index % 3),
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColor.textWhite.withOpacity(0.6),
boxShadow: [
BoxShadow(
color: AppColor.textWhite.withOpacity(0.3),
blurRadius: 6,
spreadRadius: 1,
),
],
color: AppColor.textWhite.withOpacity(0.08),
),
),
),
);
}),
// Wave patterns
Positioned.fill(
child: CustomPaint(
painter: WavePainter(
animation: _waveAnimation.value,
color: AppColor.textWhite.withOpacity(0.1),
Positioned(
top: 30,
right: 20,
child: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColor.textWhite.withOpacity(0.05),
),
),
),
// Sparkle effects
// 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: 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: 10 + (index % 3) * 3,
color: AppColor.textWhite.withOpacity(0.4),
),
),
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(
@@ -184,6 +110,8 @@ class _CustomAppBarState extends State<CustomAppBar>
),
),
],
),
),
);
}
}
@@ -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<AssetGenImage> 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<AssetGenImage> get values => [logo];
List<AssetGenImage> get values => [icNotification, logo];
}
class Assets {
const Assets._();
static const $AssetsIconsGen icons = $AssetsIconsGen();
static const $AssetsImagesGen images = $AssetsImagesGen();
}
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
import '../../../common/extension/extension.dart';
class DateRangePickerBottomSheet {
static Future<DateRangePickerSelectionChangedArgs?> show({
required BuildContext context,
@@ -9,8 +11,8 @@ class DateRangePickerBottomSheet {
DateTime? initialEndDate,
DateTime? minDate,
DateTime? maxDate,
String confirmText = 'Pilih',
String cancelText = 'Batal',
String? confirmText,
String? cancelText,
Color primaryColor = Colors.blue,
Function(DateTime? startDate, DateTime? endDate)? onChanged,
}) async {
@@ -26,8 +28,8 @@ class DateRangePickerBottomSheet {
initialEndDate: initialEndDate,
minDate: minDate,
maxDate: maxDate,
confirmText: confirmText,
cancelText: cancelText,
confirmText: confirmText ?? context.lang.select,
cancelText: cancelText ?? context.lang.cancel,
primaryColor: primaryColor,
onChanged: onChanged,
),
@@ -104,7 +106,7 @@ class _DateRangePickerBottomSheetState
return _formatDate(range.startDate!);
}
}
return 'Belum ada tanggal dipilih';
return context.lang.no_date_selected;
}
String _formatDate(DateTime date) {
@@ -187,7 +189,7 @@ class _DateRangePickerBottomSheetState
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tanggal Terpilih:',
'${context.lang.selected_date}:',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
@@ -1,6 +1,7 @@
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';
@@ -22,7 +23,7 @@ class DateRangePickerField extends StatefulWidget {
final double height;
const DateRangePickerField({
Key? key,
super.key,
this.label,
this.placeholder = 'Pilih rentang tanggal',
this.startDate,
@@ -38,7 +39,7 @@ class DateRangePickerField extends StatefulWidget {
this.placeholderStyle,
this.decoration,
this.height = 52.0,
}) : super(key: key);
});
@override
State<DateRangePickerField> createState() => _DateRangePickerFieldState();
@@ -83,7 +84,7 @@ class _DateRangePickerFieldState extends State<DateRangePickerField> {
final result = await DateRangePickerBottomSheet.show(
context: context,
title: widget.label ?? 'Pilih Rentang Tanggal',
title: widget.label ?? context.lang.select_date_range,
initialStartDate: widget.startDate,
initialEndDate: widget.endDate,
minDate: widget.minDate,
@@ -294,7 +295,7 @@ class _DateRangePickerFieldOutlinedState
final result = await DateRangePickerBottomSheet.show(
context: context,
title: widget.label ?? 'Pilih Rentang Tanggal',
title: widget.label ?? context.lang.select_date_range,
initialStartDate: widget.startDate,
initialEndDate: widget.endDate,
minDate: widget.minDate,
@@ -412,120 +413,3 @@ class _DateRangePickerFieldOutlinedState
);
}
}
// Usage Example Widget
class DateRangePickerExample extends StatefulWidget {
@override
_DateRangePickerExampleState createState() => _DateRangePickerExampleState();
}
class _DateRangePickerExampleState extends State<DateRangePickerExample> {
DateTime? _startDate;
DateTime? _endDate;
DateTime? _startDate2;
DateTime? _endDate2;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Date Range Picker Example'),
backgroundColor: AppColor.primary,
foregroundColor: AppColor.white,
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Default Style',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
const SizedBox(height: 16),
DateRangePickerField(
label: 'Periode Laporan',
placeholder: 'Pilih tanggal mulai - selesai',
startDate: _startDate,
endDate: _endDate,
primaryColor: AppColor.primary,
onChanged: (start, end) {
setState(() {
_startDate = start;
_endDate = end;
});
},
),
const SizedBox(height: 32),
Text(
'Outlined Style',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColor.textPrimary,
),
),
const SizedBox(height: 16),
DateRangePickerFieldOutlined(
label: 'Rentang Waktu',
placeholder: 'Pilih rentang tanggal',
startDate: _startDate2,
endDate: _endDate2,
primaryColor: AppColor.secondary,
onChanged: (start, end) {
setState(() {
_startDate2 = start;
_endDate2 = end;
});
},
),
const SizedBox(height: 24),
// Display selected dates
if (_startDate != null ||
_endDate != null ||
_startDate2 != null ||
_endDate2 != null)
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColor.background,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Selected Dates:',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
const SizedBox(height: 8),
if (_startDate != null)
Text(
'Default: ${_startDate!} - ${_endDate ?? 'Not selected'}',
),
if (_startDate2 != null)
Text(
'Outlined: ${_startDate2!} - ${_endDate2 ?? 'Not selected'}',
),
],
),
),
],
),
),
);
}
}
@@ -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<Color>? 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<Widget> _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),
),
);
});
}
}

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