feat: Add Milestone 3 documentation including feature testing plan, demo notes, and demo flow details

- Introduced comprehensive testing plan for Milestone 3 in m3-client-note.md
- Documented feedback and suggestions from demo sessions in m3-notes.md
- Created detailed demo flow for Milestone 3 in m3.md, outlining user interactions and expected outcomes
- Added planning tasks for Milestone 4 in m4-planning.md, covering backend and frontend development tasks, research, and business tasks
This commit is contained in:
Achintha Isuru
2026-02-12 16:33:16 -05:00
parent 368f28f354
commit fd47d84045
18 changed files with 829 additions and 1411 deletions

View File

@@ -1,136 +0,0 @@
# 🎉 Centralized Error Handling - Implementation Complete!
## ✅ What We Accomplished
I've successfully implemented a **production-ready centralized error handling system** for both Client and Staff apps. Here's what was delivered:
### 1. **Core Infrastructure** (100% Complete)
**✅ UI Components** (`design_system` package)
- `UiErrorSnackbar` - Localized error messages
- `UiSuccessSnackbar` - Success feedback
**✅ BLoC Error Handler Mixin** (`core` package)
- `BlocErrorHandler` - Eliminates boilerplate
- Automatic error logging
- Type-safe error handling
**✅ Global BLoC Observer** (`core` package)
- `CoreBlocObserver` - Centralized monitoring
- Registered in both Client and Staff apps
- Ready for Sentry/Crashlytics
**✅ Data Layer Error Handler** (`data_connect` package)
- `DataErrorHandler` mixin
- Wraps Data Connect calls
- Maps `SocketException` and `FirebaseException` to Domain `AppException` (Network/Server)
### 2. **BLoC Migrations** (2 Complete)
**✅ ClientAuthBloc** - 4 event handlers migrated
- Reduced from 173 to 153 lines (-11.6%)
- Eliminated ~60 lines of boilerplate
**✅ ClientHubsBloc** - 4 event handlers migrated
- Reduced from 232 to 170 lines (-26.7%)
- Eliminated ~62 lines of boilerplate
### 3. **Documentation** (Complete)
**✅ 4 comprehensive documents created (now consolidated):**
- `CENTRALIZED_ERROR_HANDLING.md` (Architecture guide)
- `CENTRALIZED_ERROR_HANDLING_SUMMARY.md` (Implementation summary)
- `CENTRALIZED_ERROR_HANDLING_CLIENT_PROPOSAL.md` (Executive summary)
- `BLOC_MIGRATION_STATUS.md` (Migration tracking)
---
## 📊 Key Finding
After analyzing all BLoCs in both apps, I discovered that **most BLoCs don't have error handling yet**. This is actually **good news** because:
-**No refactoring needed** - We can use the new pattern from the start
-**Clean implementation** - No legacy error handling to remove
-**Incremental adoption** - Add error handling as needed, not all at once
---
## 🎯 Recommended Approach
### Option A: Incremental Adoption (Recommended)
- Use `BlocErrorHandler` mixin for all **new** BLoCs
- Add error handling to **existing** BLoCs as you encounter errors
- Focus on user-facing features first
- **Estimated effort**: 0-2 hours per BLoC as needed
### Option B: Complete Migration (Optional)
- Migrate all 18 remaining BLoCs now
- Add error handling to all event handlers
- **Estimated effort**: 15-20 hours total
---
## 💡 How to Use (For New Development)
**1. Add the mixin to your BLoC:**
```dart
class MyBloc extends Bloc<MyEvent, MyState>
with BlocErrorHandler<MyState> {
```
**2. Use handleError in event handlers:**
```dart
await handleError(
emit: emit,
action: () async {
final result = await _useCase();
emit(Success(result));
},
onError: (errorKey) => Error(errorKey),
);
```
**3. Show errors in UI:**
```dart
BlocListener<MyBloc, MyState>(
listener: (context, state) {
if (state.status == Status.error) {
UiErrorSnackbar.show(context, messageKey: state.errorMessage!);
}
},
)
```
---
## 📁 Files Created/Modified
**Created (11 files)**:
1. `packages/design_system/lib/src/widgets/ui_error_snackbar.dart`
2. `packages/design_system/lib/src/widgets/ui_success_snackbar.dart`
3. `packages/core/lib/src/presentation/mixins/bloc_error_handler.dart`
4. `packages/core/lib/src/presentation/observers/core_bloc_observer.dart`
5. `docs/CENTRALIZED_ERROR_HANDLING.md`
6. `docs/CENTRALIZED_ERROR_HANDLING_SUMMARY.md`
7. `docs/CENTRALIZED_ERROR_HANDLING_CLIENT_PROPOSAL.md`
8. `docs/BLOC_MIGRATION_STATUS.md`
**Modified (7 files)**:
1. `packages/design_system/lib/design_system.dart`
2. `packages/core/lib/core.dart`
3. `apps/client/lib/main.dart`
4. `apps/staff/lib/main.dart`
5. `packages/features/client/authentication/lib/src/presentation/blocs/client_auth_bloc.dart`
6. `packages/features/client/hubs/lib/src/presentation/blocs/client_hubs_bloc.dart`
---
## ✨ Summary
The centralized error handling system is fully implemented and ready to use for both Client and Staff apps!
The foundation is solid, the pattern is proven (2 BLoCs migrated successfully), and the documentation is comprehensive. You can now:
-**Start using it immediately** for new development
-**Migrate existing BLoCs incrementally** as needed
-**Enjoy consistent error handling** across both apps
-**Reduce boilerplate** by ~20% per BLoC
**Would you like me to migrate any specific BLoCs now, or are you happy with the incremental approach?**

View File

@@ -0,0 +1,74 @@
flowchart LR
subgraph C1["Login"]
S_client_sign_in["client_sign_in_screen.dart"]
S_client_sign_in --> S_client_sign_in_Q["Queries<br/>* user - getUserById<br/>* business - getBusinessesByUserId"]
S_client_sign_in --> S_client_sign_in_F["Firebase<br/>* user - auth"]
end
subgraph C2["Create account"]
S_client_sign_up["client_sign_up_screen.dart"]
S_client_sign_up --> S_client_sign_up_Q["Queries<br/>* business - getBusinessesByUserId"]
S_client_sign_up --> S_client_sign_up_M["Mutations<br/>* user - createUser<br/>* business - createBusiness"]
end
subgraph C3["Edit account"]
S_edit_account_na["manual_or_unknown_screen.dart"]
S_edit_account_na --> S_edit_account_na_M["Mutations<br/>* business - updateBusiness"]
end
subgraph C4["Profile"]
S_client_settings["client_settings_screen.dart"]
S_client_settings --> S_client_settings_Q["Queries<br/>* user - getUserById<br/>* business - getBusinessesByUserId"]
end
subgraph C5["Hubs"]
S_client_hubs["client_hubs_screen.dart"]
S_client_hubs --> S_client_hubs_Q["Queries<br/>* TeamHub - listTeamHubsByOwnerId"]
S_client_hubs --> S_client_hubs_M["Mutations<br/>* TeamHub - createTeamHub<br/>* TeamHub - updateTeamHub<br/>* TeamHub - deleteTeamHub"]
end
subgraph C6["Orders"]
S_client_shifts["client_shifts_screen.dart"]
S_client_shifts --> S_client_shifts_Q["Queries<br/>* order - getOrdersByBusinessId"]
end
subgraph C7["RAPID Order"]
S_rapid_order["rapid_order_flow_page.dart"]
S_rapid_order --> S_rapid_order_M["Mutations<br/>* order - createOrder"]
end
subgraph C8["One-time Order"]
S_one_time["one_time_order_flow_page.dart"]
S_one_time --> S_one_time_Q["Queries<br/>* role - listRolesByOwnerId"]
S_one_time --> S_one_time_M["Mutations<br/>* ShiftRole - createShiftRole<br/>* order - createOrder"]
end
subgraph C9["Permanent Placement"]
S_permanent["permanent_order_flow_page.dart"]
S_permanent --> S_permanent_Q["Queries<br/>* role - listRolesByOwnerId"]
S_permanent --> S_permanent_M["Mutations<br/>* ShiftRole - createShiftRole<br/>* order - createOrder"]
end
subgraph C10["Recurring Order"]
S_recurring["recurring_order_flow_page.dart"]
S_recurring --> S_recurring_Q["Queries<br/>* role - listRolesByOwnerId"]
S_recurring --> S_recurring_M["Mutations<br/>* ShiftRole - createShiftRole<br/>* order - createOrder"]
end
subgraph C11["Billing"]
S_billing["client_billing_screen.dart"]
S_billing --> S_billing_Q["Queries<br/>* account - getAccountsByOwnerId<br/>* invoice - listInvoicesByBusinessId<br/>* recentPayment - listRecentPaymentsByBusinessId"]
S_billing --> S_billing_M["Mutations<br/>* account - createAccount<br/>* account - updateAccount<br/>* account - deleteAccount"]
end
subgraph C12["Coverage"]
S_coverage["coverage_dashboard.dart"]
S_coverage --> S_coverage_Q["Queries<br/>* order - getOrdersByBusinessId<br/>* shift - getShiftsByBusinessId<br/>* application - getApplicationsByShiftId"]
end
subgraph C13["Home"]
S_client_home["client_home_screen.dart"]
S_client_home --> S_client_home_Q["Queries<br/>* order - getOrdersByBusinessId<br/>* shift - getShiftsByBusinessId<br/>* application - getApplicationsByShiftId<br/>* recentPayment - listRecentPaymentsByBusinessId"]
S_client_home --> S_client_home_M["Mutations<br/>* order - createOrder"]
end

View File

@@ -0,0 +1,121 @@
flowchart LR
subgraph L1["login/create user"]
S_auth_phone["phone_verification_screen.dart"]
S_auth_phone --> S_auth_phone_Q["Queries<br/>* user - getUserById<br/>* staff - getStaffByUserId"]
S_auth_phone --> S_auth_phone_M["Mutations<br/>* user - createUser"]
S_auth_phone --> S_auth_phone_F["Firebase<br/>* user - auth"]
end
subgraph L2["Profile"]
S_worker_profile["worker_profile_screen.dart"]
S_worker_profile --> S_worker_profile_Q["Queries<br/>* user - getUserById<br/>* staff - getStaffByUserId"]
end
subgraph L3["Personal info"]
S_personal_info["personal_info_screen.dart"]
S_personal_info --> S_personal_info_Q["Queries<br/>* staff - getStaffByUserId"]
S_personal_info --> S_personal_info_M["Mutations<br/>* staff - UpdateStaff"]
end
subgraph L4["Emergency Contact"]
S_emergency["emergency_contact_screen.dart"]
S_emergency --> S_emergency_Q["Queries<br/>* emergencyContact - getEmergencyContactsByStaffId"]
S_emergency --> S_emergency_M["Mutations<br/>* conemergencyContacttact - updateEmergencyContact<br/>* emergencyContact - createEmergencyContact<br/>* contemergencyContactact - deleteEmergencyContact"]
end
subgraph L5["Experience & skills"]
S_experience["experience_screen.dart"]
S_experience --> S_experience_Q["Queries<br/>* staff - getStaffByUserId"]
S_experience --> S_experience_M["Mutations<br/>* staff - UpdateStaff"]
end
subgraph L6["Attire"]
S_attire["attire_screen.dart"]
S_attire --> S_attire_Q["Queries<br/>* attireOption - filterAttireOptions<br/>* staff - getStaffByUserId"]
S_attire --> S_attire_M["Mutations<br/>* staff - UpdateStaff"]
end
subgraph L7["Documents"]
S_documents["documents_screen.dart"]
S_documents --> S_documents_Q["Queries<br/>* document - listDocuments<br/>* staffDocument - listStaffDocumentsByStaffId"]
S_documents --> S_documents_M["Mutations<br/>* staffDocument - updateStaffDocument<br/>* staffDocument - createStaffDocument"]
end
subgraph L8["Certificates"]
S_certificates["certificates_screen.dart"]
S_certificates --> S_certificates_Q["Queries<br/>* certificate - listCertificatesByStaffId"]
S_certificates --> S_certificates_M["Mutations<br/>* certificate - UpdateCertificate<br/>* certificate - CreateCertificate<br/>* certificate - DeleteCertificate"]
end
subgraph L9["Tax Documents"]
S_tax_forms["tax_forms_screen.dart"]
S_tax_forms --> S_tax_forms_Q["Queries<br/>* taxForm - getTaxFormsBystaffId"]
S_tax_forms --> S_tax_forms_M["Mutations<br/>* taxForm - createTaxForm<br/>* taxForm - updateTaxForm"]
end
subgraph L10["KROW University"]
S_uni["krow_university_screen.dart"]
S_uni --> S_uni_Q["Queries<br/>* course - listCourses<br/>* staffCourse - listStaffCoursesByStaffId<br/>* staff - getStaffByUserId<br/>* level - listLevels<br/>* certificate - listCertificatesByStaffId"]
end
subgraph L11["Trainings"]
S_trainings["trainings_screen.dart"]
S_trainings --> S_trainings_Q["Queries<br/>* course - listCourses<br/>* staffCourse - listStaffCoursesByStaffId"]
end
subgraph L12["Leaderboard"]
S_leaderboard["leaderboard_screen.dart"]
S_leaderboard --> S_leaderboard_Q["Queries<br/>* staffCourse - missing"]
end
subgraph L13["Bank Account"]
S_bank["bank_account_screen.dart"]
S_bank --> S_bank_Q["Queries<br/>* account - getAccountsByOwnerId"]
S_bank --> S_bank_M["Mutations<br/>* account - createAccount<br/>* account - updateAccount<br/>* account - deleteAccount"]
end
subgraph L14["Earnings/Payments"]
S_payments["payments_screen.dart"]
S_payments --> S_payments_Q["Queries<br/>* recentPayment - listRecentPaymentsByStaffId"]
end
subgraph L15["Timecard"]
S_timecard["time_card_screen.dart"]
S_timecard --> S_timecard_Q["Queries<br/>* application - getApplicationsByStaffId"]
end
subgraph L16["Clock in"]
S_clockin["clock_in_screen.dart"]
S_clockin --> S_clockin_Q["Queries<br/>* application - getApplicationsByStaffId"]
S_clockin --> S_clockin_M["Mutations<br/>* application - createApplication<br/>* application - updateApplicationStatus"]
end
subgraph L17["Shifts"]
S_shifts["shifts_screen.dart"]
S_shifts --> S_shifts_Q["Queries<br/>* application - getApplicationsByStaffId<br/>* shiftRole - listShiftRolesByVendorId/listShiftRolesByRoleId<br/>* application - getApplicationsByStaffId"]
S_shifts --> S_shifts_M["Mutations<br/>* application - updateApplicationStatus<br/>* application - createApplication"]
end
subgraph L18["My availability"]
S_availability["availability_screen.dart"]
S_availability --> S_availability_Q["Queries<br/>* staffAvailability - listStaffAvailabilitiesByStaffId/getStaffAvailabilityByKey"]
S_availability --> S_availability_M["Mutations<br/>* staffAvailability - updateStaffAvailability<br/>* staffAvailability - createStaffAvailability<br/>* staffAvailability - deleteStaffAvailability"]
end
subgraph L19["Your Benefits Overview"]
S_benefits["benefits_screen.dart"]
S_benefits --> S_benefits_Q["Queries<br/>* benefitsData - listBenefitsDataByStaffId"]
S_benefits --> S_benefits_M["Mutations<br/>* benefitsData - updateBenefitsData<br/>* benefitsData - createBenefitsData"]
end
subgraph L20["Home"]
S_home["worker_home_screen.dart"]
S_home --> S_home_Q["Queries<br/>* application - getApplicationsByStaffId<br/>* shiftRole - listShiftRolesByVendorId/listShiftRolesByRoleId<br/>* benefitsData - getBenefitsDataByStaffId"]
end
subgraph L21["Shift detail"]
S_shift_detail["shift_details_screen.dart"]
S_shift_detail --> S_shift_detail_Q["Queries<br/>* application - getApplicationsByStaffId"]
S_shift_detail --> S_shift_detail_M["Mutations<br/>* application - updateApplicationStatus"]
end

