Merge branch 'dev' into authentication-web

This commit is contained in:
dhinesh-m24
2026-02-04 11:58:21 +05:30
committed by GitHub
371 changed files with 19516 additions and 16134 deletions

10
.gitignore vendored
View File

@@ -18,7 +18,6 @@ $RECYCLE.BIN/
# IDE & Editors # IDE & Editors
.idea/ .idea/
.vscode/
*.iml *.iml
*.iws *.iws
*.swp *.swp
@@ -111,6 +110,9 @@ vite.config.ts.timestamp-*
.flutter-plugins .flutter-plugins
.flutter-plugins-dependencies .flutter-plugins-dependencies
# Firebase Data Connect Generated SDK (regenerated via make mobile-install)
**/dataconnect_generated/
# Android # Android
.gradle/ .gradle/
**/android/app/libs/ **/android/app/libs/
@@ -127,6 +129,12 @@ build/
**/ios/Pods/ **/ios/Pods/
**/ios/.symlinks/ **/ios/.symlinks/
# Ephemeral files (generated by Flutter for desktop platforms)
**/linux/flutter/ephemeral/
**/windows/flutter/ephemeral/
**/macos/Flutter/ephemeral/
**/ios/Flutter/ephemeral/
# ============================================================================== # ==============================================================================
# FIREBASE & BACKEND # FIREBASE & BACKEND
# ============================================================================== # ==============================================================================

41
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,41 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Client (Dev) - Android",
"request": "launch",
"type": "dart",
"program": "apps/mobile/apps/client/lib/main.dart",
"args": [
"--dart-define-from-file=${workspaceFolder}/apps/mobile/config.dev.json"
]
},
{
"name": "Client (Dev) - iOS",
"request": "launch",
"type": "dart",
"program": "apps/mobile/apps/client/lib/main.dart",
"args": [
"--dart-define-from-file=${workspaceFolder}/apps/mobile/config.dev.json"
]
},
{
"name": "Staff (Dev) - Android",
"request": "launch",
"type": "dart",
"program": "apps/mobile/apps/staff/lib/main.dart",
"args": [
"--dart-define-from-file=${workspaceFolder}/apps/mobile/config.dev.json"
]
},
{
"name": "Staff (Dev) - iOS",
"request": "launch",
"type": "dart",
"program": "apps/mobile/apps/staff/lib/main.dart",
"args": [
"--dart-define-from-file=${workspaceFolder}/apps/mobile/config.dev.json"
]
}
]
}

View File

@@ -46,4 +46,12 @@
- Staff APP: - Staff APP:
- On app launch, check whether there is an active session. If a valid session exists, skip the auth flow and navigate directly to Home, loading Staff account. - On app launch, check whether there is an active session. If a valid session exists, skip the auth flow and navigate directly to Home, loading Staff account.
- Add an expiration time (TTL) to the session (store expiresAt / expiryTimestamp) and invalidate/clear the session when it has expired. - Add an expiration time (TTL) to the session (store expiresAt / expiryTimestamp) and invalidate/clear the session when it has expired.
- For staffs Skills = Roles? thinking in the future for the smart assigned that need to know the roles of staff to assign. - For staffs Skills = Roles? thinking in the future for the smart assigned that need to know the roles of staff to assign.
## App
- Staff Application
### Github issue
- https://github.com/Oloodi/krow-workforce/issues/248
### Deveations:
- Assumed that a worker can only have one shift per day.

129
CLAUDE.md Normal file
View File

@@ -0,0 +1,129 @@
# CLAUDE.md - Project Context for AI Assistants
This file provides context for Claude Code and other AI assistants working on this codebase.
## Project Overview
**KROW Workforce** is a workforce management platform connecting businesses with temporary/on-demand workers. It consists of:
- **Client App**: For businesses to create orders, manage hubs, handle billing
- **Staff App**: For workers to manage availability, clock in/out, view earnings
- **Web Dashboard**: Admin portal (React/Vite - WIP)
- **Backend**: Firebase Data Connect + PostgreSQL on Cloud SQL
## Monorepo Structure
```
/apps
/mobile # Flutter apps (managed by Melos)
/apps
/client # krowwithus_client - Business app
/staff # krowwithus_staff - Worker app
/design_system_viewer
/packages
/core # Base utilities
/domain # Business entities, repository interfaces
/data_connect # Data layer, Firebase Data Connect SDK
/design_system # Shared UI components
/core_localization # i18n (Slang)
/features
/client/* # Client-specific features
/staff/* # Staff-specific features
/web-dashboard # React web app (WIP)
/backend
/dataconnect # GraphQL schemas, Firebase Data Connect config
/cloud-functions # Serverless functions (placeholder)
/internal
/launchpad # Internal DevOps portal
/api-harness # API testing tool
/makefiles # Modular Make targets
/docs # Project documentation
```
## Key Commands
### Mobile Development
```bash
# Install dependencies
make mobile-install
# Run client app (specify your device ID)
make mobile-client-dev-android DEVICE=<device_id>
# Run staff app
make mobile-staff-dev-android DEVICE=<device_id>
# Find your device ID
flutter devices
# Build APK
make mobile-client-build PLATFORM=apk
make mobile-staff-build PLATFORM=apk
# Code generation (localization + build_runner)
cd apps/mobile && melos run gen:all
```
### Web Development
```bash
make install # Install web dependencies
make dev # Run web dev server
```
### Data Connect
```bash
make dataconnect-sync # Deploy schemas, migrate, regenerate SDK
```
## Architecture Patterns
- **State Management**: BLoC pattern (flutter_bloc)
- **Navigation**: Flutter Modular
- **Architecture**: Clean Architecture (domain/data/presentation layers)
- **Feature Organization**: Each feature is a separate package
- **Value Objects**: Equatable for entity equality
## Code Conventions
- Features go in `/apps/mobile/packages/features/{client|staff}/`
- Shared code goes in `/apps/mobile/packages/{core|domain|data_connect}/`
- UI components go in `/apps/mobile/packages/design_system/`
- GraphQL schemas go in `/backend/dataconnect/schema/`
- Documentation language: **English**
## Important Files
- `apps/mobile/melos.yaml` - Melos workspace config
- `makefiles/mobile.mk` - Mobile Make targets
- `backend/dataconnect/dataconnect.yaml` - Data Connect config
- `firebase.json` - Firebase hosting/emulator config
- `BLOCKERS.md` - Known blockers and deviations
## Branch Protection
- `main` and `dev` branches are protected
- Always create feature branches: `feature/`, `fix/`, `chore/`
- PRs required for merging
## Testing Mobile Apps
1. Connect your Android device or start emulator
2. Run `flutter devices` to get device ID
3. Run `make mobile-client-dev-android DEVICE=<your_device_id>`
## Common Issues
### "No devices found with name 'android'"
The Makefile defaults to device ID `android`. Override with your actual device:
```bash
make mobile-client-dev-android DEVICE=3fb285a7
```
### Dependency resolution issues
```bash
cd apps/mobile && melos clean && melos bootstrap
```
### Code generation out of sync
```bash
cd apps/mobile && melos run gen:all
```

138
GEMINI.md Normal file
View File

@@ -0,0 +1,138 @@
# GEMINI.md - Project Context for AI Assistants
This file provides context for Gemini and other AI assistants working on this codebase.
## Project Overview
**KROW Workforce** is a workforce management platform connecting businesses with temporary/on-demand workers. It consists of:
- **Client App**: For businesses to create orders, manage hubs, handle billing
- **Staff App**: For workers to manage availability, clock in/out, view earnings
- **Web Dashboard**: Admin portal (React/Vite - WIP)
- **Backend**: Firebase Data Connect + PostgreSQL on Cloud SQL
## Monorepo Structure
```
/apps
/mobile # Flutter apps (managed by Melos)
/apps
/client # krowwithus_client - Business app
/staff # krowwithus_staff - Worker app
/design_system_viewer
/packages
/core # Base utilities
/domain # Business entities, repository interfaces
/data_connect # Data layer, Firebase Data Connect SDK
/design_system # Shared UI components
/core_localization # i18n (Slang)
/features
/client/* # Client-specific features
/staff/* # Staff-specific features
/web-dashboard # React web app (WIP)
/backend
/dataconnect # GraphQL schemas, Firebase Data Connect config
/cloud-functions # Serverless functions (placeholder)
/internal
/launchpad # Internal DevOps portal
/api-harness # API testing tool
/makefiles # Modular Make targets
/docs # Project documentation
/bugs # Bug reports and screenshots
```
## Key Commands
### Mobile Development
```bash
# Install dependencies
make mobile-install
# Run client app (specify your device ID)
make mobile-client-dev-android DEVICE=<device_id>
# Run staff app
make mobile-staff-dev-android DEVICE=<device_id>
# Find your device ID
flutter devices
# Build APK
make mobile-client-build PLATFORM=apk
make mobile-staff-build PLATFORM=apk
# Code generation (localization + build_runner)
cd apps/mobile && melos run gen:all
```
### Web Development
```bash
make install # Install web dependencies
make dev # Run web dev server
```
### Data Connect
```bash
make dataconnect-sync # Deploy schemas, migrate, regenerate SDK
```
## Architecture Patterns
- **State Management**: BLoC pattern (flutter_bloc)
- **Navigation**: Flutter Modular
- **Architecture**: Clean Architecture (domain/data/presentation layers)
- **Feature Organization**: Each feature is a separate package
- **Value Objects**: Equatable for entity equality
## Code Conventions
- Features go in `/apps/mobile/packages/features/{client|staff}/`
- Shared code goes in `/apps/mobile/packages/{core|domain|data_connect}/`
- UI components go in `/apps/mobile/packages/design_system/`
- GraphQL schemas go in `/backend/dataconnect/schema/`
- Documentation language: **English**
## Important Files
- `apps/mobile/melos.yaml` - Melos workspace config
- `makefiles/mobile.mk` - Mobile Make targets
- `backend/dataconnect/dataconnect.yaml` - Data Connect config
- `firebase.json` - Firebase hosting/emulator config
- `BLOCKERS.md` - Known blockers and deviations
- `bugs/BUG-REPORT-*.md` - Bug reports with analysis
## Branch Protection
- `main` and `dev` branches are protected
- Always create feature branches: `feature/`, `fix/`, `chore/`
- PRs required for merging
## Testing Mobile Apps
1. Connect your Android device or start emulator
2. Run `flutter devices` to get device ID
3. Run `make mobile-client-dev-android DEVICE=<your_device_id>`
## Common Issues
### "No devices found with name 'android'"
The Makefile defaults to device ID `android`. Override with your actual device:
```bash
make mobile-client-dev-android DEVICE=3fb285a7
```
### Dependency resolution issues
```bash
cd apps/mobile && melos clean && melos bootstrap
```
### Code generation out of sync
```bash
cd apps/mobile && melos run gen:all
```
## Known Technical Debt
See `bugs/BUG-REPORT-*.md` for detailed analysis of:
- Authentication/User sync issues
- Error handling architecture (needs AppException pattern)
- BLoC state management patterns (copyWith null handling)

View File

