- fix zona provinciale

- email abilitazione circuito: invio email ad admin
- admin che abilita la fiducia cliccando sul bottone
This commit is contained in:
Surya Paolo
2025-11-27 23:51:43 +01:00
parent 1bd41058a6
commit cfb830a0ad
19 changed files with 710 additions and 79 deletions

View File

@@ -1,11 +1,11 @@
VITE_APP_ID="13"
VITE_APP_URL="https://riso.app"
VITE_MONGODB_HOST="https://api.riso.app"
VITE_LOGO_REG='riso-logo-full.png'
VITE_APP_URL="https://test.riso.app"
VITE_MONGODB_HOST="https://testapi.riso.app"
VITE_LOGO_REG="riso-logo-full.png"
VITE_PUBLICKEY_PUSH="BGXRf1TgcqocqD6J7qnRgCG7AvM2lxAoW7peb7UEzB4SxBb6DxGRdJ0UvD9ewnrB9KrSrh0-aDCODXBm7sZ1DDs"
VITE_DEBUG="0"
VITE_VUE_APP_ISTEST="0"
DIRECTORY_LOCAL=myprojplanet_vite
DIRECTORY_SERVER=/var/www/nodejs_riso_server
SERVERDIR_WEBSITE="/var/www/riso.app"
VITE_DEBUG="1"
VITE_VUE_APP_ISTEST="1"
DIRECTORY_LOCAL="myprojplanet_vite"
DIRECTORY_SERVER="/var/www/nodejs_test.riso_server"
SERVERDIR_WEBSITE="/var/www/test.riso.app"
SERVERPW_WEBSITE="pwdadmin@1AOK"

View File

