refactor: everything to nuxt.js

This commit is contained in:
2026-03-19 14:30:36 -04:00
parent 6e1f58cd8e
commit bb3042014e
159 changed files with 6786 additions and 11198 deletions

View File

@@ -1,101 +0,0 @@
# Session Handoff: Build Fixes & Dev Environment
**Date:** 2026-03-15
**Session Duration:** ~2 hours
**Session Focus:** Resolve all TypeScript/ESLint build errors from dependency updates; fix dev server startup
**Context Usage at Handoff:** Medium
## What Was Accomplished
1. Fixed 30 TypeScript errors (14 files) → build now passes with 0 errors
2. Fixed 12 ESLint problems (6 errors, 6 warnings) → 0 remaining
3. Fixed `quasar dev` startup error (`FlatESLint is not a constructor`) → downgraded ESLint v10→v9
4. Fixed missing Appwrite env vars in `.env.local` → app connects to backend on dev
## Exact State of Work in Progress
- **Build**: CLEAN — `yarn quasar build` exits 0, no TS or ESLint errors
- **Dev server**: FUNCTIONAL — `quasar dev` starts without errors; ESLint inline checking via `vite-plugin-checker` is restored
- **Runtime**: UNTESTED this session — app has not been manually tested against the dev Appwrite backend
## Decisions Made This Session
- **`as unknown as Type` for all Appwrite store casts** — CONFIRMED: Appwrite v23 made `DefaultDocument` strict; it no longer overlaps domain types, so the double-cast is required. Applied to: `boat.ts`, `interval.ts`, `intervalTemplate.ts`, `reservation.ts`, `task.ts`
- **ESLint downgraded v10.0.3 → v9.39.4** — CONFIRMED: `vite-plugin-checker` v0.12.0 calls `FlatESLint` which was merged back into `ESLint` in v10; v9 preserves the API. Also downgraded `@eslint/js` (v10→v9) and `eslint-plugin-vue` (v10→v9)
- **`getWeekdaySkips` removed** — CONFIRMED: removed from `@quasar/quasar-ui-qcalendar` API; `createDayList` now takes `weekdays` array directly as 4th param (previously took `weekdaySkips` computed value)
- **`subtasks` removed from TaskCardComponent template** — ASSUMED SAFE: `Task` type has no `subtasks` field; template refs were dead code. See open question.
- **`no-debugger: 'off'`** — CONFIRMED: hardcoded because `process` is not available in ESLint globals when linting `.js` files (config file context)
- **`.env.local` variable names corrected** — CONFIRMED: file had `VITE_APPWRITE_ENDPOINT` / `VITE_APPWRITE_PROJECT`; `appwrite.ts` reads `VITE_APPWRITE_API_ENDPOINT` / `VITE_APPWRITE_API_PROJECT`
## Key Numbers Generated or Discovered This Session
- TypeScript errors at session start: 30 (across 14 files)
- ESLint problems at session start: 12 (6 errors, 6 warnings)
- TypeScript errors at session end: 0
- ESLint problems at session end: 0
- ESLint: v10.0.3 → v9.39.4
- `@eslint/js`: v10 → v9
- `eslint-plugin-vue`: v10 → v9
- `register-service-worker`: newly added (was missing from package.json)
## Conditional Logic Established
- IF Appwrite SDK returns `DefaultDocument` THEN cast via `as unknown as DomainType` BECAUSE v23 `DefaultDocument` is strict and no longer assignable to domain types that extend `Partial<Models.Document>`
- IF `vite-plugin-checker` is v0.12.x THEN ESLint must be v9.x BECAUSE v0.12.x uses `FlatESLint` constructor removed in ESLint v10
- IF `createDayList` is called from qcalendar THEN pass `weekdays` array as 4th arg directly BECAUSE `getWeekdaySkips` was removed from the qcalendar public API
- IF `.env.local` is updated THEN variable names must match `import.meta.env.VITE_APPWRITE_API_ENDPOINT` / `VITE_APPWRITE_API_PROJECT` as read in `src/boot/appwrite.ts`
## Files Created or Modified
| File Path | Action | Description |
|-----------|--------|-------------|
| `src/stores/boat.ts` | Modified | `as unknown as Boat[]` |
| `src/stores/interval.ts` | Modified | `as unknown as Interval` (3 places) |
| `src/stores/intervalTemplate.ts` | Modified | Map callback cast + `as unknown as IntervalTemplate` (3 places); `timeTuple` cast |
| `src/stores/reservation.ts` | Modified | `as unknown as Reservation` (5 places) |
| `src/stores/task.ts` | Modified | `as unknown as Task[]`, `TaskTag[]`, `SkillTag[]`, `Task` (5 places) |
| `src/stores/sampledata/schedule.ts` | Modified | `id``$id`, `blocks``timeTuples`, removed `reservationDate` |
| `src/components/boat/BoatPreviewComponent.vue` | Modified | `boat.id``boat.$id` |
| `src/components/scheduling/boat/BoatScheduleTableComponent.vue` | Modified | `block.id``block.$id`; `NodeJS.Timeout``ReturnType<typeof setInterval>`; ternary→if/else |
| `src/components/scheduling/boat/CalendarHeaderComponent.vue` | Modified | Removed `getWeekdaySkips` import+computed; `createDayList` now passes `weekdays` directly |
| `src/components/task/TaskCardComponent.vue` | Modified | Removed `defineProps` explicit import; removed `subtasks` template refs |
| `src/components/task/TaskListComponent.vue` | Modified | `task.id``task.$id` |
| `src/components/task/TaskTableComponent.vue` | Modified | Removed `defineProps` from explicit import |
| `src/components/ResourceScheduleViewerComponent.vue` | Modified | Removed `|| undefined`; `catch { }`; removed stale eslint-disable comments |
| `src/pages/LoginPage.vue` | Modified | `catch { }` |
| `src/pages/schedule/ManageCalendar.vue` | Modified | `block.id``block.$id` |
| `src/boot/appwrite.ts` | Modified | Removed stale `console.log(API_ENDPOINT)` |
| `eslint.config.js` | Modified | `no-debugger` hardcoded to `'off'` |
| `quasar.config.ts` | Modified | ESLint checker restored (had been temporarily removed) |
| `package.json` / `yarn.lock` | Modified | ESLint v10→v9; `@eslint/js` v10→v9; `eslint-plugin-vue` v10→v9; added `register-service-worker` |
| `.env.local` | Modified | Variable names corrected: `VITE_APPWRITE_ENDPOINT``VITE_APPWRITE_API_ENDPOINT`, `VITE_APPWRITE_PROJECT``VITE_APPWRITE_API_PROJECT`; endpoint URL updated to include `/v1` |
| `docs/summaries/handoff-2026-03-15-build-fixes.md` | Created | This file |
| `docs/archive/handoffs/handoff-2026-03-15-dependency-updates.md` | Archived | Superseded by this handoff |
## What the NEXT Session Should Do
1. **First**: Run `quasar dev` and manually test the login flow against the dev Appwrite backend to validate v23 API calls work at runtime
2. **Validate**: Boat listing, reservation creation/cancellation, interval loading — confirm no runtime errors from the v23 positional-param deprecations
3. **Commit**: Stage all modified files and commit as `"fix: Resolve build errors from dependency updates"` (single clean commit covering all TS/ESLint/qcalendar/env fixes)
4. **Optional**: Migrate Appwrite calls from deprecated positional-param style to object-param style (affects all stores — low priority, they still work)
5. **Optional**: Add `subtasks?: Task[]` to `Task` interface in `src/stores/task.ts` if that feature is planned
## Open Questions Requiring User Input
- [ ] `task.subtasks` removed from `TaskCardComponent` template — should `subtasks?: Task[]` be added to the `Task` interface for future use, or is subtask support not planned?
- [ ] Appwrite v23 deprecated positional-param overloads (hints in every store call). Migrate now or leave for later?
## Assumptions That Need Validation
- ASSUMED: Appwrite v23 positional-param API calls behave identically at runtime to v14 — validate by doing a full login + reservation flow against the dev backend
- ASSUMED: `subtasks` in `TaskCardComponent` was dead/future code — no user confirmed this
## What NOT to Re-Read
- `docs/archive/handoffs/handoff-2026-03-15-dependency-updates.md` — archived; superseded by this file
- `docs/archive/handoffs/handoff-2026-03-15-auth-magic-link.md` — archived; auth work complete
## Files to Load Next Session
- `src/stores/task.ts` — if adding `subtasks` to Task interface
- `src/boot/appwrite.ts` — if migrating to Appwrite v23 object-param style
- Any store file (`boat.ts`, `interval.ts`, `reservation.ts`, etc.) — if migrating Appwrite calls

