Mobile traffic was breaking on narrow viewports because the header nav
overflowed and several pages used desktop-only spacing. This adds a
shared phone breakpoint, a hamburger menu, and scroll-to-top on route
changes so footer and menu navigation always land at the top of the page.
- Add --page-gutter and max-width 639px rules in base.css
- AppHeader: hamburger panel on small screens; flat account links on mobile
- AppFooter: stack footer links vertically on phones
- Home, compose, edit order, orders, auth, and legal pages: tighter gutters
and responsive layout (orders card actions stack; home grids single-column)
- Router scrollBehavior: scroll to top on navigation; restore on browser back
- Tests: AppHeader menu toggle, Router scrollBehavior, mobile Playwright checks
Admin page is intentionally unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the header "Byt lösenord" link with an Inställningar menu for
changing email or password. Email changes are two-step: request with
password, confirmation link to the new address, then password again on
confirm so a wrong inbox cannot take over the account.
- Backend: EmailChangeService, V10 email_change_tokens, confirm API
- Frontend: ChangeEmailPage, ConfirmEmailChangePage, header dropdown
- E2E: account-settings round-trips, Mailpit verification, wrong-password guard
- Flyway: V9 restore for dev DBs, CI migration checks, V10 for email tokens
Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace placeholder about card with hero, prose, steps, and CTA
- Add primary route /om-oss with redirect from legacy /om
- Update footer tagline and Om oss link to match new URL
- Extend AboutPage and AppFooter tests for new content and routing
Co-authored-by: Cursor <cursoragent@cursor.com>
Operators can fix prod admin passwords without email via Byt lösenord;
end users can use forgot-password when SMTP is configured. Local and CI
use Mailpit to capture outbound mail and verify reset links end-to-end.
- Backend: V8 password_reset_tokens, PasswordResetService, EmailService,
POST /api/auth/forgot-password, reset-password, change-password
- Optional testToken in forgot-password response (docker profile only, for E2E)
- Frontend: ForgotPasswordPage, ResetPasswordPage, ChangePasswordPage,
routes, login link, header Byt lösenord
- Mailpit (ghcr.io/axllent/mailpit:v1.28) in docker-compose + e2e stack
- E2E: password-reset.spec.ts + Mailpit API helper tests SMTP delivery
- Separate dev/e2e Docker image names to avoid overwriting bilhej-frontend
- Docs: README email section, production-email-checklist, .env.example
- Unit/integration tests for reset, change password, and Vitest page specs
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add typed API module api/vehicles.ts with lookupVehicle(plate) function
- Replace FAKE_VEHICLES record with async API call in HomePage.vue
- Remove setTimeout-based fake lookup, use lookupVehicle() instead
- Handle errors: show not-found for unknown plates, catch network failures
- Add fuel field to VehicleInfo interface and display (e.g. 'Gul, Bensin')
- VehicleInfo now shows make, model, year, color, and fuel from API
- Rewrite homepage: practical headline, use-case cards, calm trust note
- Switch from purple to blue brand tokens across all pages
- Replace all CTA buttons with brand-primary, reserve green for success
- Remove emoji from template picker and compose page
- Replace unicode chevrons with SVG expand buttons in admin
- Redesign template picker modal with accessibility semantics
- Add aria-invalid, aria-describedby to form validation
- Add role=status/alert to loading, error, and result messages
- Remove inline styles, replace with scoped utility classes
- Update compose submit text, payment button, order empty state copy
- Remove icon field from letter templates
- Add design tokens (colors, spacing, radius, shadows, typography, transitions)
- Add global reset, body/link/focus/typography base styles
- Add utility classes (container, surface-card, btn variants, field, badge, message, divider)
- Replace header ✉ symbol with inline SVG envelope icon
- Update favicon to license-plate shaped mark with blue gradient and bold B
- Rename brand from BilHälsning to Bilhej in header, footer, and HTML title
- Rewrite footer tagline: focus on service, not privacy
- Add theme-color meta tag for browser chrome
- Add 'Mina beställningar' RouterLink to AppHeader in authenticated template
- Add Vitest tests: link visible when authenticated, hidden when not
- Add Playwright E2E test: shows orders link when authenticated
- Add Playwright E2E test: can navigate from home to orders via header link
Update AppHeader to reflect authentication state. When not authenticated,
show Logga in and Registrera links. When authenticated, show the user's
email address and a Logga ut button. Uses v-if/v-else with template blocks
for clean conditional rendering without wrapper elements.
Changes:
- authStore: add email computed that extracts sub claim from JWT payload
- AppHeader: conditional nav with v-if/v-else (guest vs authenticated)
- AppHeader: add email display and logout button with styles
- App.spec.ts: add Pinia to test setup (required by AppHeader now)
- AppHeader.spec.ts: rewrite with tests for both auth states
- authStore.spec.ts: add tests for email extraction and clearing
- header-auth.spec.ts: 5 Playwright E2E tests for header auth state
Add the frontend login page (LoginPage.vue) with email and password
fields, Swedish UI strings, and integration with the backend login
endpoint. Also sets up Playwright as the E2E testing framework with
browser tests for both login and registration flows.
Frontend login implementation:
- Add LoginPage.vue with form validation, error handling, and link to
registration page
- Add login() API function in auth.ts
- Add loginUser() method to authStore that stores JWT token
- Add /logga-in route to Vue Router
- Add 'Logga in' nav link to AppHeader alongside existing 'Registrera'
- Add 10 unit tests for LoginPage component
- Add 4 unit tests for loginUser auth store method
- Add 1 route resolution test and 1 AppHeader link test
Playwright E2E setup and tests:
- Install @playwright/test and configure playwright.config.ts
- Add npm scripts: test:e2e (local) and test:e2e:ci (Docker CI)
- Exclude e2e/ directory from Vitest to prevent test runner conflicts
- Add .gitignore entries for test-results/ and playwright-report/
- Add 5 E2E tests for login (navigation, invalid credentials, success
redirect, navigation to register, input types)
- Add 6 E2E tests for register (navigation, success redirect, validation
errors for invalid email/short password/mismatched passwords,
navigation to login)
Add AppHeader and AppFooter to give the site a consistent chrome
around the core page content. Add ComposePage stub reachable via
"Skicka ett brev till ägaren" CTA on HomePage after vehicle lookup
succeeds. Add stub pages for about, contact, and privacy.
- Create AppHeader.vue with logo link (BilHälsning) and Hem nav link
- Create AppFooter.vue with 4 links: Om oss, Kontakt, Integritetspolicy, Villkor
- Create ComposePage.vue stub that reads plate from route query params
- Create AboutPage.vue and ContactPage.vue stub pages
- Add 4 new routes: /compose, /om, /kontakt, /integritetspolicy
- Update App.vue to render AppHeader + <main> + AppFooter around RouterView
- Add home__cta RouterLink button to HomePage, visible only when vehicle
lookup succeeds, linking to /compose?plate=<plate>
- Remove BilHälsning h1 from HomePage (moved to header)
- Add 17 new tests: AppHeader (2), AppFooter (1), ComposePage (3),
AboutPage (1), ContactPage (1), HomePage rewrite (6), App update (2)
- Update App.spec.ts to verify header/footer components render
Move vehicle-info display logic out of HomePage into a reusable
VehicleInfo component. The component accepts vehicle, loading,
notFound, and plate props and renders the correct state with
priority: vehicle card > loading > not found. Follows the
small-page-component pattern from CODING_GUIDELINES.md.
- Create VehicleInfo.vue with 3-state v-if chain and scoped styles
- Define and export VehicleInfo interface (make/model/year/color)
- Add VehicleInfo.spec.ts with 7 tests covering all states and
priority edge cases
- Update HomePage.vue to use VehicleInfo, replacing 3 inline
v-if/else-if blocks with a single component tag
- Remove 5 unused CSS classes from HomePage (home__status,
home__vehicle, home__vehicle-text, home__not-found,
home__not-found p)
- Update AGENTS.md to require thorough commit messages with bullet
points