Files
bamort/.github/instructions/vue.instructions.md
T
Bardioc26 042a1d4773 Learncost frontend (#42)
* 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
2026-05-01 18:15:31 +02:00

4.6 KiB
Raw Blame History

description, applyTo
description applyTo
Instructions for writing Vue 3 components following project conventions and best practices **/*.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