View File

@@ -0,0 +1,106 @@
# Session Handoff: Nuxt Migration — Phases 1 & 2 Complete
**Date:** 2026-03-19
**Session Duration:** ~2 hours
**Session Focus:** Framework selection, migration planning, and execution of Phases 1 & 2 of Quasar → Nuxt 3 migration
**Context Usage at Handoff:** ~60%
## What Was Accomplished
1. Framework analysis (React Native vs Flutter vs Next/Nuxt) → decision: Nuxt 3 + Capacitor (deferred) + FullCalendar
2. Migration plan created → `docs/summaries/handoff-2026-03-18-nuxt-migration-plan.md` (now the active plan reference)
3. Phase 1 — Foundation complete → `/home/ptoal/Dev/mobile-projects/bab-app-nuxt/`
4. Phase 2 — Appwrite plugin + types complete → `app/utils/`, `app/plugins/`
5. Integration tests written and passing (11/11) → `tests/appwrite-connection.test.ts`
6. Task feature parked → removed from AppwriteIds and tests
## Exact State of Work in Progress
- **Migration plan**: 10-phase plan in `docs/summaries/handoff-2026-03-18-nuxt-migration-plan.md`. Phases 12 marked complete. Phase 3 (Auth) is next.
- **New project**: `/home/ptoal/Dev/mobile-projects/bab-app-nuxt/` — scaffolded and running. Dev server confirmed clean on `localhost:3000`.
- **Old project**: `/home/ptoal/Dev/mobile-projects/bab-app/` — untouched, still operational. Do not delete until Phase 6 is complete.
## Decisions Made This Session
- **Nuxt 3 + nuxt-quasar-ui** — keeps all Quasar (`q-*`) components working; avoids big-bang UI rewrite. CONFIRMED.
- **FullCalendar non-commercial license** — key `CC-Attribution-NonCommercial-NoDerivatives` confirmed valid. OYS is Ontario not-for-profit #000082982. CONFIRMED.
- **PWA only initially** — Capacitor deferred until native camera/GPS features are actively needed. CONFIRMED.
- **Static output** — `nuxt generate``.output/public/` served via nginx. Consistent with existing Ansible deploy. CONFIRMED.
- **TestFlight/App Store deferred** — revisit when PWA hits UX or capability limits. CONFIRMED.
- **Auth: magic link + email OTP only** — password auth and Google (`vue3-google-login`) removed. CONFIRMED.
- **Task feature parked** — collections `task`, `taskTags`, `skillTags` absent from `bab_prod`. Not migrated until Appwrite collections are created. CONFIRMED.
## Key Numbers Generated or Discovered This Session
- **11/11 tests passing** — backend connection verified
- **4 collections confirmed reachable** — `boat`, `reservation`, `interval`, `intervalTemplate` (return 401 unauthenticated = exist and require auth)
- **3 collections absent** — `task`, `taskTags`, `skillTags` return 404 from `bab_prod`
- **Appwrite project ID**: `65ede55a213134f2b688`
- **Appwrite endpoint**: `https://appwrite.toal.ca/v1`
- **Database ID**: `bab_prod`
- **~12 days** total estimated migration effort (unchanged)
- **Nuxt version**: 4.4.2 (installed as `nuxt@^4.4.2`)
- **nuxt-quasar-ui version**: 3.0.1
- **fontIcons config** must be an array `['material-icons']`, not a string — bug if passed as string (iterates characters)
## Conditional Logic Established
- IF task feature is needed, THEN create collections `task`, `taskTags`, `skillTags` in Appwrite dashboard first, THEN migrate `stores/task.ts`, `components/task/*`, `pages/task/*`
- IF Capacitor is added later, THEN change `nuxt.config.ts` `webDir` to `.output/public` and run `npx cap add ios && npx cap add android`
- IF App Store publishing is pursued, THEN use TestFlight (iOS) + Play Store internal testing track, NOT full public store listing (3050 user club app)
## Files Created or Modified
| File Path | Action | Description |
|-----------|--------|-------------|
| `/home/ptoal/Dev/mobile-projects/bab-app-nuxt/` | Created | New Nuxt 4.4.2 project root |
| `bab-app-nuxt/nuxt.config.ts` | Created | ssr:false, nuxt-quasar-ui, @pinia/nuxt, @vite-pwa/nuxt, PWA manifest, runtimeConfig |
| `bab-app-nuxt/.env.local` | Created | `NUXT_PUBLIC_APPWRITE_ENDPOINT`, `NUXT_PUBLIC_APPWRITE_PROJECT_ID` |
| `bab-app-nuxt/public/icons/` | Created | Copied from old project — all PWA icon sizes |
| `bab-app-nuxt/app/utils/appwrite.ts` | Created | Appwrite client + services + AppwriteIds (task collections excluded) |
| `bab-app-nuxt/app/utils/boat.types.ts` | Created | `Boat` interface (extracted so schedule.ts can depend on it without the store) |
| `bab-app-nuxt/app/utils/schedule.types.ts` | Created | `Interval`, `Reservation`, `IntervalTemplate`, `TimeTuple` |
| `bab-app-nuxt/app/utils/misc.ts` | Created | `getNewId()`, `LoadingTypes` |
| `bab-app-nuxt/app/utils/schedule.ts` | Created | Schedule utilities; `date` from quasar kept; imports updated to `~/utils/*` |
| `bab-app-nuxt/app/plugins/appwrite.client.ts` | Created | Stub plugin; auth store init wired in Phase 3 |
| `bab-app-nuxt/vitest.config.ts` | Created | Vitest with `loadEnv` to pick up `.env.local` |
| `bab-app-nuxt/tests/appwrite-connection.test.ts` | Created | 11 integration tests verifying backend connectivity |
| `bab-app-nuxt/package.json` | Modified | Added `test` and `test:watch` scripts |
| `docs/summaries/handoff-2026-03-18-nuxt-migration-plan.md` | Modified | Added confirmed decisions, updated Phase 1 complete, task parked in Phase 7 |
## What the NEXT Session Should Do
1. **First**: Read `docs/summaries/handoff-2026-03-18-nuxt-migration-plan.md` for the full 10-phase plan and current state
2. **Then**: Execute **Phase 3 — Auth**
- Migrate `src/stores/auth.ts``bab-app-nuxt/app/stores/auth.ts`
- Strip password auth methods; keep magic link + email OTP only
- Remove `vue3-google-login` from `bab-app-nuxt/package.json`
- Create `app/middleware/auth.global.ts` (replaces old router navigation guard in `src/router/index.ts`)
- Create `app/pages/auth/callback.vue` — handles magic link redirect `?userId=&secret=` params
- Wire `authStore.init()` call into `app/plugins/appwrite.client.ts`
3. **Then**: Execute **Phase 4 — Remaining Stores** (all are near-verbatim Pinia ports)
- `stores/boat.ts` — import `Boat` from `~/utils/boat.types` instead of defining inline
- `stores/reservation.ts`, `interval.ts`, `intervalTemplate.ts`, `reference.ts`, `realtime.ts`, `memberProfile.ts`
- Skip `stores/task.ts` (parked)
## Open Questions Requiring User Input
- [ ] **Appwrite `task`/`taskTags`/`skillTags` collections** — will these ever be created in `bab_prod`? Determines whether task feature gets migrated at all, or is permanently dropped.
## Assumptions That Need Validation
- ASSUMED: `nuxt generate` (static) is sufficient — no SSR/server-side rendering needed. Validate: all Appwrite calls are client-side only (no server routes needed).
- ASSUMED: `LeftDrawer.vue` exists in `src/components/` (referenced in codebase exploration but not confirmed by direct file read). Verify before Phase 6.
## What NOT to Re-Read
- `src/boot/appwrite.ts` — fully migrated; summarized above
- `src/utils/misc.ts`, `src/utils/schedule.ts`, `src/stores/schedule.types.ts` — fully migrated; summarized above
- `templates/claude-templates.md` — not needed next session
## Files to Load Next Session
- `docs/summaries/handoff-2026-03-18-nuxt-migration-plan.md` — active migration plan with all phases
- `bab-app-nuxt/app/utils/appwrite.ts` — current AppwriteIds shape (needed for store migration)
- `bab-app-nuxt/app/plugins/appwrite.client.ts` — needs auth init wired in Phase 3
- `src/stores/auth.ts` — source for Phase 3 migration (read once, then discard)
- `src/router/index.ts` — source for middleware logic (read once, then discard)

