style(app): apply eslint --fix to Tier 2 (TypeScript plumbing)
WS-3 session 1b-i Tier 2. Scope: composables, lib, stores, plugins, types, utils, navigation, main.ts. Mechanical fixes only — predominantly newline-before-return, arrow-parens, antfu/if-newline, padding-line-between-statements, plus one unicorn/prefer-includes (.some(p => x === p) → .includes(x)) in router guards. Excludes (per session prompt): - apps/app/vite.config.ts (Tier 3) - apps/app/themeConfig.ts (Tier 3) - apps/app/vitest.config.ts (Tier 3) - All .vue files (already in Tier 1) Hand-reviewed diffs for the three auth/router-critical files before committing: - src/lib/axios.ts: reviewed clean. Pure mechanical (quote-props on Accept header, curly-strip on single-statement ifs, one blank line before impersonationStore.clearState()). No type-import changes, no logic touched. - src/stores/useAuthStore.ts: reviewed clean. curly-strip + padding before returns. The initialize()/doInitialize() race-condition guard on isInitialized is preserved verbatim. - src/plugins/1.router/guards.ts: reviewed clean. if-newline reformat + one .some() → .includes() rewrite that's behaviorally identical for primitive equality on the guestOnlyPaths string array. Tests + typecheck verified green post-fix: - apps/app vitest: 49 passed (unchanged) - apps/app vue-tsc: clean (unchanged) Lint baseline progression: - Pre-Tier-2: 422 problems (post-Tier-1) - Post-Tier-2: 246 problems Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -4,10 +4,12 @@ import { isAxiosError } from 'axios'
|
||||
* Human-readable message from Laravel API validation / exception responses.
|
||||
*/
|
||||
export function getApiErrorMessage(error: unknown, fallback: string): string {
|
||||
if (!isAxiosError(error)) return fallback
|
||||
if (!isAxiosError(error))
|
||||
return fallback
|
||||
|
||||
const data = error.response?.data as Record<string, unknown> | undefined
|
||||
if (!data) return fallback
|
||||
if (!data)
|
||||
return fallback
|
||||
|
||||
const errors = data.errors
|
||||
if (errors && typeof errors === 'object' && errors !== null && !Array.isArray(errors)) {
|
||||
@@ -15,12 +17,14 @@ export function getApiErrorMessage(error: unknown, fallback: string): string {
|
||||
if (Array.isArray(value) && value.length > 0 && typeof value[0] === 'string')
|
||||
return value[0]
|
||||
|
||||
if (typeof value === 'string') return value
|
||||
if (typeof value === 'string')
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
const message = data.message
|
||||
if (typeof message === 'string' && message.trim() !== '') return message
|
||||
if (typeof message === 'string' && message.trim() !== '')
|
||||
return message
|
||||
|
||||
return fallback
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ const apiClient: AxiosInstance = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeout: 30000,
|
||||
@@ -17,9 +17,8 @@ apiClient.interceptors.request.use(
|
||||
(config: InternalAxiosRequestConfig) => {
|
||||
const orgStore = useOrganisationStore()
|
||||
|
||||
if (orgStore.activeOrganisationId) {
|
||||
if (orgStore.activeOrganisationId)
|
||||
config.headers['X-Organisation-Id'] = orgStore.activeOrganisationId
|
||||
}
|
||||
|
||||
// Add impersonation header when active
|
||||
// Lazy import to avoid circular dependency with store
|
||||
@@ -27,18 +26,16 @@ apiClient.interceptors.request.use(
|
||||
if (impersonationData) {
|
||||
try {
|
||||
const parsed = JSON.parse(impersonationData) as { targetUserId?: string }
|
||||
if (parsed.targetUserId) {
|
||||
if (parsed.targetUserId)
|
||||
config.headers['X-Impersonate-User'] = parsed.targetUserId
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Invalid data — ignore
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
if (import.meta.env.DEV)
|
||||
console.log(`🚀 ${config.method?.toUpperCase()} ${config.url}`, config.data)
|
||||
}
|
||||
|
||||
return config
|
||||
},
|
||||
@@ -47,16 +44,14 @@ apiClient.interceptors.request.use(
|
||||
|
||||
apiClient.interceptors.response.use(
|
||||
response => {
|
||||
if (import.meta.env.DEV) {
|
||||
if (import.meta.env.DEV)
|
||||
console.log(`✅ ${response.status} ${response.config.url}`, response.data)
|
||||
}
|
||||
|
||||
return response
|
||||
},
|
||||
error => {
|
||||
if (import.meta.env.DEV) {
|
||||
if (import.meta.env.DEV)
|
||||
console.error(`❌ ${error.response?.status} ${error.config?.url}`, error.response?.data)
|
||||
}
|
||||
|
||||
const status = error.response?.status
|
||||
const notificationStore = useNotificationStore()
|
||||
@@ -65,6 +60,7 @@ apiClient.interceptors.response.use(
|
||||
if (status === 403 && error.response?.data?.impersonation_ended) {
|
||||
import('@/stores/useImpersonationStore').then(({ useImpersonationStore }) => {
|
||||
const impersonationStore = useImpersonationStore()
|
||||
|
||||
impersonationStore.clearState()
|
||||
window.location.href = '/platform'
|
||||
})
|
||||
@@ -76,9 +72,8 @@ apiClient.interceptors.response.use(
|
||||
// Lazy import to avoid circular dependency
|
||||
import('@/stores/useAuthStore').then(({ useAuthStore }) => {
|
||||
const authStore = useAuthStore()
|
||||
if (authStore.isInitialized) {
|
||||
if (authStore.isInitialized)
|
||||
authStore.handleUnauthorized()
|
||||
}
|
||||
})
|
||||
}
|
||||
else if (status === 403) {
|
||||
@@ -90,9 +85,8 @@ apiClient.interceptors.response.use(
|
||||
else if (status === 422) {
|
||||
// Show validation message to user; still reject so component onError handlers can react
|
||||
const message = error.response?.data?.message
|
||||
if (message && typeof message === 'string') {
|
||||
if (message && typeof message === 'string')
|
||||
notificationStore.show(message, 'error')
|
||||
}
|
||||
}
|
||||
else if (status === 503) {
|
||||
notificationStore.show('Service temporarily unavailable. Please try again later.', 'error')
|
||||
|
||||
@@ -4,12 +4,18 @@
|
||||
*/
|
||||
export function dutchPlural(word: string): string {
|
||||
// Words ending in -ie: add -s (editie → edities, locatie → locaties)
|
||||
if (word.endsWith('ie')) return `${word}s`
|
||||
if (word.endsWith('ie'))
|
||||
return `${word}s`
|
||||
|
||||
// Words ending in -e: add -s (ronde → rondes)
|
||||
if (word.endsWith('e')) return `${word}s`
|
||||
if (word.endsWith('e'))
|
||||
return `${word}s`
|
||||
|
||||
// Double vowel before final consonant(s): single vowel + en (onderdeel → onderdelen)
|
||||
const match = word.match(/^(.*)([aeiou])\2([^aeiou]+)$/i)
|
||||
if (match) return `${match[1]}${match[2]}${match[3]}en`
|
||||
if (match)
|
||||
return `${match[1]}${match[2]}${match[3]}en`
|
||||
|
||||
// Default: add -en (dag → dagen)
|
||||
return `${word}en`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user