style(app): apply eslint --fix to Tier 1 (Vue templates)
WS-3 session 1b-i Tier 1. Scope: src/components/**, src/pages/**, src/layouts/**, src/views/** restricted to *.vue files. Mechanical formatting only — predominantly vue/html-indent (506 fixes in CrowdListDetailPanel.vue alone), padding-line-between-statements, antfu/if-newline. 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 TypeScript-only files in src/composables, src/lib, src/stores, src/plugins, src/types (Tier 2 — separate commit) Includes session 1a layouts (PortalLayout.vue, PublicLayout.vue) where 2 'lines-around-comment' errors were flagged in the previous 1b-i pre-flight inspection. Tests + typecheck verified green post-fix: - apps/app vitest: 49 passed (unchanged) - apps/app vue-tsc: clean (unchanged) - apps/portal vitest: 113 passed (unchanged — not touched) - backend pest: 1486 passed (unchanged — not touched) Lint baseline progression: - Pre-Tier-1: 1451 problems - Post-Tier-1: 422 problems Visual smoke status: - NOT YET SMOKED — Bert to verify before merge. This Claude Code session has no UI access; cannot run pnpm dev and click through affected routes. The high-traffic candidates are CrowdListDetailPanel (506 fixes), AssignPersonDialog (44), ShiftDetailPanel (36), and the events / form-failures pages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useAuthStore } from '@/stores/useAuthStore'
|
||||
import { useUpdateProfile, useChangeEmail } from '@/composables/api/useAccount'
|
||||
import { useChangeEmail, useUpdateProfile } from '@/composables/api/useAccount'
|
||||
import type { UpdateProfilePayload } from '@/composables/api/useAccount'
|
||||
import { avatarText } from '@core/utils/formatters'
|
||||
|
||||
@@ -15,6 +15,7 @@ const profileForm = ref<UpdateProfilePayload>({
|
||||
timezone: 'Europe/Amsterdam',
|
||||
locale: 'nl',
|
||||
})
|
||||
|
||||
const profileFieldErrors = ref<Record<string, string>>({})
|
||||
const profileSuccess = ref('')
|
||||
|
||||
@@ -23,7 +24,7 @@ const updateProfileMutation = useUpdateProfile()
|
||||
// Populate form from auth store
|
||||
watch(
|
||||
() => authStore.user,
|
||||
(user) => {
|
||||
user => {
|
||||
if (user) {
|
||||
profileForm.value = {
|
||||
first_name: user.first_name,
|
||||
@@ -49,20 +50,20 @@ async function handleProfileSave() {
|
||||
date_of_birth: profileForm.value.date_of_birth || null,
|
||||
},
|
||||
{
|
||||
onSuccess: async (data) => {
|
||||
onSuccess: async data => {
|
||||
profileSuccess.value = data.message
|
||||
|
||||
// Re-fetch user data to update the store
|
||||
const { apiClient } = await import('@/lib/axios')
|
||||
const { data: meData } = await apiClient.get<{ success: boolean; data: import('@/types/auth').MeResponse }>('/auth/me')
|
||||
|
||||
authStore.setUser(meData.data)
|
||||
},
|
||||
onError: (err: unknown) => {
|
||||
const ax = err as { response?: { data?: { message?: string; errors?: Record<string, string[]> } } }
|
||||
if (ax.response?.data?.errors) {
|
||||
for (const [key, messages] of Object.entries(ax.response.data.errors)) {
|
||||
for (const [key, messages] of Object.entries(ax.response.data.errors))
|
||||
profileFieldErrors.value[key] = messages[0]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -74,6 +75,7 @@ const emailForm = ref({
|
||||
new_email: '',
|
||||
password: '',
|
||||
})
|
||||
|
||||
const emailFieldErrors = ref<Record<string, string>>({})
|
||||
const emailSuccess = ref('')
|
||||
const showEmailPw = ref(false)
|
||||
@@ -87,16 +89,15 @@ async function handleEmailChange() {
|
||||
changeEmailMutation.mutate(
|
||||
{ ...emailForm.value, app: 'app' },
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
onSuccess: data => {
|
||||
emailSuccess.value = data.message
|
||||
emailForm.value = { new_email: '', password: '' }
|
||||
},
|
||||
onError: (err: unknown) => {
|
||||
const ax = err as { response?: { data?: { message?: string; errors?: Record<string, string[]> } } }
|
||||
if (ax.response?.data?.errors) {
|
||||
for (const [key, messages] of Object.entries(ax.response.data.errors)) {
|
||||
for (const [key, messages] of Object.entries(ax.response.data.errors))
|
||||
emailFieldErrors.value[key] = messages[0]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -111,6 +112,7 @@ const avatarSrc = computed((): string | null => {
|
||||
if (raw.startsWith('http://') || raw.startsWith('https://'))
|
||||
return raw
|
||||
const base = (import.meta.env.VITE_API_URL as string | undefined)?.replace(/\/api\/v1\/?$/, '') ?? ''
|
||||
|
||||
return raw.startsWith('/') ? `${base}${raw}` : `${base}/${raw}`
|
||||
})
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ import { useAuthStore } from '@/stores/useAuthStore'
|
||||
import { useChangePassword } from '@/composables/api/useAccount'
|
||||
import {
|
||||
useMfaStatus,
|
||||
useTrustedDevices,
|
||||
useRevokeDevice,
|
||||
useRevokeAllDevices,
|
||||
useRegenerateBackupCodes,
|
||||
useRevokeAllDevices,
|
||||
useRevokeDevice,
|
||||
useSetPreferredMethod,
|
||||
useTrustedDevices,
|
||||
} from '@/composables/api/useMfa'
|
||||
import MfaTotpSetupDialog from '@/components/settings/MfaTotpSetupDialog.vue'
|
||||
import MfaEmailSetupDialog from '@/components/settings/MfaEmailSetupDialog.vue'
|
||||
@@ -22,6 +22,7 @@ const passwordForm = ref({
|
||||
password: '',
|
||||
password_confirmation: '',
|
||||
})
|
||||
|
||||
const passwordFieldErrors = ref<Record<string, string>>({})
|
||||
const passwordSuccess = ref('')
|
||||
const showCurrentPw = ref(false)
|
||||
@@ -30,8 +31,11 @@ const showConfirmPw = ref(false)
|
||||
const passwordReqsRef = ref<InstanceType<typeof PasswordRequirements>>()
|
||||
|
||||
const confirmationError = computed(() => {
|
||||
if (!passwordForm.value.password_confirmation) return ''
|
||||
if (passwordForm.value.password !== passwordForm.value.password_confirmation) return 'Wachtwoorden komen niet overeen'
|
||||
if (!passwordForm.value.password_confirmation)
|
||||
return ''
|
||||
if (passwordForm.value.password !== passwordForm.value.password_confirmation)
|
||||
return 'Wachtwoorden komen niet overeen'
|
||||
|
||||
return ''
|
||||
})
|
||||
|
||||
@@ -46,12 +50,13 @@ const canSubmitPassword = computed(() =>
|
||||
const changePasswordMutation = useChangePassword()
|
||||
|
||||
async function handlePasswordChange() {
|
||||
if (!canSubmitPassword.value) return
|
||||
if (!canSubmitPassword.value)
|
||||
return
|
||||
passwordFieldErrors.value = {}
|
||||
passwordSuccess.value = ''
|
||||
|
||||
changePasswordMutation.mutate(passwordForm.value, {
|
||||
onSuccess: (data) => {
|
||||
onSuccess: data => {
|
||||
passwordSuccess.value = data.message
|
||||
passwordForm.value = {
|
||||
current_password: '',
|
||||
@@ -62,9 +67,8 @@ async function handlePasswordChange() {
|
||||
onError: (err: unknown) => {
|
||||
const ax = err as { response?: { data?: { message?: string; errors?: Record<string, string[]> } } }
|
||||
if (ax.response?.data?.errors) {
|
||||
for (const [key, messages] of Object.entries(ax.response.data.errors)) {
|
||||
for (const [key, messages] of Object.entries(ax.response.data.errors))
|
||||
passwordFieldErrors.value[key] = messages[0]
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -98,17 +102,23 @@ function handleSetPreferred(method: 'totp' | 'email') {
|
||||
}
|
||||
|
||||
const backupCodesRemaining = computed(() => mfaStatus.value?.backup_codes_remaining ?? 0)
|
||||
|
||||
const backupCodesColor = computed(() => {
|
||||
if (backupCodesRemaining.value > 5) return 'success'
|
||||
if (backupCodesRemaining.value >= 3) return 'warning'
|
||||
if (backupCodesRemaining.value > 5)
|
||||
return 'success'
|
||||
if (backupCodesRemaining.value >= 3)
|
||||
return 'warning'
|
||||
|
||||
return 'error'
|
||||
})
|
||||
|
||||
function onSetupCompleted() {
|
||||
// Refetch MFA status so the method cards update (enabled, method, backup codes)
|
||||
refetchMfaStatus()
|
||||
|
||||
// Immediately clear the enforcement flag so the router guard unblocks navigation
|
||||
authStore.mfaSetupRequired = false
|
||||
|
||||
// Refresh the full /auth/me response into the store so the flag stays
|
||||
// correct on subsequent navigations (without needing a full page reload)
|
||||
authStore.refreshUser()
|
||||
@@ -252,7 +262,8 @@ function copyRegeneratedCodes() {
|
||||
>
|
||||
<VCard
|
||||
variant="outlined"
|
||||
:class="['mfa-method-card h-100', { 'mfa-method-card--primary': totpConfigured && preferredMethod === 'totp' }]"
|
||||
class="mfa-method-card h-100"
|
||||
:class="[{ 'mfa-method-card--primary': totpConfigured && preferredMethod === 'totp' }]"
|
||||
>
|
||||
<VCardText>
|
||||
<VAvatar
|
||||
@@ -336,7 +347,8 @@ function copyRegeneratedCodes() {
|
||||
>
|
||||
<VCard
|
||||
variant="outlined"
|
||||
:class="['mfa-method-card h-100', { 'mfa-method-card--primary': emailConfigured && preferredMethod === 'email' }]"
|
||||
class="mfa-method-card h-100"
|
||||
:class="[{ 'mfa-method-card--primary': emailConfigured && preferredMethod === 'email' }]"
|
||||
>
|
||||
<VCardText>
|
||||
<VAvatar
|
||||
|
||||
Reference in New Issue
Block a user