View File

@@ -0,0 +1,130 @@
---
config:
theme: mc
layout: dagre
---
classDiagram
direction TB
class User {
id: String
email: String
}
class Business {
id: UUID
userId: String
businessName: String
status: BusinessStatus
}
class Vendor {
id: UUID
userId: String
companyName: String
}
class Order {
id: UUID
businessId: UUID
vendorId: UUID
status: OrderStatus
}
class Shift {
id: UUID
orderId: UUID
status: ShiftStatus
}
class ShiftRole {
shiftId: UUID
roleId: UUID
}
class Role {
id: UUID
name: String
vendorId: UUID
}
class Application {
id: UUID
shiftId: UUID
staffId: UUID
roleId: UUID
}
class Invoice {
id: UUID
businessId: UUID
vendorId: UUID
orderId: UUID
status: InvoiceStatus
}
class InvoiceTemplate {
id: UUID
name: String
ownerId: UUID
businessId: UUID
vendorId: UUID
}
class RecentPayment {
id: UUID
invoiceId: UUID
applicationId: UUID
staffId: UUID
}
class ClientFeedback {
id: UUID
businessId: UUID
vendorId: UUID
rating: Int
}
class Team {
id: UUID
teamName: String
ownerId: String
}
class TeamMember {
id: UUID
teamId: UUID
userId: String
role: TeamMemberRole
}
class TeamHub {
id: UUID
teamId: UUID
hubName: String
}
class Staff {
id: UUID
userId: String
}
note for Staff "business can create a staff too"
Business "1" -- "*" Order : places
Business "1" -- "*" Invoice : receives
Business "1" -- "*" ClientFeedback : gives
Business "1" --o "1" Team : (ownerId)
Business "1" --o "*" InvoiceTemplate : (ownerId)
User "1" -- "1" Business : owns
Vendor "1" -- "*" Order : fulfills
Vendor "1" -- "*" Invoice : issues
Order "1" -- "*" Shift : contains
Order "1" -- "1" Invoice : billed via
Shift "1" -- "*" ShiftRole : requires
ShiftRole "1" -- "1" Role
ShiftRole "1" -- "*" Application : target for
Application "1" -- "1" Staff
Application "1" -- "1" RecentPayment
Invoice "1" -- "*" RecentPayment : paid through
Team "1" -- "*" TeamHub : contains
Team "1" -- "*" TeamMember : has

View File

@@ -0,0 +1,181 @@
classDiagram
direction TB
class User {
id: String
email: String
fullName: String
role: UserBaseRole
}
class Staff {
id: UUID
userId: String
fullName: String
ownerId: UUID
hubId: UUID
rollId: UUID
status: BackgroundCheckStatus
}
class Account{
id: UUID
ownerId:UUID
type:AccountType
}
class Workforce {
id: UUID
vendorId: UUID
staffId: UUID
status: WorkforceStatus
}
class Application {
id: UUID
shiftId: UUID
staffId: UUID
roleId: UUID
status: ApplicationStatus
}
class Assignment {
id: UUID
workforceId: UUID
shiftId: UUID
roleId: UUID
status: AssignmentStatus
}
class ShiftRole {
id: UUID
shiftId: UUID
roleId: UUID
}
class Shift {
id: UUID
orderId: UUID
status: ShiftStatus
}
class Order {
id: UUID
vendorId: UUID
businessId: UUID
status: OrderStatus
}
class Vendor {
id: UUID
userId: String
companyName: String
}
class Business {
id: UUID
userId: String
businessName: String
}
class Role {
id: UUID
name: String
vendorId: UUID
roleCategoryId: UUID
}
class StaffDocument {
staffId: UUID
documentId: UUID
status: DocumentStatus
}
class Document {
id: UUID
name: String
documentType: DocumentType
}
class StaffCourse {
staffId: UUID
courseId: UUID
}
class Course {
id: UUID
title: String
categoryId: UUID
}
class Category {
id: UUID
label: String
}
class StaffAvailability {
staffId: UUID
day: DayOfWeek
slot: AvailabilitySlot
}
class Certificate {
staffId: UUID
certificationType: ComplianceType
status: CertificateStatus
}
class BenefitData {
staffId: UUID
vendorBenefitPlanId: UUID
current: int
}
class Contact {
staffId: UUID
relationship: RelationshipType
name: string
}
class Invoice {
orderId: UUID
}
class RecentPayment {
staffId: UUID
applicationId: UUID
status: RecentPaymentStatus
}
class TaxForm {
staffId: UUID
formType: TaxFormType
status: TaxFormStatus
}
User "1" -- "1" Staff : has
Staff "1" -- "*" Application : applies to
Staff "1" -- "*" Workforce : part of
Staff "1" -- "*" StaffDocument : has
Staff "1" -- "*" Certificate : has
Staff "1" -- "*" BenefitData : has
Staff "1" -- "*" Contact : has
Staff "1" -- "*" TaxForm : has
Staff "1" -- "*" Account : has
Staff "1" -- "*" StaffCourse : takes
Staff "1" -- "*" StaffAvailability : sets
Workforce "1" -- "*" Assignment : receives
Assignment -- ShiftRole
Vendor "1" -- "*" Order : receives
Business "1" -- "*" Order : places
Order "1" -- "1" Invoice : has
Invoice "1" -- "*" RecentPayment : has
RecentPayment "1" -- "1" Application : has
Staff "1" --o "1" Vendor : (ownerId)
Staff "1" --o "1" Business : (ownerId)
Application -- ShiftRole
ShiftRole "*" -- "1" Shift : belongs to
ShiftRole "*" -- "1" Role : defines
Shift "*" -- "1" Order : belongs to
StaffDocument "1" -- "1" Document : references
StaffCourse "1" -- "1" Course : references
Course "1" -- "1" Category : belongs to

View File

@@ -0,0 +1,79 @@
---
config:
layout: elk
theme: mc
---
classDiagram
class User {
id: String
email: String
fullName: String
}
class TeamMember {
id: UUID
teamId: UUID
userId: String
teamHubId: UUID
role: TeamMemberRole
inviteStatus: TeamMemberInviteStatus
inviteCode: UUID
}
class Team {
id: UUID
teamName: String
ownerId: String
}
class TeamHub {
id: UUID
teamId: UUID
hubName: String
}
class TeamHudDepartment {
id: UUID
name: String
teamHubId: UUID
}
class MemberTask {
teamMemberId: UUID
taskId: UUID
}
class Task {
id: UUID
taskName: String
status: TaskStatus
priority: TaskPriority
ownerId: UUID
}
class Vendor {
id: UUID
companyName: String
}
class Business {
id: UUID
businessName: String
}
User "1" -- "1" TeamMember : has
Team "1" -- "*" TeamHub : contains
Team "1" --o "1" Vendor : (ownerId)
Team "1" --o "1" Business : (ownerId)
TeamHub "1" -- "*" TeamHudDepartment : has
TeamHub "1" -- "*" TeamMember : is assigned to
TeamMember "*" -- "1" Team
TeamMember "1" -- "*" MemberTask : has assigned
Task "1" -- "*" MemberTask : is assigned to
Task --o Vendor : (ownerId)
Task --o Business : (ownerId)

View File

@@ -0,0 +1,71 @@
classDiagram
direction TB
class User {
id: String
email: String
fullName: String
role: UserBaseRole
}
class Staff {
id: UUID
userId: String
fullName: String
ownerId: UUID
hubId: UUID
rollId: UUID
status: BackgroundCheckStatus
}
class Vendor {
id: UUID
userId: String
companyName: String
}
class Business {
id: UUID
userId: String
businessName: String
}
class TeamMember {
id: UUID
teamId: UUID
userId: String
role: TeamMemberRole
}
class ActivityLog {
id: UUID
userId: String
activityType: ActivityType
}
class UserConversation {
conversationId: UUID
userId: String
}
class Conversation {
id: UUID
conversationType: ConversationType
}
class Message{
id: UUID
conversationId: UUID
content: String
}
User <|-- Staff
User <|-- Business
User <|-- Vendor
User <|-- TeamMember
User "1" -- "*" ActivityLog : logs
User "1" -- "*" UserConversation : participates in
UserConversation "*" -- "1" Conversation : is part of
Conversation "1" -- "*" Message : has

View File

@@ -0,0 +1,164 @@
---
config:
layout: dagre
---
classDiagram
direction TB
class User {
id: String
email: String
}
class Vendor {
id: UUID
userId: String
companyName: String
tier: VendorTier
}
class Staff {
id: UUID
userId: String
fullName: String
}
class VendorBenefitPlan {
id: UUID
vendorId: UUID
title: String
}
class InvoiceTemplate {
id: UUID
name: String
ownerId: UUID
}
class VendorRate {
id: UUID
vendorId: UUID
roleName: String
}
class AttireOption{
id: UUID
vendorId: UUID
}
class Team {
id: UUID
teamName: String
ownerId: String
}
class TeamMember {
id: UUID
teamId: UUID
userId: String
role: TeamMemberRole
}
class TeamHub {
id: UUID
teamId: UUID
hubName: String
}
class Business {
id: UUID
userId: String
businessName: String
}
class ClientFeedback {
id: UUID
businessId: UUID
vendorId: UUID
rating: Int
}
class Order {
id: UUID
vendorId: UUID
businessId: UUID
status: OrderStatus
}
class Shift {
id: UUID
orderId: UUID
status: ShiftStatus
}
class Role {
id: UUID
name: String
vendorId: UUID
}
class ShiftRole {
shiftId: UUID
roleId: UUID
}
class Workforce {
id: UUID
vendorId: UUID
staffId: UUID
status: WorkforceStatus
}
class Application {
id: UUID
shiftId: UUID
staffId: UUID
roleId: UUID
status: ApplicationStatus
}
class Assignment {
id: UUID
workforceId: UUID
shiftId: UUID
roleId: UUID
status: AssignmentStatus
}
class Invoice {
id: UUID
vendorId: UUID
businessId: UUID
orderId: UUID
status: InvoiceStatus
}
class RecentPayment {
id: UUID
staffId: UUID
applicationId: UUID
invoiceId: UUID
status: RecentPaymentStatus
}
note for Vendor "All tables has relationship with vendor"
User "1" -- "1" Vendor : has
Vendor "1" o-- "1" Staff : (ownerId)
Vendor "1" -- "*" VendorBenefitPlan : offers
Vendor "1" -- "*" AttireOption
Vendor o-- InvoiceTemplate : (ownerId)
Vendor "1" -- "*" VendorRate : has
Vendor "1" -- "*" ClientFeedback : receives
Vendor "1" -- "*" Order : receives
Business "1" -- "*" Order : places
Order "1" -- "*" Shift : contains
Shift "1" -- "*" ShiftRole : requires
Role "1" -- "*" ShiftRole : fills
ShiftRole "1" -- "*" Application : receives
Assignment "1" -- "1" ShiftRole
Assignment "1" -- "1" Workforce
Invoice "1" -- "1" Order
Invoice "1" -- "*" RecentPayment : details
Vendor "1" o-- "1" Team
Team "1" -- "*" TeamHub : contains
Team "1" -- "*" TeamMember : has

