Files
crewli-old/apps/portal/src/pages/wachtwoord-vergeten.vue
bert.hausmans e5fdb3efb1 fix: add client-side validation to forgot-password forms
Both the organizer app and portal forgot-password pages now
validate the email field before submission: required + email
format check. Backend already validated this, but empty or
malformed emails were being sent to the API unnecessarily.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 20:51:01 +02:00

142 lines
3.8 KiB
Vue

<script setup lang="ts">
import authV1BottomShape from '@images/svg/auth-v1-bottom-shape.svg?raw'
import authV1TopShape from '@images/svg/auth-v1-top-shape.svg?raw'
import { VNodeRenderer } from '@layouts/components/VNodeRenderer'
import { themeConfig } from '@themeConfig'
import { requiredValidator, emailValidator } from '@core/utils/validators'
import { VForm } from 'vuetify/components/VForm'
import { apiClient } from '@/lib/axios'
definePage({
name: 'forgot-password',
meta: {
layout: 'blank',
requiresAuth: false,
},
})
const refVForm = ref<VForm>()
const email = ref('')
const isSubmitting = ref(false)
const done = ref(false)
async function onSubmit(): Promise<void> {
const { valid } = await refVForm.value!.validate()
if (!valid) return
isSubmitting.value = true
try {
await apiClient.post('/auth/forgot-password', { email: email.value.trim(), app: 'portal' })
}
catch {
// Always show generic success (no email enumeration)
}
finally {
isSubmitting.value = false
done.value = true
}
}
</script>
<template>
<div class="auth-wrapper d-flex align-center justify-center pa-4">
<div class="position-relative my-sm-16">
<VNodeRenderer
:nodes="h('div', { innerHTML: authV1TopShape })"
class="text-primary auth-v1-top-shape d-none d-sm-block"
/>
<VNodeRenderer
:nodes="h('div', { innerHTML: authV1BottomShape })"
class="text-primary auth-v1-bottom-shape d-none d-sm-block"
/>
<VCard
class="auth-card"
max-width="460"
:class="$vuetify.display.smAndUp ? 'pa-6' : 'pa-0'"
>
<VCardItem class="justify-center">
<VCardTitle>
<RouterLink to="/">
<div class="app-logo">
<VNodeRenderer :nodes="themeConfig.app.logo" />
<h1 class="app-logo-title">
{{ themeConfig.app.title }}
</h1>
</div>
</RouterLink>
</VCardTitle>
</VCardItem>
<VCardText>
<h4 class="text-h4 mb-1">
Wachtwoord vergeten?
</h4>
<p class="mb-0">
Vul je e-mailadres in en we sturen je een link om je wachtwoord te herstellen.
</p>
</VCardText>
<VCardText>
<VAlert
v-if="done"
type="success"
variant="tonal"
class="mb-4"
>
Als dit e-mailadres bij ons bekend is, ontvang je een link om je wachtwoord te resetten.
</VAlert>
<VForm
v-if="!done"
ref="refVForm"
@submit.prevent="onSubmit"
>
<VRow>
<VCol cols="12">
<AppTextField
v-model="email"
autofocus
label="E-mailadres"
type="email"
placeholder="je@email.nl"
:rules="[requiredValidator, emailValidator]"
/>
</VCol>
<VCol cols="12">
<VBtn
block
type="submit"
:loading="isSubmitting"
>
Verstuur herstelmail
</VBtn>
</VCol>
<VCol cols="12">
<RouterLink
class="d-flex align-center justify-center"
to="/login"
>
<VIcon
icon="tabler-chevron-left"
size="20"
class="me-1 flip-in-rtl"
/>
<span>Terug naar inloggen</span>
</RouterLink>
</VCol>
</VRow>
</VForm>
</VCardText>
</VCard>
</div>
</div>
</template>
<style lang="scss">
@use "@core/scss/template/pages/page-auth";
</style>