@@ -23,6 +23,7 @@ const msg_website_it = {
mygood2: 'mygood2',
InvitoReg: 'Invito',
Ammetti: 'Ammetti',
AbilitaCircuito: 'Abilita Circuito',
installaApp: 'Installa App',
fundraising: 'Sostieni il Progetto',
notifs: 'Configura le Notifiche',

View File

@@ -138,8 +138,8 @@
</div>
<h3 class="card-title">App già installata! 🎉</h3>
<p class="card-description">
Ottimo! Stai già usando RISO come app installata. Puoi accedere sempre dalla
tua schermata home.
Ottimo! Stai già usando l'App installata. Puoi accedere sempre dalla
tua schermata Home.
</p>
<div class="benefits-list">

View File

@@ -15,7 +15,7 @@ import type { ISpecialField } from '@src/model'
export default defineComponent({
name: 'CMySelectCity',
emits: ['update:modelValue'],
emits: ['update:modelValue', 'changevalRec'],
props: {
modelValue: [String, Number, Object],
label: {
@@ -109,8 +109,10 @@ export default defineComponent({
}
function changevalRec(newval: any) {
if (props.db_type > 0)
if (props.db_type > 0) {
setValDb($q, props.db_field, newval, props.db_type, false, props.table, props.db_subfield, props.db_id, 0, props.db_subsubfield, props.db_specialField)
emit('changevalRec')
}
}

View File

@@ -291,7 +291,9 @@ export default defineComponent({
disabled: false,
title: 'Verifica Telegram',
description:
'Collega il tuo account Telegram per partecipare alle community RISO ed essere contattato!',
'Collega il tuo account Telegram per partecipare alle community ' +
tools.sitename() +
' ed essere contattato!',
completed: isTelegramVerified.value,
avatar: {
color: isTelegramVerified.value ? 'positive' : telegramStatus.value.color,
@@ -572,16 +574,22 @@ export default defineComponent({
$q.dialog({
title: 'Perché Telegram?',
message:
'<p><strong>RISO utilizza Telegram per connettere la sua community in tutta Italia!</strong></p>' +
'<p><strong>' +
tools.sitename() +
' utilizza Telegram per connettere la sua community in tutta Italia!</strong></p>' +
'<p style="margin-top: 12px;">' +
'✅ Contatta direttamente i membri usando il bottone "Messaggia"<br>' +
'✅ Chat provinciali e nazionali RISO attive<br>' +
'✅ Chat provinciali e nazionali' +
tools.sitename() +
' attive<br>' +
'✅ Migliaia di utenti con cui interagire<br>' +
'✅ Eventi, iniziative e aggiornamenti in tempo reale<br>' +
'✅ Gruppi ampi senza limiti WhatsApp<br>' +
'✅ Gratuito, sicuro e senza pubblicità' +
'</p>' +
'<p style="margin-top: 12px;"><em>Unisciti alla community su Telegram e scopri tutto quello che RISO ha da offrire!</em></p>',
'<p style="margin-top: 12px;"><em>Unisciti alla community su Telegram e scopri tutto quello che ' +
tools.sitename() +
' ha da offrire!</em></p>',
html: true,
options: {
type: 'radio',
@@ -638,16 +646,22 @@ export default defineComponent({
$q.dialog({
title: 'Perché Telegram?',
message:
'<p><strong>RISO utilizza Telegram per connettere la sua community in tutta Italia!</strong></p>' +
'<p><strong>' +
tools.sitename() +
' utilizza Telegram per connettere la sua community in tutta Italia!</strong></p>' +
'<p style="margin-top: 12px;">' +
'✅ Contatta direttamente i membri usando il bottone "Messaggia"<br>' +
'✅ Chat provinciali e nazionali RISO attive<br>' +
'✅ Chat provinciali e nazionali ' +
tools.sitename() +
' attive<br>' +
'✅ Migliaia di utenti con cui interagire<br>' +
'✅ Eventi, iniziative e aggiornamenti in tempo reale<br>' +
'✅ Gruppi ampi senza limiti WhatsApp<br>' +
'✅ Gratuito, sicuro e senza pubblicità' +
'</p>' +
'<p style="margin-top: 12px;"><em>Unisciti alla community su Telegram e scopri tutto quello che RISO ha da offrire!</em></p>',
'<p style="margin-top: 12px;"><em>Unisciti alla community su Telegram e scopri tutto quello che ' +
tools.sitename() +
' ha da offrire!</em></p>',
html: true,
ok: {
label: 'Chiudi',
@@ -825,6 +839,29 @@ export default defineComponent({
contact.value.profile.resid_str_comune = '';
}
// Se la provincia selezionata non esiste, mostra comunque il primo Circuito in cui si è entrati !
if (!strProv.value && contact.value.profile.mycircuits.length >= 0) {
mycircuit.value = circuitStore.getCircuitByName(
contact.value.profile.mycircuits[0].circuitname
);
}
if (!globalStore.isPresenteCardsByProv(strProv.value)) {
if (contact.value && contact.value.profile.resid_card) {
contact.value.profile.resid_card = '';
}
}
if (card.value) {
circuitsel.value = card.value;
}
// Initialize circuits based on residence
if (strProv.value) {
mylistcircuits.value = circuitStore.getCircuitsNameByProvince(strProv.value);
updateCircuito()
}
// Trova il primo step non completato e aprilo
const firstIncompleteIndex = orderedSteps.value.findIndex(
(step) => !step.completed
@@ -842,39 +879,28 @@ export default defineComponent({
watch(
() => strProv.value,
(newval: string) => {
mycircuit.value = circuitStore.getCircuitByProvinceAndCard(
strProv.value,
card.value
);
// Se la provincia selezionata non esiste, mostra comunque il primo Circuito in cui si è entrati !
if (!strProv.value && contact.value.profile.mycircuits.length >= 0) {
mycircuit.value = circuitStore.getCircuitByName(
contact.value.profile.mycircuits[0].circuitname
);
}
if (!globalStore.isPresenteCardsByProv(strProv.value)) {
if (contact.value && contact.value.profile.resid_card) {
contact.value.profile.resid_card = '';
}
}
updateCircuito()
updateContact();
}
);
watch(
() => card.value,
() => {
mycircuit.value = circuitStore.getCircuitByProvinceAndCard(
strProv.value,
card.value
);
}
() => { updateCircuito()}
);
const updateCircuito = () => {
mycircuit.value = circuitStore.getCircuitByProvinceAndCard(
strProv.value,
card.value
);
};
watch(
() => circuitsel.value,
() => {
if (circuitsel.value) {
mycircuit.value = circuitStore.getCircuitByName(circuitsel.value);
updateCircuito()
}
}
);
@@ -928,15 +954,11 @@ export default defineComponent({
if (userStore.isUserOk()) {
updateContact();
// Initialize circuits based on residence
if (contact.value?.profile.resid_province) {
mylistcircuits.value = circuitStore.getCircuitsNameByProvince(strProv.value);
mycircuit.value = circuitStore.getCircuitByProvinceAndCard(
strProv.value,
card.value
);
}
if (!mycircuit.value && !strProv.value && contact.value.profile.mycircuits.length >= 0) {
if (
!mycircuit.value &&
!strProv.value &&
contact.value.profile.mycircuits.length >= 0
) {
mycircuit.value = circuitStore.getCircuitByName(
contact.value.profile.mycircuits[0].circuitname
);
@@ -944,6 +966,14 @@ export default defineComponent({
}
});
function updateZona(newval: any) {
if (circuitsel.value) {
contact.value.profile.resid_card = circuitsel.value;
userStore.saveZona($q, t, contact.value._id, contact.value.profile.resid_card);
}
}
onBeforeUnmount(() => {
stopPolling();
});
@@ -1015,6 +1045,7 @@ export default defineComponent({
updateContact,
strProv,
isCurrentStepComune,
updateZona,
};
},
});

View File

@@ -198,7 +198,7 @@
<!-- Contenuto Circuito Locale -->
<template v-if="stepConfig.key === 'circuit'">
<div v-if="stepResidence.checkOk()">
<CMySelectCity
<!--CMySelectCity
v-if="
globalStore.isPresenteCardsByProv(contact.profile.resid_province)
"
@@ -214,7 +214,8 @@
:db_rec="contact"
:value2="contact.profile.resid_province"
class="q-mt-md"
/>
@changevalRec="updateContact"
/>-->
<p v-if="contact.profile.resid_province" class="step-description">
Entra nel circuito locale per scambiare beni e servizi con le persone
@@ -225,7 +226,7 @@
⚠️ Attenzione: Se non si sceglie il Comune di Residenza (il passaggio precedente) non è possibile poter scegliere la Provincia in cui accedere al Circuito RIS del tuo territorio.
</div>
<div v-if="mycircuit">mycircuit.value: {{ mycircuit.name }}</div>
<q-select
v-if="mylistcircuits && mylistcircuits.length > 1"
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
@@ -236,6 +237,7 @@
:options="mylistcircuits"
label="Scegli il Circuito della tua Zona"
class="modern-select q-mb-md"
@change="updateZona"
/>
<CMyCircuit

View File

@@ -99,7 +99,7 @@
/>
<div class="text-h6 q-mt-md">Configura Username Telegram</div>
<p class="q-mt-sm">
Vai su <strong>BOT RISO</strong> Telegram ed imposta l'Username.
Vai su <strong>BOT {{tools.sitename()}}</strong> Telegram ed imposta l'Username.
</p>
<q-btn
unelevated
@@ -736,7 +736,7 @@
color="primary"
class="q-mr-sm"
/>
<div class="text-h6">Come entrare in RISO</div>
<div class="text-h6">Come entrare in {{tools.sitename()}}</div>
<q-space />
<q-btn
icon="close"
@@ -757,13 +757,13 @@
/>
<div>
<p class="text-weight-medium q-mb-sm">
Per accedere a RISO hai bisogno di un invito
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 RISO
ti ha parlato di {{tools.sitename()}}
</li>
<li>
<strong>Link di registrazione:</strong> usa il link personale che ti è
@@ -781,7 +781,7 @@
color="secondary"
/>
<div>
<p class="text-weight-medium q-mb-sm">Non conosci nessuno di RISO?</p>
<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

View File

@@ -91,9 +91,9 @@
<q-expansion-item expand-separator group="somegroup" icon="fas fa-medal"
:label="$t('statusreg.lastsharedlink')" header-class="text-purple">
<div>
<div class="text-center text-bold text-h6">Unisciti a RISO</div>
<div class="text-center text-bold text-h6">Unisciti a {{tools.sitename()}}</div>
<div class="text-center">
Se ancora non sei registrato a RISO, scegli un invitante che
Se ancora non sei registrato a {{tools.sitename()}}, scegli un invitante che
conosci. Questa persona dovrà ammetterti per permetterti di
accedere alle funzionalità.
</div>
@@ -187,11 +187,11 @@
<q-card-section>
<div class="q-pa-md" style="max-width: 350px; margin: auto">
<div class="text-center text-bold text-h6">
Aiuta RISO a crescere
Aiuta {{tools.sitename()}} a crescere
</div>
<div class="text-center">
Condividi il tuo link d'invito, alimentando nuovi ingressi
alla RETE Solidale di RISO.
alla RETE Solidale di {{tools.sitename()}}.
</div>
<q-list bordered>
<TransitionGroup name="fade" appear enter-active-class="animazione fadeIn"

View File

@@ -141,7 +141,7 @@ export default defineComponent({
if (navigator.share) {
try {
await navigator.share({
title: 'Progetto RISO',
title: tools.sitename(),
text: messaggioBase,
});

View File

@@ -1427,6 +1427,7 @@ export interface IMyCircuit {
_id: string
circuitname: string
date: Date
token?: string
}
export interface ISendCoin {

View File

@@ -15,6 +15,12 @@ export interface IAmmetti {
token: string
username: string
}
export interface IAbilitaCirc {
cmd: string
token: string
username: string
groupname?: string
}
export interface ICallResult {
code?: string

View File

@@ -677,6 +677,17 @@ function getRoutesAd(site: ISites) {
infooter: false,
separator: false
},
{
active: true,
order: 1005,
path: '/abcirc/:cmd/:token/:username',
materialIcon: 'how_to_reg',
name: 'pages.AbilitaCircuito',
component: () => import('@src/views/login/abilitacircuito/abilitacircuito.vue'),
inmenu: false,
infooter: false,
separator: false
},
{
active: true,
order: 1001,

View File

@@ -564,6 +564,7 @@ const msg_it = {
ritessitura: 'RITESSITURA',
},
reg: {
title_abilita_circuito: 'Abilitazione Circuito',
title_reg_con_link: 'Registrati scegliendo quale invitante conosci:',
scelgo_l_invitante: 'Ho l\'username della persona che mi ha invitato',
nameorg: 'Nome Organizzazione',

View File

@@ -6409,12 +6409,6 @@ export const colTableCircuitComplete = [
fieldtype: costanti.FieldType.boolean,
onlyforAdmin: true,
}),
AddCol({
name: 'sendEmailAfterAskingToEnter',
label_trans: 'circuit.sendEmailAfterAskingToEnter',
fieldtype: costanti.FieldType.boolean,
onlyforAdmin: true,
}),
AddCol(ModifRec),
AddCol(DeleteRec),
AddCol(DuplicateRec),

View File

@@ -4226,9 +4226,13 @@ export const tools = {
//T_TOLTO
if (short) {
return t('ws.siteshortname');
return translate('ws.siteshortname');
}
return t('ws.sitename');
return translate('ws.sitename');
},
sitename() {
return this.getappname()
},
getproc() {
@@ -9205,13 +9209,13 @@ export const tools = {
if (field) {
const mycol = fieldsTable.getColByTable(tablesel, field);
if (mycol) {
console.log(
/*console.log(
'remote_table = ',
mycol.remote_table,
'remote_key',
mycol.remote_key
);
console.log('ROW', row);
console.log('ROW', row);*/
return tools.getValueByRemoteField(mycol, row);
}
}

View File

@@ -19,7 +19,7 @@ import type {
import { IFriends, ISettings } from '@src/model';
import { tools } from '@tools';
import translate from '@src/globalroutines/util';
import type { IAmmetti, ILinkReg, IToken } from '@model/other';
import type { IAbilitaCirc, IAmmetti, ILinkReg, IToken } from '@model/other';
import { ICallResult, IResult } from '@model/other';
import objectId from '@src/js/objectId';
@@ -1157,6 +1157,35 @@ export const useUserStore = defineStore('UserStore', {
});
},
async abilita(paramquery: IAbilitaCirc) {
const usertosend = {
cmd: paramquery.cmd,
token: paramquery.token,
username: paramquery.username,
username_action: this.my.username,
groupname: paramquery.groupname,
};
console.log(usertosend);
this.setServerCode(tools.CALLING);
return Api.SendReq('/abcirc', 'POST', usertosend)
.then((res) => {
// console.log("RITORNO 2 ");
// mutations.setServerCode(myres);
if (res.data.code === serv_constants.RIS_CODE_AMMESSO) {
console.log('ABILITATO !!');
} else {
console.log('Risultato di abilita: ', res.data.code);
}
return { code: res.data.code, msg: res.data.msg, circuitName: res.data.circuitName };
})
.catch((error) => {
this.setErrorCatch(error);
return { code: this.getServerCode, msg: error.getMsgError() };
});
},
async unsubscribe(paramquery: any) {
return Api.SendReq('/news/unsubscribe', 'POST', paramquery)
.then((res) => {
@@ -1508,7 +1537,10 @@ export const useUserStore = defineStore('UserStore', {
);
else tools.localStSetItem(toolsext.localStorage.img, '');
localStorage.setItem(toolsext.localStorage.token, this.x_auth_token);
localStorage.setItem(toolsext.localStorage.browser_random, this.getBrowserRandom());
localStorage.setItem(
toolsext.localStorage.browser_random,
this.getBrowserRandom()
);
// console.log('updateLocalStorage: salva refreshtoken', this.refreshToken)
localStorage.setItem(toolsext.localStorage.refreshToken, this.refreshToken);
localStorage.setItem(
@@ -1591,7 +1623,10 @@ export const useUserStore = defineStore('UserStore', {
tools.localStSetItem(toolsext.localStorage.name, newuser.name);
tools.localStSetItem(toolsext.localStorage.surname, newuser.surname);
localStorage.setItem(toolsext.localStorage.token, this.x_auth_token);
localStorage.setItem(toolsext.localStorage.browser_random, this.getBrowserRandom());
localStorage.setItem(
toolsext.localStorage.browser_random,
this.getBrowserRandom()
);
localStorage.setItem(
toolsext.localStorage.refreshToken,
this.refreshToken
@@ -1810,7 +1845,7 @@ export const useUserStore = defineStore('UserStore', {
tools.checkApp();
this.clearAuthData()
this.clearAuthData();
return await Api.SendReq('/users/me/token', 'DELETE', null)
.then((res) => {
@@ -2683,9 +2718,26 @@ export const useUserStore = defineStore('UserStore', {
this.browser_random = localStorage.getItem(toolsext.localStorage.browser_random);
}
if (!this.browser_random) {
this.browser_random = tools.getTokenRandom()
this.browser_random = tools.getTokenRandom();
}
return this.browser_random;
}
},
saveZona($q: any, t: any, id: any, valzona: any) {
const globalStore = useGlobalStore();
const mydatatosave = {
id,
table: 'users',
fieldsvalue: { 'profile.resid_card': valzona },
};
globalStore.saveFieldValue(mydatatosave).then((esito) => {
if (esito) {
tools.showPositiveNotif($q, t('db.recupdated'));
} else {
tools.showNegativeNotif($q, t('db.recfailed'));
}
});
},
},
});

View File

@@ -0,0 +1,323 @@
// Abilitazione Circuito - Modern Design
.circuit-activation-page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 16px;
@media (max-width: 600px) {
padding: 12px;
}
}
.circuit-container {
max-width: 600px;
margin: 0 auto;
}
// Header Section
.circuit-header {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.95) 0%, rgba(118, 75, 162, 0.95) 100%);
border-radius: 16px;
padding: 32px 24px;
margin-bottom: 24px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
text-align: center;
@media (max-width: 600px) {
padding: 24px 16px;
margin-bottom: 16px;
border-radius: 12px;
}
.header-content {
.header-icon {
margin-bottom: 16px;
animation: pulse 2s ease-in-out infinite;
@media (max-width: 600px) {
margin-bottom: 12px;
}
}
.header-title {
font-size: 1.75rem;
font-weight: 700;
color: white;
margin: 0 0 8px 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
@media (max-width: 600px) {
font-size: 1.5rem;
margin: 0 0 6px 0;
}
}
.header-subtitle {
font-size: 1rem;
color: rgba(255, 255, 255, 0.9);
margin: 0;
font-weight: 400;
@media (max-width: 600px) {
font-size: 0.9rem;
}
}
}
}
// Loading State
.loading-state {
text-align: center;
padding: 48px 24px;
@media (max-width: 600px) {
padding: 32px 16px;
}
.loading-text {
font-size: 1rem;
color: rgba(255, 255, 255, 0.9);
margin-top: 16px;
font-weight: 500;
@media (max-width: 600px) {
font-size: 0.9rem;
margin-top: 12px;
}
}
}
// Result Card
.result-card {
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
background: white;
margin-bottom: 16px;
@media (max-width: 600px) {
border-radius: 12px;
margin-bottom: 12px;
}
// Warning Section
.warning-section {
background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);
color: white;
padding: 20px;
@media (max-width: 600px) {
padding: 16px;
}
}
// Success Section
.success-section {
background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%);
color: white;
padding: 20px;
@media (max-width: 600px) {
padding: 16px;
}
}
.status-content {
display: flex;
align-items: center;
gap: 16px;
@media (max-width: 600px) {
gap: 12px;
flex-direction: column;
text-align: center;
}
.q-icon {
flex-shrink: 0;
animation: scaleIn 0.5s ease-out;
@media (max-width: 600px) {
font-size: 40px !important;
}
}
.status-text {
flex: 1;
.status-title {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 4px;
@media (max-width: 600px) {
font-size: 1.1rem;
margin-bottom: 6px;
}
}
.status-message {
font-size: 1rem;
opacity: 0.95;
@media (max-width: 600px) {
font-size: 0.9rem;
}
}
}
}
// Actions Section
.actions-section {
padding: 20px;
gap: 12px;
flex-wrap: wrap;
background: linear-gradient(to bottom, rgba(102, 126, 234, 0.03) 0%, transparent 100%);
@media (max-width: 600px) {
padding: 16px;
gap: 8px;
flex-direction: column;
}
.action-btn-primary {
padding: 8px 32px;
font-weight: 600;
text-transform: none;
letter-spacing: 0.5px;
transition: all 0.3s ease;
@media (max-width: 600px) {
width: 100%;
padding: 10px 24px;
}
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
}
.action-btn-outline {
font-weight: 600;
text-transform: none;
letter-spacing: 0.5px;
transition: all 0.3s ease;
@media (max-width: 600px) {
width: 100%;
padding: 10px 24px;
}
&:hover {
transform: translateY(-2px);
}
}
}
}
// Info Card
.info-card {
border-radius: 12px;
overflow: hidden;
background: rgba(255, 255, 255, 0.95);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
@media (max-width: 600px) {
border-radius: 10px;
}
.info-section {
padding: 16px;
@media (max-width: 600px) {
padding: 12px;
}
.info-content {
display: flex;
align-items: center;
gap: 12px;
@media (max-width: 600px) {
gap: 10px;
}
.q-icon {
flex-shrink: 0;
@media (max-width: 600px) {
font-size: 20px !important;
}
}
.info-text {
font-size: 0.9rem;
color: #555;
line-height: 1.5;
@media (max-width: 600px) {
font-size: 0.85rem;
}
}
}
}
}
// Animations
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
@keyframes scaleIn {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeOut {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-10px);
}
}
.animated {
animation-duration: 0.3s;
animation-fill-mode: both;
}
.fadeIn {
animation-name: fadeIn;
}
.fadeOut {
animation-name: fadeOut;
}

View File

@@ -0,0 +1,97 @@
import { defineComponent, onMounted, ref } from 'vue';
import { serv_constants } from '../../../store/Modules/serv_constants';
import type { IAbilitaCirc, Iabilita, ILinkReg } from '../../../model/other';
import { ICallResult } from '../../../model/other';
import { CSigninNoreg } from '../../../components/CSigninNoreg';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useGlobalStore } from '@store/globalStore';
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@store/UserStore';
import { tools } from '@tools';
export default defineComponent({
name: 'AbilitaCircuito',
components: { CSigninNoreg },
setup(props) {
const $q = useQuasar();
const route = useRoute();
const $router = useRouter();
const { t } = useI18n();
const globalStore = useGlobalStore();
const userStore = useUserStore();
const router = useRouter();
const isLoading = ref(false);
const username = ref('')
const circuitName = ref('')
const risultato = ref('---');
const riscode = ref(0);
function myrisultato() {
return risultato;
}
function giaammesso() {
return riscode.value !== serv_constants.RIS_CODE_AMMESSO;
}
function abilitaok() {
return riscode.value === serv_constants.RIS_CODE_AMMESSO;
}
function load() {
console.log('load Abilita');
isLoading.value = true
username.value = (route.params.username) ? route.params.username.toString() : '';
let param: IAbilitaCirc = { cmd: '', token: '', username: '' };
if (route.params.token) param = { cmd: route.params.cmd.toString(), token: route.params.token.toString(), username: username.value };
// console.log('idlink = ', param)
return userStore
.abilita(param)
.then((ris: any) => {
riscode.value = ris.code;
risultato.value = ris.msg;
circuitName.value = ris.circuitName
isLoading.value = false
})
.catch((err: any) => {
console.log('ERR = ' + err);
isLoading.value = false
});
}
onMounted(() => {
load();
});
const goToProfile = () => {
// Naviga al profilo del membro ammesso
router.push(`/my/${username.value}`);
};
const goHome = () => {
router.push('/');
};
return {
tools,
abilitaok,
giaammesso,
myrisultato,
t,
isLoading,
goHome,
goToProfile,
circuitName,
};
},
});

View File

@@ -0,0 +1,106 @@
<template>
<q-page class="circuit-activation-page">
<div class="circuit-container">
<!-- Header con gradient -->
<div class="circuit-header">
<div class="header-content">
<q-img
src="/images/1ris_rosso_100.png"
width="64px"
class="header-icon"
/>
<h4 class="header-title">
{{ t('reg.title_abilita_circuito') }}
</h4>
<p class="header-subtitle">
Abilitazione fiducia del <strong>{{ circuitName }}</strong>
</p>
</div>
</div>
<!-- Loading state -->
<transition
enter-active-class="animated fadeIn"
leave-active-class="animated fadeOut"
mode="out-in"
>
<div v-if="isLoading" class="loading-state">
<q-spinner-dots color="primary" size="50px" />
<p class="loading-text">
Elaborazione in corso...
</p>
</div>
<!-- Result card -->
<q-card v-else class="result-card" flat bordered>
<!-- Already activated warning -->
<q-card-section
v-if="giaammesso()"
class="warning-section"
>
<div class="status-content">
<q-icon name="warning" size="48px" />
<div class="status-text">
<div class="status-title">Attenzione</div>
<div class="status-message">{{ myrisultato() }}</div>
</div>
</div>
</q-card-section>
<!-- Success message -->
<q-card-section
v-else-if="abilitaok()"
class="success-section"
>
<div class="status-content">
<q-icon name="check_circle" size="48px" />
<div class="status-text">
<div class="status-title">Circuito Abilitato</div>
<div class="status-message">{{ myrisultato() }}</div>
</div>
</div>
</q-card-section>
<!-- Actions -->
<q-card-actions align="center" class="actions-section">
<q-btn
v-if="abilitaok()"
label="Visualizza Profilo"
color="primary"
unelevated
icon="person"
@click="goToProfile"
class="action-btn-primary"
/>
<q-btn
label="Torna alla Home"
color="primary"
outline
@click="goHome"
class="action-btn-outline"
/>
</q-card-actions>
</q-card>
</transition>
<!-- Info card -->
<q-card flat bordered class="info-card">
<q-card-section class="info-section">
<div class="info-content">
<q-icon name="info" color="primary" size="24px" />
<div class="info-text">
L'attivazione del circuito verrà notificata via email
</div>
</div>
</q-card-section>
</q-card>
</div>
</q-page>
</template>
<script lang="ts" src="./abilitacircuito.ts">
</script>
<style lang="scss" scoped>
@import './abilitacircuito.scss';
</style>