042a1d4773
* introduced central package registry by package init function * dynamic registration of routes, model, migrations and initializers. * setting a docker compose project name to prevent shutdown of other containers with the same (composer)name * ai documentation * app template * Create tests for ALL API entpoints in ALL packages Based on current data. Ensure that all API endpoints used in frontend are tested. These tests are crucial for the next refactoring tasks. * adopting agent instructions for a more consistent coding style * added desired module layout and debugging information * Fix All Failing tests All failing tests are fixed now that makes the refactoring more easy since all tests must pass * restored routes for maintenance * added common translations * added new tests for API Endpoint * Merge branch 'separate_business_logic' * added lern and skill improvement cost editing * Set Docker image tag when building to prevent rebuild when nothing has changed * add and remove PP for Weaponskill fixed * add and remove PP for same named skills fixed * add new task
87 lines
4.6 KiB
Markdown
87 lines
4.6 KiB
Markdown
---
|
||
description: 'Instructions for writing Vue 3 components following project conventions and best practices'
|
||
applyTo: '**/*.vue, **/*.ts, **/*.js, **/*.scss'
|
||
---
|
||
|
||
# Vue 3 Development Instructions
|
||
|
||
## Architecture & Code Organisation
|
||
|
||
### Folder Responsibilities
|
||
| Path | Purpose |
|
||
|---|---|
|
||
| `src/views/` | Page-level components mounted by the router — orchestrate layout and child components |
|
||
| `src/components/` | Reusable UI components — self-contained, receive data via props, emit events upward |
|
||
| `src/utils/` | Shared utility functions and the central API client — **always prefer these over local re-implementations** |
|
||
| `src/stores/` | Pinia stores for global state (auth, language, etc.) |
|
||
| `src/locales/` | i18n translation objects (`de` and `en`, `.js` files, not JSON) |
|
||
| `src/assets/main.css` | Central styles — see css.instructions.md |
|
||
|
||
### Component vs. Inline Code
|
||
- **Extract to a component** whenever UI logic would be repeated in more than one view, or when a dialog/panel is complex enough to have its own state
|
||
- **Prefer a dedicated component** for modal dialogs over writing inline modal markup inside a view — keeps views clean and the dialog reusable
|
||
- **Write utility functions in `src/utils/`** for any logic that could be used in more than one component (formatting, validation helpers, API wrappers)
|
||
- **Local methods** are fine for view/component-specific logic that will never be reused
|
||
|
||
### Component File Layout (order matters)
|
||
```
|
||
<template> → <style scoped> → <script>
|
||
```
|
||
Use **Options API** for consistency with the existing codebase (`data`, `created`, `methods`).
|
||
|
||
## API Communication
|
||
|
||
All HTTP calls go through `src/utils/api.js` — an Axios instance with JWT and 401-redirect interceptors.
|
||
|
||
- Import `API` from `utils/api.js`; **never** construct raw `axios` calls or add `Authorization` headers manually
|
||
- Base URL is read from `import.meta.env.VITE_API_URL` (default `http://localhost:8180`)
|
||
- Catch errors with `try/catch`; extract the message via `error.response?.data?.error ?? error.message` and show it to the user
|
||
|
||
## Modal Dialogs
|
||
|
||
**Always implement modals as separate components** in `src/components/`, not as inline markup in a view.
|
||
|
||
- The view renders `<MyDialog v-if="showDialog" @close="showDialog = false" />`
|
||
- The dialog component handles its own internal state and emits `close` (and any result events) to the parent
|
||
- Use global CSS classes `modal-overlay`, `modal-content`, `modal-header`, `modal-body`, `modal-footer`, `btn-primary`, `btn-cancel`, `close-button` — all defined in `main.css`, do not redefine them in scoped styles
|
||
- Close on overlay click with `@click.self`; always include a `×` close button in the header
|
||
|
||
## State & Reactivity
|
||
|
||
- **Pinia stores** (`src/stores/`) for state shared across multiple views (language, auth token, etc.)
|
||
- **Component-local `data()`** for state that belongs only to that component
|
||
- Always track async operations with an `isLoading` flag; disable interactive elements and show feedback while loading
|
||
- Use `v-if` for infrequently toggled elements, `v-show` for frequent toggles; always use `:key` with `v-for`
|
||
|
||
## Internationalization
|
||
|
||
- All user-visible strings use `$t('key')` — never hardcode text in templates
|
||
- **Always add translations to both** `src/locales/de` and `src/locales/en` at the same time
|
||
- Use nested keys that reflect the domain (e.g., `export.selectTemplate`)
|
||
|
||
## Browser Compatibility
|
||
|
||
**Popup blocker**: `window.open()` must be called **synchronously** in the click handler — before any `await`. Open the window first, then perform the async API call and update `window.location.href` afterwards.
|
||
|
||
## Code Conventions
|
||
|
||
- `const` by default, `let` when reassignment is needed — never `var`
|
||
- `===` for all comparisons, never `==`
|
||
- Optional chaining `?.` and nullish coalescing `??` for safe property access
|
||
- Keep template expressions simple — move logic to `methods`
|
||
- PascalCase for component file names (`CharacterDetails.vue`)
|
||
- Handle errors gracefully — with user-friendly messages
|
||
- Test with actual API — running in Docker container
|
||
- Check HMR reload — view logs: `docker logs bamort-frontend-dev`
|
||
|
||
## Anti-Patterns
|
||
|
||
❌ Don't write inline modal markup in views — extract to a component
|
||
❌ Don't duplicate API call setup — use `utils/api.js`
|
||
❌ Don't duplicate utility logic — add it to `src/utils/` and import it
|
||
❌ Don't use inline styles — use global CSS classes from `main.css`; scoped CSS only for genuinely unique local overrides
|
||
❌ Don't use `v-if` and `v-for` on the same element
|
||
❌ Don't mutate props directly
|
||
❌ Don't forget translations — always update both `de` and `en`
|
||
❌ Don't call API methods in template expressions
|