fix: eliminate all TypeScript any usage across Vue components

Replace 24 `err: any` error handler types with proper `AxiosError<ApiErrorResponse>`
typing. Fix additional `as any` casts and `Record<string, any>` patterns in registration
field components, event settings, and portal layout. Create shared `ApiErrorResponse`
type for portal app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-15 21:54:01 +02:00
parent 0be2956ea4
commit cd2c775692
29 changed files with 151 additions and 80 deletions

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import { useAvailableShifts, useClaimShift } from '@/composables/api/usePortalShifts'
import type { AvailableShift } from '@/types/portal-shift'
import axios from 'axios'
import type { ApiErrorResponse } from '@/types/api'
const props = defineProps<{
eventId: string
@@ -45,9 +47,10 @@ async function confirmClaim() {
snackbarColor.value = 'success'
snackbar.value = true
}
catch (err: any) {
const message = err?.response?.data?.message ?? 'Er is een fout opgetreden.'
claimError.value = message
catch (err: unknown) {
claimError.value = axios.isAxiosError<ApiErrorResponse>(err)
? err.response?.data?.message ?? 'Er is een fout opgetreden.'
: 'Er is een fout opgetreden.'
}
}

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import { useMyShifts, useCancelAssignment } from '@/composables/api/usePortalShifts'
import type { MyShiftAssignment } from '@/types/portal-shift'
import axios from 'axios'
import type { ApiErrorResponse } from '@/types/api'
const props = defineProps<{
eventId: string
@@ -51,8 +53,10 @@ async function confirmCancel() {
snackbarMessage.value = result.message
snackbar.value = true
}
catch (err: any) {
cancelError.value = err?.response?.data?.message ?? 'Er is een fout opgetreden.'
catch (err: unknown) {
cancelError.value = axios.isAxiosError<ApiErrorResponse>(err)
? err.response?.data?.message ?? 'Er is een fout opgetreden.'
: 'Er is een fout opgetreden.'
}
}
</script>

View File

@@ -16,7 +16,7 @@ const isMobileMenuOpen = ref(false)
// Navbar mode: 'event' shows org name + event name + back link
// Default ('platform') shows Crewli logo + page title
const isEventMode = computed(() => route.meta.navMode === 'event')
const navTitle = computed(() => (route.meta as any).navTitle as string | undefined)
const navTitle = computed(() => route.meta.navTitle)
const eventName = computed(() => portal.activeEvent?.event_name ?? '')
const orgName = computed(() => portal.activeEvent?.organisation_name ?? '')

View File

@@ -7,6 +7,8 @@ import { apiClient } from '@/lib/axios'
import MfaTotpSetupDialog from '@/components/settings/MfaTotpSetupDialog.vue'
import MfaEmailSetupDialog from '@/components/settings/MfaEmailSetupDialog.vue'
import MfaDisableDialog from '@/components/settings/MfaDisableDialog.vue'
import axios from 'axios'
import type { ApiErrorResponse } from '@/types/api'
definePage({
name: 'portal-profiel',
@@ -199,14 +201,19 @@ async function saveProfile() {
snackbarColor.value = 'success'
snackbar.value = true
}
catch (err: any) {
const data = err?.response?.data
if (data?.errors) {
const firstError = Object.values(data.errors).flat()[0] as string
profileError.value = firstError
catch (err: unknown) {
if (axios.isAxiosError<ApiErrorResponse>(err)) {
const data = err.response?.data
if (data?.errors) {
const firstError = Object.values(data.errors).flat()[0]
profileError.value = firstError ?? 'Er is een fout opgetreden.'
}
else {
profileError.value = data?.message ?? 'Er is een fout opgetreden.'
}
}
else {
profileError.value = data?.message ?? 'Er is een fout opgetreden.'
profileError.value = 'Er is een fout opgetreden.'
}
}
}
@@ -228,16 +235,21 @@ async function savePassword() {
snackbarColor.value = 'success'
snackbar.value = true
}
catch (err: any) {
const data = err?.response?.data
if (data?.errors) {
passwordFieldErrors.value = {}
for (const [key, messages] of Object.entries(data.errors)) {
passwordFieldErrors.value[key] = (messages as string[])[0]
catch (err: unknown) {
if (axios.isAxiosError<ApiErrorResponse>(err)) {
const data = err.response?.data
if (data?.errors) {
passwordFieldErrors.value = {}
for (const [key, messages] of Object.entries(data.errors)) {
passwordFieldErrors.value[key] = messages[0]
}
}
else {
passwordError.value = data?.message ?? 'Er is een fout opgetreden.'
}
}
else {
passwordError.value = data?.message ?? 'Er is een fout opgetreden.'
passwordError.value = 'Er is een fout opgetreden.'
}
}
}

View File

@@ -0,0 +1,5 @@
export interface ApiErrorResponse {
success: false
message: string
errors?: Record<string, string[]>
}