Merge branch 'dev' into authentication-web
This commit is contained in:
10
.gitignore
vendored
10
.gitignore
vendored
@@ -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
41
.vscode/launch.json
vendored
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -47,3 +47,11 @@
|
|||||||
- 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
129
CLAUDE.md
Normal 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
138
GEMINI.md
Normal 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)
|
||||||
74
Makefile
74
Makefile
@@ -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 "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
18
apps/mobile/NEXT_SPRINT_TASKS.md
Normal file
18
apps/mobile/NEXT_SPRINT_TASKS.md
Normal 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.
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
1
apps/mobile/apps/client/firebase.json
Normal file
1
apps/mobile/apps/client/firebase.json
Normal 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"}}}}}}
|
||||||
@@ -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 --")
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
command script import --relative-to-command-file flutter_lldb_helper.py
|
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
36
apps/mobile/apps/client/ios/Runner/GoogleService-Info.plist
Normal file
36
apps/mobile/apps/client/ios/Runner/GoogleService-Info.plist
Normal 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>
|
||||||
78
apps/mobile/apps/client/lib/firebase_options.dart
Normal file
78
apps/mobile/apps/client/lib/firebase_options.dart
Normal 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',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
);
|
],
|
||||||
},
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.2/
|
|
||||||
@@ -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
|
|
||||||
@@ -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"
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_auth-6.1.4/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_core-4.4.0/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.5/
|
|
||||||
@@ -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 --")
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
command script import --relative-to-command-file flutter_lldb_helper.py
|
|
||||||
@@ -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
|
|
||||||
@@ -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"
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
162
apps/mobile/apps/staff/android/app/google-services.json_back
Normal file
162
apps/mobile/apps/staff/android/app/google-services.json_back
Normal 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"
|
||||||
|
}
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 --")
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#
|
|
||||||
# Generated file, do not edit.
|
|
||||||
#
|
|
||||||
|
|
||||||
command script import --relative-to-command-file flutter_lldb_helper.py
|
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
apps/mobile/apps/staff/ios/Runner/GoogleService-Info.plist
Normal file
36
apps/mobile/apps/staff/ios/Runner/GoogleService-Info.plist
Normal 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>
|
||||||
78
apps/mobile/apps/staff/lib/firebase_options.dart
Normal file
78
apps/mobile/apps/staff/lib/firebase_options.dart
Normal 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',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/
|
|
||||||
@@ -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"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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"
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_auth-6.1.4/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/firebase_core-4.4.0/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/Users/achinthaisuru/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/
|
|
||||||
@@ -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"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
3
apps/mobile/config.dev.json
Normal file
3
apps/mobile/config.dev.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"GOOGLE_PLACES_API_KEY": "AIzaSyAS9yTf4q51_CNSZ7mbmeS9V3l_LZR80lU"
|
||||||
|
}
|
||||||
@@ -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';
|
||||||
|
|||||||
@@ -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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,3 +11,5 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
design_system:
|
||||||
|
path: ../design_system
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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,23 +13,39 @@ 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);
|
||||||
@@ -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,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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!"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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!"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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>(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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,
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -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
Reference in New Issue
Block a user