- aggiornata la grafica della Home di RISO
- Profilo Completition - Email Verificata - Invita un Amico (invio di email)
This commit is contained in:
394
src/stores/useInvitaAmicoStore.ts
Normal file
394
src/stores/useInvitaAmicoStore.ts
Normal file
@@ -0,0 +1,394 @@
|
||||
// stores/useInvitaAmicoStore.ts
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, computed } from 'vue';
|
||||
import type {
|
||||
InvitoAmicoForm,
|
||||
InvitoAmicoRequest,
|
||||
InvitoAmicoResponse,
|
||||
} from '../types/invita-amico.types.ts';
|
||||
import { useUserStore } from '../store/index.js';
|
||||
import { Api } from '../store/Api/index.js';
|
||||
|
||||
/**
|
||||
* Store Pinia per la gestione degli inviti amici
|
||||
* Gestisce lo stato, le chiamate API e la cronologia degli inviti
|
||||
*/
|
||||
export const useInvitaAmicoStore = defineStore('invitaAmico', () => {
|
||||
// ==========================================
|
||||
// STATE
|
||||
// ==========================================
|
||||
|
||||
// Loading state
|
||||
const loading = ref(false);
|
||||
|
||||
// Errori
|
||||
const error = ref<string | null>(null);
|
||||
|
||||
// Ultimo invito inviato con successo
|
||||
const ultimoInvitoInviato = ref<{
|
||||
email: string;
|
||||
data: Date;
|
||||
successo: boolean;
|
||||
} | null>(null);
|
||||
|
||||
// Cronologia inviti (ultimi 10)
|
||||
const cronologiaInviti = ref<
|
||||
Array<{
|
||||
id: string;
|
||||
email: string;
|
||||
usernameInvitante?: string;
|
||||
messaggio?: string;
|
||||
data: Date;
|
||||
successo: boolean;
|
||||
errore?: string;
|
||||
}>
|
||||
>([]);
|
||||
|
||||
// Contatori
|
||||
const contatoreInvitiRiusciti = ref(0);
|
||||
const contatoreInvitiFalliti = ref(0);
|
||||
|
||||
// ==========================================
|
||||
// GETTERS
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Verifica se ci sono inviti in cronologia
|
||||
*/
|
||||
const hasCronologia = computed(() => cronologiaInviti.value.length > 0);
|
||||
|
||||
/**
|
||||
* Numero totale di inviti
|
||||
*/
|
||||
const totaleInviti = computed(
|
||||
() => contatoreInvitiRiusciti.value + contatoreInvitiFalliti.value
|
||||
);
|
||||
|
||||
/**
|
||||
* Percentuale successo inviti
|
||||
*/
|
||||
const percentualeSuccesso = computed(() => {
|
||||
if (totaleInviti.value === 0) return 0;
|
||||
return Math.round((contatoreInvitiRiusciti.value / totaleInviti.value) * 100);
|
||||
});
|
||||
|
||||
/**
|
||||
* Ultimi 5 inviti
|
||||
*/
|
||||
const ultimi5Inviti = computed(() => cronologiaInviti.value.slice(0, 5));
|
||||
|
||||
/**
|
||||
* Verifica se un'email è già stata invitata (nelle ultime 24h)
|
||||
*/
|
||||
const isEmailGiaInvitata = computed(() => (email: string) => {
|
||||
const now = new Date();
|
||||
const oreIndietro24 = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
||||
|
||||
return cronologiaInviti.value.some(
|
||||
(invito) =>
|
||||
invito.email.toLowerCase() === email.toLowerCase() &&
|
||||
invito.data > oreIndietro24 &&
|
||||
invito.successo
|
||||
);
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// ACTIONS
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Invia un invito via email
|
||||
*/
|
||||
const inviaInvitoEmail = async (
|
||||
idapp: string,
|
||||
emailAmico: string,
|
||||
messaggioPersonalizzato?: string
|
||||
): Promise<InvitoAmicoResponse> => {
|
||||
// Reset errori
|
||||
error.value = null;
|
||||
loading.value = true;
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
let usernameInvitante = userStore.my.username;
|
||||
|
||||
try {
|
||||
// Validazione email
|
||||
if (!emailAmico || !isValidEmail(emailAmico)) {
|
||||
throw new Error('Email non valida');
|
||||
}
|
||||
|
||||
// Check se già invitata recentemente
|
||||
if (isEmailGiaInvitata.value(emailAmico)) {
|
||||
throw new Error('Questa email è già stata invitata nelle ultime 24 ore');
|
||||
}
|
||||
|
||||
// Prepara request
|
||||
const requestBody: InvitoAmicoRequest = {
|
||||
emailAmico,
|
||||
messaggioPersonalizzato,
|
||||
usernameInvitante,
|
||||
};
|
||||
|
||||
// Chiamata API
|
||||
const response = await Api.SendReq('/inviti/invia-email', 'POST', requestBody);
|
||||
|
||||
if (!response.data) {
|
||||
throw new Error("Errore durante l'invio");
|
||||
}
|
||||
|
||||
const data: InvitoAmicoResponse = response.data;
|
||||
|
||||
if (data.success) {
|
||||
// Aggiorna stato successo
|
||||
ultimoInvitoInviato.value = {
|
||||
email: emailAmico,
|
||||
data: new Date(),
|
||||
successo: true,
|
||||
};
|
||||
|
||||
// Incrementa contatore
|
||||
contatoreInvitiRiusciti.value++;
|
||||
|
||||
// Aggiungi a cronologia
|
||||
aggiungiACronologia({
|
||||
email: emailAmico,
|
||||
usernameInvitante,
|
||||
messaggio: messaggioPersonalizzato,
|
||||
successo: true,
|
||||
});
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(data.message || 'Invio fallito');
|
||||
}
|
||||
} catch (err) {
|
||||
// Gestione errori
|
||||
const errorMessage = err instanceof Error ? err.message : 'Errore sconosciuto';
|
||||
error.value = errorMessage;
|
||||
|
||||
// Incrementa contatore fallimenti
|
||||
contatoreInvitiFalliti.value++;
|
||||
|
||||
// Aggiungi a cronologia come fallito
|
||||
aggiungiACronologia({
|
||||
email: emailAmico,
|
||||
usernameInvitante,
|
||||
messaggio: messaggioPersonalizzato,
|
||||
successo: false,
|
||||
errore: errorMessage,
|
||||
});
|
||||
|
||||
// Ritorna risposta di errore
|
||||
return {
|
||||
success: false,
|
||||
message: errorMessage,
|
||||
emailInviata: false,
|
||||
};
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Invia invito via Telegram
|
||||
* (placeholder - integra con la tua logica esistente)
|
||||
*/
|
||||
const inviaInvitoTelegram = async (messaggio?: string): Promise<boolean> => {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
// TODO: Integra con la tua logica Telegram esistente
|
||||
// Esempio:
|
||||
// await telegramBotService.sendMessage(messaggio);
|
||||
|
||||
console.log('Invio via Telegram:', messaggio);
|
||||
|
||||
// Simula invio
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : 'Errore invio Telegram';
|
||||
return false;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Aggiunge un invito alla cronologia
|
||||
*/
|
||||
const aggiungiACronologia = (invito: {
|
||||
email: string;
|
||||
usernameInvitante?: string;
|
||||
messaggio?: string;
|
||||
successo: boolean;
|
||||
errore?: string;
|
||||
}) => {
|
||||
const nuovoInvito = {
|
||||
id: generateId(),
|
||||
...invito,
|
||||
data: new Date(),
|
||||
};
|
||||
|
||||
// Aggiungi in testa
|
||||
cronologiaInviti.value.unshift(nuovoInvito);
|
||||
|
||||
// Mantieni solo gli ultimi 10
|
||||
if (cronologiaInviti.value.length > 10) {
|
||||
cronologiaInviti.value = cronologiaInviti.value.slice(0, 10);
|
||||
}
|
||||
|
||||
// Salva in localStorage
|
||||
salvaInLocalStorage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancella un invito dalla cronologia
|
||||
*/
|
||||
const rimuoviDaCronologia = (id: string) => {
|
||||
cronologiaInviti.value = cronologiaInviti.value.filter((invito) => invito.id !== id);
|
||||
salvaInLocalStorage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancella tutta la cronologia
|
||||
*/
|
||||
const svuotaCronologia = () => {
|
||||
cronologiaInviti.value = [];
|
||||
salvaInLocalStorage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset dello stato
|
||||
*/
|
||||
const resetStato = () => {
|
||||
loading.value = false;
|
||||
error.value = null;
|
||||
ultimoInvitoInviato.value = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset contatori
|
||||
*/
|
||||
const resetContatori = () => {
|
||||
contatoreInvitiRiusciti.value = 0;
|
||||
contatoreInvitiFalliti.value = 0;
|
||||
localStorage.removeItem('invita-amico-contatori');
|
||||
};
|
||||
|
||||
/**
|
||||
* Carica dati da localStorage
|
||||
*/
|
||||
const caricaDaLocalStorage = () => {
|
||||
try {
|
||||
// Carica cronologia
|
||||
const cronologiaSalvata = localStorage.getItem('invita-amico-cronologia');
|
||||
if (cronologiaSalvata) {
|
||||
const parsed = JSON.parse(cronologiaSalvata);
|
||||
// Converte stringhe date in oggetti Date
|
||||
cronologiaInviti.value = parsed.map((invito: any) => ({
|
||||
...invito,
|
||||
data: new Date(invito.data),
|
||||
}));
|
||||
}
|
||||
|
||||
// Carica contatori
|
||||
const contatoriSalvati = localStorage.getItem('invita-amico-contatori');
|
||||
if (contatoriSalvati) {
|
||||
const parsed = JSON.parse(contatoriSalvati);
|
||||
contatoreInvitiRiusciti.value = parsed.riusciti || 0;
|
||||
contatoreInvitiFalliti.value = parsed.falliti || 0;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Errore caricamento localStorage:', err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Salva dati in localStorage
|
||||
*/
|
||||
const salvaInLocalStorage = () => {
|
||||
try {
|
||||
// Salva cronologia
|
||||
localStorage.setItem(
|
||||
'invita-amico-cronologia',
|
||||
JSON.stringify(cronologiaInviti.value)
|
||||
);
|
||||
|
||||
// Salva contatori
|
||||
localStorage.setItem(
|
||||
'invita-amico-contatori',
|
||||
JSON.stringify({
|
||||
riusciti: contatoreInvitiRiusciti.value,
|
||||
falliti: contatoreInvitiFalliti.value,
|
||||
})
|
||||
);
|
||||
} catch (err) {
|
||||
console.error('Errore salvataggio localStorage:', err);
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================
|
||||
// UTILITY
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Validazione email
|
||||
*/
|
||||
const isValidEmail = (email: string): boolean => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
};
|
||||
|
||||
/**
|
||||
* Genera ID univoco
|
||||
*/
|
||||
const generateId = (): string => {
|
||||
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
};
|
||||
|
||||
// ==========================================
|
||||
// INIZIALIZZAZIONE
|
||||
// ==========================================
|
||||
|
||||
// Carica dati all'avvio
|
||||
caricaDaLocalStorage();
|
||||
|
||||
// ==========================================
|
||||
// RETURN
|
||||
// ==========================================
|
||||
|
||||
return {
|
||||
// State
|
||||
loading,
|
||||
error,
|
||||
ultimoInvitoInviato,
|
||||
cronologiaInviti,
|
||||
contatoreInvitiRiusciti,
|
||||
contatoreInvitiFalliti,
|
||||
|
||||
// Getters
|
||||
hasCronologia,
|
||||
totaleInviti,
|
||||
percentualeSuccesso,
|
||||
ultimi5Inviti,
|
||||
isEmailGiaInvitata,
|
||||
|
||||
// Actions
|
||||
inviaInvitoEmail,
|
||||
inviaInvitoTelegram,
|
||||
aggiungiACronologia,
|
||||
rimuoviDaCronologia,
|
||||
svuotaCronologia,
|
||||
resetStato,
|
||||
resetContatori,
|
||||
caricaDaLocalStorage,
|
||||
salvaInLocalStorage,
|
||||
|
||||
// Utility
|
||||
isValidEmail,
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user