2.8 KiB
2.8 KiB
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 ini18n/locales/{en,fr}.json, defaulten, use$t())@nuxt/icon,@nuxt/fonts,vue-tippy(tooltips/popovers, registered viaapp/plugins/vue-tippy.client.ts)
Commands
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].vueis 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.cssimportsreset.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 asRecord<voyageId, Record<entityId, Entity>>. Generic CRUD viafetchItems/addItem/updateItem/removeItem, keyed by theVoyageEntitiesNamesenum. The per-entity actions (addEvent, etc.) just delegate to these generics — extend the generics, not each entity by hand.services/voyageService.tshits the nested REST routesvoyages/{voyageLinkId}/{entity}/.services/voyagesLinksService.tshitsvoyages/.
Conventions
- Prettier: no semicolons (
.prettierrc→"semi": false). ESLint viawithNuxt(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 intypes/index.tsare 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.