68 lines
2.8 KiB
Markdown
68 lines
2.8 KiB
Markdown
# ptitlutins (frontend)
|
|
|
|
Nuxt 4 SPA for **ptitlutins**, a collaborative trip-planning app. Talks to the
|
|
Django backend in `../ptitlutins-backend` (sibling repo).
|
|
|
|
## Stack
|
|
|
|
- **Nuxt 4** (Vue 3, `<script setup lang="ts">`), Pinia, Vue Router (file-based)
|
|
- `@nuxtjs/i18n` (locales in `i18n/locales/{en,fr}.json`, default `en`, use `$t()`)
|
|
- `@nuxt/icon`, `@nuxt/fonts`, `vue-tippy` (tooltips/popovers, registered via
|
|
`app/plugins/vue-tippy.client.ts`)
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev # http://localhost:3000
|
|
npm run build
|
|
npm run generate # static
|
|
npx nuxt typecheck # types
|
|
npx eslint . # lint
|
|
```
|
|
|
|
The backend must be running on `http://localhost:8000` (hardcoded in
|
|
`app/services/api.ts` as `baseURL`).
|
|
|
|
## Layout (atomic design under `app/`)
|
|
|
|
- `components/{atoms,molecules,organisms,templates}/` — `pathPrefix: false`, so
|
|
components are referenced by bare name (e.g. `<Voyage>`, `<Button>`) with no
|
|
import. `app.config.ts`-style auto-import is on.
|
|
- `pages/` — routes. `pages/voyages/[id].vue` is the main view; `[id]` is a
|
|
**VoyageLink id**, not a voyage id (see architecture).
|
|
- `stores/` — Pinia (option-store style). `services/` — thin API wrappers.
|
|
- `types/index.ts` — shared TS types.
|
|
- `assets/css/` — `main.css` imports `reset.css`, `variables.css`, `global.css`.
|
|
|
|
## Architecture: voyages are accessed through links
|
|
|
|
A user never addresses a `Voyage` directly — always through a **`VoyageLink`**,
|
|
a shareable handle carrying its own `permission` (`view`/`change`). This mirrors
|
|
the backend.
|
|
|
|
- `voyagesLinksStore` — list of links + `currentVoyageLink`. `setCurrentVoyageLink(id)`
|
|
loads one. Routes key off the link id.
|
|
- `voyageStore` — holds a voyage's entities (`events`, `trips`, `needs`,
|
|
`locations`), each normalized as `Record<voyageId, Record<entityId, Entity>>`.
|
|
Generic CRUD via `fetchItems`/`addItem`/`updateItem`/`removeItem`, keyed by the
|
|
`VoyageEntitiesNames` enum. The per-entity actions (`addEvent`, etc.) just
|
|
delegate to these generics — extend the generics, not each entity by hand.
|
|
- `services/voyageService.ts` hits the **nested** REST routes
|
|
`voyages/{voyageLinkId}/{entity}/`. `services/voyagesLinksService.ts` hits
|
|
`voyages/`.
|
|
|
|
## Conventions
|
|
|
|
- Prettier: **no semicolons** (`.prettierrc` → `"semi": false`). ESLint via
|
|
`withNuxt` (`eslint.config.mjs`).
|
|
- TS interface fields are camelCase; note the backend (DRF) serializes snake_case
|
|
(`postal_address`, `proposed_by`, `start_date`) — there is no auto-mapping yet,
|
|
so some types in `types/index.ts` are inconsistent with the wire format. Check
|
|
the actual JSON when wiring new fields.
|
|
- User-facing strings go through `$t()` / i18n; don't hardcode.
|
|
|
|
## State of the code
|
|
|
|
Early WIP. `VoyageMap.vue` is a stub. Some store/service methods (update/delete
|
|
voyage) are commented out. No tests yet.
|