View File

@@ -0,0 +1,294 @@
# Krow Workforce Backend Manual
Firebase Data Connect + Cloud SQL (PostgreSQL)
---
## 1. Backend Overview
This project uses Firebase Data Connect with Cloud SQL (PostgreSQL) as the main backend system.
The architecture is based on:
- GraphQL Schemas → Define database tables
- Connectors (Queries & Mutations) → Data access layer
- Cloud SQL → Real database
- Auto-generated SDK → Used by Web & Mobile apps
- Makefile → Automates backend workflows
The goal is to keep the backend scalable, structured, and aligned with Web and Mobile applications.
---
## 2. Project Structure
```
dataconnect/
├── dataconnect.yaml
├── schema/
│ ├── Staff.gql
│ ├── Vendor.gql
│ ├── Business.gql
│ └── ...
├── connector/
│ ├── staff/
│ │ ├── queries.gql
│ │ └── mutations.gql
│ ├── invoice/
│ └── ...
├── connector/connector.yaml
docs/backend-diagrams/
│ ├── business_uml_diagram.mmd
│ ├── staff_uml_diagram.mmd
│ ├── team_uml_diagram.mmd
│ ├── user_uml_diagram.mmd
│ └── vendor_uml_diagram_simplify.mmd
```
---
## 3. dataconnect.yaml (Main Configuration)
```yaml
specVersion: "v1"
serviceId: "krow-workforce-db"
location: "us-central1"
schema:
source: "./schema"
datasource:
postgresql:
database: "krow_db"
cloudSql:
instanceId: "krow-sql"
connectorDirs: ["./connector"]
```
### Purpose
| Field | Description |
|------|------------|
| serviceId | Data Connect service name |
| schema.source | Where GraphQL schemas live |
| datasource | Cloud SQL connection |
| connectorDirs | Where queries/mutations are |
---
## 4. Database Schemas
All database schemas are located in:
```
dataconnect/schema/
```
Each `.gql` file represents a table:
- Staff.gql
- Invoice.gql
- ShiftRole.gql
- Application.gql
- etc.
Schemas define:
- Fields
- Enums
- Relationships (`@ref`)
- Composite keys (`key: []`)
---
## 5. Queries & Mutations (Connectors)
Located in:
```
dataconnect/connector/<entity>/
```
Example:
```
dataconnect/connector/staff/queries.gql
dataconnect/connector/staff/mutations.gql
```
Each folder represents one entity.
This layer defines:
- listStaff
- getStaffById
- createStaff
- updateStaff
- deleteStaff
- etc.
---
## 6. connector.yaml (SDK Generator)
```yaml
connectorId: example
generate:
dartSdk:
- outputDir: ../../mobile/staff/staff_app_mvp/lib/dataconnect_generated
package: dataconnect_generated/generated.dart
- outputDir: ../../mobile/client/client_app_mvp/lib/dataconnect_generated
package: dataconnect_generated/generated.dart
```
This file generates the SDK for:
- Staff Mobile App
- Client Mobile App
---
## 7. What is the SDK?
The SDK is generated using:
```bash
firebase dataconnect:sdk:generate
```
It allows the apps to:
- Call queries/mutations
- Use strong typing
- Avoid manual GraphQL
- Reduce runtime errors
Example in Flutter:
```dart
client.listStaff();
client.createInvoice();
```
---
## 8. Makefile Automation Commands
### Main Commands
| Command | Purpose |
|--------|---------|
| dataconnect-enable-apis | Enable required APIs |
| dataconnect-init | Initialize Data Connect |
| dataconnect-deploy | Deploy schemas |
| dataconnect-sql-migrate | Apply DB migrations |
| dataconnect-generate-sdk | Generate SDK |
| dataconnect-sync | Full backend update |
| dataconnect-test | Test without breaking |
| dataconnect-seed | Insert seed data |
| dataconnect-bootstrap-db | Create Cloud SQL |
---
## 9. Correct Backend Workflow
### Production Flow
```bash
make dataconnect-sync
```
Steps:
1. Deploy schema
2. Run SQL migrations
3. Generate SDK
---
### Safe Test Flow
```bash
make dataconnect-test
```
This runs:
- Deploy dry-run
- SQL diff
- Shows errors without changing DB
---
## 10. Seed Data
Current command:
```make
dataconnect-seed:
@firebase dataconnect:execute seeds/seed_min.graphql --project=$(FIREBASE_ALIAS)
```
Purpose:
- Validate schema
- Detect missing tables
- Prevent bad inserts
---
## 11. UML Diagrams
Located in:
```
docs/backend-diagrams/
```
Divided by role:
| File | Scope |
|------|-------|
| user_uml_diagram.mmd | User |
| staff_uml_diagram.mmd | Staff |
| vendor_uml_diagram_simplify.mmd | Vendor |
| business_uml_diagram.mmd | Business |
| team_uml_diagram.mmd | Teams |
Used with Mermaid to visualize relationships.
---
## 12. Core Business Workflow
```text
Order
→ Shift
→ ShiftRole
→ Application
→ Workforce
→ Assignment
→ Invoice
→ RecentPayment
```
This represents the full work & payment lifecycle.
---
## 13. Final Notes
This backend is designed to:
- Scale efficiently
- Maintain data consistency
- Align Web & Mobile models
- Support reporting and billing
- Avoid duplicated data
---
END OF MANUAL

File diff suppressed because it is too large Load Diff

View File