View File

@@ -0,0 +1,112 @@
# Session Handoff: Nuxt Migration — Phases 35 Complete
**Date:** 2026-03-19
**Session Focus:** Auth, all stores, all pages, all layouts, all components
**Context at Handoff:** High — recommend fresh session for Phase 6+
## What Was Accomplished
1. Phase 3 — Auth (stores/auth.ts, middleware, callback page, plugin)
2. Phase 4 — All 7 non-task stores
3. Phase 5 — All pages, layouts, and non-task components
## Exact State of bab-app-nuxt
### Layouts
- `app/layouts/default.vue` — MainLayout port; reads `route.meta.title` for header title
- `app/layouts/admin.vue` — AdminLayout port; tabs updated to `/admin/user` and `/admin/boat`
- `app/app.vue` — Updated to `<NuxtLayout><NuxtPage /></NuxtLayout>`
### Pages (all created)
| Nuxt Path | Old Path | Notes |
|-----------|----------|-------|
| `pages/index.vue` | `IndexPage.vue` | Uses `useNavLinks()` composable |
| `pages/login.vue` | `LoginPage.vue` | `layout: false`; magic link `onMounted` removed (→ `auth/callback.vue`) |
| `pages/auth/callback.vue` | (new) | Handles `?userId=&secret=` from magic link |
| `pages/boat.vue` | `BoatPage.vue` | |
| `pages/profile.vue` | `ProfilePage.vue` | |
| `pages/certification.vue` | `CertificationPage.vue` | |
| `pages/checklist.vue` | `ChecklistPage.vue` | |
| `pages/schedule.vue` | `SchedulePageView.vue` | Parent wrapper; `<NuxtPage />` |
| `pages/schedule/index.vue` | `ScheduleIndexPage.vue` | |
| `pages/schedule/book.vue` | `BoatReservationPage.vue` | |
| `pages/schedule/view.vue` | `BoatScheduleView.vue` | |
| `pages/schedule/list.vue` | `ListReservationsPage.vue` | |
| `pages/schedule/edit/[id].vue` | `ModifyBoatReservation.vue` | |
| `pages/schedule/manage.vue` | `ManageCalendar.vue` | `requiredRoles: ['Schedule Admins']` |
| `pages/reference.vue` | `ReferencePage.vue` | Parent wrapper |
| `pages/reference/index.vue` | `ReferenceIndexPage.vue` | |
| `pages/reference/reference/[id]/view.vue` | `ReferenceItemPage.vue` | Double `reference` path preserved from old routes |
| `pages/admin/user.vue` | `UserAdminPage.vue` | `layout: 'admin'`, `requiredRoles: ['admin']` |
| `pages/admin/boat.vue` | `BoatAdminPage.vue` | `layout: 'admin'`, `requiredRoles: ['admin']` |
| `pages/signup.vue` | `SignupPage.vue` | **STUB** — password auth removed; shows "contact admin" |
| `pages/pwreset.vue` | `ResetPassword.vue` | **STUB** — password auth removed |
| `pages/terms-of-service.vue` | `TermsOfServicePage.vue` | `layout: false` |
| `pages/privacy-policy.vue` | `PrivacyPolicyPage.vue` | `layout: false` |
| `pages/[...slug].vue` | `ErrorNotFound.vue` | Catch-all 404 |
### Components (all created under `app/components/`)
- `boat/BoatComponent.vue` — stub
- `boat/BoatPickerComponent.vue`
- `boat/BoatPreviewComponent.vue`
- `CertificationComponent.vue`
- `ReferencePreviewComponent.vue`
- `BoatReservationComponent.vue`
- `ResourceScheduleViewerComponent.vue` — abandoned/retained for reference
- `scheduling/NavigationBar.vue`
- `scheduling/ReservationCardComponent.vue` — named route updated to `/schedule/edit/${id}`
- `scheduling/BoatSelection.vue` — empty stub
- `scheduling/IntervalTemplateComponent.vue`
- `scheduling/boat/BoatScheduleTableComponent.vue`
- `scheduling/boat/CalendarHeaderComponent.vue`
- `LeftDrawer.vue` — uses `useNavLinks()` composable; logout via `authStore.logout()`
- `BottomNavComponent.vue`
### Utils added
- `app/utils/navlinks.ts``useNavLinks()` composable (replaces module-level `enabledLinks`)
- `app/utils/version.ts``APP_VERSION = '0.0.0'`
- `app/assets/` — All assets copied from old project
### Skipped (task feature parked)
- `task/TaskEditPage.vue`, `task/TaskPage.vue`, `admin/TaskAdminPage.vue`
- `task/TaskEditComponent.vue`, `task/TaskListComponent.vue`, `task/TaskCardComponent.vue`, `task/TaskTableComponent.vue`
- `NewPasswordComponent.vue` (password auth removed)
## Key Decisions Made This Session
- **ToolbarComponent dropped** — layout `default.vue` handles title via `route.meta.title`. Pages use `definePageMeta({ title: '...' })` instead.
- **Public pages pattern** — `definePageMeta({ public: true, layout: false })` for all auth-less full-layout pages
- **Magic link redirect** — `/auth/callback` (not `/login`) — matches Phase 3 decision
- **signup.vue / pwreset.vue as stubs** — password auth removed; stubs show redirect message. CONFIRMED.
- **navlinks.ts → composable** — original had module-level `useAuthStore()` which would break in Nuxt; converted to `useNavLinks()` composable
- **Nuxt named routes not used** — all navigation uses explicit paths (`/schedule/edit/${id}` not `{ name: 'edit-reservation' }`) to avoid Nuxt route name collisions
## Open Questions
- [ ] **OPEN**: `task`/`taskTags`/`skillTags` collections — will they ever be created in `bab_prod`?
- [x] **RESOLVED**: `signup.vue` — admin-only invite is permanent. `signup.vue` stub is the final state; self-service registration will not be built.
## What NEXT Session Should Do
1. **Phase 6 — Build & Test**
- Run `yarn dev` in `bab-app-nuxt/` — verify dev server starts clean
- Navigate to `/login` — verify page renders
- Test login flow (magic link or OTP)
- Navigate through key pages post-login
- Fix any TypeScript or import errors that surface
2. **Phase 7 — nuxt.config.ts QCalendar registration**
- `@quasar/quasar-ui-qcalendar` is imported directly in components — verify this works in Nuxt (no plugin registration needed if imported directly)
- If calendar components don't render, add CSS import to `nuxt.config.ts`
3. **Phase 8 — Deploy** (if Phase 6 passes)
- `yarn generate` → verify `.output/public/` built correctly
- Update Ansible deploy playbook if needed (path may differ from old `dist/`)
## Files to Load Next Session
- `bab-app-nuxt/nuxt.config.ts` — check QCalendar CSS import, verify PWA config
- `bab-app-nuxt/package.json` — verify no missing deps
- Any error output from `yarn dev`
## What NOT to Re-Read
- All files in `bab-app-nuxt/app/` — just created; content known
- All files in `bab-app/src/` — fully migrated; do not re-read

