vcard4reseller/frontend/src/api/client.ts
Thomas Peterson ebaf509a2f Fundament: Symfony+API-Platform-Backend & Vue-SPA (Phase 0–2)
Stack & Setup
- Dockerisierte Dev-Umgebung (PHP 8.4-FPM, Nginx, MariaDB 11.4)
- Symfony 7.4 + API Platform 4.3, Doctrine ORM, LexikJWT, Messenger
- Vue 3 + TS (Vite), Vue Router, Pinia, Axios

Kern-Domäne & Auth
- Entitäten: User, PlatformPlan, Reseller, Company, Domain, Location,
  Employee, ContactLink (UUIDv7)
- JWT-Login (/api/login), Rollen-Hierarchie, /api/me
- Mandantentrennung via API-Platform-Query-Extension (Lesen) +
  TenantStampProcessor (Schreiben)

Öffentliche Profile (SSR)
- Profil-Landingpage, vCard-Download, QR-Code im Marken-Look
- Stabiler NFC/QR-Kurz-Link /t/{code} -> Redirect aufs aktuelle Profil
- Firmenspezifisches Branding (Farben/Logo) auf der Profilseite

Verwaltungsoberfläche (SPA)
- Brand-Look (dunkle Sidebar), rollenbasierte Navigation
- Dashboard, Reseller (+Provisioning), Firmen, Mitarbeiter, Standorte,
  Domains, Design/Branding mit Live-Vorschau

Konzept & Doku: docs/KONZEPT.md (inkl. Wallet/Sync §12), README.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:12:53 +02:00

39 lines
1013 B
TypeScript

import axios from 'axios'
// Zentraler HTTP-Client für die Symfony-API.
// Im Dev läuft alles über den Vite-Proxy (/api → :8080).
const client = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL ?? '/api',
headers: {
Accept: 'application/ld+json',
},
})
// JWT (falls vorhanden) an jede Anfrage hängen
client.interceptors.request.use((config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// Bei abgelaufenem/ungültigem Token automatisch ausloggen
client.interceptors.response.use(
(res) => res,
(error) => {
const status = error?.response?.status
const url: string = error?.config?.url ?? ''
if (status === 401 && !url.includes('/login')) {
localStorage.removeItem('token')
localStorage.removeItem('user')
if (location.pathname !== '/login') {
location.href = '/login'
}
}
return Promise.reject(error)
},
)
export default client