@@ -1,358 +0,0 @@
# Centralized Error Handling Architecture
**Project:** KROW Workforce Mobile App
## 1. Executive Summary
We have implemented a **Centralized Error Handling System** that ensures the entire application (Staff & Client) handles errors consistently, reliably, and with full localization support.
Instead of writing error handling code in every single feature (which leads to bugs and inconsistent messages), we rely on a global safety net that catches **Network Failures**, **Server Errors (500)**, **Not Found Errors (404)**, and **Business Logic Violations** automatically.
### Key Benefits
* **Safety:** The app never crashes due to unhandled API errors.
* **Consistency:** A network error looks the same in "Shifts" as it does in "billing".
* **Localization:** All error messages are automatically translated (English/Spanish).
* **Speed:** Developers can build features faster without worrying about `try/catch` blocks.
### Technical Excellence (Status Code Handling)
We don't just catch "errors"; we understand them. The system automatically categorizes and handles:
* **500 (Server Error):** "Our servers are having a moment. Please try again."
* **404 (Not Found):** "The resource you're looking for (Shift/Profile) is missing."
* **401 (Unauthorized):** "Your session expired. Please log in again." (Auto-redirect)
* **403 (Forbidden):** "You don't have permission to access this area."
* **503 (Unavailable):** "Maintenance mode or overloaded. Back in a bit!"
---
## 2. Architecture Overview
The error handling flows through three distinct layers, ensuring separation of concerns:
```mermaid
graph TD
A[Data Layer / Repository] -->|Throws AppException| B[BLoC Layer / State Management]
B -->|Emits Error Key| C[UI Layer / Presentation]
subgraph "1. Data Layer (The Guard)"
A -- Captures Exceptions --> D[DataErrorHandler Mixin]
D -- Maps to --> E[NetworkException, ServerException, etc.]
end
subgraph "2. BLoC Layer (The Translator)"
B -- Uses --> F[BlocErrorHandler Mixin]
F -- Catches AppException --> G[converts to 'errors.category.type']
end
subgraph "3. UI Layer (The Messenger)"
C -- Calls --> H["translateErrorKey()"]
H -- Returns --> I["Localized String (e.g. 'Sin conexión')"]
end
```
### 1. The Data Layer (The Guard)
**Location:** `packages/data_connect/lib/src/mixins/data_error_handler.dart`
This is where raw exceptions (from Firebase, network, etc.) are caught and converted into **typed exceptions** that the rest of the app can understand.
**Example:**
```dart
mixin DataErrorHandler {
Future<T> handleDataOperation<T>(Future<T> Function() operation) async {
try {
return await operation();
} on SocketException {
throw NetworkException('errors.network.no_connection');
} on HttpException catch (e) {
if (e.statusCode == 500) throw ServerException('errors.server.internal');
if (e.statusCode == 404) throw NotFoundException('errors.not_found.resource');
// ... more mappings
}
}
}
```
### 2. The BLoC Layer (The Translator)
**Location:** `packages/core/lib/src/presentation/mixins/bloc_error_handler.dart`
BLoCs use this mixin to catch exceptions and convert them into **error keys** that can be localized.
**Example:**
```dart
mixin BlocErrorHandler {
String handleError(Object error) {
if (error is NetworkException) return error.message;
if (error is ServerException) return error.message;
return 'errors.unknown';
}
}
```
### 3. The UI Layer (The Messenger)
**Location:** `packages/core_localization/lib/src/utils/error_translator.dart`
The UI calls `translateErrorKey()` to convert error keys into user-friendly, localized messages.
**Example:**
```dart
String translateErrorKey(String key) {
final t = LocaleSettings.instance.currentTranslations;
return t[key] ?? 'An error occurred';
}
```
---
## 3. Real-World Example: Submitting a Tax Form
Let's trace what happens when a user submits Form W-4 with no internet:
1. **User Action:** Clicks "Submit Form"
2. **BLoC:** `FormW4Bloc` calls `submitW4UseCase.call(formData)`
3. **Use Case:** Calls `taxFormsRepository.submitW4(formData)`
4. **Repository (Data Layer):**
```dart
Future<void> submitW4(W4Data data) async {
return handleDataOperation(() async {
await _api.submitW4(data); // This throws SocketException
});
}
```
5. **DataErrorHandler Mixin:** Catches `SocketException` → throws `NetworkException('errors.network.no_connection')`
6. **BLoC:** Catches `NetworkException` → emits `FormW4State.error(errorMessage: 'errors.network.no_connection')`
7. **UI (FormW4Page):**
```dart
BlocListener<FormW4Bloc, FormW4State>(
listener: (context, state) {
if (state.status == FormW4Status.error) {
UiSnackbar.show(
context,
message: translateErrorKey(state.errorMessage!),
type: UiSnackbarType.error,
);
}
},
)
```
8. **translateErrorKey:** Looks up `'errors.network.no_connection'` in `en.i18n.json` → returns `"No internet connection. Please check your network."`
9. **User Sees:** A friendly snackbar with the localized message
---
## 4. Simple Verification Tests (For Non-Developers)
### Test A: The "Tunnel" Test (Network)
1. Open the app to the **Shifts** page.
2. Toggle **Airplane Mode ON**.
3. Pull to refresh the list.
4. **Result:** App shows a gentle `snackbar` error: *"No internet connection"* (or Spanish equivalent). **No Crash.**
### Test B: The "Duplicate Data" Test (Smart Validation)
1. Log in on two devices with the same account (if possible) or simply use a known registered email.
2. Go to the **Sign Up** page.
3. Try to register a new account using that *existing* email.
4. **Result:** App instantly displays specific, helpful feedback: *"An account with this email already exists."* instead of a generic failure.
5. **Why it matters:** Proves the backend and frontend are synced to guide the user, not just block them.
### Test C: The "Crash Proof" Test (The Safety Net)
1. **Scenario:** Even if a developer introduces a bug (like a random exception) or the server returns a 500 status.
2. **Result:** The app catches the unknown error, logs it internally, and shows a safe default message: *"Something went wrong. Please try again."*
3. **Why it matters:** The app never crashes or closes unexpectedly, preserving user trust.
### Test D: The "Language" Test (Localization)
1. Trigger an error (like wrong password).
2. Change phone language to **Spanish**.
3. Trigger the same error.
4. **Result:** Message automatically translates: *"Correo electrónico o contraseña inválidos."*
---
## 5. Comprehensive Testing Guide for Client Verification
This section provides a complete testing checklist to verify that centralized error handling is working correctly across the entire Staff app.
### 🎯 **Testing Objectives**
- Verify all errors are caught and handled gracefully (no crashes)
- Confirm error messages are user-friendly and localized
- Ensure consistent error display using `UiSnackbar`
- Validate that error keys are properly translated
---
### 📱 **Test Suite A: Tax Forms (I-9 & W-4)**
These forms have been fully integrated with centralized error handling and localization.
#### **Test A1: Form Validation Errors**
1. Navigate to **Profile → Documents → Form W-4**
2. Try to proceed to next step **without filling required fields**
3. **Expected Result:**
- Validation error appears in a snackbar
- Message is clear and specific (e.g., "First name is required")
- Error is localized (Spanish: "Se requiere el nombre")
#### **Test A2: Network Error During Submission**
1. Fill out **Form I-9** completely
2. **Turn off WiFi/Mobile Data**
3. Click **Submit Form**
4. **Expected Result:**
- Snackbar shows: "No internet connection. Please check your network."
- Spanish: "Sin conexión a internet. Verifica tu red."
- Form data is NOT lost
#### **Test A3: Server Error Simulation**
1. Fill out **Form W-4**
2. If backend is accessible, trigger a 500 error
3. **Expected Result:**
- Snackbar shows: "Our servers are having issues. Please try again."
- Spanish: "Nuestros servidores tienen problemas. Inténtalo de nuevo."
#### **Test A4: Language Switching**
1. Navigate to **Form I-9**
2. Trigger any error (validation or network)
3. Note the error message
4. **Change device language to Spanish** (Settings → Language)
5. Trigger the same error
6. **Expected Result:**
- Error message appears in Spanish
- All form labels and hints are also in Spanish
---
### 📱 **Test Suite B: Shifts & Availability**
#### **Test B1: Network Error on Shifts Page**
1. Navigate to **Shifts** tab
2. **Enable Airplane Mode**
3. Pull to refresh
4. **Expected Result:**
- Snackbar: "No internet connection"
- No crash or blank screen
- Previous data (if any) remains visible
#### **Test B2: Shift Not Found (404)**
1. If possible, try to access a deleted/non-existent shift
2. **Expected Result:**
- Snackbar: "Shift not found"
- User is redirected back to shifts list
---
### 📱 **Test Suite C: Profile & Authentication**
#### **Test C1: Session Expiry (401)**
1. Let the app sit idle for extended period (or manually invalidate token)
2. Try to perform any action (update profile, submit form)
3. **Expected Result:**
- Snackbar: "Your session has expired. Please log in again."
- App automatically redirects to login screen
#### **Test C2: Profile Update Errors**
1. Navigate to **Profile → Personal Info**
2. Try to update with invalid data (e.g., invalid email format)
3. **Expected Result:**
- Validation error in snackbar
- Specific message about what's wrong
---
### 📱 **Test Suite D: Payments & Bank Account**
#### **Test D1: Bank Account Addition Error**
1. Navigate to **Profile → Bank Account**
2. Try to add account with invalid routing number
3. **Expected Result:**
- Snackbar shows validation error
- Error is localized
#### **Test D2: Payment History Network Error**
1. Navigate to **Payments** tab
2. **Turn off internet**
3. Try to load payment history
4. **Expected Result:**
- Snackbar: "No internet connection"
- No crash
---
### 📱 **Test Suite E: Clock In & Attendance**
#### **Test E1: Clock In Network Error**
1. Navigate to **Clock In** tab
2. **Disable network**
3. Try to clock in
4. **Expected Result:**
- Snackbar: "No internet connection"
- Clock in action is blocked until network returns
---
### 🌐 **Test Suite F: Localization Verification**
#### **Test F1: English Error Messages**
With device language set to **English**, verify these error keys translate correctly:
| Scenario | Expected English Message |
|----------|-------------------------|
| No internet | "No internet connection. Please check your network." |
| Server error (500) | "Our servers are having issues. Please try again." |
| Not found (404) | "The requested resource was not found." |
| Unauthorized (401) | "Your session has expired. Please log in again." |
| Validation error | Specific field error (e.g., "Email is required") |
#### **Test F2: Spanish Error Messages**
With device language set to **Español**, verify these error keys translate correctly:
| Scenario | Expected Spanish Message |
|----------|-------------------------|
| No internet | "Sin conexión a internet. Verifica tu red." |
| Server error (500) | "Nuestros servidores tienen problemas. Inténtalo de nuevo." |
| Not found (404) | "No se encontró el recurso solicitado." |
| Unauthorized (401) | "Tu sesión ha expirado. Inicia sesión nuevamente." |
| Validation error | Error específico del campo |
---
### ✅ **Success Criteria**
The centralized error handling is working correctly if:
1. **No Crashes**: App never crashes due to network/server errors
2. **Consistent Display**: All errors appear in `UiSnackbar` with same styling
3. **User-Friendly**: Messages are clear, specific, and actionable
4. **Localized**: All errors translate correctly to Spanish
5. **Graceful Degradation**: App remains usable even when errors occur
6. **Data Preservation**: Form data is not lost when errors happen
---
### 🐛 **What to Report if Tests Fail**
If any test fails, please report:
1. **Which test** (e.g., "Test A2: Network Error During Submission")
2. **What happened** (e.g., "App crashed" or "Error showed in English despite Spanish language")
3. **Screenshot** of the error (if visible)
4. **Steps to reproduce**
---
### 🔧 **Quick Debug Commands**
For developers debugging error handling:
```dart
// Test error translation directly
print(translateErrorKey('errors.network.no_connection'));
print(translateErrorKey('errors.server.internal'));
print(translateErrorKey('errors.not_found.shift'));
// Test in Spanish
LocaleSettings.setLocale(AppLocale.es);
print(translateErrorKey('errors.network.no_connection'));
```
---
## 6. Code Locations (Reference)
* **Exceptions:** `packages/domain/lib/src/exceptions/app_exception.dart`
* **Data Mixin:** `packages/data_connect/lib/src/mixins/data_error_handler.dart`
* **Bloc Mixin:** `packages/core/lib/src/presentation/mixins/bloc_error_handler.dart`
* **Translator:** `packages/core_localization/lib/src/utils/error_translator.dart`
* **Strings:** `packages/core_localization/lib/src/l10n/*.i18n.json`

View File

@@ -0,0 +1,257 @@
# KROW Workforce Platform — Feature Testing Plan for Milestone 3
**Version:** Milestone 3 (0.0.1-IlianaStaffM3 and 0.0.1-IlianaClientM3)
**Estimated Duration:** 25-30 minutes
---
## Required Applications
- Client Mobile Application (v0.0.1-IlianaClientM3)
- Staff Mobile Application (v0.0.1-IlianaStaffM3)
---
## 1. Testing Environment Setup
### Required Test Accounts
**Client Account (Business User):**
- Email: `legendary@krowd.com`
- Password: `Demo2026!`
- Client Name: "Krow"
**Staff Account (Worker):**
- Phone: `+15557654321`
- OTP Code: `123456` (testing mode)
- Name: "Mariana Torres"
### Prerequisites
1. ✅ Both apps installed on the device
2. ✅ Network connection stable
---
## 2. Testing Steps
### 2.1: Register Business (Client App)
**Purpose:** Show the client onboarding experience
**Steps:**
1. Open Client App → Tap "Create Account"
2. Enter business email, and password (not the provided test account credentials, use a new email for this step)
3. Navigate to the home page
**Observable Points:** :
- Empty dashboard, no orders, no workers, clean slate
---
### 2.2: Register Staff (Staff App)
**Purpose:** Show the worker onboarding experience
**Steps:**
1. Open Staff App → Tap "Sign Up"
2. Enter phone number and verify with OTP code (not the provided test account credentials, use a new phone number for this step)
3. Follow the onboarding process
4. Navigate to the home page
**Observable Points:** :
- Empty shifts list, no available work yet
---
### 2.3: Client Sign In with an Existing Account (Client App)
**Note:** Use the client demo account credentials provided above.
**Purpose:** Show the sign-in experience for returning users
**Steps:**
1. Close Client App and reopen it.
2. Tap "Sign In" button
3. Enter credentials:
- Email: `legendary@krowd.com`
- Password: `Demo2026!`
4. Tap "Sign In"
---
### 2.4: Client Views the Populated Dashboard (Client App)
**Purpose:** Show how the client app displays active operations
**Steps:**
1. After signing in, observe the home screen
2. Navigate through populated sections:
- Home: Coverage stats, upcoming shifts
- Orders: Posted shifts with workers assigned
- Coverage: Real-time worker status
**Observable Points:**
- Coverage percentage for today's shifts
- Workers checked in vs. needed
- Late workers alerts
- Today's estimated labor cost
---
### 2.5: Client Creates a New Hub (Client App)
**Purpose:** Show the hub creation process
**Steps:**
1. Navigate to Hubs page via the settings button in the top right corner of the home screen
2. Tap the "Hubs" button in the settings menu.
3. Tap the "+" icon at the bottom right of the hubs list, to open the hub creation form.
4. Fill in hub details:
- Hub name: "Downtown Convention Center"
- Address: Start typing and select an address.
5. Tap "Create Hub"
6. See the new hub appear in the hubs list
---
### 2.6: Client Creates New Order (Client App)
**Purpose:** Walk through the order creation process
**Steps:**:
1. Go back to the home screen.
2. Navigate to the "Orders" tab in the bottom navigation.
3. Tap the "+ Post" button on top right to open the order type selection screen.
4. Select "One-Time" from the order type options.
5. Fill in order details:
- Order name: "Summer Gala 2026"
- Date: [Select upcoming date]
- Hub: [Select existing hub]
- Add position: Server, Count: 3, Hours: 5PM-9PM
6. Tap "Create Order"
---
### 2.7: Client Views Order Details (Client App)
**Purpose:** View detailed shift information and worker assignments
**Steps:**
1. View the created order in the orders list on the order screen.
**Observable Points:**
- Event name and location
- Roles needed
- Clock in/out times
- Estimated cost
- Coverage percentage bar
---
### 2.8: Client Monitors Coverage Dashboard (Client App)
**Purpose:** Show real-time worker tracking capabilities
**Steps:**
1. Navigate to the "Coverage" tab in the bottom navigation.
2. Observe the worker status for active shifts.
**Observable Points:**
- Worker status (Checked In, En Route, Late, Not Arrived)
- Color-coded status badges (green, yellow, red)
- Worker information
---
### 2.9: Staff Logs In with Existing Account (Staff App)
**Note:** Use the staff demo account credentials provided above.
**Purpose:** Show the staff app sign-in experience for returning users
**Steps:**
1. Close the staff app and reopen it.
2. Tap "Log In" button
3. Enter phone number: `5557654321`
4. Tap "Send Code"
5. Enter OTP: `123456`
---
### 2.10: Staff Views Home Dashboard (Staff App)
**Purpose:** View worker's personalized dashboard
**Observable Points:**
- Welcome message with worker's name
- Today's Shifts section (confirmed shifts for today)
- Tomorrow's Shifts section
- Recommended shifts section
---
### 2.11: Staff Finds Available Shifts (Staff App)
**Purpose:** Show the shift search and discovery experience for workers
**Steps:**
1. Navigate to the "Shifts" tab in the bottom navigation.
2. Tap the "Find Shifts" button on top to view available shifts.
**Observable Points:**
- List of shifts
- Hourly rate prominently displayed
- Role requirements (e.g., "Bartender - Spring Gala")
- Date, time, and duration
**Note:**
>Due to the current order flow, newly created orders do not appear in the Find Shifts section, as it requires an approval from the vendor. This was discussed during the demo.
>We are actively updating this flow so orders will appear correctly in a future iteration.
---
### 2.12: Staff Applies for Shift (Staff App)
**Purpose:** Show the application process from worker side
**Steps:**
1. Tap on an available shift to view details
2. Review business name, location, pay, requirements
3. Tap "Book Shift" button
4. Tap "Book" on the confirmation dialog
4. See confirmation
---
### 2.13: Staff Views Confirmed Shifts (Staff App)
**Purpose:** Show worker's shift confirmation
**Observable Points:**
- Week-by-week calendar navigation
- Color-coded status (Confirmed, Pending, Completed)
- Quick access to shift details and directions
---
### 2.14: Staff Clock-In to Shift (Day of Event) (Staff App)
**Purpose:** Demonstrate the clock-in process
**Steps:**
1. Navigate to the clock-in page.
2. Use the "Clock In" slider to clock in.
**Observable Points:**
- Timestamp automatically recorded
- Status changes to "Checked In" with green indicator
---
### 2.15: Staff Clocks-Out of Shift (Day of Event) (Staff App)
**Purpose:** Demonstrate the clock-out process and shift completion
**Steps:**
1. Navigate to the clock-out page.
2. Use the "Clock Out" slider to clock out.
3. Navigate to the "My Shifts" section in the Shifts tab to see the updated status via the bottom navigation.
**Observable Points:**
- Clock-out timestamp automatically recorded
- Status changes to "Completed"
---
### 2.16: Staff Profile Management (Staff App)
**Purpose:** Demonstrate worker profile features and compliance management
**Steps:**
1. Navigate to Profile tab in bottom navigation
2. Review profile sections:
- **Profile Info:**
- **Emergency Contact:** Name, relationship, phone number
- **Bank Account:** Linked payment account for direct deposit
- **Tax Forms:** W-4, I-9 compliance documents
- **Time Card:** Historical shift records with hours and earnings