View File

@@ -0,0 +1,82 @@
# Session Handoff: Nuxt Migration — Phase 6 Complete
**Date:** 2026-03-19
**Session Focus:** Build & TypeScript error fixes
**Context at Handoff:** Low — clean build, ready for Phase 7+
## What Was Accomplished
**Phase 6 — Build & Test**
1. Added missing dependency `@quasar/quasar-ui-qcalendar@4.1.2` to `bab-app-nuxt/package.json` (was in original app but omitted from nuxt package.json)
2. Fixed all TypeScript errors — 0 errors after fixes (verified via `nuxi typecheck`)
3. Dev server (`yarn dev`) starts clean — no errors, one benign PWA workbox warning
## TypeScript Fixes Applied
### verbatimModuleSyntax: split type-only imports (TS1484/TS1485)
| File | Fixed |
|------|-------|
| `app/stores/reservation.ts` | `ComputedRef` from vue, `Timestamp` from qcalendar |
| `app/stores/intervalTemplate.ts` | `Ref` from vue, `Models` from appwrite |
| `app/stores/interval.ts` | `Timestamp` from qcalendar |
| `app/components/ResourceScheduleViewerComponent.vue` | `TimestampOrNull`, `Timestamp` from qcalendar |
| `app/components/scheduling/boat/BoatScheduleTableComponent.vue` | `Timestamp` from qcalendar |
| `app/components/scheduling/boat/CalendarHeaderComponent.vue` | `Timestamp` from qcalendar |
| `app/pages/schedule/manage.vue` | `Timestamp` from qcalendar |
| `app/pages/schedule/view.vue` | `Timestamp` from qcalendar |
### Actual type errors fixed
| File | Error | Fix |
|------|-------|-----|
| `app/stores/auth.ts:85` | `string \| undefined` return | `?? 'Unknown'` |
| `app/utils/schedule.ts:8` | array index `string \| undefined` | non-null assertion `!` on `arr[i]` |
| `app/utils/schedule.ts:23` | `split()[1]` is `string \| undefined` | non-null assertion `!` |
| `app/utils/schedule.ts:33-34` | `arr[i-1]` possibly undefined | non-null assertion `!` |
| `app/components/BoatReservationComponent.vue:57` | `updateInterval` handler type mismatch with `defineModel` emit | widened to `Interval \| null \| undefined` |
| `app/components/scheduling/boat/BoatScheduleTableComponent.vue:79` | `boats.value[i].displayName` after guard | `?.displayName ?? ''` |
| `app/components/scheduling/boat/BoatScheduleTableComponent.vue:119` | `result[key].push()` after undefined check | non-null assertion `!` |
| `app/components/scheduling/boat/BoatScheduleTableComponent.vue:126` | `Record[key]` returns `T \| undefined` | `?? []` |
| `app/components/scheduling/boat/BoatScheduleTableComponent.vue:175` | `boats[i].name` in template | `?.name` |
## Known Non-Errors (ignored)
- **PWA workbox WARN**: `_nuxt/builds/**/*.json` pattern matches nothing in dev mode — expected, not present in dev SW dist
- **vue-router volar warning**: `Cannot find module '@vue/language-core'` during `nuxi typecheck` — npx version mismatch, does not affect build
- **Deprecated Appwrite API hints (TS6387)**: `databases.listDocuments`, `createDocument`, etc. show as deprecated — these are hints, not errors; the old API still works. OPEN: migrate to new Appwrite SDK v14+ API signatures in a future session.
## Current State
- `yarn dev` — clean build, no errors
- `nuxi typecheck` — 0 TS errors
- All pages, stores, layouts, components in place from Phases 15
- `@quasar/quasar-ui-qcalendar@4.1.2` installed
## What NEXT Session Should Do
1. **Phase 7 — QCalendar CSS / runtime verification**
- Start `yarn dev`, open browser to `http://localhost:3000`
- Navigate to `/login` — verify page renders
- Test login flow (OTP or magic link)
- Navigate to `/schedule/book` — verify QCalendarDay renders correctly
- If calendar has no styling, add to `nuxt.config.ts`:
```ts
css: ['@quasar/quasar-ui-qcalendar/dist/index.css']
```
- Navigate to `/admin/user` and `/admin/boat` — verify admin layout renders
2. **Phase 8 — Generate & Deploy**
- `yarn generate` → verify `.output/public/` built
- Update Ansible deploy playbook if dist path changed from old `dist/` to `.output/public/`
- Check `.gitea/workflows/build.yaml` — may need path update
## Open Questions
- [ ] **OPEN**: Appwrite SDK deprecated API calls — migrate to v14+ signatures? (TS6387 hints in all stores)
- [ ] **OPEN**: `task`/`taskTags`/`skillTags` collections — will they ever be created in `bab_prod`?
## Files to Load Next Session
- `bab-app-nuxt/nuxt.config.ts` — if CSS import needed
- `.gitea/workflows/build.yaml` — check output path for deploy
- Any browser console errors from `yarn dev`