@@ -17,9 +17,9 @@ include makefiles/tools.mk
.PHONY: help .PHONY: help
help: help:
@echo "--------------------------------------------------" @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo " KROW Workforce - Available Makefile Commands" @echo " 🚀 KROW Workforce - Available Makefile Commands"
@echo "--------------------------------------------------" @echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo "" @echo ""
@echo " --- WEB APP DEVELOPMENT ---" @echo " --- WEB APP DEVELOPMENT ---"
@echo " make web-install - Installs web frontend dependencies." @echo " make web-install - Installs web frontend dependencies."
@@ -29,31 +29,53 @@ help:
@echo " make web-lint - Runs linter for web frontend." @echo " make web-lint - Runs linter for web frontend."
@echo " make web-preview - Previews the web frontend build." @echo " make web-preview - Previews the web frontend build."
@echo " make launchpad-dev - Starts the local launchpad server (Firebase Hosting emulator)." @echo " make launchpad-dev - Starts the local launchpad server (Firebase Hosting emulator)."
@echo " 📦 WEB FRONTEND (internal/api-harness)"
@echo " ────────────────────────────────────────────────────────────────────"
@echo " make install Install web frontend dependencies"
@echo " make dev Start local web frontend dev server"
@echo " make build Build web frontend for production"
@echo " make deploy-app [ENV=dev] Build and deploy web app (dev/staging/prod)"
@echo "" @echo ""
@echo " --- MOBILE APP DEVELOPMENT ---" @echo " 🏠 LAUNCHPAD (internal/launchpad)"
@echo " make mobile-install - Bootstrap the mobile workspace (Melos)." @echo " ────────────────────────────────────────────────────────────────────"
@echo " make mobile-info - List custom mobile development commands." @echo " make launchpad-dev Start launchpad dev server (Firebase Hosting)"
@echo " make mobile-client-dev-android - Run client app in dev mode (Android)." @echo " make deploy-launchpad-hosting Deploy launchpad to Firebase Hosting"
@echo " make mobile-client-build PLATFORM=apk - Build client app for specified platform."
@echo " make mobile-staff-dev-android - Run staff app in dev mode (Android)."
@echo " make mobile-staff-build PLATFORM=apk - Build staff app for specified platform."
@echo "" @echo ""
@echo " --- DEPLOYMENT ---" @echo " 📱 MOBILE APPS (apps/mobile)"
@echo " make deploy-launchpad-hosting - Deploys internal launchpad to Firebase Hosting." @echo " ────────────────────────────────────────────────────────────────────"
@echo " make deploy-app [ENV=staging] - Builds and deploys the main web app (default: dev)." @echo " make mobile-install Bootstrap mobile workspace + SDK"
@echo " make mobile-info List mobile development commands"
@echo " make mobile-client-dev-android [DEVICE=android] Run client app (Android)"
@echo " make mobile-client-build PLATFORM=apk Build client app (apk/ipa/etc)"
@echo " make mobile-staff-dev-android [DEVICE=android] Run staff app (Android)"
@echo " make mobile-staff-build PLATFORM=apk Build staff app (apk/ipa/etc)"
@echo " make mobile-hot-reload Hot reload running Flutter app"
@echo " make mobile-hot-restart Hot restart running Flutter app"
@echo "" @echo ""
@echo " --- DEVELOPMENT TOOLS ---" @echo " 🗄️ DATA CONNECT & BACKEND (backend/dataconnect)"
@echo " make install-melos - Installs Melos globally if not already present." @echo " ────────────────────────────────────────────────────────────────────"
@echo " make install-git-hooks - Installs git pre-push hook to protect main/dev branches." @echo " make dataconnect-init Initialize Firebase Data Connect"
@echo " make sync-prototypes - Builds and copies prototypes from adjacent 'client-krow-poc' repo." @echo " make dataconnect-deploy Deploy Data Connect schemas to Cloud SQL"
@echo " make dataconnect-sql-migrate Apply pending SQL migrations"
@echo " make dataconnect-generate-sdk Regenerate Data Connect client SDK"
@echo " make dataconnect-sync Full sync: deploy + migrate + generate SDK"
@echo " make dataconnect-seed Seed database with test data"
@echo " make dataconnect-clean Delete all data from Data Connect"
@echo " make dataconnect-test Test Data Connect deployment (dry-run)"
@echo " make dataconnect-enable-apis Enable required GCP APIs"
@echo " make dataconnect-bootstrap-db ONE-TIME: Full Cloud SQL + Data Connect setup"
@echo "" @echo ""
@echo " --- DATA CONNECT MANAGEMENT ---" @echo " 🛠️ DEVELOPMENT TOOLS"
@echo " make dataconnect-init - Initializes Firebase Data Connect." @echo " ────────────────────────────────────────────────────────────────────"
@echo " make dataconnect-deploy - Deploys Data Connect schemas." @echo " make install-melos Install Melos globally (for mobile dev)"
@echo " make dataconnect-sql-migrate - Applies SQL migrations." @echo " make install-git-hooks Install git pre-push hook (protect main/dev)"
@echo " make dataconnect-generate-sdk - Regenerates the Data Connect SDK." @echo " make sync-prototypes Sync prototypes from client-krow-poc repo"
@echo " make dataconnect-sync - Runs migrate + deploy + generate-sdk."
@echo " make dataconnect-bootstrap-db - ONE-TIME: Full Cloud SQL + Data Connect setup."
@echo "" @echo ""
@echo " make help - Shows this help message." @echo " HELP"
@echo "--------------------------------------------------" @echo " ────────────────────────────────────────────────────────────────────"
@echo " make help Show this help message"
@echo ""
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@echo " 💡 Tip: Run 'make mobile-install' first for mobile development"
@echo " 💡 Tip: Use 'make dataconnect-sync' after schema changes"
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

View File

@@ -0,0 +1,18 @@
## Recommended tasks for the next sprint
* In the mobile applications, since the structure is now finalized (at least for the existing features), we need to **strictly follow best practices while coding**:
* Break down large widgets into **smaller, reusable widgets**
* Add **doc comments** where necessary to improve readability and maintainability
* **Remove overly complicated or unnecessary logic** introduced by AI and simplify where possible
* **Adhere to the design system** and remove all **hard-coded colors and typography**, using shared tokens instead
* Improvement points
- apps/mobile/packages/features/client/client_coverage/lib/src/data/repositories_impl/coverage_repository_impl.dart
- Fix the location field in CoverageShiftRole to use the correct fallback logic.
- line 125 remove redundant location values.
- Need to clarify the difference b/w `case dc.ApplicationStatus.ACCEPTED` and `case dc.ApplicationStatus.CONFIRMED`.
- Update the dataconnect docs.
- Track `lat` and `lng` in the staff preferred work locations (for now we are only storing the name).
- Remove "Up Next (x)" counter from orders list in client app as it is confusing, becase the tab already has a badge showing the number of the upcoming orders.

View File

@@ -27,32 +27,43 @@ The project is organized into modular packages to ensure separation of concerns
Ensure you have the Flutter SDK installed and configured. Ensure you have the Flutter SDK installed and configured.
### 2. Initial Setup ### 2. Initial Setup
Run the following command from the **project root** to install Melos, bootstrap all packages, and generate localization files: Run the following command from the **project root** to install Melos, bootstrap all packages, generate localization files, and generate the Firebase Data Connect SDK:
```bash ```bash
# Using Makefile # Using Makefile (Recommended)
make mobile-install make mobile-install
# Using Melos
melos bootstrap
``` ```
This command will:
- Install Melos if not already installed
- Generate the Firebase Data Connect SDK from schema files
- Bootstrap all packages (install dependencies)
- Generate localization files
**Note:** The Firebase Data Connect SDK files (`dataconnect_generated/`) are auto-generated and not committed to the repository. They will be regenerated automatically when you run `make mobile-install` or any mobile development commands.
### 3. Running the Apps ### 3. Running the Apps
You can run the applications using Melos scripts or through the `Makefile`: You can run the applications using Melos scripts or through the `Makefile`:
First, find your device ID:
```bash
flutter devices
```
#### Client App #### Client App
```bash ```bash
# Using Melos # Using Melos
melos run start:client -d android # or ios melos run start:client -- -d <device_id>
# Using Makefile # Using Makefile (DEVICE defaults to 'android' if not specified)
make mobile-client-dev-android make mobile-client-dev-android DEVICE=<device_id>
``` ```
#### Staff App #### Staff App
```bash ```bash
# Using Melos # Using Melos
melos run start:staff -d android # or ios melos run start:staff -- -d <device_id>
# Using Makefile # Using Makefile (DEVICE defaults to 'android' if not specified)
make mobile-staff-dev-android make mobile-staff-dev-android DEVICE=<device_id>
``` ```
## 🛠 Useful Commands ## 🛠 Useful Commands

View File