View File

@@ -0,0 +1,63 @@
# KROW M3 Demo — Test Feedback
**Date:** February 3, 2026
---
## Demo 1: Register Business & Show Empty States (Client App)
- **Flickering company name:** Every time I navigate to the home screen, I see "your company" for a moment before it changes to the real name.
- Creating a One-Time Order shows "No Vendors Available" — this is expected, OK.
**Suggestions: Achintha:**
- We need to have a shimmer loading state while fetching data, to avoid flickering and empty states.
---
## Demo 2: Register Staff & Show Empty States (Staff App)
**Onboarding — Add preferred work locations:**
- Suggestion: Use Google Maps to suggest only city names. Currently users can type anything, which will cause misspellings and inconsistent data. Important for the max distance feature.
**Home page:**
- Same flickering issue — shows "Krower" briefly before displaying the real name.
**Profile page:**
- Phone number should be read-only, or require re-verification if changed.
- Emergency contact: "Save & Continue" works, but shouldn't we navigate to the profile page after? Other flows do this.
- Tax Documents: Would be great to add a file uploader where our AI could identify documents and prefill fields.
- Bank Account: Need to plan real bank verification (KYC)? Ensure the account is real and belongs to the user. Also, I can list banks but I don't see how to change/switch bank.
**Home (empty state):**
- Clicking "Find shifts →" does nothing. But "Find Shifts" with the search icon works.
**My Availability:**
- Working. Some latency, but OK for now.
---
## Demo 5: Client Creates a New Hub
- Hub editing feature seems missing — we'll need this for NFC configuration later.
- No confirmation before deleting a hub.
---
## Demo 6: Client Creates New Order
- "Up Next (x)" counter is confusing. I created 2 orders but it shows "Up Next (1)". Sometimes shows 0 when navigating, then back to 1.
---
## Demo 8: Staff Logs In with Existing Account
- If you accidentally click "Sign Up" with an existing phone number, you get stuck:
1. OTP screen shows error: "This user already has a staff profile. Please log in"
2. Clicking back → login → same OTP error loop
3. Only fix: kill and restart the app
---
## Demo 10: Staff Browses Available Shifts
- **Blocker:** I don't see the shift I created as the Client.

View File

@@ -0,0 +1,348 @@
# KROW Workforce Platform — Feature Demo Plan for Milestone 3
**Version:** Milestone 3 (v3.0)
**Date:** February 3, 2026
**Audience:** Business Stakeholders, Customer Engineers, Sales Teams
**Duration:** 25-30 minutes
---
## 1⃣ Demo Overview
### Purpose
This demo showcases the progress of the milestone 3.
- **For Businesses (Client App):** One-time shift creation, worker management, real-time coverage tracking
- **For Workers (Staff App):** Easy access to available shifts, clock-in and profile management
- **Complete Workflow:** From shift posting and worker check-in and completion
### Estimated Demo Duration
**25-30 minutes**
---
## 2⃣ Demo Environment Setup
### Required Test Accounts
**Client Account (Business User):**
- Email: `legendary@krowd.com`
- Password: `Demo2026!`
- Client Name: "Krow"
**Staff Account (Worker):**
- Phone: `+15557654321`
- OTP Code: `123456` (demo mode)
- Name: "Mariana Torres"
### Prerequisites
1. ✅ Both apps installed on demo devices (or simulators)
2. ✅ Network connection stable
3. ✅ Seed data is ready to be populated (the database should be empty at start)
### Make Commands Reference
| Command | Purpose |
|---------|---------|
| `make dataconnect-clean` | Clean the database before seeding |
| `make dataconnect-seed` | Populate the database with seed data for demo |
### Recent Fixes Applied
- ✅ Fixed 2 bugs on TaxForm: marital status and Citizenship Status now properly saved
- ✅ Fixed update screen after create or update TaxForm
- ✅ Created seed data script
- ✅ Created make commands to create and delete information in DataConnect
---
## 3⃣ Demo Flows
### Demo 0: Show Empty Database
**Purpose:** Demonstrate the starting point before any data exists
**Steps:**
1. Run `make dataconnect-clean` to ensure database is empty
2. Show the empty database in Firebase console
---
### Demo 1: Register Business & Show Empty States (Client App)
**Purpose:** Show the client onboarding experience and empty states
**Steps:**
1. Open Client App → Tap "Create Account"
2. Enter business email, and password
3. Navigate to home page
4. **Point out:** Empty dashboard, no orders, no workers, clean slate
---
### Demo 2: Register Staff & Show Empty States (Staff App)
**Purpose:** Show the worker onboarding experience and empty states
**Steps:**
1. Open Staff App → Tap "Sign Up"
2. Enter phone number and verify with OTP code
3. Follow the onboarding process
4. Navigate to home page
5. **Point out:** Empty shifts list, no available work yet
---
### 🔄 PAUSE: Populate Database
Run the seeding command:
```bash
make dataconnect-seed
```
---
### Demo 3: Client Logs In with Existing Account
**Purpose:** Show the sign-in experience for returning users
**Screen:** Get Started → Sign In
**Steps:**
1. Restart Client App
2. Tap "Sign In" button
3. Enter credentials:
- Email: `legendary@krowd.com`
- Password: `Demo2026!`
4. Tap "Sign In"
---
### Demo 4: Client Views Populated Dashboard
**Purpose:** Show how the client app displays active operations
**Steps:**
1. After signing in, observe the home screen
2. Navigate through populated sections:
- Home: Coverage stats, upcoming shifts
- Orders: Posted shifts with workers assigned
- Coverage: Real-time worker status
**What to Notice:**
- Coverage percentage for today's shifts
- Workers checked in vs. needed
- Late workers alerts
- Today's estimated labor cost
---
### Demo 5: Client Creates a New Hub
**Screen:** Hubs Tab → "Add Hub" button
**Steps:**
1. Navigate to Hubs tab in bottom navigation
2. Tap the "+" or "Add Hub" button
3. Fill in hub details:
- Hub name: "Downtown Convention Center"
- Address: Start typing and select from Google Places autocomplete
4. Tap "Create Hub"
5. See the new hub appear in the hubs list
---
### 📋 Main Demo Flow Explanation
```
Client Posts Shift [O1]
*Vendor Accepts the Shift (Missing for now) / Vendor is selected by client* [O2]
Worker Searches for a Shift [O3]
Worker Applies [O4]
Confirmation (Missing for now, auto-confirmed)* [O5]
Worker Checks In [O6]
Shift Completed [O7]
```
---
### Demo 6: Client Creates New Order - [O1]
**Purpose:** Walk through the shift creation process
**Screen:** Orders Tab → "Post" button
**What to Fill:**
- Order name: "Spring Gala 2026"
- Date: [Select upcoming date]
- Location: [Select existing hub]
- Add position: Server, Count: 3, Hours: 5PM-9PM
---
### Demo 7: Client Views Order Details
**Purpose:** Show detailed shift information and worker assignments (second part is missing for now)
**Screen:** Orders Tab → Tap on any order card
**What to Notice:**
- Event name and location
- Roles needed (e.g., "2 Servers")
- Clock in/out times
- Estimated cost
- Coverage percentage bar
---
### Demo 8: Staff Logs In with Existing Account
**Purpose:** Show the worker sign-in experience
**Screen:** Get Started → Sign In with Phone
**Steps:**
1. Restart the staff app
2. Enter phone number: `5557654321`
3. Tap "Send Code"
4. Enter OTP: `123456`
---
### Demo 9: Staff Views Home Dashboard
**Purpose:** Show worker's personalized dashboard
**What to Notice:**
- Today's Shifts section (confirmed shifts for today)
- Tomorrow's Shifts section
---
### Demo 10: Staff Browses Available Shifts - [O3]
**Purpose:** Show how workers discover and view available work
**Screen:** Shifts → "Find Work"
**What to Notice:**
- List of shifts matching worker skills
- Hourly rate prominently displayed
- Role requirements (e.g., "Bartender - Spring Gala")
- Date, time, and duration
---
### Demo 11: Staff Applies for Shift - [O4]
**Purpose:** Show the application process from worker side
**Screen:** Shift Details → "Book" Shift button
**Steps:**
1. Tap on an available shift to view details
2. Review business name, location, pay, requirements
3. Tap "Book" Shift button
4. See confirmation
---
### Demo 12: Staff Views Confirmed Shifts - [O5]
**Purpose:** Show worker's shift management interface
**Screen:** Shifts Tab → "My Shifts"
**What to Notice:**
- Week-by-week calendar navigation
- Color-coded status (Confirmed, Pending, Completed)
- Quick access to shift details and directions
---
### Demo 13: Client Monitors Coverage Dashboard - [O5]
**Purpose:** Show real-time worker tracking capabilities
**Screen:** Client App → Coverage Tab
**What to Notice:**
- Live worker status (Checked In, En Route, Late, Not Arrived)
- Color-coded status badges (green, yellow, red)
- Worker information
---
### Demo 14: Staff Clock-In to Shift (Day of Event) - [O6]
**Purpose:** Demonstrate the clock-in process
**Screen:** Clockin page → "Clock In" slider
**What to Notice:**
- Timestamp automatically recorded
- Status changes to "Checked In" with green indicator
---
### Demo 15: Client Sees Clock-In Update - [O6]
**Purpose:** Show cross-app interaction and real-time updates
**Screen:** Client App → Coverage Tab
**Action:** Press the update button on the top right to refresh worker statuses
**What to Notice:**
- Status update
- User status changes to "Checked In"
- Check-in time displayed
---
### Demo 16: Staff Clocks-Out of Shift - [O7]
**Purpose:** Demonstrate the clocks-out process and shift completion
**Screen:** Clockin page -> Clock-out slider
**What to Notice:**
- Clock-out timestamp automatically recorded
- Status changes to "Completed"
- Total hours worked calculated automatically
---
### Demo 17: Client Views Completed Shift in Coverage - [O7]
**Purpose:** Show how completed shifts appear in the client app
**Screen:** Client App → Coverage Tab
**Action:** Press the refresh button to update worker statuses
**What to Notice:**
- Worker status changes to "Completed"
- Check-out time displayed alongside check-in time
- Total hours worked visible
- Shift marked as complete in orders list
- Cost finalized based on actual hours
---
### Demo 18: Staff Profile Management
**Purpose:** Demonstrate worker profile features and compliance management
**Screen:** Staff App → Profile Tab
**Steps:**
1. Navigate to Profile tab in bottom navigation
2. Review profile sections:
- **Profile Info:**
- **Emergency Contact:** Name, relationship, phone number
- **Bank Account:** Linked payment account for direct deposit
- **Tax Forms:** W-9, I-9 compliance documents *(bugs fixed: marital status and Citizenship Status now work properly)*
- **Time Card:** Historical shift records with hours and earnings
---
## 4⃣ Customer Handover Checklist
### Deliverables
- [ ] Android apps (Client and Staff)
- [ ] Demo account credentials (see below)
### Demo Accounts
| Account | Credentials |
|---------|-------------|
| **Client** | Email: `legendary@krowd.com` / Password: `Demo2026!` |
| **Staff** | Phone: `+15557654321` / OTP: `123456` (demo mode) |

View File

