Files
frontend/app/pages/auth/register.vue
T

171 lines
6.2 KiB
Vue

<script setup lang="ts">
import CodiceFiscale from 'codice-fiscale-js'
import { ref } from 'vue'
definePageMeta({
middleware: 'guest'
})
useHead({ title: 'Registrazione - Visione' })
const { register } = useAuth()
const router = useRouter()
const isLoading = ref(false)
const errorMessage = ref('')
const successMessage = ref(false)
const form = ref({
first_name: '',
last_name: '',
fiscal_code: '',
email: '',
phone: '',
privacy: false
})
const normalizeFiscalCode = (fiscalCode = '') => fiscalCode.trim().toUpperCase()
const handleRegister = async () => {
if (!form.value.privacy) {
errorMessage.value = "È necessario accettare l'informativa sulla privacy."
return
}
const fiscalCode = normalizeFiscalCode(form.value.fiscal_code)
const expected = CodiceFiscale.surnameCode(form.value.last_name) + CodiceFiscale.nameCode(form.value.first_name)
if (!CodiceFiscale.check(fiscalCode)) {
errorMessage.value = 'Il Codice Fiscale inserito non è valido.'
return
}
if (fiscalCode.slice(0, 6) !== expected) {
errorMessage.value = 'Il Codice Fiscale non corrisponde a nome e cognome inseriti.'
return
}
isLoading.value = true
errorMessage.value = ''
try {
await register({
first_name: form.value.first_name,
last_name: form.value.last_name,
fiscal_code: fiscalCode,
email: form.value.email,
phone: form.value.phone || undefined
})
successMessage.value = true
setTimeout(() => {
router.push('/auth/login')
}, 3000)
} catch (err: any) {
errorMessage.value = err.data?.message || 'Errore durante la registrazione. Controlla i dati inseriti.'
} finally {
isLoading.value = false
}
}
</script>
<template>
<div class="d-flex align-items-center bg-light py-5">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-lg-8">
<div class="text-center mb-4">
<BIIcon name="it-user" size="xl" color="primary" class="mb-2" />
<h1 class="h3 font-weight-bold">Registrazione Cittadino</h1>
<p class="text-muted">Crea il tuo profilo per iniziare a segnalare</p>
</div>
<div class="card card-bg shadow-sm">
<div class="card-body p-4 p-md-5">
<div v-if="successMessage" class="alert alert-success" role="alert">
Registrazione completata con successo! Reindirizzamento all'accesso con OTP...
</div>
<div v-if="errorMessage" class="alert alert-danger mb-4" role="alert">
{{ errorMessage }}
</div>
<form v-if="!successMessage" @submit.prevent="handleRegister">
<h2 class="h5 text-primary font-weight-bold mb-4 border-bottom pb-2">Dati Anagrafici</h2>
<!-- FIX LAYOUT: form-group separato da col -->
<div class="row mb-4">
<div class="col-12 col-md-6 mb-4 mb-md-0">
<div class="form-group">
<input type="text" class="form-control" id="nome" v-model="form.first_name" required>
<label for="nome" :class="{ 'active': form.first_name.length > 0 }">Nome</label>
</div>
</div>
<div class="col-12 col-md-6">
<div class="form-group">
<input type="text" class="form-control" id="cognome" v-model="form.last_name" required>
<label for="cognome" :class="{ 'active': form.last_name.length > 0 }">Cognome</label>
</div>
</div>
</div>
<div class="form-group mb-4">
<input type="text" class="form-control text-uppercase" id="cf" v-model="form.fiscal_code" required maxlength="16">
<label for="cf" :class="{ 'active': form.fiscal_code.length > 0 }">Codice Fiscale</label>
<small class="form-text text-muted">Sarà utilizzato come identificativo univoco nel sistema PA.</small>
</div>
<h2 class="h5 text-primary font-weight-bold mt-5 mb-4 border-bottom pb-2">Contatti</h2>
<div class="row mb-4">
<div class="col-12">
<div class="form-group position-relative">
<input type="email" class="form-control" id="regEmail" v-model="form.email" required>
<label for="regEmail" :class="{ 'active': form.email.length > 0 }">Indirizzo Email</label>
</div>
</div>
</div>
<div class="form-group mb-5">
<input type="tel" class="form-control" id="phone" v-model="form.phone">
<label for="phone" :class="{ 'active': form.phone?.length > 0 }">Numero di telefono (Opzionale)</label>
<small class="form-text text-muted">Faciliterà il contatto da parte degli operatori comunali in caso di intervento.</small>
</div>
<!-- Privacy Checkbox -->
<div class="form-check mb-4">
<input class="form-check-input" type="checkbox" id="privacyCheck" v-model="form.privacy" required>
<label class="form-check-label small" for="privacyCheck">
Dichiaro di aver letto l'<NuxtLink to="/privacy" target="_blank">Informativa sulla Privacy</NuxtLink> e accetto il trattamento dei dati personali.
</label>
</div>
<button type="submit" class="btn btn-primary w-100 btn-lg" :disabled="isLoading">
<span v-if="isLoading" class="spinner-border spinner-border-sm me-2" role="status"></span>
Registra Profilo
</button>
<p class="small text-muted mt-3 mb-0">
Dopo la registrazione potrai accedere usando OTP via email o CIE, quando disponibile.
</p>
</form>
</div>
</div>
<div class="text-center mt-4">
<p class="small text-muted">Hai già un account? <NuxtLink to="/auth/login" class="font-weight-bold">Torna al Login</NuxtLink></p>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
</style>