@@ -7,7 +7,7 @@ plugins {
} }
android { android {
namespace = "com.example.krow_client" namespace = "com.krowwithus.client"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion

View File

@@ -5,42 +5,6 @@
"storage_bucket": "krow-workforce-dev.firebasestorage.app" "storage_bucket": "krow-workforce-dev.firebasestorage.app"
}, },
"client": [ "client": [
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:87d41566f8dda41d7757db",
"android_client_info": {
"package_name": "com.example.krow_workforce"
}
},
"oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
},
{ {
"client_info": { "client_info": {
"mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db", "mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db",
@@ -67,10 +31,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]
@@ -103,10 +67,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]
@@ -121,6 +85,14 @@
} }
}, },
"oauth_client": [ "oauth_client": [
{
"client_id": "933560802882-fbqg2icq24bmci3f84evjrbth5huh87f.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.krowwithus.client",
"certificate_hash": "c3efbe1642239c599c16ad04c7fac340902fe280"
}
},
{ {
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3 "client_type": 3
@@ -139,10 +111,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]
@@ -151,12 +123,20 @@
}, },
{ {
"client_info": { "client_info": {
"mobilesdk_app_id": "1:933560802882:android:d26bde4ee337b0b17757db", "mobilesdk_app_id": "1:933560802882:android:1ae05d85c865f77c7757db",
"android_client_info": { "android_client_info": {
"package_name": "com.krowwithus.krow_workforce.dev" "package_name": "com.krowwithus.staff"
} }
}, },
"oauth_client": [ "oauth_client": [
{
"client_id": "933560802882-ikdfv3o5f47g36qqgvfq55o4m19n7gk4.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.krowwithus.staff",
"certificate_hash": "ac917ae8470ab29f1107c773c6017ff5ea5d102d"
}
},
{ {
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3 "client_type": 3
@@ -175,10 +155,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]

View File

@@ -1,4 +1,4 @@
package com.example.krow_client package com.krowwithus.client
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity

View File

@@ -0,0 +1 @@
{"flutter":{"platforms":{"android":{"default":{"projectId":"krow-workforce-dev","appId":"1:933560802882:android:da13569105659ead7757db","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"krow-workforce-dev","appId":"1:933560802882:ios:d2b6d743608e2a527757db","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"krow-workforce-dev","configurations":{"android":"1:933560802882:android:da13569105659ead7757db","ios":"1:933560802882:ios:d2b6d743608e2a527757db","web":"1:933560802882:web:173a841992885bb27757db"}}}}}}

View File

@@ -1,32 +0,0 @@
#
# Generated file, do not edit.
#
import lldb
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
base = frame.register["x0"].GetValueAsAddress()
page_len = frame.register["x1"].GetValueAsUnsigned()
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
# first page to see if handled it correctly. This makes diagnosing
# misconfiguration (e.g. missing breakpoint) easier.
data = bytearray(page_len)
data[0:8] = b'IHELPED!'
error = lldb.SBError()
frame.GetThread().GetProcess().WriteMemory(base, data, error)
if not error.Success():
print(f'Failed to write into {base}[+{page_len}]', error)
return
def __lldb_init_module(debugger: lldb.SBDebugger, _):
target = debugger.GetDummyTarget()
# Caveat: must use BreakpointCreateByRegEx here and not
# BreakpointCreateByName. For some reasons callback function does not
# get carried over from dummy target for the later.
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
bp.SetAutoContinue(True)
print("-- LLDB integration loaded --")

View File

@@ -1,5 +0,0 @@
#
# Generated file, do not edit.
#
command script import --relative-to-command-file flutter_lldb_helper.py

View File

@@ -14,6 +14,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
E8C1A28BFABAEE32FB779C9A /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 221E00B70DE845BE3D50D0A0 /* GoogleService-Info.plist */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -42,6 +43,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; 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>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
221E00B70DE845BE3D50D0A0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; 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; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
@@ -94,6 +96,7 @@
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */, 331C8082294A63A400263BE5 /* RunnerTests */,
221E00B70DE845BE3D50D0A0 /* GoogleService-Info.plist */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -216,6 +219,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
E8C1A28BFABAEE32FB779C9A /* GoogleService-Info.plist in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>933560802882-jqpv1l3gjmi3m87b2gu1iq4lg46lkdfg.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.933560802882-jqpv1l3gjmi3m87b2gu1iq4lg46lkdfg</string>
<key>ANDROID_CLIENT_ID</key>
<string>933560802882-fbqg2icq24bmci3f84evjrbth5huh87f.apps.googleusercontent.com</string>
<key>API_KEY</key>
<string>AIzaSyDyEXkzZAWpXXe4dAesYaZflt5BEtMn9tA</string>
<key>GCM_SENDER_ID</key>
<string>933560802882</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.krowwithus.client</string>
<key>PROJECT_ID</key>
<string>krow-workforce-dev</string>
<key>STORAGE_BUCKET</key>
<string>krow-workforce-dev.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:933560802882:ios:d2b6d743608e2a527757db</string>
</dict>
</plist>

View File

@@ -0,0 +1,78 @@
// File generated by FlutterFire CLI.
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyBqRtZPMGU-Sz5x5UnRrunKu5NSWYyPRn8',
appId: '1:933560802882:web:173a841992885bb27757db',
messagingSenderId: '933560802882',
projectId: 'krow-workforce-dev',
authDomain: 'krow-workforce-dev.firebaseapp.com',
storageBucket: 'krow-workforce-dev.firebasestorage.app',
measurementId: 'G-9S7WEQTDKX',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4',
appId: '1:933560802882:android:da13569105659ead7757db',
messagingSenderId: '933560802882',
projectId: 'krow-workforce-dev',
storageBucket: 'krow-workforce-dev.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyDyEXkzZAWpXXe4dAesYaZflt5BEtMn9tA',
appId: '1:933560802882:ios:d2b6d743608e2a527757db',
messagingSenderId: '933560802882',
projectId: 'krow-workforce-dev',
storageBucket: 'krow-workforce-dev.firebasestorage.app',
androidClientId: '933560802882-fbqg2icq24bmci3f84evjrbth5huh87f.apps.googleusercontent.com',
iosClientId: '933560802882-jqpv1l3gjmi3m87b2gu1iq4lg46lkdfg.apps.googleusercontent.com',
iosBundleId: 'com.krowwithus.client',
);
}

View File

@@ -12,10 +12,15 @@ import 'package:client_hubs/client_hubs.dart' as client_hubs;
import 'package:client_create_order/client_create_order.dart' import 'package:client_create_order/client_create_order.dart'
as client_create_order; as client_create_order;
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:krow_core/core.dart';
import 'firebase_options.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); await Firebase.initializeApp(
options: kIsWeb ? DefaultFirebaseOptions.currentPlatform : null,
);
runApp(ModularApp(module: AppModule(), child: const AppWidget())); runApp(ModularApp(module: AppModule(), child: const AppWidget()));
} }
@@ -54,35 +59,38 @@ class AppWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider<core_localization.LocaleBloc>( return WebMobileFrame(
create: (BuildContext context) => appName: 'KROW Client\nApplication',
Modular.get<core_localization.LocaleBloc>() logo: Image.asset('assets/logo.png'),
..add(const core_localization.LoadLocale()), child: BlocProvider<core_localization.LocaleBloc>(
child: create: (BuildContext context) =>
BlocBuilder< Modular.get<core_localization.LocaleBloc>(),
core_localization.LocaleBloc, child:
core_localization.LocaleState BlocBuilder<
>( core_localization.LocaleBloc,
builder: core_localization.LocaleState
(BuildContext context, core_localization.LocaleState state) { >(
return core_localization.TranslationProvider( builder:
child: MaterialApp.router( (BuildContext context, core_localization.LocaleState state) {
debugShowCheckedModeBanner: false, return core_localization.TranslationProvider(
title: "Krow Client", child: MaterialApp.router(
theme: UiTheme.light, debugShowCheckedModeBanner: false,
routerConfig: Modular.routerConfig, title: "Krow Client",
locale: state.locale, theme: UiTheme.light,
supportedLocales: state.supportedLocales, routerConfig: Modular.routerConfig,
localizationsDelegates: locale: state.locale,
const <LocalizationsDelegate<dynamic>>[ supportedLocales: state.supportedLocales,
GlobalMaterialLocalizations.delegate, localizationsDelegates:
GlobalWidgetsLocalizations.delegate, const <LocalizationsDelegate<dynamic>>[
GlobalCupertinoLocalizations.delegate, GlobalMaterialLocalizations.delegate,
], GlobalWidgetsLocalizations.delegate,
), GlobalCupertinoLocalizations.delegate,
); ],
}, ),
), );
},
),
),
); );
} }
} }

View File

@@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "krow_client") set(BINARY_NAME "krow_client")
# The unique GTK application identifier for this application. See: # The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID # https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "com.example.krow_client") set(APPLICATION_ID "com.krowwithus.client")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake. # versions of CMake.

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.2/

View File

@@ -1,13 +0,0 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/josesalazar/flutter
FLUTTER_APPLICATION_PATH=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client/lib/main.dart
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/.dart_tool/package_config.json

View File

@@ -1,14 +0,0 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/josesalazar/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/apps/client/lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=/Users/josesalazar/Documents/DEV/krow-workforce/apps/mobile/.dart_tool/package_config.json"

View File

@@ -1,11 +1,11 @@
name: krowwithus_client name: krowwithus_client
description: "Krow Client Application" description: "Krow Client Application"
publish_to: "none" publish_to: "none"
version: 0.0.1-M+301 version: 0.0.1-M3+5
resolution: workspace resolution: workspace
environment: environment:
sdk: ^3.10.7 sdk: '>=3.10.0 <4.0.0'
dependencies: dependencies:
flutter: flutter:
@@ -32,6 +32,8 @@ dependencies:
path: ../../packages/features/client/hubs path: ../../packages/features/client/hubs
client_create_order: client_create_order:
path: ../../packages/features/client/create_order path: ../../packages/features/client/create_order
krow_core:
path: ../../packages/core
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
flutter_modular: ^6.3.2 flutter_modular: ^6.3.2

View File

@@ -33,6 +33,29 @@
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
</head> </head>
<body> <body>
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-analytics.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyBqRtZPMGU-Sz5x5UnRrunKu5NSWYyPRn8",
authDomain: "krow-workforce-dev.firebaseapp.com",
projectId: "krow-workforce-dev",
storageBucket: "krow-workforce-dev.firebasestorage.app",
messagingSenderId: "933560802882",
appId: "1:933560802882:web:173a841992885bb27757db",
measurementId: "G-9S7WEQTDKX"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
</script>
<script src="flutter_bootstrap.js" async></script> <script src="flutter_bootstrap.js" async></script>
</body> </body>
</html> </html>

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_auth-6.1.4/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_core-4.4.0/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.5/

View File

@@ -1,32 +0,0 @@
#
# Generated file, do not edit.
#
import lldb
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
base = frame.register["x0"].GetValueAsAddress()
page_len = frame.register["x1"].GetValueAsUnsigned()
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
# first page to see if handled it correctly. This makes diagnosing
# misconfiguration (e.g. missing breakpoint) easier.
data = bytearray(page_len)
data[0:8] = b'IHELPED!'
error = lldb.SBError()
frame.GetThread().GetProcess().WriteMemory(base, data, error)
if not error.Success():
print(f'Failed to write into {base}[+{page_len}]', error)
return
def __lldb_init_module(debugger: lldb.SBDebugger, _):
target = debugger.GetDummyTarget()
# Caveat: must use BreakpointCreateByRegEx here and not
# BreakpointCreateByName. For some reasons callback function does not
# get carried over from dummy target for the later.
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
bp.SetAutoContinue(True)
print("-- LLDB integration loaded --")

View File

@@ -1,5 +0,0 @@
#
# Generated file, do not edit.
#
command script import --relative-to-command-file flutter_lldb_helper.py

View File

@@ -1,11 +0,0 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/achinthaisuru/Documents/flutter
FLUTTER_APPLICATION_PATH=/Users/achinthaisuru/Documents/Github/krow-workforce/apps/mobile/apps/design_system_viewer
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json

View File

@@ -1,12 +0,0 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/achinthaisuru/Documents/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/achinthaisuru/Documents/Github/krow-workforce/apps/mobile/apps/design_system_viewer"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

View File

@@ -16,11 +16,11 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1 version: 0.0.1
resolution: workspace resolution: workspace
environment: environment:
sdk: ^3.10.7 sdk: '>=3.10.0 <4.0.0'
# Dependencies specify other packages that your package needs in order to work. # Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions # To automatically upgrade your package dependencies to the latest versions

View File

@@ -7,7 +7,7 @@ plugins {
} }
android { android {
namespace = "com.example.krow_staff" namespace = "com.krowwithus.staff"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion

View File

@@ -5,42 +5,6 @@
"storage_bucket": "krow-workforce-dev.firebasestorage.app" "storage_bucket": "krow-workforce-dev.firebasestorage.app"
}, },
"client": [ "client": [
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:87d41566f8dda41d7757db",
"android_client_info": {
"package_name": "com.example.krow_workforce"
}
},
"oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
},
{ {
"client_info": { "client_info": {
"mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db", "mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db",
@@ -67,10 +31,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]
@@ -103,10 +67,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]
@@ -122,41 +86,13 @@
}, },
"oauth_client": [ "oauth_client": [
{ {
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", "client_id": "933560802882-fbqg2icq24bmci3f84evjrbth5huh87f.apps.googleusercontent.com",
"client_type": 3 "client_type": 1,
} "android_info": {
], "package_name": "com.krowwithus.client",
"api_key": [ "certificate_hash": "c3efbe1642239c599c16ad04c7fac340902fe280"
{ }
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4" },
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:d26bde4ee337b0b17757db",
"android_client_info": {
"package_name": "com.krowwithus.krow_workforce.dev"
}
},
"oauth_client": [
{ {
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3 "client_type": 3
@@ -175,10 +111,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]
@@ -193,6 +129,14 @@
} }
}, },
"oauth_client": [ "oauth_client": [
{
"client_id": "933560802882-ikdfv3o5f47g36qqgvfq55o4m19n7gk4.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.krowwithus.staff",
"certificate_hash": "ac917ae8470ab29f1107c773c6017ff5ea5d102d"
}
},
{ {
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3 "client_type": 3
@@ -211,10 +155,10 @@
"client_type": 3 "client_type": 3
}, },
{ {
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com", "client_id": "933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com",
"client_type": 2, "client_type": 2,
"ios_info": { "ios_info": {
"bundle_id": "com.krow.app.staff.dev" "bundle_id": "com.krowwithus.staff"
} }
} }
] ]

View File

@@ -0,0 +1,162 @@
{
"project_info": {
"project_number": "933560802882",
"project_id": "krow-workforce-dev",
"storage_bucket": "krow-workforce-dev.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db",
"android_client_info": {
"package_name": "com.krow.app.business.dev"
}
},
"oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:d49b8c0f4d19e95e7757db",
"android_client_info": {
"package_name": "com.krow.app.staff.dev"
}
},
"oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:da13569105659ead7757db",
"android_client_info": {
"package_name": "com.krowwithus.client"
}
},
"oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:933560802882:android:1ae05d85c865f77c7757db",
"android_client_info": {
"package_name": "com.krowwithus.staff"
}
},
"oauth_client": [
{
"client_id": "933560802882-ikdfv3o5f47g36qqgvfq55o4m19n7gk4.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "com.krowwithus.staff",
"certificate_hash": "ac917ae8470ab29f1107c773c6017ff5ea5d102d"
}
},
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "933560802882-dppsapp5i3lsfrlm1mhob2s21peofg1t.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.krow.app.staff.dev"
}
}
]
}
}
}
],
"configuration_version": "1"
}

View File

@@ -30,11 +30,21 @@ public final class GeneratedPluginRegistrant {
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error registering plugin firebase_core, io.flutter.plugins.firebase.core.FlutterFirebaseCorePlugin", e); Log.e(TAG, "Error registering plugin firebase_core, io.flutter.plugins.firebase.core.FlutterFirebaseCorePlugin", e);
} }
try {
flutterEngine.getPlugins().add(new com.baseflow.geolocator.GeolocatorPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin geolocator_android, com.baseflow.geolocator.GeolocatorPlugin", e);
}
try { try {
flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e); Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
} }
try {
flutterEngine.getPlugins().add(new com.baseflow.permissionhandler.PermissionHandlerPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin permission_handler_android, com.baseflow.permissionhandler.PermissionHandlerPlugin", e);
}
try { try {
flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin()); flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin());
} catch (Exception e) { } catch (Exception e) {

View File

@@ -1,4 +1,4 @@
package com.example.krow_staff package com.krowwithus.staff
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity

View File

@@ -1,32 +0,0 @@
#
# Generated file, do not edit.
#
import lldb
def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
base = frame.register["x0"].GetValueAsAddress()
page_len = frame.register["x1"].GetValueAsUnsigned()
# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
# first page to see if handled it correctly. This makes diagnosing
# misconfiguration (e.g. missing breakpoint) easier.
data = bytearray(page_len)
data[0:8] = b'IHELPED!'
error = lldb.SBError()
frame.GetThread().GetProcess().WriteMemory(base, data, error)
if not error.Success():
print(f'Failed to write into {base}[+{page_len}]', error)
return
def __lldb_init_module(debugger: lldb.SBDebugger, _):
target = debugger.GetDummyTarget()
# Caveat: must use BreakpointCreateByRegEx here and not
# BreakpointCreateByName. For some reasons callback function does not
# get carried over from dummy target for the later.
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
bp.SetAutoContinue(True)
print("-- LLDB integration loaded --")

View File

@@ -1,5 +0,0 @@
#
# Generated file, do not edit.
#
command script import --relative-to-command-file flutter_lldb_helper.py

View File

@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
1E967D034ADA3A16EF82CB3E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9F0B07DEC91B141354438F79 /* GoogleService-Info.plist */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
@@ -55,6 +56,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9F0B07DEC91B141354438F79 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -94,6 +96,7 @@
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */, 331C8082294A63A400263BE5 /* RunnerTests */,
9F0B07DEC91B141354438F79 /* GoogleService-Info.plist */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -216,6 +219,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
1E967D034ADA3A16EF82CB3E /* GoogleService-Info.plist in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@@ -24,6 +24,18 @@
@import firebase_core; @import firebase_core;
#endif #endif
#if __has_include(<geolocator_apple/GeolocatorPlugin.h>)
#import <geolocator_apple/GeolocatorPlugin.h>
#else
@import geolocator_apple;
#endif
#if __has_include(<permission_handler_apple/PermissionHandlerPlugin.h>)
#import <permission_handler_apple/PermissionHandlerPlugin.h>
#else
@import permission_handler_apple;
#endif
#if __has_include(<shared_preferences_foundation/SharedPreferencesPlugin.h>) #if __has_include(<shared_preferences_foundation/SharedPreferencesPlugin.h>)
#import <shared_preferences_foundation/SharedPreferencesPlugin.h> #import <shared_preferences_foundation/SharedPreferencesPlugin.h>
#else #else
@@ -36,6 +48,8 @@
[FLTFirebaseAppCheckPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseAppCheckPlugin"]]; [FLTFirebaseAppCheckPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseAppCheckPlugin"]];
[FLTFirebaseAuthPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseAuthPlugin"]]; [FLTFirebaseAuthPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseAuthPlugin"]];
[FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]]; [FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]];
[GeolocatorPlugin registerWithRegistrar:[registry registrarForPlugin:@"GeolocatorPlugin"]];
[PermissionHandlerPlugin registerWithRegistrar:[registry registrarForPlugin:@"PermissionHandlerPlugin"]];
[SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]]; [SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]];
} }

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh</string>
<key>ANDROID_CLIENT_ID</key>
<string>933560802882-fbqg2icq24bmci3f84evjrbth5huh87f.apps.googleusercontent.com</string>
<key>API_KEY</key>
<string>AIzaSyDyEXkzZAWpXXe4dAesYaZflt5BEtMn9tA</string>
<key>GCM_SENDER_ID</key>
<string>933560802882</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.krowwithus.staff</string>
<key>PROJECT_ID</key>
<string>krow-workforce-dev</string>
<key>STORAGE_BUCKET</key>
<string>krow-workforce-dev.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:933560802882:ios:fa584205b356de937757db</string>
</dict>
</plist>

View File

@@ -0,0 +1,78 @@
// File generated by FlutterFire CLI.
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyBqRtZPMGU-Sz5x5UnRrunKu5NSWYyPRn8',
appId: '1:933560802882:web:173a841992885bb27757db',
messagingSenderId: '933560802882',
projectId: 'krow-workforce-dev',
authDomain: 'krow-workforce-dev.firebaseapp.com',
storageBucket: 'krow-workforce-dev.firebasestorage.app',
measurementId: 'G-9S7WEQTDKX',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4',
appId: '1:933560802882:android:1ae05d85c865f77c7757db',
messagingSenderId: '933560802882',
projectId: 'krow-workforce-dev',
storageBucket: 'krow-workforce-dev.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyDyEXkzZAWpXXe4dAesYaZflt5BEtMn9tA',
appId: '1:933560802882:ios:fa584205b356de937757db',
messagingSenderId: '933560802882',
projectId: 'krow-workforce-dev',
storageBucket: 'krow-workforce-dev.firebasestorage.app',
androidClientId: '933560802882-fbqg2icq24bmci3f84evjrbth5huh87f.apps.googleusercontent.com',
iosClientId: '933560802882-29olj9ku64jbe9h7flinha6hbi8qrluh.apps.googleusercontent.com',
iosBundleId: 'com.krowwithus.staff',
);
}

View File

@@ -1,17 +1,21 @@
import 'package:core_localization/core_localization.dart' as core_localization; import 'package:core_localization/core_localization.dart' as core_localization;
import 'package:design_system/design_system.dart'; import 'package:design_system/design_system.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:krowwithus_staff/firebase_options.dart';
import 'package:staff_authentication/staff_authentication.dart' import 'package:staff_authentication/staff_authentication.dart'
as staff_authentication; as staff_authentication;
import 'package:staff_main/staff_main.dart' as staff_main; import 'package:staff_main/staff_main.dart' as staff_main;
import 'package:firebase_core/firebase_core.dart'; import 'package:krow_core/core.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(ModularApp(module: AppModule(), child: const AppWidget())); runApp(ModularApp(module: AppModule(), child: const AppWidget()));
} }
@@ -34,31 +38,37 @@ class AppWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider<core_localization.LocaleBloc>( return WebMobileFrame(
create: (BuildContext context) => appName: 'KROW Staff\nApplication',
Modular.get<core_localization.LocaleBloc>() logo: Image.asset('assets/logo.png'),
..add(const core_localization.LoadLocale()), child: BlocProvider<core_localization.LocaleBloc>(
child: create: (BuildContext context) =>
BlocBuilder< Modular.get<core_localization.LocaleBloc>(),
core_localization.LocaleBloc, child:
core_localization.LocaleState BlocBuilder<
>( core_localization.LocaleBloc,
builder: (BuildContext context, core_localization.LocaleState state) { core_localization.LocaleState
return core_localization.TranslationProvider( >(
child: MaterialApp.router( builder:
title: "KROW Staff", (BuildContext context, core_localization.LocaleState state) {
theme: UiTheme.light, return core_localization.TranslationProvider(
routerConfig: Modular.routerConfig, child: MaterialApp.router(
locale: state.locale, title: "KROW Staff",
supportedLocales: state.supportedLocales, theme: UiTheme.light,
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[ routerConfig: Modular.routerConfig,
GlobalMaterialLocalizations.delegate, locale: state.locale,
GlobalWidgetsLocalizations.delegate, supportedLocales: state.supportedLocales,
GlobalCupertinoLocalizations.delegate, localizationsDelegates:
], const <LocalizationsDelegate<dynamic>>[
)); GlobalMaterialLocalizations.delegate,
}, GlobalWidgetsLocalizations.delegate,
), GlobalCupertinoLocalizations.delegate,
],
),
);
},
),
),
); );
} }
} }

View File

@@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "krow_staff") set(BINARY_NAME "krow_staff")
# The unique GTK application identifier for this application. See: # The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID # https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "com.example.krow_staff") set(APPLICATION_ID "com.krowwithus.staff")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake. # versions of CMake.

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/

View File

@@ -8,11 +8,13 @@ import Foundation
import firebase_app_check import firebase_app_check
import firebase_auth import firebase_auth
import firebase_core import firebase_core
import geolocator_apple
import shared_preferences_foundation import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin")) FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
} }

View File

@@ -1,11 +0,0 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/achinthaisuru/Documents/flutter
FLUTTER_APPLICATION_PATH=/Users/achinthaisuru/Documents/Github/krow-workforce/apps/mobile/apps/staff
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_BUILD_DIR=build
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=true
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.dart_tool/package_config.json

View File

@@ -1,12 +0,0 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/achinthaisuru/Documents/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/achinthaisuru/Documents/Github/krow-workforce/apps/mobile/apps/staff"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=true"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"

View File

@@ -1,21 +1,143 @@
PODS: PODS:
- AppCheckCore (11.2.0):
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- Firebase/AppCheck (12.8.0):
- Firebase/CoreOnly
- FirebaseAppCheck (~> 12.8.0)
- Firebase/Auth (12.8.0):
- Firebase/CoreOnly
- FirebaseAuth (~> 12.8.0)
- Firebase/CoreOnly (12.8.0):
- FirebaseCore (~> 12.8.0)
- firebase_app_check (0.4.1-4):
- Firebase/AppCheck (~> 12.8.0)
- Firebase/CoreOnly (~> 12.8.0)
- firebase_core
- FlutterMacOS
- firebase_auth (6.1.4):
- Firebase/Auth (~> 12.8.0)
- Firebase/CoreOnly (~> 12.8.0)
- firebase_core
- FlutterMacOS
- firebase_core (4.4.0):
- Firebase/CoreOnly (~> 12.8.0)
- FlutterMacOS
- FirebaseAppCheck (12.8.0):
- AppCheckCore (~> 11.0)
- FirebaseAppCheckInterop (~> 12.8.0)
- FirebaseCore (~> 12.8.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/UserDefaults (~> 8.1)
- FirebaseAppCheckInterop (12.8.0)
- FirebaseAuth (12.8.0):
- FirebaseAppCheckInterop (~> 12.8.0)
- FirebaseAuthInterop (~> 12.8.0)
- FirebaseCore (~> 12.8.0)
- FirebaseCoreExtension (~> 12.8.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
- GoogleUtilities/Environment (~> 8.1)
- GTMSessionFetcher/Core (< 6.0, >= 3.4)
- RecaptchaInterop (~> 101.0)
- FirebaseAuthInterop (12.8.0)
- FirebaseCore (12.8.0):
- FirebaseCoreInternal (~> 12.8.0)
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
- FirebaseCoreExtension (12.8.0):
- FirebaseCore (~> 12.8.0)
- FirebaseCoreInternal (12.8.0):
- "GoogleUtilities/NSData+zlib (~> 8.1)"
- FlutterMacOS (1.0.0) - FlutterMacOS (1.0.0)
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (8.1.0):
- GoogleUtilities/Privacy
- GoogleUtilities/Logger (8.1.0):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/Network (8.1.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (8.1.0)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (8.1.0)
- GoogleUtilities/Reachability (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (8.1.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GTMSessionFetcher/Core (5.0.0)
- PromisesObjC (2.4.0)
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
DEPENDENCIES: DEPENDENCIES:
- firebase_app_check (from `Flutter/ephemeral/.symlinks/plugins/firebase_app_check/macos`)
- firebase_auth (from `Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos`)
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- geolocator_apple (from `Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
SPEC REPOS:
trunk:
- AppCheckCore
- Firebase
- FirebaseAppCheck
- FirebaseAppCheckInterop
- FirebaseAuth
- FirebaseAuthInterop
- FirebaseCore
- FirebaseCoreExtension
- FirebaseCoreInternal
- GoogleUtilities
- GTMSessionFetcher
- PromisesObjC
EXTERNAL SOURCES: EXTERNAL SOURCES:
firebase_app_check:
:path: Flutter/ephemeral/.symlinks/plugins/firebase_app_check/macos
firebase_auth:
:path: Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos
firebase_core:
:path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos
FlutterMacOS: FlutterMacOS:
:path: Flutter/ephemeral :path: Flutter/ephemeral
geolocator_apple:
:path: Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin
shared_preferences_foundation: shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
SPEC CHECKSUMS: SPEC CHECKSUMS:
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
Firebase: 9a58fdbc9d8655ed7b79a19cf9690bb007d3d46d
firebase_app_check: daf97f2d7044e28b68d23bc90e16751acee09732
firebase_auth: 2c2438e41f061c03bd67dcb045dfd7bc843b5f52
firebase_core: b1697fb64ff2b9ca16baaa821205f8b0c058e5d2
FirebaseAppCheck: 11da425929a45c677d537adfff3520ccd57c1690
FirebaseAppCheckInterop: ba3dc604a89815379e61ec2365101608d365cf7d
FirebaseAuth: 4c289b1a43f5955283244a55cf6bd616de344be5
FirebaseAuthInterop: 95363fe96493cb4f106656666a0768b420cba090
FirebaseCore: 0dbad74bda10b8fb9ca34ad8f375fb9dd3ebef7c
FirebaseCoreExtension: 6605938d51f765d8b18bfcafd2085276a252bee2
FirebaseCoreInternal: fe5fa466aeb314787093a7dce9f0beeaad5a2a21
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
GTMSessionFetcher: 02d6e866e90bc236f48a703a041dfe43e6221a29
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009 PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009

View File

@@ -1,20 +1,17 @@
name: krowwithus_staff name: krowwithus_staff
description: "Krow Staff Application" description: "Krow Staff Application"
publish_to: 'none' publish_to: 'none'
version: 0.0.1+M301 version: 0.0.1-M3+3
resolution: workspace resolution: workspace
environment: environment:
sdk: ^3.10.7 sdk: '>=3.10.0 <4.0.0'
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
cupertino_icons: ^1.0.8 # Architecture Packages
flutter_modular: ^6.3.0
# Architecture Packages
design_system: design_system:
path: ../../packages/design_system path: ../../packages/design_system
core_localization: core_localization:
@@ -23,6 +20,18 @@ dependencies:
# Feature Packages # Feature Packages
staff_authentication: staff_authentication:
path: ../../packages/features/staff/authentication path: ../../packages/features/staff/authentication
staff_availability:
path: ../../packages/features/staff/availability
staff_clock_in:
path: ../../packages/features/staff/clock_in
staff_main:
path: ../../packages/features/staff/staff_main
krow_core:
path: ../../packages/core
cupertino_icons: ^1.0.8
flutter_modular: ^6.3.0
firebase_core: ^4.4.0
flutter_bloc: ^8.1.6
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@@ -34,5 +34,28 @@
</head> </head>
<body> <body>
<script src="flutter_bootstrap.js" async></script> <script src="flutter_bootstrap.js" async></script>
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-analytics.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyBqRtZPMGU-Sz5x5UnRrunKu5NSWYyPRn8",
authDomain: "krow-workforce-dev.firebaseapp.com",
projectId: "krow-workforce-dev",
storageBucket: "krow-workforce-dev.firebasestorage.app",
messagingSenderId: "933560802882",
appId: "1:933560802882:web:4508ef1ee6d4e6907757db",
measurementId: "G-DTDL7YRRM6"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
</script>
</body> </body>
</html> </html>

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_auth-6.1.4/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_core-4.4.0/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/

View File

@@ -1 +0,0 @@
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/

View File

@@ -8,10 +8,16 @@
#include <firebase_auth/firebase_auth_plugin_c_api.h> #include <firebase_auth/firebase_auth_plugin_c_api.h>
#include <firebase_core/firebase_core_plugin_c_api.h> #include <firebase_core/firebase_core_plugin_c_api.h>
#include <geolocator_windows/geolocator_windows.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FirebaseAuthPluginCApiRegisterWithRegistrar( FirebaseAuthPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi"));
FirebaseCorePluginCApiRegisterWithRegistrar( FirebaseCorePluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
GeolocatorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GeolocatorWindows"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
} }

View File

@@ -5,6 +5,8 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
firebase_auth firebase_auth
firebase_core firebase_core
geolocator_windows
permission_handler_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@@ -0,0 +1,3 @@
{
"GOOGLE_PLACES_API_KEY": "AIzaSyAS9yTf4q51_CNSZ7mbmeS9V3l_LZR80lU"
}

View File

@@ -2,3 +2,5 @@ library core;
export 'src/domain/arguments/usecase_argument.dart'; export 'src/domain/arguments/usecase_argument.dart';
export 'src/domain/usecases/usecase.dart'; export 'src/domain/usecases/usecase.dart';
export 'src/utils/date_time_utils.dart';
export 'src/presentation/widgets/web_mobile_frame.dart';

View File

@@ -0,0 +1,263 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/// A wrapper widget that renders the application inside an iPhone-like frame
/// specifically for Flutter Web. On other platforms, it simply returns the child.
class WebMobileFrame extends StatelessWidget {
const WebMobileFrame({
super.key,
required this.child,
required this.logo,
required this.appName,
});
final Widget child;
final Widget logo;
final String appName;
@override
Widget build(BuildContext context) {
if (!kIsWeb) return child;
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
home: _WebFrameContent(logo: logo, appName: appName, child: child),
);
}
}
class _WebFrameContent extends StatefulWidget {
const _WebFrameContent({
required this.child,
required this.logo,
required this.appName,
});
final Widget child;
final Widget logo;
final String appName;
@override
State<_WebFrameContent> createState() => _WebFrameContentState();
}
class _WebFrameContentState extends State<_WebFrameContent> {
// ignore: unused_field
Offset _cursorPosition = Offset.zero;
// ignore: unused_field
bool _isHovering = false;
@override
Widget build(BuildContext context) {
// iPhone 14 Pro Max-ish dimensions (scaled for frame look)
const double frameWidth = 390 * 1.2;
const double frameHeight = 844 * 1.3;
const double borderRadius = 54.0;
const double borderThickness = 12.0;
return Scaffold(
backgroundColor: UiColors.foreground,
body: MouseRegion(
cursor: SystemMouseCursors.none,
onHover: (PointerHoverEvent event) {
setState(() {
_cursorPosition = event.position;
_isHovering = true;
});
},
onExit: (_) => setState(() => _isHovering = false),
child: Stack(
children: <Widget>[
// Logo and Title on the left (Web only)
Positioned(
left: 60,
top: 0,
bottom: 0,
child: Center(
child: Opacity(
opacity: 0.5,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(width: 140, child: widget.logo),
const SizedBox(height: 12),
Text(
widget.appName,
textAlign: TextAlign.left,
style: UiTypography.display1b.copyWith(
color: UiColors.white,
),
),
const SizedBox(height: 4),
Container(
height: 2,
width: 40,
color: UiColors.white.withOpacity(0.3),
),
],
),
),
),
),
// Frame and Content
Center(
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
// Scale down if screen is too small
final double scaleX = constraints.maxWidth / (frameWidth - 150);
final double scaleY = constraints.maxHeight / (frameHeight - 220);
final double scale = (scaleX < 1 || scaleY < 1)
? (scaleX < scaleY ? scaleX : scaleY)
: 1.0;
return Transform.scale(
scale: scale,
child: Container(
width: frameWidth,
height: frameHeight,
decoration: BoxDecoration(
color: UiColors.black,
borderRadius: BorderRadius.circular(borderRadius),
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.6),
blurRadius: 40,
spreadRadius: 10,
),
],
border: Border.all(
color: const Color(0xFF2C2C2C),
width: borderThickness,
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
borderRadius - borderThickness,
),
child: Stack(
children: <Widget>[
// The actual app + status bar
Column(
children: <Widget>[
// Mock iOS Status Bar
Container(
height: 48,
padding: const EdgeInsets.symmetric(
horizontal: 24,
),
decoration: const BoxDecoration(
color: UiColors.background,
border: Border(
bottom: BorderSide(
color: UiColors.border,
width: 0.5,
),
),
),
child: const Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
// Time side
SizedBox(
width: 80,
child: Text(
'9:41 PM',
textAlign: TextAlign.center,
style: TextStyle(
color: UiColors.black,
fontWeight: FontWeight.w700,
fontSize: 14,
letterSpacing: -0.2,
),
),
),
// Status Icons side
SizedBox(
width: 80,
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
spacing: 12,
children: <Widget>[
Icon(
Icons.signal_cellular_alt,
size: 14,
color: UiColors.black,
),
Icon(
Icons.wifi,
size: 14,
color: UiColors.black,
),
Icon(
Icons.battery_full,
size: 14,
color: UiColors.black,
),
],
),
),
],
),
),
// The main app content
Expanded(child: widget.child),
],
),
// Dynamic Island / Notch Mockup
Align(
alignment: Alignment.topCenter,
child: Container(
width: 120,
height: 35,
margin: const EdgeInsets.only(top: 10),
decoration: BoxDecoration(
color: UiColors.black,
borderRadius: BorderRadius.circular(20),
),
),
),
],
),
),
),
);
},
),
),
if (_isHovering)
Positioned(
left: _cursorPosition.dx - 15,
top: _cursorPosition.dy - 15,
child: IgnorePointer(
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: UiColors.mutedForeground.withOpacity(0.3),
shape: BoxShape.circle,
border: Border.all(color: UiColors.white.withOpacity(0.7), width: 2),
boxShadow: <BoxShadow>[
BoxShadow(
color: UiColors.black.withOpacity(0.2),
blurRadius: 4,
spreadRadius: 1,
),
],
),
),
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,7 @@
class DateTimeUtils {
/// Converts a [DateTime] (assumed UTC if not specified) to the device's local time.
static DateTime toDeviceTime(DateTime date) {
return date.toLocal();
}
}

View File

@@ -11,3 +11,5 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
design_system:
path: ../design_system

View File

@@ -8,3 +8,4 @@ export 'src/domain/usecases/set_locale_use_case.dart';
export 'src/data/repositories_impl/locale_repository_impl.dart'; export 'src/data/repositories_impl/locale_repository_impl.dart';
export 'src/data/datasources/locale_local_data_source.dart'; export 'src/data/datasources/locale_local_data_source.dart';
export 'src/localization_module.dart'; export 'src/localization_module.dart';
export 'src/utils/error_translator.dart';

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import '../domain/usecases/get_default_locale_use_case.dart';
import '../domain/usecases/get_locale_use_case.dart'; import '../domain/usecases/get_locale_use_case.dart';
import '../domain/usecases/get_supported_locales_use_case.dart';
import '../domain/usecases/set_locale_use_case.dart'; import '../domain/usecases/set_locale_use_case.dart';
import '../l10n/strings.g.dart'; import '../l10n/strings.g.dart';
import 'locale_event.dart'; import 'locale_event.dart';
@@ -11,27 +13,43 @@ import 'locale_state.dart';
/// It coordinates the flow between user language requests and persistent storage /// It coordinates the flow between user language requests and persistent storage
/// using [SetLocaleUseCase] and [GetLocaleUseCase]. /// using [SetLocaleUseCase] and [GetLocaleUseCase].
class LocaleBloc extends Bloc<LocaleEvent, LocaleState> { class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
final GetLocaleUseCase getLocaleUseCase;
final SetLocaleUseCase setLocaleUseCase;
/// Creates a [LocaleBloc] with the required use cases. /// Creates a [LocaleBloc] with the required use cases.
LocaleBloc({required this.getLocaleUseCase, required this.setLocaleUseCase}) LocaleBloc({
: super(LocaleState.initial()) { required this.getLocaleUseCase,
required this.setLocaleUseCase,
required this.getSupportedLocalesUseCase,
required this.getDefaultLocaleUseCase,
}) : super(LocaleState.initial()) {
on<ChangeLocale>(_onChangeLocale); on<ChangeLocale>(_onChangeLocale);
on<LoadLocale>(_onLoadLocale); on<LoadLocale>(_onLoadLocale);
/// Initial event
add(const LoadLocale());
} }
/// Use case for retrieving the saved locale.
final GetLocaleUseCase getLocaleUseCase;
/// Use case for saving the selected locale.
final SetLocaleUseCase setLocaleUseCase;
/// Use case for retrieving supported locales.
final GetSupportedLocalesUseCase getSupportedLocalesUseCase;
/// Use case for retrieving the default locale.
final GetDefaultLocaleUseCase getDefaultLocaleUseCase;
/// Handles the [ChangeLocale] event by saving it via the use case and emitting new state. /// Handles the [ChangeLocale] event by saving it via the use case and emitting new state.
Future<void> _onChangeLocale( Future<void> _onChangeLocale(
ChangeLocale event, ChangeLocale event,
Emitter<LocaleState> emit, Emitter<LocaleState> emit,
) async { ) async {
// 1. Update slang settings // 1. Update slang settings
LocaleSettings.setLocaleRaw(event.locale.languageCode); await LocaleSettings.setLocaleRaw(event.locale.languageCode);
// 2. Persist using Use Case // 2. Persist using Use Case
await setLocaleUseCase(event.locale); await setLocaleUseCase(event.locale);
// 3. Emit new state // 3. Emit new state
emit( emit(
LocaleState( LocaleState(
@@ -46,11 +64,14 @@ class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
LoadLocale event, LoadLocale event,
Emitter<LocaleState> emit, Emitter<LocaleState> emit,
) async { ) async {
final Locale? savedLocale = await getLocaleUseCase(); final Locale savedLocale = await getLocaleUseCase();
final Locale locale = const Locale('es'); final List<Locale> supportedLocales = getSupportedLocalesUseCase();
LocaleSettings.setLocaleRaw(locale.languageCode); await LocaleSettings.setLocaleRaw(savedLocale.languageCode);
emit(LocaleState(locale: locale, supportedLocales: state.supportedLocales)); emit(LocaleState(
locale: savedLocale,
supportedLocales: supportedLocales,
));
} }
} }

View File

@@ -1,20 +1,21 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../l10n/strings.g.dart'; import '../l10n/strings.g.dart';
/// Represents the current state of the application's localization. /// Represents the current state of the application's localization.
class LocaleState { class LocaleState {
/// Creates a [LocaleState] with the specified [locale].
const LocaleState({required this.locale, required this.supportedLocales});
/// The initial state of the application, defaulting to English.
factory LocaleState.initial() => LocaleState(
locale: AppLocaleUtils.findDeviceLocale().flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
);
/// The current active locale. /// The current active locale.
final Locale locale; final Locale locale;
/// The list of supported locales for the application. /// The list of supported locales for the application.
final List<Locale> supportedLocales; final List<Locale> supportedLocales;
/// Creates a [LocaleState] with the specified [locale].
const LocaleState({required this.locale, required this.supportedLocales});
/// The initial state of the application, defaulting to English.
factory LocaleState.initial() => LocaleState(
locale: const Locale('es'),
supportedLocales: AppLocaleUtils.supportedLocales,
);
} }

View File

@@ -1,4 +1,6 @@
import 'dart:ui'; import 'dart:ui';
import 'package:core_localization/src/l10n/strings.g.dart';
import '../../domain/repositories/locale_repository_interface.dart'; import '../../domain/repositories/locale_repository_interface.dart';
import '../datasources/locale_local_data_source.dart'; import '../datasources/locale_local_data_source.dart';
@@ -7,22 +9,36 @@ import '../datasources/locale_local_data_source.dart';
/// This class handles the mapping between domain [Locale] objects and the raw /// This class handles the mapping between domain [Locale] objects and the raw
/// strings handled by the [LocaleLocalDataSource]. /// strings handled by the [LocaleLocalDataSource].
class LocaleRepositoryImpl implements LocaleRepositoryInterface { class LocaleRepositoryImpl implements LocaleRepositoryInterface {
final LocaleLocalDataSource _localDataSource; /// Creates a [LocaleRepositoryImpl] with the provided [localDataSource].
LocaleRepositoryImpl({required this.localDataSource});
/// Creates a [LocaleRepositoryImpl] with the provided [_localDataSource]. final LocaleLocalDataSource localDataSource;
LocaleRepositoryImpl(this._localDataSource);
@override @override
Future<void> saveLocale(Locale locale) { Future<void> saveLocale(Locale locale) {
return _localDataSource.saveLanguageCode(locale.languageCode); return localDataSource.saveLanguageCode(locale.languageCode);
} }
@override @override
Future<Locale?> getSavedLocale() async { Future<Locale> getSavedLocale() async {
final String? languageCode = await _localDataSource.getLanguageCode(); return getDefaultLocale();
/// TODO: FEATURE_NOT_IMPLEMENTED: Implement saved locale retrieval later
final String? languageCode = await localDataSource.getLanguageCode();
if (languageCode != null) { if (languageCode != null) {
return Locale(languageCode); return Locale(languageCode);
} }
return null;
} }
@override
Locale getDefaultLocale() {
final Locale deviceLocale = AppLocaleUtils.findDeviceLocale().flutterLocale;
if (getSupportedLocales().contains(deviceLocale)) {
return deviceLocale;
}
return const Locale('en');
}
@override
List<Locale> getSupportedLocales() => AppLocaleUtils.supportedLocales;
} }

View File

@@ -13,5 +13,11 @@ abstract interface class LocaleRepositoryInterface {
/// Retrieves the saved [locale] from persistent storage. /// Retrieves the saved [locale] from persistent storage.
/// ///
/// Returns `null` if no locale has been previously saved. /// Returns `null` if no locale has been previously saved.
Future<Locale?> getSavedLocale(); Future<Locale> getSavedLocale();
/// Retrieves the default [Locale] for the application.
Locale getDefaultLocale();
/// Retrieves the list of supported [Locale]s.
List<Locale> getSupportedLocales();
} }

View File

@@ -0,0 +1,15 @@
import 'dart:ui';
import '../repositories/locale_repository_interface.dart';
/// Use case to retrieve the default locale.
class GetDefaultLocaleUseCase {
final LocaleRepositoryInterface _repository;
/// Creates a [GetDefaultLocaleUseCase] with the required [LocaleRepositoryInterface].
GetDefaultLocaleUseCase(this._repository);
/// Retrieves the default locale.
Locale call() {
return _repository.getDefaultLocale();
}
}

View File

@@ -13,7 +13,7 @@ class GetLocaleUseCase extends NoInputUseCase<Locale?> {
GetLocaleUseCase(this._repository); GetLocaleUseCase(this._repository);
@override @override
Future<Locale?> call() { Future<Locale> call() {
return _repository.getSavedLocale(); return _repository.getSavedLocale();
} }
} }

View File

@@ -0,0 +1,15 @@
import 'dart:ui';
import '../repositories/locale_repository_interface.dart';
/// Use case to retrieve the list of supported locales.
class GetSupportedLocalesUseCase {
final LocaleRepositoryInterface _repository;
/// Creates a [GetSupportedLocalesUseCase] with the required [LocaleRepositoryInterface].
GetSupportedLocalesUseCase(this._repository);
/// Retrieves the supported locales.
List<Locale> call() {
return _repository.getSupportedLocales();
}
}

View File

@@ -517,6 +517,8 @@
"secure_subtitle": "Your account details are encrypted and safe.", "secure_subtitle": "Your account details are encrypted and safe.",
"primary": "Primary", "primary": "Primary",
"add_new_account": "Add New Account", "add_new_account": "Add New Account",
"bank_name": "Bank Name",
"bank_hint": "Enter bank name",
"routing_number": "Routing Number", "routing_number": "Routing Number",
"routing_hint": "Enter routing number", "routing_hint": "Enter routing number",
"account_number": "Account Number", "account_number": "Account Number",
@@ -526,7 +528,8 @@
"savings": "Savings", "savings": "Savings",
"cancel": "Cancel", "cancel": "Cancel",
"save": "Save", "save": "Save",
"account_ending": "Ending in $last4" "account_ending": "Ending in $last4",
"account_added_success": "Bank account added successfully!"
}, },
"logout": { "logout": {
"button": "Sign Out" "button": "Sign Out"
@@ -725,6 +728,60 @@
"paid": "Paid", "paid": "Paid",
"pending": "Pending" "pending": "Pending"
} }
},
"errors": {
"auth": {
"invalid_credentials": "The email or password you entered is incorrect.",
"account_exists": "An account with this email already exists. Try signing in instead.",
"session_expired": "Your session has expired. Please sign in again.",
"user_not_found": "We couldn't find your account. Please check your email and try again.",
"unauthorized_app": "This account is not authorized for this app.",
"weak_password": "Please choose a stronger password with at least 8 characters.",
"sign_up_failed": "We couldn't create your account. Please try again.",
"sign_in_failed": "We couldn't sign you in. Please try again.",
"not_authenticated": "Please sign in to continue.",
"password_mismatch": "This email is already registered. Please use the correct password or tap 'Forgot Password' to reset it.",
"google_only_account": "This email is registered via Google. Please use 'Forgot Password' to set a password, then try signing up again with the same information."
},
"hub": {
"has_orders": "This hub has active orders and cannot be deleted.",
"not_found": "The hub you're looking for doesn't exist.",
"creation_failed": "We couldn't create the hub. Please try again."
},
"order": {
"missing_hub": "Please select a location for your order.",
"missing_vendor": "Please select a vendor for your order.",
"creation_failed": "We couldn't create your order. Please try again.",
"shift_creation_failed": "We couldn't schedule the shift. Please try again.",
"missing_business": "Your business profile couldn't be loaded. Please sign in again."
},
"profile": {
"staff_not_found": "Your profile couldn't be loaded. Please sign in again.",
"business_not_found": "Your business profile couldn't be loaded. Please sign in again.",
"update_failed": "We couldn't update your profile. Please try again."
},
"shift": {
"no_open_roles": "There are no open positions available for this shift.",
"application_not_found": "Your application couldn't be found.",
"no_active_shift": "You don't have an active shift to clock out from."
},
"generic": {
"unknown": "Something went wrong. Please try again.",
"no_connection": "No internet connection. Please check your network and try again."
}
},
"success": {
"hub": {
"created": "Hub created successfully!",
"deleted": "Hub deleted successfully!",
"nfc_assigned": "NFC tag assigned successfully!"
},
"order": {
"created": "Order created successfully!"
},
"profile": {
"updated": "Profile updated successfully!"
}
} }
} }

View File

@@ -515,6 +515,8 @@
"secure_title": "Seguro y Cifrado", "secure_title": "Seguro y Cifrado",
"secure_subtitle": "Su información bancaria está cifrada y almacenada de forma segura. Nunca compartimos sus detalles.", "secure_subtitle": "Su información bancaria está cifrada y almacenada de forma segura. Nunca compartimos sus detalles.",
"add_new_account": "Agregar Nueva Cuenta", "add_new_account": "Agregar Nueva Cuenta",
"bank_name": "Nombre del Banco",
"bank_hint": "Ingrese nombre del banco",
"routing_number": "Número de Ruta", "routing_number": "Número de Ruta",
"routing_hint": "9 dígitos", "routing_hint": "9 dígitos",
"account_number": "Número de Cuenta", "account_number": "Número de Cuenta",
@@ -525,7 +527,8 @@
"cancel": "Cancelar", "cancel": "Cancelar",
"save": "Guardar", "save": "Guardar",
"primary": "Principal", "primary": "Principal",
"account_ending": "Termina en $last4" "account_ending": "Termina en $last4",
"account_added_success": "¡Cuenta bancaria agregada exitosamente!"
}, },
"logout": { "logout": {
"button": "Cerrar Sesión" "button": "Cerrar Sesión"
@@ -724,5 +727,59 @@
"paid": "Pagado", "paid": "Pagado",
"pending": "Pendiente" "pending": "Pendiente"
} }
},
"errors": {
"auth": {
"invalid_credentials": "El correo electrónico o la contraseña que ingresaste es incorrecta.",
"account_exists": "Ya existe una cuenta con este correo electrónico. Intenta iniciar sesión.",
"session_expired": "Tu sesión ha expirado. Por favor, inicia sesión de nuevo.",
"user_not_found": "No pudimos encontrar tu cuenta. Por favor, verifica tu correo electrónico e intenta de nuevo.",
"unauthorized_app": "Esta cuenta no está autorizada para esta aplicación.",
"weak_password": "Por favor, elige una contraseña más segura con al menos 8 caracteres.",
"sign_up_failed": "No pudimos crear tu cuenta. Por favor, intenta de nuevo.",
"sign_in_failed": "No pudimos iniciar sesión. Por favor, intenta de nuevo.",
"not_authenticated": "Por favor, inicia sesión para continuar.",
"password_mismatch": "Este correo ya está registrado. Por favor, usa la contraseña correcta o toca 'Olvidé mi contraseña' para restablecerla.",
"google_only_account": "Este correo está registrado con Google. Por favor, usa 'Olvidé mi contraseña' para establecer una contraseña, luego intenta registrarte de nuevo con la misma información."
},
"hub": {
"has_orders": "Este hub tiene órdenes activas y no puede ser eliminado.",
"not_found": "El hub que buscas no existe.",
"creation_failed": "No pudimos crear el hub. Por favor, intenta de nuevo."
},
"order": {
"missing_hub": "Por favor, selecciona una ubicación para tu orden.",
"missing_vendor": "Por favor, selecciona un proveedor para tu orden.",
"creation_failed": "No pudimos crear tu orden. Por favor, intenta de nuevo.",
"shift_creation_failed": "No pudimos programar el turno. Por favor, intenta de nuevo.",
"missing_business": "No se pudo cargar tu perfil de empresa. Por favor, inicia sesión de nuevo."
},
"profile": {
"staff_not_found": "No se pudo cargar tu perfil. Por favor, inicia sesión de nuevo.",
"business_not_found": "No se pudo cargar tu perfil de empresa. Por favor, inicia sesión de nuevo.",
"update_failed": "No pudimos actualizar tu perfil. Por favor, intenta de nuevo."
},
"shift": {
"no_open_roles": "No hay posiciones abiertas disponibles para este turno.",
"application_not_found": "No se pudo encontrar tu solicitud.",
"no_active_shift": "No tienes un turno activo para registrar salida."
},
"generic": {
"unknown": "Algo salió mal. Por favor, intenta de nuevo.",
"no_connection": "Sin conexión a internet. Por favor, verifica tu red e intenta de nuevo."
}
},
"success": {
"hub": {
"created": "¡Hub creado exitosamente!",
"deleted": "¡Hub eliminado exitosamente!",
"nfc_assigned": "¡Etiqueta NFC asignada exitosamente!"
},
"order": {
"created": "¡Orden creada exitosamente!"
},
"profile": {
"updated": "¡Perfil actualizado exitosamente!"
}
} }
} }

View File

@@ -1,183 +0,0 @@
/// Generated file. Do not edit.
///
/// Source: lib/src/l10n
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 1038 (519 per locale)
///
/// Built on 2026-01-27 at 19:37 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import
// dart format off
import 'package:flutter/widgets.dart';
import 'package:intl/intl.dart';
import 'package:slang/generated.dart';
import 'package:slang_flutter/slang_flutter.dart';
export 'package:slang_flutter/slang_flutter.dart';
import 'strings_es.g.dart' deferred as l_es;
part 'strings_en.g.dart';
/// Supported locales.
///
/// Usage:
/// - LocaleSettings.setLocale(AppLocale.en) // set locale
/// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum
/// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check
enum AppLocale with BaseAppLocale<AppLocale, Translations> {
en(languageCode: 'en'),
es(languageCode: 'es');
const AppLocale({
required this.languageCode,
this.scriptCode, // ignore: unused_element, unused_element_parameter
this.countryCode, // ignore: unused_element, unused_element_parameter
});
@override final String languageCode;
@override final String? scriptCode;
@override final String? countryCode;
@override
Future<Translations> build({
Map<String, Node>? overrides,
PluralResolver? cardinalResolver,
PluralResolver? ordinalResolver,
}) async {
switch (this) {
case AppLocale.en:
return TranslationsEn(
overrides: overrides,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
case AppLocale.es:
await l_es.loadLibrary();
return l_es.TranslationsEs(
overrides: overrides,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
}
}
@override
Translations buildSync({
Map<String, Node>? overrides,
PluralResolver? cardinalResolver,
PluralResolver? ordinalResolver,
}) {
switch (this) {
case AppLocale.en:
return TranslationsEn(
overrides: overrides,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
case AppLocale.es:
return l_es.TranslationsEs(
overrides: overrides,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
}
}
/// Gets current instance managed by [LocaleSettings].
Translations get translations => LocaleSettings.instance.getTranslations(this);
}
/// Method A: Simple
///
/// No rebuild after locale change.
/// Translation happens during initialization of the widget (call of t).
/// Configurable via 'translate_var'.
///
/// Usage:
/// String a = t.someKey.anotherKey;
/// String b = t['someKey.anotherKey']; // Only for edge cases!
Translations get t => LocaleSettings.instance.currentTranslations;
/// Method B: Advanced
///
/// All widgets using this method will trigger a rebuild when locale changes.
/// Use this if you have e.g. a settings page where the user can select the locale during runtime.
///
/// Step 1:
/// wrap your App with
/// TranslationProvider(
/// child: MyApp()
/// );
///
/// Step 2:
/// final t = Translations.of(context); // Get t variable.
/// String a = t.someKey.anotherKey; // Use t variable.
/// String b = t['someKey.anotherKey']; // Only for edge cases!
class TranslationProvider extends BaseTranslationProvider<AppLocale, Translations> {
TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance);
static InheritedLocaleData<AppLocale, Translations> of(BuildContext context) => InheritedLocaleData.of<AppLocale, Translations>(context);
}
/// Method B shorthand via [BuildContext] extension method.
/// Configurable via 'translate_var'.
///
/// Usage (e.g. in a widget's build method):
/// context.t.someKey.anotherKey
extension BuildContextTranslationsExtension on BuildContext {
Translations get t => TranslationProvider.of(this).translations;
}
/// Manages all translation instances and the current locale
class LocaleSettings extends BaseFlutterLocaleSettings<AppLocale, Translations> {
LocaleSettings._() : super(
utils: AppLocaleUtils.instance,
lazy: true,
);
static final instance = LocaleSettings._();
// static aliases (checkout base methods for documentation)
static AppLocale get currentLocale => instance.currentLocale;
static Stream<AppLocale> getLocaleStream() => instance.getLocaleStream();
static Future<AppLocale> setLocale(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocale(locale, listenToDeviceLocale: listenToDeviceLocale);
static Future<AppLocale> setLocaleRaw(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRaw(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
static Future<AppLocale> useDeviceLocale() => instance.useDeviceLocale();
static Future<void> setPluralResolver({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolver(
language: language,
locale: locale,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
// synchronous versions
static AppLocale setLocaleSync(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocaleSync(locale, listenToDeviceLocale: listenToDeviceLocale);
static AppLocale setLocaleRawSync(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRawSync(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
static AppLocale useDeviceLocaleSync() => instance.useDeviceLocaleSync();
static void setPluralResolverSync({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolverSync(
language: language,
locale: locale,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
}
/// Provides utility functions without any side effects.
class AppLocaleUtils extends BaseAppLocaleUtils<AppLocale, Translations> {
AppLocaleUtils._() : super(
baseLocale: AppLocale.en,
locales: AppLocale.values,
);
static final instance = AppLocaleUtils._();
// static aliases (checkout base methods for documentation)
static AppLocale parse(String rawLocale) => instance.parse(rawLocale);
static AppLocale parseLocaleParts({required String languageCode, String? scriptCode, String? countryCode}) => instance.parseLocaleParts(languageCode: languageCode, scriptCode: scriptCode, countryCode: countryCode);
static AppLocale findDeviceLocale() => instance.findDeviceLocale();
static List<Locale> get supportedLocales => instance.supportedLocales;
static List<String> get supportedLocalesRaw => instance.supportedLocalesRaw;
}

View File

@@ -3,7 +3,9 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'data/datasources/locale_local_data_source.dart'; import 'data/datasources/locale_local_data_source.dart';
import 'data/repositories_impl/locale_repository_impl.dart'; import 'data/repositories_impl/locale_repository_impl.dart';
import 'domain/repositories/locale_repository_interface.dart'; import 'domain/repositories/locale_repository_interface.dart';
import 'domain/usecases/get_default_locale_use_case.dart';
import 'domain/usecases/get_locale_use_case.dart'; import 'domain/usecases/get_locale_use_case.dart';
import 'domain/usecases/get_supported_locales_use_case.dart';
import 'domain/usecases/set_locale_use_case.dart'; import 'domain/usecases/set_locale_use_case.dart';
import 'bloc/locale_bloc.dart'; import 'bloc/locale_bloc.dart';
@@ -18,28 +20,36 @@ class LocalizationModule extends Module {
i.addInstance<SharedPreferencesAsync>(SharedPreferencesAsync()); i.addInstance<SharedPreferencesAsync>(SharedPreferencesAsync());
// Data Sources // Data Sources
i.addSingleton<LocaleLocalDataSource>( i.addLazySingleton<LocaleLocalDataSource>(
() => LocaleLocalDataSourceImpl(i.get<SharedPreferencesAsync>()), () => LocaleLocalDataSourceImpl(i.get<SharedPreferencesAsync>()),
); );
// Repositories // Repositories
i.addSingleton<LocaleRepositoryInterface>( i.addLazySingleton<LocaleRepositoryInterface>(
() => LocaleRepositoryImpl(i.get<LocaleLocalDataSource>()), () => LocaleRepositoryImpl(localDataSource: i.get<LocaleLocalDataSource>()),
); );
// Use Cases // Use Cases
i.addSingleton<GetLocaleUseCase>( i.addLazySingleton<GetLocaleUseCase>(
() => GetLocaleUseCase(i.get<LocaleRepositoryInterface>()), () => GetLocaleUseCase(i.get<LocaleRepositoryInterface>()),
); );
i.addSingleton<SetLocaleUseCase>( i.addLazySingleton<SetLocaleUseCase>(
() => SetLocaleUseCase(i.get<LocaleRepositoryInterface>()), () => SetLocaleUseCase(i.get<LocaleRepositoryInterface>()),
); );
i.addLazySingleton<GetSupportedLocalesUseCase>(
() => GetSupportedLocalesUseCase(i.get<LocaleRepositoryInterface>()),
);
i.addLazySingleton<GetDefaultLocaleUseCase>(
() => GetDefaultLocaleUseCase(i.get<LocaleRepositoryInterface>()),
);
// BLoCs // BLoCs
i.addSingleton<LocaleBloc>( i.add<LocaleBloc>(
() => LocaleBloc( () => LocaleBloc(
getLocaleUseCase: i.get<GetLocaleUseCase>(), getLocaleUseCase: i.get<GetLocaleUseCase>(),
setLocaleUseCase: i.get<SetLocaleUseCase>(), setLocaleUseCase: i.get<SetLocaleUseCase>(),
getSupportedLocalesUseCase: i.get<GetSupportedLocalesUseCase>(),
getDefaultLocaleUseCase: i.get<GetDefaultLocaleUseCase>(),
), ),
); );
} }

View File

@@ -0,0 +1,139 @@
import '../l10n/strings.g.dart';
/// Translates error message keys to localized strings.
///
/// This utility function takes a dot-notation key like 'errors.auth.account_exists'
/// and returns the corresponding localized string from the translation system.
///
/// If the key is not found or doesn't match the expected format, the original
/// key is returned as a fallback.
///
/// Example:
/// ```dart
/// final message = translateErrorKey('errors.auth.account_exists');
/// // Returns: "An account with this email already exists. Try signing in instead."
/// ```
String translateErrorKey(String key) {
final List<String> parts = key.split('.');
// Expected format: errors.{category}.{error_type}
if (parts.length != 3 || parts[0] != 'errors') {
return key;
}
final String category = parts[1];
final String errorType = parts[2];
switch (category) {
case 'auth':
return _translateAuthError(errorType);
case 'hub':
return _translateHubError(errorType);
case 'order':
return _translateOrderError(errorType);
case 'profile':
return _translateProfileError(errorType);
case 'shift':
return _translateShiftError(errorType);
case 'generic':
return _translateGenericError(errorType);
default:
return key;
}
}
String _translateAuthError(String errorType) {
switch (errorType) {
case 'invalid_credentials':
return t.errors.auth.invalid_credentials;
case 'account_exists':
return t.errors.auth.account_exists;
case 'session_expired':
return t.errors.auth.session_expired;
case 'user_not_found':
return t.errors.auth.user_not_found;
case 'unauthorized_app':
return t.errors.auth.unauthorized_app;
case 'weak_password':
return t.errors.auth.weak_password;
case 'sign_up_failed':
return t.errors.auth.sign_up_failed;
case 'sign_in_failed':
return t.errors.auth.sign_in_failed;
case 'not_authenticated':
return t.errors.auth.not_authenticated;
case 'password_mismatch':
return t.errors.auth.password_mismatch;
case 'google_only_account':
return t.errors.auth.google_only_account;
default:
return t.errors.generic.unknown;
}
}
String _translateHubError(String errorType) {
switch (errorType) {
case 'has_orders':
return t.errors.hub.has_orders;
case 'not_found':
return t.errors.hub.not_found;
case 'creation_failed':
return t.errors.hub.creation_failed;
default:
return t.errors.generic.unknown;
}
}
String _translateOrderError(String errorType) {
switch (errorType) {
case 'missing_hub':
return t.errors.order.missing_hub;
case 'missing_vendor':
return t.errors.order.missing_vendor;
case 'creation_failed':
return t.errors.order.creation_failed;
case 'shift_creation_failed':
return t.errors.order.shift_creation_failed;
case 'missing_business':
return t.errors.order.missing_business;
default:
return t.errors.generic.unknown;
}
}
String _translateProfileError(String errorType) {
switch (errorType) {
case 'staff_not_found':
return t.errors.profile.staff_not_found;
case 'business_not_found':
return t.errors.profile.business_not_found;
case 'update_failed':
return t.errors.profile.update_failed;
default:
return t.errors.generic.unknown;
}
}
String _translateShiftError(String errorType) {
switch (errorType) {
case 'no_open_roles':
return t.errors.shift.no_open_roles;
case 'application_not_found':
return t.errors.shift.application_not_found;
case 'no_active_shift':
return t.errors.shift.no_active_shift;
default:
return t.errors.generic.unknown;
}
}
String _translateGenericError(String errorType) {
switch (errorType) {
case 'unknown':
return t.errors.generic.unknown;
case 'no_connection':
return t.errors.generic.no_connection;
default:
return t.errors.generic.unknown;
}
}

View File

@@ -3,10 +3,12 @@ import 'package:krow_domain/krow_domain.dart' as domain;
class StaffSession { class StaffSession {
final domain.User user; final domain.User user;
final domain.Staff? staff; final domain.Staff? staff;
final String? ownerId;
const StaffSession({ const StaffSession({
required this.user, required this.user,
this.staff, this.staff,
this.ownerId,
}); });
} }

View File

@@ -14,3 +14,4 @@ dependencies:
krow_domain: krow_domain:
path: ../domain path: ../domain
flutter_modular: ^6.3.0 flutter_modular: ^6.3.0
firebase_data_connect: ^0.2.2+2

View File

@@ -37,4 +37,7 @@ class UiConstants {
static const double space12 = 48.0; static const double space12 = 48.0;
static const double space14 = 56.0; static const double space14 = 56.0;
static const double space16 = 64.0; static const double space16 = 64.0;
static const double space20 = 80.0;
static const double space24 = 96.0;
static const double space32 = 128.0;
} }

View File

@@ -63,6 +63,9 @@ class UiIcons {
/// Checkmark icon /// Checkmark icon
static const IconData check = _IconLib.check; static const IconData check = _IconLib.check;
/// Checkmark circle icon
static const IconData checkCircle = _IconLib.checkCircle;
/// X/Cancel icon /// X/Cancel icon
static const IconData close = _IconLib.x; static const IconData close = _IconLib.x;

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'ui_colors.dart'; import 'ui_colors.dart';
import 'ui_typography.dart';
import 'ui_constants.dart'; import 'ui_constants.dart';
import 'ui_typography.dart';
/// The main entry point for the Staff Design System theme. /// The main entry point for the Staff Design System theme.
/// Assembles colors, typography, and constants into a comprehensive Material 3 theme. /// Assembles colors, typography, and constants into a comprehensive Material 3 theme.

View File

@@ -50,7 +50,7 @@ class UiButton extends StatelessWidget {
this.trailingIcon, this.trailingIcon,
this.style, this.style,
this.iconSize = 20, this.iconSize = 20,
this.size = UiButtonSize.medium, this.size = UiButtonSize.large,
this.fullWidth = false, this.fullWidth = false,
}) : assert( }) : assert(
text != null || child != null, text != null || child != null,
@@ -67,7 +67,7 @@ class UiButton extends StatelessWidget {
this.trailingIcon, this.trailingIcon,
this.style, this.style,
this.iconSize = 20, this.iconSize = 20,
this.size = UiButtonSize.medium, this.size = UiButtonSize.large,
this.fullWidth = false, this.fullWidth = false,
}) : buttonBuilder = _elevatedButtonBuilder, }) : buttonBuilder = _elevatedButtonBuilder,
assert( assert(
@@ -85,7 +85,7 @@ class UiButton extends StatelessWidget {
this.trailingIcon, this.trailingIcon,
this.style, this.style,
this.iconSize = 20, this.iconSize = 20,
this.size = UiButtonSize.medium, this.size = UiButtonSize.large,
this.fullWidth = false, this.fullWidth = false,
}) : buttonBuilder = _outlinedButtonBuilder, }) : buttonBuilder = _outlinedButtonBuilder,
assert( assert(
@@ -103,7 +103,7 @@ class UiButton extends StatelessWidget {
this.trailingIcon, this.trailingIcon,
this.style, this.style,
this.iconSize = 20, this.iconSize = 20,
this.size = UiButtonSize.medium, this.size = UiButtonSize.large,
this.fullWidth = false, this.fullWidth = false,
}) : buttonBuilder = _textButtonBuilder, }) : buttonBuilder = _textButtonBuilder,
assert( assert(
@@ -121,7 +121,7 @@ class UiButton extends StatelessWidget {
this.trailingIcon, this.trailingIcon,
this.style, this.style,
this.iconSize = 20, this.iconSize = 20,
this.size = UiButtonSize.medium, this.size = UiButtonSize.large,
this.fullWidth = false, this.fullWidth = false,
}) : buttonBuilder = _textButtonBuilder, }) : buttonBuilder = _textButtonBuilder,
assert( assert(
@@ -132,10 +132,14 @@ class UiButton extends StatelessWidget {
@override @override
/// Builds the button UI. /// Builds the button UI.
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ButtonStyle? mergedStyle = style != null
? _getSizeStyle().merge(style)
: _getSizeStyle();
final Widget button = buttonBuilder( final Widget button = buttonBuilder(
context, context,
onPressed, onPressed,
style, mergedStyle,
_buildButtonContent(), _buildButtonContent(),
); );
@@ -146,6 +150,65 @@ class UiButton extends StatelessWidget {
return button; return button;
} }
/// Gets the style based on the button size.
ButtonStyle _getSizeStyle() {
switch (size) {
case UiButtonSize.extraSmall:
return ButtonStyle(
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(
horizontal: UiConstants.space2,
vertical: UiConstants.space1,
),
),
minimumSize: WidgetStateProperty.all(const Size(0, 28)),
maximumSize: WidgetStateProperty.all(const Size(double.infinity, 28)),
textStyle: WidgetStateProperty.all(
const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
),
);
case UiButtonSize.small:
return ButtonStyle(
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(
horizontal: UiConstants.space3,
vertical: UiConstants.space2,
),
),
minimumSize: WidgetStateProperty.all(const Size(0, 36)),
maximumSize: WidgetStateProperty.all(const Size(double.infinity, 36)),
textStyle: WidgetStateProperty.all(
const TextStyle(fontSize: 13, fontWeight: FontWeight.w500),
),
);
case UiButtonSize.medium:
return ButtonStyle(
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(
horizontal: UiConstants.space4,
vertical: UiConstants.space3,
),
),
minimumSize: WidgetStateProperty.all(const Size(0, 44)),
maximumSize: WidgetStateProperty.all(const Size(double.infinity, 44)),
);
case UiButtonSize.large:
return ButtonStyle(
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(
horizontal: UiConstants.space6,
vertical: UiConstants.space4,
),
),
minimumSize: WidgetStateProperty.all(const Size(0, 52)),
maximumSize: WidgetStateProperty.all(const Size(double.infinity, 52)),
textStyle: WidgetStateProperty.all(
const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
);
}
}
/// Builds the button content with optional leading and trailing icons. /// Builds the button content with optional leading and trailing icons.
Widget _buildButtonContent() { Widget _buildButtonContent() {
if (child != null) { if (child != null) {
@@ -229,6 +292,9 @@ class UiButton extends StatelessWidget {
/// Defines the size of a [UiButton]. /// Defines the size of a [UiButton].
enum UiButtonSize { enum UiButtonSize {
/// Extra small button (very compact)
extraSmall,
/// Small button (compact) /// Small button (compact)
small, small,

View File

@@ -5,7 +5,7 @@ homepage:
resolution: workspace resolution: workspace
environment: environment:
sdk: ^3.10.7 sdk: '>=3.10.0 <4.0.0'
flutter: ">=1.17.0" flutter: ">=1.17.0"
dependencies: dependencies:

View File

@@ -29,6 +29,7 @@ export 'src/entities/events/work_session.dart';
// Shifts // Shifts
export 'src/entities/shifts/shift.dart'; export 'src/entities/shifts/shift.dart';
export 'src/adapters/shifts/shift_adapter.dart';
// Orders & Requests // Orders & Requests
export 'src/entities/orders/order_type.dart'; export 'src/entities/orders/order_type.dart';
@@ -45,9 +46,11 @@ export 'src/entities/skills/skill_kit.dart';
// Financial & Payroll // Financial & Payroll
export 'src/entities/financial/invoice.dart'; export 'src/entities/financial/invoice.dart';
export 'src/entities/financial/time_card.dart';
export 'src/entities/financial/invoice_item.dart'; export 'src/entities/financial/invoice_item.dart';
export 'src/entities/financial/invoice_decline.dart'; export 'src/entities/financial/invoice_decline.dart';
export 'src/entities/financial/staff_payment.dart'; export 'src/entities/financial/staff_payment.dart';
export 'src/entities/financial/payment_summary.dart';
// Profile // Profile
export 'src/entities/profile/staff_document.dart'; export 'src/entities/profile/staff_document.dart';
@@ -78,12 +81,24 @@ export 'src/entities/home/home_dashboard_data.dart';
export 'src/entities/home/reorder_item.dart'; export 'src/entities/home/reorder_item.dart';
// Availability // Availability
export 'src/adapters/availability/availability_adapter.dart';
export 'src/entities/clock_in/attendance_status.dart';
export 'src/adapters/clock_in/clock_in_adapter.dart';
export 'src/entities/availability/availability_slot.dart'; export 'src/entities/availability/availability_slot.dart';
export 'src/entities/availability/day_availability.dart'; export 'src/entities/availability/day_availability.dart';
// Coverage
export 'src/entities/coverage_domain/coverage_shift.dart';
export 'src/entities/coverage_domain/coverage_worker.dart';
export 'src/entities/coverage_domain/coverage_stats.dart';
// Adapters // Adapters
export 'src/adapters/profile/emergency_contact_adapter.dart'; export 'src/adapters/profile/emergency_contact_adapter.dart';
export 'src/adapters/profile/experience_adapter.dart'; export 'src/adapters/profile/experience_adapter.dart';
export 'src/entities/profile/experience_skill.dart'; export 'src/entities/profile/experience_skill.dart';
export 'src/adapters/profile/bank_account_adapter.dart'; export 'src/adapters/profile/bank_account_adapter.dart';
export 'src/adapters/profile/tax_form_adapter.dart'; export 'src/adapters/profile/tax_form_adapter.dart';
export 'src/adapters/financial/payment_adapter.dart';
// Exceptions
export 'src/exceptions/app_exception.dart';

View File

@@ -0,0 +1,33 @@
import '../../entities/availability/availability_slot.dart';
/// Adapter for [AvailabilitySlot] domain entity.
class AvailabilityAdapter {
static const Map<String, Map<String, String>> _slotDefinitions = {
'MORNING': {
'id': 'morning',
'label': 'Morning',
'timeRange': '4:00 AM - 12:00 PM',
},
'AFTERNOON': {
'id': 'afternoon',
'label': 'Afternoon',
'timeRange': '12:00 PM - 6:00 PM',
},
'EVENING': {
'id': 'evening',
'label': 'Evening',
'timeRange': '6:00 PM - 12:00 AM',
},
};
/// Converts a backend slot name (e.g. 'MORNING') to a Domain [AvailabilitySlot].
static AvailabilitySlot fromPrimitive(String slotName, {bool isAvailable = false}) {
final def = _slotDefinitions[slotName.toUpperCase()] ?? _slotDefinitions['MORNING']!;
return AvailabilitySlot(
id: def['id']!,
label: def['label']!,
timeRange: def['timeRange']!,
isAvailable: isAvailable,
);
}
}

View File

@@ -0,0 +1,28 @@
import '../../entities/shifts/shift.dart';
import '../../entities/clock_in/attendance_status.dart';
/// Adapter for Clock In related data.
class ClockInAdapter {
/// Converts primitive attendance data to [AttendanceStatus].
static AttendanceStatus toAttendanceStatus({
required String status,
DateTime? checkInTime,
DateTime? checkOutTime,
String? activeShiftId,
String? activeApplicationId,
}) {
final bool isCheckedIn = status == 'CHECKED_IN' || status == 'LATE'; // Assuming LATE is also checked in?
// Statuses that imply active attendance: CHECKED_IN, LATE.
// Statuses that imply completed: CHECKED_OUT.
return AttendanceStatus(
isCheckedIn: isCheckedIn,
checkInTime: checkInTime,
checkOutTime: checkOutTime,
activeShiftId: activeShiftId,
activeApplicationId: activeApplicationId,
);
}
}

View File

@@ -0,0 +1,19 @@
import '../../entities/financial/staff_payment.dart';
/// Adapter for Payment related data.
class PaymentAdapter {
/// Converts string status to [PaymentStatus].
static PaymentStatus toPaymentStatus(String status) {
switch (status) {
case 'PAID':
return PaymentStatus.paid;
case 'PENDING':
return PaymentStatus.pending;
case 'FAILED':
return PaymentStatus.failed;
default:
return PaymentStatus.unknown;
}
}
}

View File

@@ -0,0 +1,50 @@
import '../../entities/financial/time_card.dart';
/// Adapter for [TimeCard] to map data layer values to domain entity.
class TimeCardAdapter {
/// Maps primitive values to [TimeCard].
static TimeCard fromPrimitives({
required String id,
required String shiftTitle,
required String clientName,
required DateTime date,
required String startTime,
required String endTime,
required double totalHours,
required double hourlyRate,
required double totalPay,
required String status,
String? location,
}) {
return TimeCard(
id: id,
shiftTitle: shiftTitle,
clientName: clientName,
date: date,
startTime: startTime,
endTime: endTime,
totalHours: totalHours,
hourlyRate: hourlyRate,
totalPay: totalPay,
status: _stringToStatus(status),
location: location,
);
}
static TimeCardStatus _stringToStatus(String status) {
switch (status.toUpperCase()) {
case 'CHECKED_OUT':
case 'COMPLETED':
return TimeCardStatus.approved; // Assuming completed = approved for now
case 'PAID':
return TimeCardStatus.paid; // If this status exists
case 'DISPUTED':
return TimeCardStatus.disputed;
case 'CHECKED_IN':
case 'ACCEPTED':
case 'CONFIRMED':
default:
return TimeCardStatus.pending;
}
}
}

View File

@@ -15,18 +15,36 @@ class TaxFormAdapter {
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt, DateTime? updatedAt,
}) { }) {
return TaxForm( final TaxFormType formType = _stringToType(type);
id: id, final TaxFormStatus formStatus = _stringToStatus(status);
type: _stringToType(type), final Map<String, dynamic> formDetails =
title: title, formData is Map ? Map<String, dynamic>.from(formData as Map) : <String, dynamic>{};
subtitle: subtitle,
description: description, if (formType == TaxFormType.i9) {
status: _stringToStatus(status), return I9TaxForm(
staffId: staffId, id: id,
formData: formData is Map ? Map<String, dynamic>.from(formData) : null, title: title,
createdAt: createdAt, subtitle: subtitle,
updatedAt: updatedAt, description: description,
); status: formStatus,
staffId: staffId,
formData: formDetails,
createdAt: createdAt,
updatedAt: updatedAt,
);
} else {
return W4TaxForm(
id: id,
title: title,
subtitle: subtitle,
description: description,
status: formStatus,
staffId: staffId,
formData: formDetails,
createdAt: createdAt,
updatedAt: updatedAt,
);
}
} }
static TaxFormType _stringToType(String? value) { static TaxFormType _stringToType(String? value) {

View File

@@ -0,0 +1,59 @@
import 'package:intl/intl.dart';
import '../../entities/shifts/shift.dart';
/// Adapter for Shift related data.
class ShiftAdapter {
/// Maps application data to a Shift entity.
///
/// This method handles the common mapping logic used across different
/// repositories when converting application data from Data Connect to
/// domain Shift entities.
static Shift fromApplicationData({
required String shiftId,
required String roleId,
required String roleName,
required String businessName,
String? companyLogoUrl,
required double costPerHour,
String? shiftLocation,
required String teamHubName,
DateTime? shiftDate,
DateTime? startTime,
DateTime? endTime,
DateTime? createdAt,
required String status,
String? description,
int? durationDays,
required int count,
int? assigned,
String? eventName,
bool hasApplied = false,
}) {
final String orderName = (eventName ?? '').trim().isNotEmpty
? eventName!
: businessName;
final String title = '$roleName - $orderName';
return Shift(
id: shiftId,
roleId: roleId,
title: title,
clientName: businessName,
logoUrl: companyLogoUrl,
hourlyRate: costPerHour,
location: shiftLocation ?? '',
locationAddress: teamHubName,
date: shiftDate?.toIso8601String() ?? '',
startTime: startTime != null ? DateFormat('HH:mm').format(startTime) : '',
endTime: endTime != null ? DateFormat('HH:mm').format(endTime) : '',
createdDate: createdAt?.toIso8601String() ?? '',
status: status,
description: description,
durationDays: durationDays,
requiredSlots: count,
filledSlots: assigned ?? 0,
hasApplied: hasApplied,
);
}
}

View File

@@ -0,0 +1,27 @@
import 'package:equatable/equatable.dart';
/// Simple entity to hold attendance state
class AttendanceStatus extends Equatable {
final bool isCheckedIn;
final DateTime? checkInTime;
final DateTime? checkOutTime;
final String? activeShiftId;
final String? activeApplicationId;
const AttendanceStatus({
this.isCheckedIn = false,
this.checkInTime,
this.checkOutTime,
this.activeShiftId,
this.activeApplicationId,
});
@override
List<Object?> get props => [
isCheckedIn,
checkInTime,
checkOutTime,
activeShiftId,
activeApplicationId,
];
}

View File

@@ -0,0 +1,57 @@
import 'package:equatable/equatable.dart';
import 'coverage_worker.dart';
/// Domain entity representing a shift in the coverage view.
///
/// This is a feature-specific domain entity that encapsulates shift information
/// including scheduling details and assigned workers.
class CoverageShift extends Equatable {
/// Creates a [CoverageShift].
const CoverageShift({
required this.id,
required this.title,
required this.location,
required this.startTime,
required this.workersNeeded,
required this.date,
required this.workers,
});
/// The unique identifier for the shift.
final String id;
/// The title or role of the shift.
final String title;
/// The location where the shift takes place.
final String location;
/// The start time of the shift (e.g., "16:00").
final String startTime;
/// The number of workers needed for this shift.
final int workersNeeded;
/// The date of the shift.
final DateTime date;
/// The list of workers assigned to this shift.
final List<CoverageWorker> workers;
/// Calculates the coverage percentage for this shift.
int get coveragePercent {
if (workersNeeded == 0) return 0;
return ((workers.length / workersNeeded) * 100).round();
}
@override
List<Object?> get props => <Object?>[
id,
title,
location,
startTime,
workersNeeded,
date,
workers,
];
}

View File

@@ -0,0 +1,45 @@
import 'package:equatable/equatable.dart';
/// Domain entity representing coverage statistics.
///
/// Aggregates coverage metrics for a specific date.
class CoverageStats extends Equatable {
/// Creates a [CoverageStats].
const CoverageStats({
required this.totalNeeded,
required this.totalConfirmed,
required this.checkedIn,
required this.enRoute,
required this.late,
});
/// The total number of workers needed.
final int totalNeeded;
/// The total number of confirmed workers.
final int totalConfirmed;
/// The number of workers who have checked in.
final int checkedIn;
/// The number of workers en route.
final int enRoute;
/// The number of late workers.
final int late;
/// Calculates the overall coverage percentage.
int get coveragePercent {
if (totalNeeded == 0) return 0;
return ((totalConfirmed / totalNeeded) * 100).round();
}
@override
List<Object?> get props => <Object?>[
totalNeeded,
totalConfirmed,
checkedIn,
enRoute,
late,
];
}

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