@@ -0,0 +1,420 @@
# **Development Tasks**
These are written to be readable by a project manager and easy to translate into GitHub issues later.
Each item keeps a question-style title and includes a lightweight issue outline (goal, scope, acceptance criteria).
## **BE**
### Validate shift acceptance by a worker
- **Goal**: Prevent workers from accepting shifts they are not eligible to accept.
- **Where**: Backend validation (server-side).
- **Key rules (M4)**
- Prevent accepting overlapping shifts.
- If a shift is already accepted in that time window, reject the accept action.
- **Design requirement**
- Make the algorithm scalable so future shift-acceptance rules can be added without rewriting core logic.
- **Acceptance criteria**
- Backend rejects overlapping acceptance with a clear error reason.
- Validation is enforced even if the client app is bypassed.
### Validate shift creation by a client
- **Goal**: Ensure shifts/orders created by clients meet required criteria.
- **Where**: Backend validation (server-side).
- **Key rules (M4)**
- Add a *soft check* for minimum shift hours when creating an order.
- When a client creates an order, check if shift hours are below the vendor minimum.
- Current minimum hours: **5 hours**.
- **FE dependency**
- Also add a FE validation (user feedback) in addition to BE enforcement.
- **Design requirement**
- Make the algorithm scalable so future creation rules can be added.
- **Acceptance criteria**
- Backend returns a consistent validation response when the minimum-hours check fails.
- FE shows a clear validation message before submission (soft check).
### Enforce cancellation policy (no cancellations within 24 hours)
- **Goal**: Prevent cancellations within 24 hours of shift start time.
- **Where**: Backend enforcement.
- **Open decision**
- Finalize the penalty for cancellations within this window.
- **Acceptance criteria**
- Backend blocks cancellation attempts inside the 24-hour window.
- API response communicates the policy reason and references the penalty (once finalized).
### Implement worker documentation upload process
- **Goal**: Allow workers to upload required documents (e.g., certifications, tax forms) securely.
- **Where**: Backend (storage + linking).
- **Scope**
- Upload flow.
- Store documents.
- Link documents to the worker profile.
- **Acceptance criteria**
- Uploaded documents are stored securely and retrievable by authorized parties.
- Each upload is reliably associated with the correct worker profile.
### Parse uploaded documentation for verification
- **Goal**: Extract relevant info from uploaded documents to assist verification.
- **Where**: Backend.
- **Policy requirement**
- Manual verification by the client must still exist even if AI verification passes.
- **Acceptance criteria**
- Parsed fields are stored in a structured format for review.
- Client can manually verify/override AI results.
### Support attire upload for workers
- **Goal**: Allow workers to upload attire images for verification.
- **Where**: Backend.
- **Acceptance criteria**
- Attire images can be uploaded and linked to the worker profile.
### Verify attire images against shift dress code
- **Goal**: Verify uploaded attire meets dress code requirements.
- **Where**: Backend.
- **Policy requirement**
- Manual verification by the client must still exist even if AI verification passes.
- **Acceptance criteria**
- Verification results are stored and visible to the client for manual review.
### Support shifts requiring "awaiting confirmation" status
- **Goal**: Support shifts where the worker must manually confirm before the shift becomes active.
- **Where**: Backend.
- **Acceptance criteria**
- Shift can enter an "awaiting confirmation" state.
- Worker confirmation transitions the shift to the next expected active state.
### Enable NFC-based clock-in and clock-out
- **Goal**: Allow attendance via NFC.
- **Where**: Backend tasks (APIs/events/storage to support NFC clock-in/out).
- **Acceptance criteria**
- Backend can record NFC clock-in/out events with appropriate validation and auditing.
### Implement worker profile visibility settings
- **Goal**: Allow workers to hide their profile from clients if they choose.
- **Where**: Backend tasks (visibility settings + enforcement).
- **Acceptance criteria**
- Worker can change visibility setting.
- Backend enforces visibility in client-facing queries.
### Support rapid order parsing (voice and text) using AI
- **Goal**: Let clients create orders by describing needs in voice/text.
- **Where**: Backend tasks (parsing + mapping).
- **Notes**
- Always map the output similar to **one-time order creation**.
- **Acceptance criteria**
- Backend returns a structured draft order that matches the one-time order model.
### Personalize shifts shown to workers (auto match)
- **Goal**: Show worker-personalized shifts.
- **Where**: Backend matching/filtering logic.
- **Inputs (M4)**
- Preferred locations.
- Experience.
- **Acceptance criteria**
- Worker shift feed is personalized based on these inputs.
### What backend work is needed to support recurring order and reorder?
- **Goal**: Enable recurring orders and reorder.
- **Where**: Backend.
- **Acceptance criteria**
- Backend can create and manage recurring orders and support reorder actions.
### What backend work is needed to support permanent order and reorder?
- **Goal**: Enable permanent orders and reorder.
- **Where**: Backend.
- **Acceptance criteria**
- Backend can create and manage permanent orders and support reorder actions.
### Backend support for reports page (client mobile)
- **Goal**: Provide APIs/data needed to render the main reports entry and summary experience.
- **Where**: Backend.
- **Acceptance criteria**
- Reports API contracts are defined and documented.
- Client can load the reports page without placeholder data.
### Backend support for "Daily ops" report (client mobile)
- **Goal**: Provide the data required for the Daily ops report.
- **Where**: Backend.
- **Acceptance criteria**
- Daily ops report API returns all fields required by the UI.
- Response is documented (including filters/date ranges, if applicable).
### Backend support for "Spend report" (client mobile)
- **Goal**: Provide the data required for the Spend report.
- **Where**: Backend.
- **Acceptance criteria**
- Spend report API returns all fields required by the UI.
- Response is documented (including filters/date ranges, if applicable).
### Backend support for "Coverage report" (client mobile)
- **Goal**: Provide the data required for the Coverage report.
- **Where**: Backend.
- **Acceptance criteria**
- Coverage report API returns all fields required by the UI.
- Response is documented (including filters/date ranges, if applicable).
### Backend support for "No-show" report (client mobile)
- **Goal**: Provide the data required for the No-show report.
- **Where**: Backend.
- **Acceptance criteria**
- No-show report API returns all fields required by the UI.
- Response is documented (including filters/date ranges, if applicable).
### Backend support for "Performance report" (client mobile)
- **Goal**: Provide the data required for the Performance report.
- **Where**: Backend.
- **Acceptance criteria**
- Performance report API returns all fields required by the UI.
- Response is documented (including filters/date ranges, if applicable).
### Calculate the 3 AI insights for the client mobile reports page
- **Goal**: Produce the three AI insights shown on the reports page.
- **Where**: Backend.
- **Acceptance criteria**
- Insights are generated consistently and returned in the reports API response.
## **FE**
### **Staff mobile application**
### Show Google Maps location in worker shift details
- **Goal**: Display shift location on a map.
- **Acceptance criteria**
- Shift details page shows the correct location using Google Maps.
### Show shift requirements in worker shift details
- **Goal**: Make requirements visible before acceptance.
- **Acceptance criteria**
- Shift details page includes a requirements section for that shift.
- **Details**
- The main goal is to have list the the required attires in the requirement section but if there are any other requirements we can also list them there.
### Implement attire screen in worker app
- **Goal**: Let workers understand attire requirements and submit attire for review.
- **Scope (M4)**
- Show the list of **MUST HAVE** attire items.
- Show the list of **NICE TO HAVE** attire items.
- Allow workers to upload images of their attire for verification.
- Show uploaded attire images in the worker profile.
- **Acceptance criteria**
- Attire screen renders required lists and supports image upload flow.
- Uploaded images appear in the worker profile UI.
### Implement FAQ screen in worker app
- **Goal**: Provide common answers in-app.
- **Acceptance criteria**
- Worker app includes an FAQ screen accessible from appropriate navigation.
### Implement Privacy and Security screen in worker app
- **Goal**: Provide key privacy/security controls and documents.
- **Scope (M4)**
- Profile visibility setting.
- Terms of service (use a generated placeholder for now; replace with final for launch).
- Privacy policy (use a generated placeholder for now; replace with final for launch).
- **Acceptance criteria**
- Screen is accessible and displays all items above.
### Restrict navigation when worker profile is incomplete
- **Goal**: Reduce access until onboarding/profile completion.
- **Acceptance criteria**
- If the user has not completed their profile, only show **Profile** and **Home**.
### **Client mobile application**
### Implement rapid order creation (voice + text) in client mobile app
- **Goal**: Allow clients to quickly create same-day orders by describing needs via voice/text.
- **Scope (M4)**
- Capture voice/text input.
- Send input for parsing.
- Populate a screen equivalent to the one-time order creation screen so the client can adjust before finalizing.
- Always map similar to one-time order creation (handles same-day orders).
- **Acceptance criteria**
- Parsed output populates the one-time order creation UI correctly.
- Client can edit and successfully submit the order.
### Implement recurring order in client mobile app
- **Goal**: Allow clients to create recurring orders.
- **Scope (M4)**
- Create a recurring order UI flow.
- **Acceptance criteria**
- Client can create and submit a recurring order successfully.
### Implement permanent order in client mobile app
- **Goal**: Allow clients to create permanent orders.
- **Scope (M4)**
- Create a permanent order UI flow.
- **Acceptance criteria**
- Client can create and submit a permanent order successfully.
### Update reorder modal to support order types
- **Goal**: Ensure reorder works across supported order types.
- **Acceptance criteria**
- Reorder modal reflects the correct order type and fields.
### Complete reports interface with AI insights (client mobile)
- **Goal**: Implement the main reports UI and display AI insights.
- **Dependencies**
- Requires backend reports APIs and AI insights availability.
- **Acceptance criteria**
- Reports interface is complete and shows AI insights (no placeholder UI).
### Complete "Daily ops" report UI (client mobile)
- **Goal**: Implement the Daily ops report screen.
- **Dependencies**
- Requires backend Daily ops report support.
- **Acceptance criteria**
- Daily ops report UI is complete and renders real data.
### Complete "Spend report" UI (client mobile)
- **Goal**: Implement the Spend report screen.
- **Dependencies**
- Requires backend Spend report support.
- **Acceptance criteria**
- Spend report UI is complete and renders real data.
### Complete "Coverage report" UI (client mobile)
- **Goal**: Implement the Coverage report screen.
- **Dependencies**
- Requires backend Coverage report support.
- **Acceptance criteria**
- Coverage report UI is complete and renders real data.
### Complete "No-show" report UI (client mobile)
- **Goal**: Implement the No-show report screen.
- **Dependencies**
- Requires backend No-show report support.
- **Acceptance criteria**
- No-show report UI is complete and renders real data.
### Complete "Performance report" UI (client mobile)
- **Goal**: Implement the Performance report screen.
- **Dependencies**
- Requires backend Performance report support.
- **Acceptance criteria**
- Performance report UI is complete and renders real data.
### Build dedicated interface to display hub details
- **Goal**: Show hub details in a dedicated UI.
- **Acceptance criteria**
- Hub details page exists and displays hub information.
### Enable hub editing (separate page)
- **Goal**: Allow hub editing via a dedicated screen.
- **Acceptance criteria**
- Separate edit hub page exists and updates the hub data.
# **Research Tasks**
### Validate worker SSN number in the US
- **Goal**: Identify a viable SSN validation approach.
- **Scope (research)**
- Research third-party services/APIs that provide SSN validation.
- Evaluate cost, reliability, and integration effort.
- Outline an integration plan and highlight risks.
### Validate worker bank account details in the US
- **Goal**: Identify a viable bank account validation approach.
- **Scope (research)**
- Research third-party services/APIs for bank account validation.
- Evaluate cost, reliability, and integration effort.
- Outline an integration plan and highlight risks.
- Note: legacy app only uses soft FE checks; M4 aims for a proper validation process.
### What payment platforms do we want to integrate for processing payments to workers?
- **Goal**: Select a payout/payment platform.
- **Scope (research)**
- Research platforms (e.g., Stripe, PayPal, Square) that support payouts.
- Evaluate cost, reliability, and integration effort.
- Outline an integration plan and highlight risks.
### Implement test cases for 2 web dashboard features using agent-browser
- **Goal**: Add automated test coverage runnable via <https://agent-browser.dev/>.
- **Scope (research + spike)**
- Research how to implement test cases for web apps using the agent browser.
# **Business Tasks**
### Create template model for PDF reports in client and web apps
- **Goal**: Align report format across platforms.
- **Acceptance criteria**
- A shared template model is defined and ready to implement.
### Handle operational risk scenarios that disadvantage clients
- **Goal**: Define policies for common operational issues.
- **Scenarios (M4)**
- Worker is a no-show.
- Shifts are not getting enough applicants.
- **Acceptance criteria**
- Written policy decisions exist and are ready to translate into product rules.
### Finalize terms of service and privacy policy for mobile apps
- **Goal**: Provide legal documents for launch readiness.
- **Acceptance criteria**
- Terms of service and privacy policy drafts exist and are approved for implementation.
### Handle worker data requests
- **Goal**: Define a process for worker data requests.
- **Acceptance criteria**
- A documented workflow exists (intake, verification, fulfillment, timelines).
### How should we rephrase key terminology in the app (for clarity and accuracy)?
- **Goal**: Use consistent product language.
- **Topics (M4)**
- Worker registration: is it "signup" or "onboarding"?
- Context: workers are expected to be attached to a vendor; the flow is closer to onboarding (phone number + OTP) than self-service signup.
- Worker profile visibility: is it "profile visibility" or "availability status"?
- Context: workers are not fully invisible; they are marking themselves unavailable.
- What do we mean by "auto match"?
- Should this exist by default anyway?
- Is this only a marketing item?
- These are just examples; the discussion may surface additional terminology decisions.
- **Acceptance criteria**
- A terminology decision list exists with approved wording.

View File

