diff --git a/src/common/shared_vuejs.ts b/src/common/shared_vuejs.ts index fbef76d4..198a40a9 100755 --- a/src/common/shared_vuejs.ts +++ b/src/common/shared_vuejs.ts @@ -1442,6 +1442,7 @@ export const shared_consts = { MSG_BENVENUTO: 2010, //MsgBenvenuto MS_SHARE_LINK: 2000, MSG_BENV_REGISTRATO: 2020, + MSG_INVITE_WHATSAPP: 2040, }, TypeSend: { diff --git a/src/components/CMyElem/CMyElem.vue b/src/components/CMyElem/CMyElem.vue index c01846b8..5d074454 100755 --- a/src/components/CMyElem/CMyElem.vue +++ b/src/components/CMyElem/CMyElem.vue @@ -1202,7 +1202,10 @@ - + diff --git a/src/components/InvitaAmico/InvitaAmico.scss b/src/components/InvitaAmico/InvitaAmico.scss index 8f92b7de..33ba30d1 100644 --- a/src/components/InvitaAmico/InvitaAmico.scss +++ b/src/components/InvitaAmico/InvitaAmico.scss @@ -4,6 +4,7 @@ justify-content: center; min-height: 120vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + @media (max-width: $breakpoint-sm-max) { min-height: 100vh; } @@ -52,20 +53,17 @@ overflow: hidden; } -// Bottoni selezione metodo .selection-buttons { display: flex; - gap: 16px; + gap: 12px; flex-wrap: wrap; - - @media (max-width: $breakpoint-xs-max) { - flex-direction: column; - } + justify-content: stretch; } .selection-btn { - flex: 1; - min-height: 180px; + flex: 0 1 calc(33.33% - 8px); // Desktop: max 1/3 dello spazio, non cresce + min-width: 140px; + min-height: 140px; border-radius: 12px; border: 2px solid #e0e0e0; background: white; @@ -82,7 +80,8 @@ } @media (max-width: $breakpoint-xs-max) { - min-height: 120px; + flex: 0 1 calc(50% - 6px); // Mobile: max 50%, 2 per riga + min-height: 130px; } } @@ -91,10 +90,7 @@ flex-direction: column; align-items: center; justify-content: center; - padding: 24px; + padding: 8px; width: 100%; text-align: center; - @media (max-width: 768px) { - padding: 8px 24px; - } } \ No newline at end of file diff --git a/src/components/InvitaAmico/InvitaAmico.ts b/src/components/InvitaAmico/InvitaAmico.ts index 9421ce86..6195a1a4 100644 --- a/src/components/InvitaAmico/InvitaAmico.ts +++ b/src/components/InvitaAmico/InvitaAmico.ts @@ -4,9 +4,11 @@ import { useInvitaAmicoStore } from '../../stores/useInvitaAmicoStore'; import type { InvitoAmicoForm } from '../../types/invita-amico.types.ts'; import { tools } from 'app/src/store/Modules/tools'; import { useI18n } from 'vue-i18n'; +import { shared_consts } from '@src/common/shared_vuejs'; // Chiave localStorage -const MESSAGGIO_STORAGE_KEY = 'invita-amico-messaggio-personalizzato'; +const MESSAGGIO_STORAGE_KEY = 'invita-amico-email'; +const MESSAGGIO_STORAGE_KEY_WHATSAPP = 'invita-amico-whatsapp'; export default defineComponent({ name: 'InvitaAmico', @@ -19,9 +21,12 @@ export default defineComponent({ const { t } = useI18n(); const invitaStore = useInvitaAmicoStore(); + const rismsgShareLink = ref({ body: '', title: '' }); + // State const mostraCronologia = ref(false); - const metodoSelezionato = ref<'email' | 'telegram' | null>(null); + const metodoSelezionato = ref<'email' | 'telegram' | 'whatsapp' | null>(null); + const form = reactive({ email: '', messaggio: '', @@ -122,6 +127,72 @@ export default defineComponent({ } }; + /** + * Gestione invio WhatsApp (con Share API fallback) + */ + const onInviaWhatsApp = async () => { + const messaggioBase = form.messaggio; + + if (form.messaggio) { + localStorage.setItem(MESSAGGIO_STORAGE_KEY_WHATSAPP, form.messaggio.trim()); + } + + // Prova prima con Share API (mobile) + if (navigator.share) { + try { + await navigator.share({ + title: 'Progetto RISO', + text: messaggioBase, + }); + + $q.notify({ + type: 'positive', + message: 'Messaggio condiviso! 📤', + icon: 'share', + timeout: 2000, + }); + return; + } catch (err) { + // Utente ha annullato o errore, prova WhatsApp diretto + } + } + + // Fallback: apri WhatsApp diretto + const messaggioCodificato = encodeURIComponent(messaggioBase); + window.open(`https://wa.me/?text=${messaggioCodificato}`, '_blank'); + + $q.notify({ + type: 'positive', + message: 'WhatsApp aperto! 💬', + icon: 'whatsapp', + timeout: 2000, + }); + }; + + /** + * Copia messaggio negli appunti + */ + const copiaMessaggio = async () => { + const messaggioDaCopiare = form.messaggio; + + try { + await navigator.clipboard.writeText(messaggioDaCopiare); + $q.notify({ + type: 'positive', + message: 'Messaggio copiato! 📋', + caption: 'Ora incollalo dove preferisci', + icon: 'content_copy', + timeout: 2000, + }); + } catch (err) { + $q.notify({ + type: 'negative', + message: 'Errore nella copia', + icon: 'error', + timeout: 2000, + }); + } + }; /** * Conferma eliminazione cronologia */ @@ -168,19 +239,68 @@ export default defineComponent({ }; // Carica messaggio all'apertura - onMounted(() => { + onMounted(async () => { + // ricevi il msg + rismsgShareLink.value = await invitaStore.ottieniMsg( + shared_consts.TypeMsgTemplate.MSG_INVITE_WHATSAPP + ); const salvato = localStorage.getItem(MESSAGGIO_STORAGE_KEY); + const salvatowa = localStorage.getItem(MESSAGGIO_STORAGE_KEY_WHATSAPP); if (salvato) { - form.messaggio = salvato; + if (metodoSelezionato.value === 'whatsapp') { + form.messaggio = salvatowa; + } else { + form.messaggio = salvato; + } + } else { + if (rismsgShareLink.value) { + form.messaggio = rismsgShareLink.value.body; + } } }); // Cancella const cancellaMessaggioSalvato = () => { - localStorage.removeItem(MESSAGGIO_STORAGE_KEY); form.messaggio = ''; + if (metodoSelezionato.value === 'whatsapp') { + localStorage.removeItem(MESSAGGIO_STORAGE_KEY_WHATSAPP); + } else { + localStorage.removeItem(MESSAGGIO_STORAGE_KEY); + } + $q.notify({ type: 'info', message: 'Messaggio cancellato' }); }; + const ripristinaMessaggioStandard = () => { + $q.dialog({ + title: 'Conferma', + message: 'Vuoi ripristinare il messaggio standard?', + persistent: false, + ok: { + label: 'Sì', + color: 'primary', + }, + cancel: { + label: 'No', + flat: true, + }, + }).onOk(() => { + form.messaggio = ''; + if (metodoSelezionato.value === 'whatsapp') { + localStorage.removeItem(MESSAGGIO_STORAGE_KEY_WHATSAPP); + if (rismsgShareLink.value) { + form.messaggio = rismsgShareLink.value.body; + } + } else { + localStorage.removeItem(MESSAGGIO_STORAGE_KEY); + } + + $q.notify({ + type: 'info', + message: 'Messaggio standard ripristinato', + icon: 'restore', + }); + }); + }; // RETURN return { @@ -191,10 +311,13 @@ export default defineComponent({ form, onInviaEmail, onInviaTelegram, + onInviaWhatsApp, + copiaMessaggio, confermaEliminaCronologia, formatDate, invitaStore, cancellaMessaggioSalvato, + ripristinaMessaggioStandard, tools, }; }, diff --git a/src/components/InvitaAmico/InvitaAmico.vue b/src/components/InvitaAmico/InvitaAmico.vue index 22e8b2a9..7f795c86 100644 --- a/src/components/InvitaAmico/InvitaAmico.vue +++ b/src/components/InvitaAmico/InvitaAmico.vue @@ -20,7 +20,7 @@
-
Come vuoi invitare?
+
Come vuoi invitare?
@@ -33,13 +33,10 @@
-
Email
-
- Invia un invito diretto via email -
+
Email
@@ -52,13 +49,25 @@
-
Telegram
-
- Condividi tramite Telegram -
+
Telegram
+
+ + +
+ +
WhatsApp o altri
@@ -68,8 +77,8 @@
@@ -164,7 +173,7 @@ icon="email" color="primary" size="lg" - class="full-width q-mt-md" + class="full-width q-my-md" outline :loading="invitaStore.loading" :disable="invitaStore.loading || !form.email" @@ -185,12 +194,7 @@ />
-
- Invita tramite Telegram -
-
- Genera un messaggio da condividere su Telegram -
+
Invita tramite Telegram
+ + +
+ +
+ +
+
Invita tramite WhatsApp
+
+ + + + + + + + + + + + + +
+ - +
-->
- + { } }; + const ottieniMsg = async ( + idTemplate: number, + ): Promise => { + // Reset errori + error.value = null; + loading.value = true; + + const userStore = useUserStore(); + + try { + if (!idTemplate) { + throw new Error('idTemplate non valido'); + } + // Chiamata API + const response = await Api.SendReq('/inviti/getmsgtempl', 'POST', { idTemplate }); + + if (response.data.success) { + return response.data.rec; // { body e title } + } + + } catch (err) { + // Gestione errori + const errorMessage = err instanceof Error ? err.message : 'Errore sconosciuto'; + error.value = errorMessage; + + // Ritorna risposta di errore + return null; + } finally { + loading.value = false; + } + }; + /** * Invia invito via Telegram * (placeholder - integra con la tua logica esistente) @@ -422,6 +455,7 @@ export const useInvitaAmicoStore = defineStore('invitaAmico', () => { ottieniInvitoByToken, inviaInvitoTelegram, aggiungiACronologia, + ottieniMsg, rimuoviDaCronologia, svuotaCronologia, resetStato, diff --git a/src/types/invita-amico.types.ts b/src/types/invita-amico.types.ts index 037dae81..6879e00d 100644 --- a/src/types/invita-amico.types.ts +++ b/src/types/invita-amico.types.ts @@ -21,6 +21,10 @@ export interface InvitoGetResponse { email: string; usernameInvitante: string; } +export interface InvitoGetMsg { + title: string; + body: string; +} export interface EmailInvitoTemplate { to: string; diff --git a/src/views/user/mycircuit/mycircuit.vue b/src/views/user/mycircuit/mycircuit.vue index c563dae0..d3a2f70f 100755 --- a/src/views/user/mycircuit/mycircuit.vue +++ b/src/views/user/mycircuit/mycircuit.vue @@ -110,872 +110,866 @@ -
- -
-
-
-
-
- - - - - - - - - {{ $t('circuit.exit_circuit') }} - - +
+
+
+ + - {{ $t('circuit.delete') }} + + {{ $t('circuit.exit_circuit') }} + - - - - - -
-
-
- -
-
-
- - - -
- {{ circuit.name }} -
-
- + + + + + + {{ $t('circuit.delete') }} + + + + + +
+
+ +
+ +
+
+
+ + + +
+ {{ circuit.name }} +
+
+ + +
+ + + + + {{ t('circuit.movements') }}: + + + + + + + + + + + + +
+
+ +
+ +
+
- - - - {{ t('circuit.movements') }}: - - - - - - - - - - - - -
-
- -
- -
- -
- - - {{ $t('db.youarerefusedcircuit') }} -
-
- -
- -
- - - - - - - - {{ $t('circuit.beforeentertolocalcircuit') }} - -
-
- - - - - {{ $t('db.insertgoodorservices_to_enter_circuit') }} - -
-
- - - - - {{ $t('db.insertgoodorservices_to_enter_circuit') }} - + {{ $t('db.youarerefusedcircuit') }}
-
- + +
+ + + + + + + + + {{ $t('circuit.beforeentertolocalcircuit') }} + +
+
+ + rounded + class="bg-deep-purple text-white" + style="text-align: center" + > + - + {{ $t('db.insertgoodorservices_to_enter_circuit') }} + +
+
+ + rounded + class="bg-deep-purple text-white" + style="text-align: center" + > + + + + {{ $t('db.insertgoodorservices_to_enter_circuit') }} + +
+
+ +
+ + + +
-
-
- - - - - - - - - - - - - -
{{ t('circuit.contideigruppi') }}:
-
-
-
- - - - - + + + + + + + - + - -
- - - Chiedi di Entrare nei Circuiti: - - + +
{{ t('circuit.contideigruppi') }}:
+
+
+
+ + + + + + + + +
+ + + Chiedi di Entrare nei Circuiti: + - - - - - - + + + + + + + - - - - - -
- - - - -
- - {{ $t('circuit.richieste_title') }} - - - - - -
-
- -
- - -
{{ t('circuit.info') }}
-
- - - - -
-
+ + + + +
+ + + + + + + {{ $t('circuit.richieste_title') }} + + + + + + + + +
+ -
{{ t('circuit.descr') }}:
+
{{ t('circuit.info') }}
+ -
- +
+
- + +
{{ t('circuit.descr') }}:
+
+ -
- - {{ numUsers() }} - {{ numUsers() === 1 ? t('shared.member') : t('shared.members') }} -
-
- - - {{ - $t('circuit.chat_gruppo_telegram_circuito', { - name: circuit.name, - }) - }}: -
- - - + +
+
- -
-
- - {{ numAdmins() }} - {{ numAdmins() === 1 ? t('shared.admin') : t('shared.admins') }} -
-
- -
-
- - {{ t('circuit.symbol') }}: - - {{ tools.getSymbolByCircuit(circuit) }} - -
-
-
- + + +
+ + {{ numUsers() }} + {{ numUsers() === 1 ? t('shared.member') : t('shared.members') }} +
+
+ + + {{ + $t('circuit.chat_gruppo_telegram_circuito', { + name: circuit.name, + }) + }}: +
+ + + +
+
+
+
+ + {{ numAdmins() }} + {{ numAdmins() === 1 ? t('shared.admin') : t('shared.admins') }} +
+
+
- - + + {{ t('circuit.symbol') }}: + + {{ tools.getSymbolByCircuit(circuit) }} +
- -
-
- - {{ t('circuit.stats') }}: -
-
-
+ -->
- + + {{ t('circuit.stats') }}: +
-
- +
+
+ +
+
+ +
-
-
- - {{ t('circuit.transactionsEnabled') }}: - - {{ circuit.transactionsEnabled ? t('dialog.yes') : t('dialog.no') }} - {{}} - -
- - - + + -
-
- - - -
- {{ t('circuit.regulation') }} {{ circuit.name }}: -
-
- - - -
- -
-
- -
-
-
- - {{ - $t('shared.createddate', { - date: tools.getstrDateYY(circuit.date_created), - }) - }} -
-
- - - {{ - $t('shared.lastmodify', { - date: tools.getstrDateYY(circuit.date_updated), - }) - }} -
-
-
- - -
-
-
-
-
-
-
+ + +
+ {{ t('circuit.regulation') }} {{ circuit.name }}: +
+
+ - - - - - - - - - - - - - - - - - - - - - - -
{{ t('circuit.contocomunitario') }}:
-
- {{ $t('circuit.info_contocom') }} -
-
- - - -
- - - -
+ +
-
- - - - -
- - -
- - -
-
{{ card.title }}
- +
+ +
+
- + + {{ + $t('shared.createddate', { + date: tools.getstrDateYY(circuit.date_created), + }) + }} +
+
+ + + {{ + $t('shared.lastmodify', { + date: tools.getstrDateYY(circuit.date_updated), + }) + }} + +
+
+
+ + + + +
+
+
+
- +
+ + + + + + + + + + + + + + + + + + + + + + + +
{{ t('circuit.contocomunitario') }}:
+
+ {{ $t('circuit.info_contocom') }} +
+
+ + + +
+ + + +
+ +
+
+
+
+
+ +
+ + +
+ + +
+
{{ card.title }}
+ +
+ +
+
+
+
-
-
- - -
- -
-
{{ path }}
-
- -
+ + +
+ +
+
{{ path }}
+
+ +
-
- -
-
- -
-
+
+ +
+
+ +
+
+
+
+ +
+
diff --git a/src/views/user/mygroup/mygroup.ts b/src/views/user/mygroup/mygroup.ts index 04376ffb..1a28e7a5 100755 --- a/src/views/user/mygroup/mygroup.ts +++ b/src/views/user/mygroup/mygroup.ts @@ -62,9 +62,13 @@ export default defineComponent({ const tabevents = ref('new'); const circuitSel = ref(''); + const spinner_visible = ref(false) const showrules = ref(false); + const sendRIS = computed(() => ($route.query.sr ? $route.query.sr : '')); + const causalDest = computed(() => ($route.query.cd ? $route.query.cd : '')); + const requestToEnterCircuit = ref(false); const mycards = computed(() => { @@ -183,6 +187,9 @@ export default defineComponent({ async function mounted() { loading.value = true; + + if (sendRIS.value) spinner_visible.value = true; + await loadGroup(); searchList.value = []; @@ -299,7 +306,7 @@ export default defineComponent({ function getRegulation(reg: string) { const strreg = reg + ''; if (!reg) { - let name = CircuitSel.value + let name = CircuitSel.value; const mystringa = t('circuit.regolamento', { nomecircuito: name }); return mystringa; } else { @@ -307,6 +314,10 @@ export default defineComponent({ } } + function showed() { + spinner_visible.value = false + } + onMounted(mounted); return { @@ -364,6 +375,10 @@ export default defineComponent({ showrules, circuit, getRegulation, + spinner_visible, + sendRIS, + causalDest, + showed, }; }, }); diff --git a/src/views/user/mygroup/mygroup.vue b/src/views/user/mygroup/mygroup.vue index 3baa6224..84db2cd8 100755 --- a/src/views/user/mygroup/mygroup.vue +++ b/src/views/user/mygroup/mygroup.vue @@ -856,6 +856,12 @@
+ + + -
+