# Migration Plan

## Phase 1 - Specification And Contracts ✅

- Document current routes and workflows.
- Document API calls and response shapes.
- Identify backend gaps that block a clean Vue client.
- Confirm JavaScript-only implementation.
- Decide exact `gnexus-ui-kit` installation method.

Deliverable:

- Complete docs in `webclient-vue/docs/`.

## Phase 2 - Project Scaffold ✅

- Create Vue app under `webclient-vue/`.
- Configure build tooling.
- Add `gnexus-ui-kit`.
- Add router.
- Add API client wrapper.
- Add app shell, layout, navigation, toast, modal, and error state primitives.

Deliverable:

- New client opens locally and can call `GET /api/v1/areas/list`.

### Phase 2.1 - Minimal Vertical Slice ✅

Build the smallest complete app slice:

- App shell.
- Hash router.
- API client.
- Areas API module.
- Favorites localStorage store with key `sh_fav_areas`.
- `/areas/favorites` page.
- Loading, empty, and error state components.

Acceptance criteria:

- Running the dev server opens the Vue client.
- `/` redirects to `/areas/favorites`.
- `/areas/favorites` calls the backend areas list endpoint.
- Existing favorite ids from localStorage are respected.
- Empty favorites state is rendered correctly.
- No old `webclient/src/js` code is imported.
- UI-kit access is isolated behind local adapter components, even if adapters are
  initially minimal.

## Phase 3 - Read-Only Screens ✅

Implement without mutations first:

- Areas favorites.
- Areas tree.
- Devices list.
- Devices scanning list.
- Scripts actions list.
- Scripts regular list.
- Scripts scopes list.

Deliverable:

- New client can display the same operational data as the current client.

## Phase 4 - Mutations And Modals ✅

Implement user actions:

- Run action script.
- Enable/disable regular scripts.
- Enable/disable scopes.
- Device details.
- Device reboot.
- Device setup.
- Area details.
- Area create/edit.
- Area devices modal.
- Area actions modal.

Deliverable:

- New client covers daily operational workflows.

## Phase 5 - Hardening ✅

- Add concurrency limits to device live-state loading.
- Add request cancellation on route leave/modal close.
- Add normalized error handling.
- Add stale data and retry states.
- Add smoke checklist.

Deliverable:

- New client is safe to use as primary UI.

## Phase 5.5 - Test Infrastructure & Unit Tests

Install and configure testing stack for Vite + Vue:

- **Vitest** — test runner (native Vite integration, replaces Jest).
- **@vue/test-utils** — mount and interact with Vue components.
- **jsdom** — DOM environment for component tests.
- **@vitest/coverage-v8** — code coverage reports.

Unit test targets (no DOM, fast, isolated):

| Target | What to test |
|--------|-------------|
| `api/client.js` | `apiRequest` success path, error path, network failure, abort |
| `api/http.js` | `requestHttp` URL building, proxy wrapping, timeout abort, JSON parse |
| `api/mappers.js` | `unifyDeviceFields` normalizes snake_case → camelCase |
| `stores/favorites.js` | localStorage read/write, toggle, add, remove |
| `stores/areas.js` | `buildAreaTree` handles roots, children, self-reference, cycles |
| `stores/devices.js` | `makeDeviceStatePatch`, `normalizeStatusSuccess`, `normalizeStatusError` |

Deliverable:

- `npm test` runs unit tests.
- Coverage report generated in `coverage/`.

## Phase 5.6 - Component Tests

Test Vue components in isolation with mocked dependencies:

| Component | What to test |
|-----------|-------------|
| `AppEmptyState` | renders title and message, slots work |
| `AppErrorState` | renders title/message, retry button fires event |
| `AppLoadingState` | renders label |
| `AppShell` | renders nav items, brand, content slot |
| `AreaTreeNode` | toggles expand, emits rename/remove/unassign, cycle detection |
| `DeviceConnectionBadge` | maps status → correct variant |
| `DeviceStateCell` | maps state → correct badge/loader |
| `AreaFavoritesPage` | loads areas, filters favorites, handles empty |
| `DevicesListPage` | loads devices + states, renders table rows, stale badge |
| `ScriptsActionsPage` | loads actions, run button triggers API, shows alert |

Mock strategy:
- Pinia stores via `createTestingPinia()`.
- API calls via `vi.mock()` or MSW (mock service worker).

Deliverable:

- Component tests cover all feature components and pages.

## Phase 5.7 - Integration Tests ✅

End-to-end user flows with mocked backend:

| Flow | Steps |
|------|-------|
| Area lifecycle | Load areas → Create area → Rename → Remove |
| Device discovery | Scan network → Select device → Setup → Appears in list |
| Script execution | Load actions → Run script → See result alert |
| Navigation | Visit each route → Assert correct page renders |

Use **MSW** (Mock Service Worker) to intercept `fetch` and return fixture data.

Deliverable:

- Integration tests verify complete user workflows.

## Phase 6 - Switch-Over

- Keep old `webclient/` available as fallback.
- Serve new client on the chosen route/domain.
- Monitor backend logs and user-reported issues.
- Remove or archive old client only after a stable period.

## Open Decisions

- Vue state library: Pinia or lightweight composables only.
- Router mode: hash mode for compatibility or history mode with server config.
- How to consume `gnexus-ui-kit` as an updatable dependency: package/git dependency preferred, submodule only if necessary.
- Whether to keep `proxy.php` or use direct backend API from the new dev server.

## Current Recommendations

- Use JavaScript.
- Use Pinia.
- Use hash router for the first production-capable version.
- Keep `proxy.php` compatibility in the API client, but allow direct backend URL
  through environment variables.
- Integrate `gnexus-ui-kit` through local adapter components, not direct imports
  across feature code.
