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>
39 lines
1013 B
TypeScript
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
|