diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2e448f3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,76 @@ +# CLAUDE.md + +Vue 3 + TypeScript SPA — frontend of MWS (My Workspace), an internal tool for small teams to manage projects, documents, and tasks. Talks to a .NET 10 backend over REST + JWT. + +## Commands + +```bash +npm install # install deps +npm run dev # vite dev server on :5173, calls backend at http://localhost:5000 +npm run build # vue-tsc typecheck + vite build → dist/ +npm run preview # serve built dist locally +``` + +No test runner, no linter configured. `vue-tsc -b` during `build` is the only static check. + +## Environment + +- `VITE_API_BASE_URL` — backend base URL (default `http://localhost:5000`). Set in `.env.local` for dev, or pass `--build-arg VITE_API_BASE_URL=...` to Docker. +- Backend dev port is **5000**, not the production 8080. The `api.ts` interceptor reads `localStorage.mws_token` and attaches `Authorization: Bearer …`; 401s clear storage and redirect to `/login`. + +## Layout & routing + +Two nested layouts (`src/layouts/`): + +- `MainLayout` — app shell with sidebar + topbar. Wraps all authenticated routes. Hosts the global `Toast` and `ConfirmDialog` (in `App.vue`). +- `ProjectLayout` — header + tabs (Overview / Documents / Tasks / Members). Loads the project by `:id` route param on mount and renders `` for the tab content. + +Routes (`src/router/index.ts`) guard everything except `/login` via `meta.public`. Auth users hitting `/login` redirect to `/projects`. Unknown paths redirect to `/projects`. + +Domain areas (each is a folder under `views/`): + +- `auth/` — `LoginView.vue` +- `projects/` — list, overview, members +- `documents/` — tree + editor +- `tasks/` — list, kanban board, detail dialog + +## Service layer pattern + +Three files in `src/services/`: + +- `api.ts` — shared axios instance + interceptors + `errorMessage(error)` helper for surfacing backend `{ message }` errors. +- `backend.ts` — auth, projects, members, users (small subset). +- `modules.ts` — documents + tasks (split here to keep files scannable). + +Every API call is a thin typed wrapper around `api.get/post/put/delete`. Views call these directly — there is no separate data layer / composable cache. New endpoints → add a typed function to `backend.ts` or `modules.ts` and a matching interface in `src/types/index.ts`. + +## State + +Only one Pinia store: `src/stores/auth.ts`. Token + user object, persisted to `localStorage` under `mws_token` / `mws_user`. Everything else (projects, documents, tasks) is fetched per-view — no client cache. Add a new store only if cross-view shared state actually appears. + +## Auto-imports + +`vite.config.ts` auto-imports: + +- Vue / vue-router / pinia globals +- PrimeVue composables: `useToast`, `useConfirm`, `useDialog` (call them without imports in components) +- PrimeVue components via `@primevue/auto-import-resolver` (no need to import `