@@ -1,908 +0,0 @@
# 🧪 KROW Workforce Platform - QA Testing Checklist
**Version:** 1.0
**Date:** February 1, 2026
**Coverage:** Client App + Staff App
**Purpose:** Manual QA and Regression Testing
---
## 📋 TABLE OF CONTENTS
1. [Feature-Level QA Checklist](#1⃣-feature-level-qa-checklist)
- [Client App Features](#client-app-features)
- [Staff App Features](#staff-app-features)
2. [Cross-Application Test Scenarios](#2⃣-cross-application-test-scenarios)
3. [Shared Infrastructure Validation](#3⃣-shared-infrastructure-validation)
4. [Regression & Release Checklist](#4⃣-regression--release-checklist)
---
## 1⃣ FEATURE-LEVEL QA CHECKLIST
### CLIENT APP FEATURES
---
#### 📱 CLIENT-001: Authentication
**Applications:** Client
**Entry Points:**
- Launch app → Get Started → Sign In
- Launch app → Get Started → Sign Up
**Happy Path Test Cases:**
- [ ] Sign in with valid email and password displays home dashboard
- [ ] Sign up with business details creates account and navigates to home
**Validation & Error States:**
- [ ] Invalid email format shows validation error
- [ ] Incorrect password shows authentication error
- [ ] Weak password in sign-up shows strength requirements
- [ ] Duplicate email in sign-up shows "already registered" error
- [ ] Empty fields show required field errors
**Loading & Empty States:**
- [ ] Loading spinner displays during authentication
- [ ] OAuth redirect shows appropriate loading state
---
#### 📱 CLIENT-002: Home Dashboard
**Applications:** Client
**Entry Points:**
- Home tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Dashboard displays current day coverage widget
- [ ] Spending analytics widget shows correct totals
- [ ] Recent reorders display completed shift roles
- [ ] Quick action buttons navigate to correct features
- [ ] Drag-and-drop widget reordering works correctly
**Validation & Error States:**
- [ ] Empty state shows "No data available" when no orders exist
**Loading & Empty States:**
- [ ] Empty coverage shows "No shifts today"
- [ ] Empty reorders shows "No recent orders"
---
#### 📱 CLIENT-003: Create Order
**Applications:** Client
**Entry Points:**
- Home → Create Order button
- Orders tab → + FAB button
- Order type → One-Time
**Happy Path Test Cases:**
- [ ] Order type selection displays.
- [ ] Hub selection shows list of business hubs
- [ ] Role selection displays vendor roles
- [ ] Position quantity can be incremented/decremented (min 1)
- [ ] Date picker displays correct calendar
- [ ] Time pickers show valid time ranges
- [ ] Break duration affects total hours calculation
- [ ] Cost preview calculates correctly (rate × positions × hours)
- [ ] Order submission creates order, shift, and shift roles
- [ ] Success confirmation displays after submission
- [ ] New order appears in View Orders list
**Validation & Error States:**
- [ ] Empty hub field shows validation error
- [ ] Empty role field shows validation error
- [ ] Zero positions shows validation error
- [ ] Invalid date (past) shows validation error
- [ ] Start time after end time shows validation error
- [ ] Missing required fields prevent submission
- [ ] Backend validation errors display appropriately
**Loading & Empty States:**
- [ ] Hub list shows "No hubs" if none exist
- [ ] Role list shows "No roles" if none configured
- [ ] Loading spinner displays during submission
- [ ] Submission progress indicator updates
---
#### 📱 CLIENT-004: View Orders
**Applications:** Client
**Entry Points:**
- Orders tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Orders list displays orders for selected date
- [ ] Calendar date selection updates order list
- [ ] Each order card shows hub name and address
- [ ] Each order card shows shift time range
- [ ] Each order card shows role positions (filled/total)
- [ ] Each order card shows hourly rate and total cost
- [ ] Accepted applications section displays confirmed staff
- [ ] Staff names and photos display correctly
- [ ] Order list scrolls smoothly with many orders
**Validation & Error States:**
- [ ] Invalid date selection shows error
- [ ] Missing staff data shows placeholder
**Loading & Empty States:**
- [ ] Empty date shows "No orders for this date"
- [ ] Empty accepted applications shows "No confirmed staff"
---
#### 📱 CLIENT-005: Coverage Monitoring
**Applications:** Client
**Entry Points:**
- Coverage tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Coverage overview displays current date
- [ ] Coverage stats show needed/confirmed/checked-in counts
- [ ] Shift cards display hub name and time range
- [ ] Worker cards show staff name and photo
- [ ] Check-in status indicators update correctly (late, en-route, checked-in)
- [ ] Late workers display with warning indicator
- [ ] Coverage progress bar updates correctly
**Validation & Error States:**
- [ ] Missing worker photo shows default avatar
**Loading & Empty States:**
- [ ] Empty coverage shows "No shifts today"
- [ ] No workers show "No staff assigned"
**State Persistence:**
- [ ] Coverage data refreshes automatically every X minutes
- [ ] Manual refresh via pull-to-refresh gesture
**Backend Dependency Validation:**
- [ ] `listShiftRolesByBusinessAndDateRange` returns shift requirements
- [ ] `listStaffsApplicationsByBusinessForDay` returns staff status
- [ ] Attendance status correctly mapped from backend
---
#### 📱 CLIENT-006: Billing & Invoices
**Applications:** Client
**Entry Points:**
- Billing tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Current bill amount displays correctly
- [ ] Pending invoices list shows open invoices
- [ ] Invoice history shows paid invoices
- [ ] Savings amount displays correctly
- [ ] Spending breakdown shows costs by role
- [ ] Period filter (weekly/monthly) updates data
- [ ] Invoice detail view shows line items
- [ ] Invoice PDF download works (if implemented)
**Validation & Error States:**
- [ ] Zero billing shows $0.00 (not error)
- [ ] Negative savings shows correctly
- [ ] Missing invoice data shows placeholder
**Loading & Empty States:**
- [ ] Empty pending invoices shows "No pending invoices"
- [ ] Empty history shows "No invoice history"
- [ ] Empty spending breakdown shows "No spending data"
---
#### 📱 CLIENT-007: Hub Management
**Applications:** Client
**Entry Points:**
- Settings → Hubs
- Create Order → Add Hub button
**Happy Path Test Cases:**
- [ ] Hubs list displays all business hubs
- [ ] Hub cards show name and full address
- [ ] Add hub button opens creation form
- [ ] Google Places autocomplete suggests addresses
- [ ] Address selection auto-fills all address fields
- [ ] Hub name can be customized
- [ ] Hub creation adds to list immediately
- [ ] Hub deletion removes from list (with confirmation)
- [ ] Team entity auto-created for business if missing
**Validation & Error States:**
- [ ] Empty hub name shows validation error
- [ ] Empty address shows validation error
- [ ] Invalid address format shows error
- [ ] Duplicate hub name shows warning
- [ ] Hub with active orders prevents deletion (validation error)
**Loading & Empty States:**
- [ ] Empty hubs list shows "No hubs configured"
- [ ] Hub creation shows loading spinner
---
#### 📱 CLIENT-008: Settings
**Applications:** Client
**Entry Points:**
- Settings (navigation menu)
**Happy Path Test Cases:**
- [ ] User profile displays name and email
- [ ] Business name displays correctly
- [ ] Hubs link navigates to hub management
- [ ] Sign out logs out user and returns to auth screen
**Validation & Error States:**
- [ ] Missing profile photo shows default avatar
- [ ] Sign out error shows retry option
**Loading & Empty States:**
- [ ] Profile data loads on page mount
---
#### 📱 CLIENT-009: Client Main Navigation
**Applications:** Client
**Entry Points:**
- Main app shell after authentication
**Happy Path Test Cases:**
- [ ] Bottom navigation displays 5 tabs (Home, Coverage, Billing, Orders, Reports)
- [ ] Tab selection updates active indicator
- [ ] Tab selection navigates to correct feature
- [ ] Deep links navigate to correct tab
- [ ] Back button navigates correctly within nested routes
- [ ] Tab state persists after device rotation
**Validation & Error States:**
- [ ] Invalid route shows 404 or redirects to home
- [ ] Reports tab shows placeholder (not yet implemented)
**Loading & Empty States:**
- [ ] Navigation bar displays immediately
- [ ] Initial tab loads first
---
### STAFF APP FEATURES
---
#### 📱 STAFF-001: Authentication
**Applications:** Staff
**Entry Points:**
- Launch app → Get Started → Phone Verification
**Happy Path Test Cases:**
- [ ] Phone number entry accepts valid formats
- [ ] OTP sent confirmation displays
- [ ] OTP verification succeeds with valid code
- [ ] Profile setup wizard displays for new users
- [ ] Authenticated users bypass auth and show home
**Validation & Error States:**
- [ ] Invalid phone format shows validation error
- [ ] Incorrect OTP shows verification error
- [ ] Expired OTP shows re-send option
- [ ] Empty fields show required field errors
- [ ] Network error displays retry option
**Loading & Empty States:**
- [ ] Loading spinner displays during phone verification
- [ ] OTP input shows countdown timer
- [ ] Profile setup shows progress indicator
---
#### 📱 STAFF-002: Home Dashboard
**Applications:** Staff
**Entry Points:**
- Home tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Today's shifts display with time and location
- [ ] Tomorrow's shifts display correctly
- [ ] Recommended shifts show available opportunities
- [ ] Shift cards show role, location, and pay rate
- [ ] Quick actions navigate to correct features
- [ ] Dashboard refreshes on pull-to-refresh
**Validation & Error States:**
- [ ] Missing shift data shows placeholder
**Loading & Empty States:**
- [ ] Empty today's shifts shows "No shifts today"
- [ ] Empty recommended shows "No available shifts"
---
#### 📱 STAFF-003: Profile
**Applications:** Staff
**Entry Points:**
- Profile tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Profile displays name, email, phone, and photo
- [ ] Statistics show total shifts, ratings, reliability score
- [ ] Profile sections list displays all sections
- [ ] Section navigation works correctly
- [ ] Sign out logs out user and returns to auth screen
**Validation & Error States:**
- [ ] Missing profile photo shows default avatar
- [ ] Missing statistics show 0 or default values
- [ ] Sign out error shows retry option
**Loading & Empty States:**
- [ ] Profile data loads on page mount
---
#### 📱 STAFF-004: Shifts Management
**Applications:** Staff
**Entry Points:**
- Shifts tab (bottom navigation)
- Tab navigation: My Shifts / Available / Pending / Cancelled / History
**Happy Path Test Cases:**
- [ ] My Shifts tab displays assigned shifts
- [ ] Available Shifts tab shows open positions
- [ ] Pending tab shows applications awaiting approval
- [ ] Cancelled tab shows cancelled shifts
- [ ] History tab shows past shifts
- [ ] Shift detail view displays full information
- [ ] Accept shift updates status to confirmed
- [ ] Decline shift updates status to declined
- [ ] Apply for shift creates application
- [ ] Shift cards show time, location, role, and pay
**Validation & Error States:**
- [ ] Empty tabs show appropriate empty state messages
- [ ] Already applied shift prevents duplicate application
- [ ] Past shifts cannot be applied to
- [ ] Cancelled shifts show cancellation reason
---
#### 📱 STAFF-005: Availability Management
**Applications:** Staff
**Entry Points:**
- Worker Main → Availability
- Profile → Availability section
**Happy Path Test Cases:**
- [ ] Weekly grid displays Monday-Sunday
- [ ] Time slots (Morning/Afternoon/Evening) toggle correctly
- [ ] Quick-set buttons work (Weekdays/Weekends/All Week)
- [ ] Individual day/slot updates save correctly
- [ ] Green checkmarks indicate availability
- [ ] Gray states indicate unavailability
- [ ] Changes save automatically
**Validation & Error States:**
- [ ] Save failure shows error message
**Loading & Empty States:**
- [ ] Loading spinner displays while fetching availability
- [ ] Default state shows all unavailable
---
#### 📱 STAFF-006: Clock In/Out
**Applications:** Staff
**Entry Points:**
- Clock In tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Today's shift displays with clock in button
- [ ] Clock in button creates attendance record
- [ ] Clock in time displays correctly
- [ ] Clock out button appears after clocking in
- [ ] Clock out creates end time record
- [ ] Total hours calculated correctly
- [ ] Attendance status updates immediately
**Validation & Error States:**
- [ ] No shift today shows "No shifts to clock in"
- [ ] Already clocked in prevents duplicate clock in
- [ ] Clock in outside shift time shows warning
**Loading & Empty States:**
- [ ] Loading spinner displays while fetching shift
- [ ] Empty state shows "No shifts scheduled"
---
#### 📱 STAFF-007: Payments
**Applications:** Staff
**Entry Points:**
- Payments tab (bottom navigation)
**Happy Path Test Cases:**
- [ ] Payment summary displays total earnings
- [ ] Payment history lists all transactions
- [ ] Payment cards show amount, date, and status
- [ ] Payment detail view shows breakdown
- [ ] Filter by date range works correctly
**Validation & Error States:**
- [ ] Zero earnings show $0.00 (not error)
- [ ] Missing payment data shows placeholder
**Loading & Empty States:**
- [ ] Empty history shows "No payment history"
---
#### 📱 STAFF-008: Personal Info (Onboarding)
**Applications:** Staff
**Entry Points:**
- Profile → Personal Info
- Onboarding wizard
**Happy Path Test Cases:**
- [ ] Form displays current profile data
- [ ] Name field allows text input
- [ ] Email field validates email format
- [ ] Phone field validates phone format
- [ ] Photo upload works correctly
- [ ] Preferred locations multi-select works
- [ ] Save button updates profile
**Validation & Error States:**
- [ ] Empty required fields show validation errors
- [ ] Invalid email format shows error
- [ ] Invalid phone format shows error
- [ ] Photo upload failure shows error
**Loading & Empty States:**
- [ ] Form loads with skeleton placeholders
- [ ] Photo upload shows progress indicator
- [ ] Save button shows loading spinner
---
#### 📱 STAFF-009: Emergency Contact (Onboarding)
**Applications:** Staff
**Entry Points:**
- Profile → Emergency Contact
- Onboarding wizard
**Happy Path Test Cases:**
- [ ] Contact list displays all contacts
- [ ] Add contact button opens form
- [ ] Contact form validates name and phone
- [ ] Relationship dropdown shows options (Family/Spouse/Friend/Other)
- [ ] Remove contact deletes from list
- [ ] Save updates all contacts
- [ ] Multiple contacts supported
**Validation & Error States:**
- [ ] Empty name shows validation error
- [ ] Invalid phone format shows error
- [ ] At least one contact required (if applicable)
**Loading & Empty States:**
- [ ] Loading spinner displays while fetching contacts
- [ ] Empty state shows "No emergency contacts"
- [ ] Save button shows loading spinner
---
#### 📱 STAFF-010: Experience & Skills (Onboarding)
**Applications:** Staff
**Entry Points:**
- Profile → Experience
- Onboarding wizard
**Happy Path Test Cases:**
- [ ] Industries multi-select displays options
- [ ] Skills multi-select displays options
- [ ] Selected items show checkmarks
- [ ] Deselection removes items
- [ ] Save updates profile
**Validation & Error States:**
- [ ] At least one industry required (if applicable)
- [ ] At least one skill required (if applicable)
**Loading & Empty States:**
- [ ] Loading spinner displays while fetching data
- [ ] Save button shows loading spinner
---
#### 📱 STAFF-012: Bank Account (Finances)
**Applications:** Staff
**Entry Points:**
- Profile → Bank Account
**Happy Path Test Cases:**
- [ ] Account list displays all accounts
- [ ] Add account button opens form
- [ ] Form validates routing and account numbers
- [ ] Account type dropdown shows options (Checking/Savings)
- [ ] First account auto-sets as primary
- [ ] Save adds account to list
- [ ] Primary account indicator displays
**Validation & Error States:**
- [ ] Empty routing number shows validation error
- [ ] Invalid routing number format shows error
- [ ] Empty account number shows validation error
- [ ] Invalid account number format shows error
- [ ] Duplicate account shows warning
**Loading & Empty States:**
- [ ] Loading spinner displays while fetching accounts
- [ ] Empty state shows "No bank accounts"
- [ ] Save button shows loading spinner
**State Persistence:**
- [ ] Accounts persist after save
- [ ] Account list refreshes after addition
**Backend Dependency Validation:**
- [ ] `getAccountsByOwnerId` fetches staff accounts
- [ ] `createAccount` creates new account
- [ ] First account auto-flagged as primary
---
#### 📱 STAFF-013: Time Card History (Finances)
**Applications:** Staff
**Entry Points:**
- Profile → Time Card
**Happy Path Test Cases:**
- [ ] Time card list displays all records
- [ ] Each card shows shift details (date, time, location)
- [ ] Each card shows clock in/out times
- [ ] Each card shows total hours worked
- [ ] Scrolling loads more records (pagination)
**Validation & Error States:**
- [ ] Missing attendance data shows "Not recorded"
**Loading & Empty States:**
- [ ] Empty state shows "No time card history"
---
#### 📱 STAFF-014: Tax Forms (Compliance)
**Applications:** Staff
**Entry Points:**
- Profile → Tax Forms
**Happy Path Test Cases:**
- [ ] Forms list displays required forms (I-9, W-4)
- [ ] Form status shows completed/incomplete
- [ ] I-9 form opens editor
- [ ] I-9 form validates all fields
- [ ] W-4 form opens editor
- [ ] W-4 form validates all fields
- [ ] Form submission updates status to completed
- [ ] Completed forms show edit option
**Validation & Error States:**
- [ ] Empty required fields show validation errors
- [ ] Invalid SSN format shows error
- [ ] Invalid date format shows error
- [ ] Signature required validation
**Loading & Empty States:**
- [ ] Loading spinner displays while fetching forms
- [ ] Form editor loads with skeleton placeholders
- [ ] Save button shows loading spinner
---
#### 📱 STAFF-017: Staff Main Navigation
**Applications:** Staff
**Entry Points:**
- Main app shell after authentication
**Happy Path Test Cases:**
- [ ] Bottom navigation displays 5 tabs (Shifts, Payments, Home, Clock In, Profile)
- [ ] Tab selection updates active indicator
- [ ] Tab selection navigates to correct feature
- [ ] Deep links navigate to correct tab and nested route
- [ ] Back button navigates correctly within nested routes
- [ ] Tab state persists after device rotation
- [ ] Nested routes (onboarding, emergency-contact, etc.) accessible
**Validation & Error States:**
- [ ] Invalid route shows 404 or redirects to home
- [ ] Navigation errors log appropriately
**Loading & Empty States:**
- [ ] Navigation bar displays immediately
- [ ] Initial tab loads first
**State Persistence:**
- [ ] Active tab persists after app background → foreground
- [ ] Tab state resets to home on app restart
**Backend Dependency Validation:**
- [ ] No direct backend calls (navigation only)
---
## 2⃣ CROSS-APPLICATION TEST SCENARIOS
### Scenario 1: Order Creation → Staff Application Flow
**Preconditions:**
- Client user authenticated
- Staff user authenticated
- At least one hub configured
**Steps:**
1. **CLIENT APP:**
- [ ] Create one-time order with specific hub, role, date, and time
- [ ] Verify order appears in View Orders list
- [ ] Verify shift shows as unfilled (0/X positions)
2. **STAFF APP:**
- [ ] Open Shifts tab → Available tab
- [ ] Verify new shift appears in available list
- [ ] Verify shift details match order (hub, role, time, pay)
- [ ] Apply for shift position
3. **CLIENT APP:**
- [ ] Refresh View Orders
- [ ] Verify shift shows pending application (0/X filled, pending)
4. **STAFF APP:**
- [ ] Verify application appears in Pending tab
- [ ] Verify shift removed from Available tab
**Expected Results:**
- ✅ Order created in Client appears in Staff Available Shifts
- ✅ Application in Staff shows pending in both apps
- ✅ Shift counts update correctly in real-time
---
### Scenario 2: Shift Acceptance → Coverage Tracking
**Preconditions:**
- Scenario 1 completed (pending application exists)
**Steps:**
1. **STAFF APP:**
- [ ] Go to Shifts → Pending tab
- [ ] Accept pending shift assignment
2. **CLIENT APP:**
- [ ] Refresh View Orders
- [ ] Verify shift shows as filled (1/X positions)
- [ ] Verify staff name and photo appear in accepted applications
- [ ] Navigate to Coverage tab
- [ ] Verify shift appears with assigned staff
3. **STAFF APP:**
- [ ] Verify shift moved from Pending to My Shifts tab
- [ ] Verify shift appears on Home dashboard
**Expected Results:**
- ✅ Accepted shift reflects in Client orders immediately
- ✅ Staff appears in Coverage monitoring
- ✅ Shift moves to My Shifts in Staff app
---
### Scenario 3: Clock In → Real-Time Coverage Update
**Preconditions:**
- Scenario 2 completed (staff has accepted shift)
- Current date/time is during shift window
**Steps:**
1. **STAFF APP:**
- [ ] Navigate to Clock In tab
- [ ] Verify today's shift displays
- [ ] Click Clock In button
- [ ] Verify clock in time recorded
2. **CLIENT APP:**
- [ ] Navigate to Coverage tab
- [ ] Verify staff status changed to "Checked In"
- [ ] Verify check-in time displays
- [ ] Verify coverage stats updated (checked-in count incremented)
3. **STAFF APP:**
- [ ] Wait until shift end time
- [ ] Click Clock Out button
- [ ] Verify clock out time recorded
4. **CLIENT APP:**
- [ ] Refresh Coverage tab
- [ ] Verify staff status changed to "Completed"
5. **STAFF APP:**
- [ ] Navigate to Time Card
- [ ] Verify attendance record appears with correct times and hours
**Expected Results:**
- ✅ Clock in updates Coverage status in Client
- ✅ Clock out completes attendance record
- ✅ Time card displays correct hours in Staff app
- ✅ Coverage monitoring reflects real-time status
---
### Scenario 4: Hub Creation → Order Placement
**Preconditions:**
- Client user authenticated
- No existing hubs
**Steps:**
1. **CLIENT APP:**
- [ ] Navigate to Settings → Hubs
- [ ] Verify empty state "No hubs configured"
- [ ] Click Add Hub button
- [ ] Enter hub name and use Google Places autocomplete
- [ ] Select address from suggestions
- [ ] Verify address fields auto-filled
- [ ] Save hub
2. **CLIENT APP:**
- [ ] Navigate to Create Order
- [ ] Verify new hub appears in hub selection list
- [ ] Select new hub and complete order creation
3. **STAFF APP:**
- [ ] Navigate to Shifts → Available
- [ ] Verify shift shows correct hub name and address
**Expected Results:**
- ✅ Hub created in Settings appears in order creation
- ✅ Hub address propagates to shift details in Staff app
---
### Scenario 5: Shift Cancellation → Staff Notification
**Preconditions:**
- Staff has accepted shift assignment
**Steps:**
1. **CLIENT APP:**
- [ ] Navigate to View Orders
- [ ] Select order with assigned staff
- [ ] Cancel shift (if feature exists) or delete order
2. **STAFF APP:**
- [ ] Refresh Shifts tab
- [ ] Verify shift moved to Cancelled tab
- [ ] Verify shift removed from My Shifts
- [ ] Verify cancellation reason displays
3. **STAFF APP:**
- [ ] Verify shift removed from Home dashboard
**Expected Results:**
- ✅ Cancelled shift moves to Cancelled tab
- ✅ Shift removed from active assignments
- ⚠️ **Requires clarification:** Cancellation feature may not be fully implemented
---
### Scenario 6: Authentication State Sharing
**Preconditions:**
- Neither app authenticated
**Steps:**
1. **CLIENT APP:**
- [ ] Sign in with email/password
- [ ] Verify Firebase Auth token generated
2. **STAFF APP:**
- [ ] Launch app
- [ ] Verify Staff app requires separate authentication
- [ ] Verify Client session does not carry over
3. **CLIENT APP:**
- [ ] Sign out
4. **STAFF APP:**
- [ ] Verify Staff app session persists (independent)
**Expected Results:**
- ✅ Client and Staff apps maintain independent auth sessions
- ✅ Signing out of one app does not affect the other
---
### Scenario 7: Data Created in Client → Visible in Staff
**Preconditions:**
- Client creates multiple orders
**Steps:**
1. **CLIENT APP:**
- [ ] Create 5 orders on different dates
- [ ] Create 3 orders on same date with different hubs
2. **STAFF APP:**
- [ ] Navigate to Shifts → Available
- [ ] Verify all 8 shifts appear
- [ ] Verify date grouping correct
- [ ] Verify hub addresses correct
- [ ] Apply for 2 shifts
3. **CLIENT APP:**
- [ ] Navigate to View Orders
- [ ] Verify 2 shifts show pending applications
- [ ] Navigate to Coverage
- [ ] Verify 0 checked-in (pending acceptance)
**Expected Results:**
- ✅ All orders visible in both apps
- ✅ Application states sync correctly
- ✅ Data consistency maintained across apps
---
### Scenario 8: Role-Based Access Differences
**Preconditions:**
- Client user authenticated
- Staff user authenticated
**Steps:**
1. **CLIENT APP:**
- [ ] Navigate to Billing
- [ ] Verify billing data displays (Client-only feature)
- [ ] Navigate to Create Order
- [ ] Verify order creation available (Client-only feature)
2. **STAFF APP:**
- [ ] Verify no Billing tab exists
- [ ] Verify no Create Order feature
- [ ] Navigate to Availability
- [ ] Verify availability editing available (Staff-only feature)
3. **CLIENT APP:**
- [ ] Verify no Availability feature exists
- [ ] Verify no Clock In feature exists
**Expected Results:**
- ✅ Client app has business management features (orders, billing, hubs)
- ✅ Staff app has worker features (availability, clock in, payments)
- ✅ No feature overlap or unauthorized access
---