# PRD: Phase 3 Stabilization & State Management Migration # Overview **Goal:** Stabilize Phase 3 (Chat Engine) through end-to-end testing and migrate Flutter state management from BLoC to Riverpod + flutter_hooks **Success looks like:** All Phase 3 features are verified working end-to-end across client_app, mitra_app, and control_center. Both Flutter apps use Riverpod as their sole state management solution. ## Background - Phase 3 (Chat Engine) is fully scaffolded but has not been end-to-end tested - Current Flutter apps use BLoC pattern; Riverpod is preferred for maintainability and reduced boilerplate - Migration should happen before Phase 4 to avoid compounding tech debt ## FCM fallback for Chat Engine ### Mitra Pairing - Add configuration on Control center to configure Mitra's app require to ping or not. - When Control Center allow non ping, application or backend will not force mitra to ping and allow them to keep online even when the app is closed or in backround - Modify Mitra Pairing confirmation to send notification through FCM when websocket to Mitra is closed ### Bi-Directional Chat (WebSocket + FCM) #### Mitra App - When there is new unread message, mitra app must shows badge on active session - When there is new unread message, mitra app must shows badge on the chat active session inside active session page - Unread badge on each active session will be cleared when the message has been read - Unread badge on active session button on main page will be cleared when the message has been read #### Customer App - When there is new unread message, Customer app must shows badge on active session - Unread badge will be cleared when unread message has been cleared ### Chat Closure & Extension - When chat closure called, backend will send closure signal to both Mitra and Customer - Backend will use FCM if the websocket connection is down ### Control Center - Control center shows configuration for ping from mitra ## Riverpod Migration ### Scope - Migrate all BLoC classes in `client_app` and `mitra_app` to Riverpod annotation-based providers - Replace `flutter_bloc` with `flutter_riverpod`, `riverpod_annotation`, `flutter_hooks`, and `hooks_riverpod` - Add `riverpod_generator` + `build_runner` as dev dependencies for code generation - No backend or control_center changes ### Migration Strategy - [ ] Add Riverpod dependencies (`flutter_riverpod`, `hooks_riverpod`, `riverpod_annotation`) and dev dependencies (`riverpod_generator`, `build_runner`, `custom_lint`, `riverpod_lint`) - [ ] Wrap app root with `ProviderScope` - [ ] Migrate one Bloc at a time, starting with the simplest (e.g. AuthBloc) - [ ] For each migrated Bloc: 1. Replace `Bloc`/`Cubit` class with `@riverpod` annotated `Notifier` or `AsyncNotifier` (extending `_$ClassName`) 2. Replace `BlocEvent` + `emit()` pattern with notifier methods that update `state` directly 3. Run `dart run build_runner build` to generate `.g.dart` files 4. Replace `BlocProvider` with generated provider (e.g. `authProvider`) 5. Replace `BlocBuilder` widgets with `ConsumerWidget` + `ref.watch()` 6. Replace `BlocListener` with `ref.listen()` inside widget or provider 7. Use `HookConsumerWidget` where flutter_hooks are needed (e.g. `useTextEditingController`, `useEffect`) - [ ] Run E2E verification after each migration to catch regressions - [ ] Remove `flutter_bloc` dependency only after all Blocs are migrated ### Affected Blocs - [ ] `client_app` — AuthBloc, PairingBloc, ChatBloc, ChatOpeningBloc, SessionClosureBloc - [ ] `mitra_app` — AuthBloc, OnlineStatusBloc, MitraChatBloc, ExtensionBloc # Non-Functional Requirement - [ ] WebSocket reconnects gracefully after network interruption (within 5s on stable network) - [ ] Use FCM to send command or message when websocket is down - [ ] No message loss during brief disconnects — undelivered messages sync on reconnect - [ ] Chat screen maintains scroll position and input draft on app lifecycle events (background/foreground) - [ ] Riverpod migration introduces zero new UI bugs — feature parity with BLoC implementation # Tech Stack - State management: Riverpod + flutter_hooks (replacing flutter_bloc) - No backend changes expected — migration is Flutter-only