395 lines
9.5 KiB
TypeScript
395 lines
9.5 KiB
TypeScript
// 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,
|
|
};
|
|
});
|