View File

@@ -0,0 +1,93 @@
# Session Handoff: Nuxt Migration — Phase 7 Complete
**Date:** 2026-03-19
**Session Focus:** Runtime verification and fix
**Context at Handoff:** Low — all pages working in dev, ready for Phase 8
## What Was Accomplished
**Phase 7 — Runtime Verification & Fixes**
All pages now load correctly in dev. Eight issues found and fixed:
### Fix 1: QCalendar CSS not imported
- Added `css: ['@quasar/quasar-ui-qcalendar/dist/index.css']` to `nuxt.config.ts`
### Fix 2: Appwrite client initialized at module load time with wrong env var pattern
- `app/utils/appwrite.ts` used `import.meta.env.NUXT_PUBLIC_*` — not available in Nuxt browser context
- **Fix**: extracted `initAppwriteClient(endpoint, projectId)` function, called from plugin after `useRuntimeConfig()`
- `app/plugins/appwrite.client.ts` now calls `useRuntimeConfig()` and guards against empty config
### Fix 3: `.env.local` not loaded by Nuxt 4
- Nuxt 4 auto-loads `.env` but NOT `.env.local`
- **Fix**: copied `.env.local``.env` (both are gitignored via `.env.*`)
### Fix 4: `AddressbarColor` plugin missing
- Added `'AddressbarColor'` to Quasar plugins list in `nuxt.config.ts`
- Added `?.` guard on `q.addressbarColor?.set(...)` in `app/layouts/default.vue`
### Fix 5: Static image assets not resolved in Vite
- `src="~/assets/oysqn_logo.png"` in component props is not processed by Vite (unlike Webpack's `~` convention)
- **Fix**: copied `oysqn_logo.png`, `oysqn_logo_only.png`, `oys_lighthouse.jpg` to `public/`
- Updated 4 pages (`login.vue`, `index.vue`, `signup.vue`, `pwreset.vue`) to use `/oysqn_logo.png`
- CSS `url('~/assets/...')` in `<style>` blocks IS handled by Vite — left unchanged
### Fix 6: Quasar SCSS variables (`$primary` etc.) undefined
- Old Quasar/Webpack auto-imported variables; Vite does not
- **Fix**: added to `nuxt.config.ts`:
```ts
vite: {
css: {
preprocessorOptions: {
sass: {
additionalData: '@use "quasar/src/css/variables.sass" as *\n',
},
},
},
},
```
- Affects: `schedule/view.vue`, `LeftDrawer.vue`, `CalendarHeaderComponent.vue`, `BoatScheduleTableComponent.vue`
### Fix 7: `sass-embedded` missing
- Added `sass-embedded` as dev dependency
### Fix 8: PWA service worker caching stale HTML in dev
- Old SW was caching HTML with empty Appwrite config
- **Fix**: set `pwa.devOptions.enabled: false` in `nuxt.config.ts`
## Current State
- `yarn dev` — all pages load correctly
- Login, schedule, admin pages verified working
- Appwrite auth flow functional
- QCalendar renders with correct styling
## Files Changed This Session
- `bab-app-nuxt/nuxt.config.ts` — CSS import, Vite SASS config, AddressbarColor plugin, PWA dev disabled
- `bab-app-nuxt/app/utils/appwrite.ts` — lazy init via `initAppwriteClient()`
- `bab-app-nuxt/app/plugins/appwrite.client.ts` — uses `useRuntimeConfig()`, guards empty config
- `bab-app-nuxt/app/layouts/default.vue` — optional chaining on `route?.meta?.title` and `q.addressbarColor?.set()`
- `bab-app-nuxt/app/pages/login.vue`, `index.vue`, `signup.vue`, `pwreset.vue` — logo src path fixed
- `bab-app-nuxt/public/` — added `oysqn_logo.png`, `oysqn_logo_only.png`, `oys_lighthouse.jpg`
- `bab-app-nuxt/.env` — created from `.env.local` for Nuxt 4 dotenv loading
## What NEXT Session Should Do
### Phase 8 — Generate & Deploy
1. **Update `.gitea/workflows/build.yaml`** — current CI is for the old Quasar app:
- Remove `yarn dlx @quasar/cli ext invoke @quasar/qcalendar` step (Quasar CLI, not needed)
- Add `cd bab-app-nuxt` or set working-directory for install/build steps
- Change build command to `yarn generate`
- Change artifact path from `dist/` to `bab-app-nuxt/.output/public/`
- Env vars: CI uses `vars.ENV_FILE` → needs to write to `bab-app-nuxt/.env`
2. **Test `yarn generate`** in `bab-app-nuxt/` — verify `.output/public/` is produced
3. **Check Ansible deploy playbook** — update dist path if needed
## Open Questions
- [ ] **OPEN**: Appwrite SDK deprecated API calls — migrate to v14+ signatures? (TS6387 hints in all stores)
- [ ] **OPEN**: `task`/`taskTags`/`skillTags` collections — will they ever be created in `bab_prod`?
- [ ] **OPEN**: Should `.env.local` be removed now that `.env` is in place, to avoid confusion?

View File

@@ -0,0 +1,43 @@
# Session Handoff: Nuxt Migration — Phase 8 Complete
**Date:** 2026-03-19
**Session Focus:** Generate & Deploy pipeline update
**Context at Handoff:** Low — build pipeline updated, ready to push and test CI
## What Was Accomplished
**Phase 8 — Generate & Deploy**
`yarn generate` verified working — outputs 22 prerendered routes to `bab-app-nuxt/.output/public`.
### Changes Made
**`generate-version.cjs`**
- Now writes `APP_VERSION` to BOTH `src/version.ts` (old Quasar) AND `bab-app-nuxt/app/utils/version.ts` (Nuxt)
**`.releaserc.json`**
- `prepareCmd`: `npm run generate-version '${nextRelease.version}' && cd bab-app-nuxt && yarn install --immutable && yarn generate`
- `publishCmd`: tar from `bab-app-nuxt/.output/public` instead of `dist/pwa`
**`.gitea/workflows/build.yaml`**
- Removed: `yarn dlx @quasar/cli ext invoke @quasar/qcalendar` (Quasar CLI step, not needed for Nuxt)
- Changed: env file written to `bab-app-nuxt/.env` instead of `.env.local`
(Nuxt 4 auto-loads `.env`, not `.env.local`)
## Current State
- `yarn generate` in `bab-app-nuxt/``.output/public/`
- CI pipeline updated for Nuxt build
- App pages working in dev (Phase 7)
## What NEXT Session Should Do
1. **Push to `devel` or `alpha` branch** and verify CI pipeline succeeds in Gitea
2. **Verify Ansible deploy** picks up the new artifact correctly (same tar.gz format, just different content)
3. **Smoke test the deployed app** in the target environment
## Open Questions
- [ ] **OPEN**: Appwrite SDK deprecated API calls — migrate to v14+ signatures? (TS6387 hints in all stores)
- [ ] **OPEN**: `task`/`taskTags`/`skillTags` collections — will they ever be created in `bab_prod`?
- [ ] **OPEN**: Should `.env.local` in `bab-app-nuxt/` be removed to avoid confusion with `.env`?
- [ ] **OPEN**: Should `nuxt_test` branch be merged to `main` once CI passes, retiring the old Quasar app?