Files
myprojplanet_vite/src/components/CSignUp/CSignUp.vue
Surya Paolo cfb830a0ad - fix zona provinciale
- email abilitazione circuito: invio email ad admin
- admin che abilita la fiducia cliccando sul bottone
2025-11-27 23:51:43 +01:00

829 lines
28 KiB
Vue
Executable File

<template>
<div class="signup-container">
<!-- Banner utente già loggato -->
<div
v-if="tools.isLogged() && tools.getUsername() && !collettivo && !visureg"
class="already-logged"
>
<q-card class="success-card">
<q-card-section class="text-center">
<q-icon
name="check_circle"
size="48px"
color="positive"
/>
<div class="text-h6 q-mt-md">{{ tools.getUsername() }} sei già registrato!</div>
<p class="text-body2 q-mt-sm">Hai già accesso completo alla piattaforma</p>
</q-card-section>
<q-card-actions
align="center"
class="q-pb-md"
>
<q-btn
unelevated
color="primary"
icon="home"
label="Vai alla Home"
to="/"
class="action-btn"
/>
<q-btn
outline
color="primary"
icon="visibility"
label="Mostra Registrazione"
@click="visureg = true"
class="action-btn"
/>
</q-card-actions>
</q-card>
</div>
<!-- Form di registrazione principale -->
<div
v-if="!tools.isLogged() || visureg || collettivo"
class="signup-form"
>
<!-- Header con Logo -->
<div
v-if="!(visubuttBOT && needTelegram && !collettivo)"
class="signup-header"
>
<div class="header-content">
<logo
class="signup-logo"
mystyle="width: 50px !important; height: 50px !important;"
/>
<div
v-if="!isalreadyReg && !(visubuttBOT && needTelegram)"
class="signup-title"
>
<h1 class="text-h5 text-weight-light">
{{ $t('pages.SignUp', { sitename: tools.getappname() }) }}
</h1>
</div>
</div>
</div>
<!-- Telegram Bot Registration -->
<div
v-if="visubuttBOT && needTelegram && !collettivo"
class="telegram-section"
>
<q-card class="telegram-card">
<q-card-section>
<CRegistration
:invited="signup.aportador_solidario"
:regexpire="regexpire"
@regEventEmail="regEventEmail"
:signupform="true"
/>
</q-card-section>
</q-card>
</div>
<!-- Main Registration Form -->
<div
v-else-if="!isalreadyReg || collettivo"
class="form-content"
>
<!-- Username non impostato su Telegram -->
<q-card
v-if="signup.username === 'undefined'"
class="warning-card"
>
<q-card-section class="text-center">
<q-icon
name="warning"
size="48px"
color="warning"
/>
<div class="text-h6 q-mt-md">Configura Username Telegram</div>
<p class="q-mt-sm">
Vai su <strong>BOT {{tools.sitename()}}</strong> Telegram ed imposta l'Username.
</p>
<q-btn
unelevated
color="primary"
icon="fab fa-telegram"
label="Apri BOT"
type="a"
:href="tools.getLinkBotTelegram(signup.aportador_solidario, regexpire)"
target="_blank"
class="q-mt-md"
/>
</q-card-section>
</q-card>
<!-- Carousel Form -->
<div
v-else
class="carousel-wrapper"
>
<!-- Progress Stepper -->
<div class="progress-stepper">
<div
v-for="step in parseInt(numStepTotali)"
:key="step"
class="step-item"
:class="{
active: slide === String(step),
completed: parseInt(slide) > step,
}"
>
<div class="step-circle">
<q-icon
v-if="parseInt(slide) > step"
name="check"
size="16px"
/>
<span v-else>{{ step }}</span>
</div>
<div
v-if="step < parseInt(numStepTotali)"
class="step-line"
></div>
</div>
</div>
<q-carousel
v-model="slide"
ref="carousel"
transition-prev="slide-right"
transition-next="slide-left"
animated
swipeable
class="modern-carousel"
:height="isMobile ? 'auto' : 'auto'"
>
<!-- Slide 1: Email e Invitante -->
<q-carousel-slide
name="1"
class="carousel-slide"
>
<div class="slide-content">
<div class="slide-header">
<q-icon
name="mail_outline"
size="40px"
color="primary"
/>
<h2 class="slide-title">Iniziamo!</h2>
</div>
<div class="form-fields">
<q-input
v-if="
showaportador && signup.aportador_solidario !== tools.APORTADOR_NONE
"
ref="inputAportador"
tabindex="1"
v-model="signup.aportador_solidario"
:readonly="!!ap_iniziale"
filled
class="modern-input"
@keyup.enter="
v$.aportador_solidario.$touch && !v$.aportador_solidario.$error
? $refs.inputEmail.focus()
: null
"
@blur="v$.aportador_solidario.$touch"
:error="v$.aportador_solidario.$error"
:error-message="
tools.errorMsg('aportador_solidario', v$.aportador_solidario)
"
maxlength="20"
debounce="1000"
:label="
collettivo
? t('reg.username_admin_collettivo')
: t('reg.aportador_solidario')
"
>
<template v-slot:prepend>
<q-icon
name="person"
color="primary"
/>
</template>
</q-input>
<div class="invitante-non-presente">
<q-btn
v-if="!signup.aportador_solidario"
dense
outline
color="primary"
label="Non hai l'invito?"
icon="description"
@click="noinvito = true"
class="policy-btn"
/>
</div>
<q-input
ref="inputEmail"
tabindex="2"
v-model="signup.email"
filled
class="modern-input"
@update:model-value="changeemail()"
maxlength="50"
v-on:keyup.enter="!checkifDisabled ? $refs.carousel.next() : null"
debounce="2000"
:rules="[myRuleEmail]"
:label="
collettivo ? t('reg.email_reg_collettivo') : t('reg.email_reg')
"
>
<template v-slot:prepend>
<q-icon
name="email"
color="primary"
/>
</template>
</q-input>
</div>
</div>
</q-carousel-slide>
<!-- Slide 2: Username e Nome/Cognome -->
<q-carousel-slide
name="2"
class="carousel-slide"
>
<div class="slide-content">
<div class="slide-header">
<h2 class="slide-title">Scegli il tuo Username</h2>
<p class="slide-subtitle">Come vuoi essere chiamato?</p>
</div>
<div class="form-fields">
<q-input
ref="inputUsername"
tabindex="1"
v-model="signup.username"
:readonly="
tools.getAskToVerifyReg() && !site.confpages?.enableRegMultiChoice
"
filled
class="modern-input"
@blur="v$.username.$touch"
@update:model-value="changeusername"
:error="v$.username.$error"
@keydown.space="(event) => event.preventDefault()"
@keyup.enter="
!v$.username.$error
? $refs.inputName
? $refs.inputName.focus()
: null
: null
"
maxlength="20"
debounce="500"
:error-message="
tools.errorMsg('username', v$.username) ||
(isalreadyReg ? 'L\'Username è gia stato registrato!' : '')
"
:label="
collettivo
? t('reg.username_reg_collettivo')
: tools.getConfSiteOptionEnabled(
shared_consts.ConfSite.askUSernameTelegramToTheReg
)
? t('reg.username_telegram')
: t('reg.username_reg')
"
>
<template v-slot:prepend>
<q-icon
name="person"
color="primary"
/>
</template>
</q-input>
<q-input
v-if="collettivo"
ref="inputName"
v-model="signup.name"
filled
class="modern-input"
@blur="v$.name.$touch"
:error="v$.name.$error"
maxlength="30"
debounce="1000"
v-on:keyup.enter="!checkifDisabled ? $refs.carousel.next() : null"
:error-message="tools.errorMsg('name', v$.name)"
:label="$t('reg.name_opt_collettivo')"
>
<template v-slot:prepend>
<q-icon
name="badge"
color="primary"
/>
</template>
</q-input>
<template v-else-if="show_namesurname">
<q-input
v-if="signup.name !== undefined"
ref="inputName"
tabindex="2"
v-model="signup.name"
filled
class="modern-input"
@blur="v$.name.$touch"
:error="v$.name.$error"
maxlength="30"
debounce="1000"
@keyup.enter="
$refs.inputSurname ? $refs.inputSurname.focus() : null
"
:error-message="tools.errorMsg('name', v$.name)"
:label="
tools.getConfSiteOptionEnabled(
shared_consts.ConfSite.regNameSurnameMandatory
)
? t('reg.name')
: t('reg.name_opt')
"
>
<template v-slot:prepend>
<q-icon
name="person"
color="primary"
/>
</template>
</q-input>
<q-input
v-if="signup.surname !== undefined"
ref="inputSurname"
tabindex="3"
v-model="signup.surname"
filled
class="modern-input"
:error="v$.surname.$error"
@blur="v$.surname.$touch"
maxlength="30"
debounce="1000"
v-on:keyup.enter="!checkifDisabled ? $refs.carousel.next() : null"
:error-message="tools.errorMsg('surname', v$.surname)"
:label="$t('reg.surname_opt')"
>
<template v-slot:prepend>
<q-icon
name="person_outline"
color="primary"
/>
</template>
</q-input>
</template>
</div>
</div>
</q-carousel-slide>
<!-- Slide 3: Password -->
<q-carousel-slide
name="3"
class="carousel-slide"
>
<div class="slide-content">
<div class="slide-header">
<q-icon
name="lock_outline"
size="40px"
color="primary"
/>
<h2 class="slide-title">Crea una Password</h2>
<p class="slide-subtitle">Proteggi il tuo account</p>
</div>
<div class="form-fields">
<q-input
ref="inputPassword"
tabindex="1"
v-model="signup.password"
:type="typePassword"
filled
class="modern-input"
@blur="v$.password.$touch"
:error="v$.password.$error"
:error-message="`${tools.errorMsg('password', v$.password)}`"
@keyup.enter="
!v$.password.$error ? $refs.inputPassword2.focus() : null
"
maxlength="30"
debounce="1000"
:label="$t('reg.password_reg')"
>
<template v-slot:prepend>
<q-icon
name="vpn_key"
color="primary"
/>
</template>
<template v-slot:append>
<q-btn
flat
round
dense
:icon="
typePassword === 'password' ? 'visibility_off' : 'visibility'
"
@click="showPassword"
/>
</template>
</q-input>
<q-input
ref="inputPassword2"
tabindex="2"
v-model="signup.repeatPassword"
:type="typePassword"
maxlength="30"
filled
class="modern-input"
@blur="v$.repeatPassword.$touch"
:error="v$.repeatPassword.$error"
:error-message="`${tools.errorMsg('repeatpassword', v$.repeatPassword)}`"
v-on:keyup.enter="!checkifDisabled ? $refs.carousel.next() : null"
:label="$t('reg.repeatPassword')"
>
<template v-slot:prepend>
<q-icon
name="lock"
color="primary"
/>
</template>
<template v-slot:append>
<q-btn
flat
round
dense
:icon="
typePassword === 'password' ? 'visibility_off' : 'visibility'
"
@click="showPassword"
/>
</template>
</q-input>
<div class="password-hint">
<q-icon
name="info"
size="16px"
color="grey-6"
/>
<span>Minimo 8 caratteri, includi lettere e numeri</span>
</div>
</div>
</div>
</q-carousel-slide>
<!-- Slide 4: Comune -->
<q-carousel-slide
name="4"
class="carousel-slide"
>
<div class="slide-content">
<div class="slide-header">
<q-icon
name="lock_outline"
size="40px"
color="primary"
/>
<h2 class="slide-title">Comune di Residenza</h2>
<p class="slide-subtitle">
Seleziona il tuo comune di residenza, o dove vivi abitualmente, per
connetterti con la Community Locale.
</p>
</div>
<div class="form-fields">
<!--<CMyFieldRec
:nosaveToDb="true"
table="users"
tablesel="cities"
jointable="cities"
:pickup="true"
:type="costanti.FieldType.select_by_server"
:rec="signup"
field="profile.resid_comune"
mysubkey_tosee="resid_str_comune"
fieldsel_tosee="comune"
:canEdit="true"
:canModify="true"
@savedInDb="updateComune"
></CMyFieldRec>-->
<CMyFieldDb
:nosaveToDb="true"
table="users"
tablesel="cities"
mykey="profile"
mysubkey="recCity"
label_trans="reg.resid_str_comune"
:useinput="false"
jointable="cities"
:pickup="true"
myclass="class_select"
:isInModif="true"
:type="costanti.FieldType.select_by_server"
:rec="reccomune"
@showandsave="updateComune"
/>
</div>
</div>
</q-carousel-slide>
<!-- Slide numStepTotali: Conferma e Policy -->
<q-carousel-slide
:name="numStepTotali"
class="carousel-slide"
>
<div class="slide-content final-slide">
<div class="slide-header">
<div class="flex items-center">
<q-icon
name="task_alt"
size="40px"
color="positive"
class="q-mr-md"
/>
<div>
<h2 class="slide-title">Conferma i dati!</h2>
<p class="slide-subtitle"></p>
</div>
</div>
</div>
<div class="summary-card">
<div class="summary-item">
<q-icon
name="email"
color="primary"
/>
<span>{{ signup.email }}</span>
</div>
<div class="summary-item">
<q-icon
name="person"
color="primary"
/>
<span>{{ signup.username }}</span>
</div>
<div
v-if="signup.name"
class="summary-item"
>
<q-icon
name="badge"
color="primary"
/>
<span>{{ signup.name }} {{ signup.surname }}</span>
</div>
<div
v-if="signup.profile.resid_str_comune"
class="summary-item"
>
<q-icon
name="home"
color="primary"
/>
<span>{{ signup.profile.resid_str_comune }} ({{ signup.profile.resid_province }})</span>
</div>
</div>
<div class="policy-section">
<q-btn
dense
outline
color="primary"
label="Leggi la Privacy Policy"
icon="description"
@click="showpolicy = true"
class="policy-btn"
/>
<q-checkbox
v-model="signup.terms"
color="primary"
@blur="v$.terms.$touch"
:error="v$.terms.$error"
class="terms-checkbox"
>
<template v-slot:default>
<span class="terms-text">{{ $t('reg.terms') }}</span>
</template>
</q-checkbox>
</div>
</div>
</q-carousel-slide>
</q-carousel>
<!-- Navigation Buttons - Fixed on Mobile -->
<div
class="navigation-buttons"
:class="{ mobile: isMobile }"
>
<q-btn
v-if="slide !== '1'"
flat
color="grey-7"
icon="arrow_back"
:label="isMobile ? '' : $t('dialog.indietro')"
@click="$refs.carousel.previous()"
class="nav-btn back-btn"
/>
<q-btn
v-if="slide !== numStepTotali"
unelevated
color="primary"
icon-right="arrow_forward"
:label="isMobile ? 'Avanti' : $t('dialog.avanti')"
:disabled="checkifDisabled"
@click="!checkifDisabled ? $refs.carousel.next() : null"
class="nav-btn next-btn"
/>
<q-btn
v-if="slide === numStepTotali"
ref="submitBtn"
unelevated
color="positive"
icon="check"
:label="$t('reg.submit')"
:disabled="!allowSubmit()"
@click="submitOk"
class="nav-btn submit-btn"
/>
</div>
<!-- Debug Stepper (nascosto di default) -->
<div
v-if="!signup.terms"
class="debug-stepper"
>
<q-btn-toggle
v-model="slide"
spread
glossy
toggle-color="primary"
:options="[
{ label: '1', value: '1' },
{ label: '2', value: '2' },
{ label: '3', value: '3' },
{ label: '4', value: '4' },
{ label: '5', value: '5' },
]"
/>
</div>
</div>
</div>
<!-- Utente già registrato -->
<div
v-else-if="isalreadyReg && !collettivo"
class="already-registered"
>
<q-card class="error-card">
<q-card-section class="text-center">
<q-icon
name="error_outline"
size="48px"
color="negative"
/>
<div class="text-h6 q-mt-md">Utente già registrato</div>
<p class="q-mt-sm">
L'username <strong>{{ signup.username }}</strong> è già stato registrato
</p>
</q-card-section>
</q-card>
</div>
</div>
<!-- Policy Dialog -->
<q-dialog
v-model="showpolicy"
maximized
>
<q-card>
<q-card-section class="row items-center q-pb-none">
<div class="text-h6">Privacy Policy</div>
<q-space />
<q-btn
icon="close"
flat
round
dense
v-close-popup
/>
</q-card-section>
<q-card-section>
<PagePolicy />
</q-card-section>
</q-card>
</q-dialog>
<q-dialog
v-model="noinvito"
maximized
>
<q-card class="noinvito-card">
<q-card-section class="row items-center q-pb-none noinvito-header">
<q-icon
name="info"
size="32px"
color="primary"
class="q-mr-sm"
/>
<div class="text-h6">Come entrare in {{tools.sitename()}}</div>
<q-space />
<q-btn
icon="close"
flat
round
dense
v-close-popup
/>
</q-card-section>
<q-card-section class="noinvito-content">
<!-- Spiegazione principale -->
<div class="info-box primary-info">
<q-icon
name="how_to_reg"
size="24px"
color="primary"
/>
<div>
<p class="text-weight-medium q-mb-sm">
Per accedere a {{ tools.sitename() }} hai bisogno di un invito
</p>
<p class="text-body2">L'invito può essere di due tipi:</p>
<ul class="invitation-types">
<li>
<strong>Username dell'invitante:</strong> inserisci lo username di chi
ti ha parlato di {{tools.sitename()}}
</li>
<li>
<strong>Link di registrazione:</strong> usa il link personale che ti è
stato inviato via email o messaggio
</li>
</ul>
</div>
</div>
<!-- Box informativo secondario -->
<div class="info-box secondary-info">
<q-icon
name="groups"
size="24px"
color="secondary"
/>
<div>
<p class="text-weight-medium q-mb-sm">Non conosci nessuno di {{tools.sitename()}}?</p>
<p class="text-body2">
Nessun problema! Puoi unirti alla comunità attraverso i nostri gruppi
territoriali su Telegram oppure contattarci direttamente via email. Saremo
felici di darti il benvenuto! 🌱
</p>
</div>
</div>
</q-card-section>
<!-- Footer con bottoni azione -->
<q-card-actions class="noinvito-actions">
<q-btn
unelevated
color="primary"
icon="telegram"
label="Gruppi Telegram Territoriali"
:href="
tools.getLinkGruppiTerritorialiTelegram()
? tools.getLinkGruppiTerritorialiTelegram()
: ''
"
target="_blank"
class="action-btn full-width q-mb-sm"
no-caps
/>
<q-btn
outline
color="primary"
icon="email"
label="Contattaci via Email"
:href="'mailto:' + (tools.getEmailSupport() || '')"
class="action-btn full-width"
no-caps
/>
</q-card-actions>
</q-card>
</q-dialog>
</div>
</template>
<script lang="ts" src="./CSignUp.ts"></script>
<style lang="scss" scoped>
@import './CSignUp.scss';
</style>