- aggiornata la grafica della Home di RISO

- Profilo Completition
- Email Verificata
- Invita un Amico (invio di email)
This commit is contained in:
Surya Paolo
2025-11-15 19:38:39 +01:00
parent d812c6c799
commit b8df3ea721
110 changed files with 10856 additions and 2765 deletions

View File

@@ -0,0 +1,37 @@
.invita-amico-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.invita-amico-card {
max-width: 600px;
width: 100%;
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
@media (max-width: $breakpoint-sm-max) {
margin: 0;
border-radius: 0;
}
}
.q-card__section--vert {
padding: 24px;
@media (max-width: $breakpoint-xs-max) {
padding: 16px;
}
}
// Animazioni
.q-btn {
transition: all 0.3s ease;
&:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
}

View File

@@ -0,0 +1,96 @@
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import type { InvitoAmicoForm, InvitoAmicoResponse } from './invita-amico.types';
// Composables
const $q = useQuasar();
// State
const loading = ref(false);
const form = reactive<InvitoAmicoForm>({
email: '',
messaggio: ''
});
// Emit events (se necessario per comunicare con il parent component)
const emit = defineEmits<{
(e: 'invito-inviato', data: InvitoAmicoResponse): void;
(e: 'telegram-click'): void;
}>();
// Validation
const isValidEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
// Invia invito via email
const onInviaEmail = async () => {
if (!form.email || !isValidEmail(form.email)) {
$q.notify({
type: 'negative',
message: 'Inserisci un\'email valida',
icon: 'warning'
});
return;
}
loading.value = true;
try {
const response = await fetch('/inviti/invia-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
emailAmico: form.email,
messaggioPersonalizzato: form.messaggio || undefined
})
});
const data: InvitoAmicoResponse = await response.json();
if (data.success) {
$q.notify({
type: 'positive',
message: 'Invito inviato con successo! 🎉',
caption: `L'email è stata inviata a ${form.email}`,
icon: 'check_circle',
timeout: 3000
});
// Reset form
form.email = '';
form.messaggio = '';
// Emit event
emit('invito-inviato', data);
} else {
throw new Error(data.message || 'Errore nell\'invio dell\'invito');
}
} catch (error) {
console.error('Errore invio invito:', error);
$q.notify({
type: 'negative',
message: 'Errore nell\'invio dell\'invito',
caption: error instanceof Error ? error.message : 'Riprova più tardi',
icon: 'error',
timeout: 5000
});
} finally {
loading.value = false;
}
};
// Gestione click Telegram (usa la funzione esistente del parent)
const onInviaTelegram = () => {
emit('telegram-click');
$q.notify({
type: 'info',
message: 'Apertura Telegram...',
icon: 'telegram',
timeout: 2000
});
};

View File

@@ -0,0 +1,121 @@
<template>
<q-page class="invita-amico-page">
<div class="q-pa-md">
<q-card class="invita-amico-card">
<!-- Header -->
<q-card-section class="bg-primary text-white text-center">
<div class="text-h5 q-mb-xs">
<q-icon name="person_add" size="md" class="q-mr-sm" />
Invita un Amico
</div>
<div class="text-subtitle2">
Condividi la nostra app con i tuoi amici!
</div>
</q-card-section>
<q-separator />
<!-- Form Section -->
<q-card-section>
<q-form @submit="onInviaEmail" class="q-gutter-md">
<!-- Email Input -->
<q-input
v-model="form.email"
type="email"
label="Email del tuo amico *"
hint="Inserisci l'indirizzo email della persona che vuoi invitare"
lazy-rules
:rules="[
val => !!val || 'L\'email è obbligatoria',
val => isValidEmail(val) || 'Inserisci un\'email valida'
]"
outlined
:disable="loading"
>
<template v-slot:prepend>
<q-icon name="email" />
</template>
</q-input>
<!-- Messaggio Personalizzato (opzionale) -->
<q-input
v-model="form.messaggio"
type="textarea"
label="Messaggio personalizzato (opzionale)"
hint="Aggiungi un messaggio personale al tuo invito"
outlined
rows="3"
counter
maxlength="500"
:disable="loading"
>
<template v-slot:prepend>
<q-icon name="message" />
</template>
</q-input>
<!-- Bottone Invio Email -->
<q-btn
type="submit"
label="Invia Invito via Email"
icon="send"
color="primary"
size="lg"
class="full-width"
:loading="loading"
:disable="loading || !form.email"
unelevated
/>
</q-form>
</q-card-section>
<q-separator inset />
<!-- Sezione Telegram -->
<q-card-section>
<div class="text-center q-mb-md">
<div class="text-subtitle1 text-grey-8 q-mb-xs">
Oppure invita tramite Telegram
</div>
<div class="text-caption text-grey-6">
Genera un messaggio da condividere su Telegram
</div>
</div>
<q-btn
@click="onInviaTelegram"
label="Invia via Telegram"
icon="telegram"
color="blue-9"
size="lg"
class="full-width"
outline
:disable="loading"
>
<template v-slot:default>
<q-icon name="img:/images/telegram-icon.svg" size="24px" class="q-mr-sm" />
Invia via Telegram
</template>
</q-btn>
</q-card-section>
<!-- Info Section -->
<q-card-section class="bg-blue-1">
<div class="text-center">
<q-icon name="info" color="primary" size="sm" class="q-mr-xs" />
<span class="text-caption text-grey-8">
Il tuo amico riceverà un link per registrarsi all'app
</span>
</div>
</q-card-section>
</q-card>
</div>
</q-page>
</template>
<script lang="ts" src="./InviteFriend.ts">
</script>
<style lang="scss" scoped>
@import './InviteFriend.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as InviteFriend} from './InviteFriend.vue'