diff --git a/.env b/.env index cc664fd0..9afe33d7 100755 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ -VITE_APP_VERSION="1.2.84" +VITE_APP_VERSION="1.2.85" VITE_LANG_DEFAULT="it" VITE_PAO_APP_ID="KKPPAA5KJK435J3KSS9F9D8S9F8SD98F9SDF" -VITE_SERVICE_WORKER_FILE="sw-1.2.84.js" +VITE_SERVICE_WORKER_FILE="sw-1.2.85.js" VITE_PROJECT_ID_MAIN="5cc0a13fe5c9d156728f400a" VITE_VUE_ROUTER_MODE="history" \ No newline at end of file diff --git a/index.html b/index.html index 58c2c732..cfd16c35 100755 --- a/index.html +++ b/index.html @@ -10,7 +10,7 @@ - + diff --git a/package.json b/package.json index 3ba69a7e..49021218 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "riso", - "version": "1.2.84", + "version": "1.2.85", "productName": "Riso 💚 - Rete Italiana Scambio orizzontale", "description": "Progetto RISO (Rete Italiana Scambio orizzontale) promuove una rete di comunità locali che favoriscono scambi di beni, servizi e ospitalità. Con l'App RISO, sviluppata per facilitare il baratto, il dono e l'uso di monete alternative come i RIS, il progetto crea legami autentici basati sulla fiducia e sostenibilità. Partecipa agli scambi e costruisci una comunità più consapevole e autosufficiente.", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "APP_VERSION='1.2.84' PORT=8084 quasar dev", + "dev": "APP_VERSION='1.2.85' PORT=8084 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/comunitanuovomondo.app/package.json b/scripts/_ALL_SITES/comunitanuovomondo.app/package.json index 2f167277..c87808b9 100755 --- a/scripts/_ALL_SITES/comunitanuovomondo.app/package.json +++ b/scripts/_ALL_SITES/comunitanuovomondo.app/package.json @@ -1,6 +1,6 @@ { "name": "cnm", - "version": "1.2.84", + "version": "1.2.85", "description": "Comunita Nuovo Mondo", "productName": "ComunitaNuovoMondo", "author": "Surya", @@ -9,7 +9,7 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8083 APP_VERSION='1.2.84' quasar dev", + "dev": "PORT=8083 APP_VERSION='1.2.85' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", "buildpwa": "NODE_ENV=production quasar build -m pwa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/freeplanet.app/package.json b/scripts/_ALL_SITES/freeplanet.app/package.json index f190eb5a..16aa71e4 100755 --- a/scripts/_ALL_SITES/freeplanet.app/package.json +++ b/scripts/_ALL_SITES/freeplanet.app/package.json @@ -1,6 +1,6 @@ { "name": "freeplanet", - "version": "1.2.84", + "version": "1.2.85", "description": "freeplanet", "productName": "freeplanet", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8087 APP_VERSION='1.2.84' quasar dev", + "dev": "PORT=8087 APP_VERSION='1.2.85' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8097 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8087 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8097 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8087 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/germogliamo.app/package.json b/scripts/_ALL_SITES/germogliamo.app/package.json index 3ba69a7e..49021218 100755 --- a/scripts/_ALL_SITES/germogliamo.app/package.json +++ b/scripts/_ALL_SITES/germogliamo.app/package.json @@ -1,6 +1,6 @@ { "name": "riso", - "version": "1.2.84", + "version": "1.2.85", "productName": "Riso 💚 - Rete Italiana Scambio orizzontale", "description": "Progetto RISO (Rete Italiana Scambio orizzontale) promuove una rete di comunità locali che favoriscono scambi di beni, servizi e ospitalità. Con l'App RISO, sviluppata per facilitare il baratto, il dono e l'uso di monete alternative come i RIS, il progetto crea legami autentici basati sulla fiducia e sostenibilità. Partecipa agli scambi e costruisci una comunità più consapevole e autosufficiente.", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "APP_VERSION='1.2.84' PORT=8084 quasar dev", + "dev": "APP_VERSION='1.2.85' PORT=8084 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/gruppomacro.app/package.json b/scripts/_ALL_SITES/gruppomacro.app/package.json index 5b8ca98d..faf4ab12 100755 --- a/scripts/_ALL_SITES/gruppomacro.app/package.json +++ b/scripts/_ALL_SITES/gruppomacro.app/package.json @@ -1,6 +1,6 @@ { "name": "gruppomacro", - "version": "1.2.84", + "version": "1.2.85", "productName": "Gruppo Macro", "description": "Il Gruppo Editoriale Macro, attivo dal 1987, è leader europeo nella pubblicazione di libri per il benessere e la consapevolezza. Con oltre 1.500 titoli, promuove una visione armonica del mondo, offrendo opere di autori internazionali e italiani come Gregg Braden, Bruce Lipton, Joe Dispenza, Louise Hay, Eckhart Tolle e molti altri. Scopri un'editoria che abbraccia il corpo, la mente, lo spirito e l'ecologia.", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8089 APP_VERSION='1.2.84' quasar dev", + "dev": "PORT=8089 APP_VERSION='1.2.85' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.84' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.85' quasar build -m spa", "lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\"", "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8089 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/nuovomondo.app/package.json b/scripts/_ALL_SITES/nuovomondo.app/package.json index dee93c88..7d0351a4 100755 --- a/scripts/_ALL_SITES/nuovomondo.app/package.json +++ b/scripts/_ALL_SITES/nuovomondo.app/package.json @@ -1,6 +1,6 @@ { "name": "nuovomondo", - "version": "1.2.84", + "version": "1.2.85", "description": "Nuovo Mondo", "productName": "Nuovo Mondo", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "APP_VERSION='1.2.84' PORT=8083 quasar dev", + "dev": "APP_VERSION='1.2.85' PORT=8083 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8083 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json b/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json index 35ccb755..a151fdfe 100755 --- a/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json +++ b/scripts/_ALL_SITES/nutriben-naturopatia.it/package.json @@ -1,6 +1,6 @@ { "name": "nutriben", - "version": "1.2.84", + "version": "1.2.85", "description": "Nutriben", "productName": "Nutriben", "author": "Surya", @@ -9,20 +9,20 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8093 APP_VERSION='1.2.84' quasar dev", + "dev": "PORT=8093 APP_VERSION='1.2.85' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", - "buildspa": "APP_VERSION='1.2.84' quasar build -m spa", + "buildspa": "APP_VERSION='1.2.85' quasar build -m spa", "lint": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\"", "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8099 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8093 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/piuchebuono.app/package.json b/scripts/_ALL_SITES/piuchebuono.app/package.json index b1fddadb..08ddaf68 100755 --- a/scripts/_ALL_SITES/piuchebuono.app/package.json +++ b/scripts/_ALL_SITES/piuchebuono.app/package.json @@ -1,6 +1,6 @@ { "name": "piuchebuono", - "version": "1.2.84", + "version": "1.2.85", "description": "PiuCheBuono", "productName": "PiuCheBuono", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "PORT=8085 APP_VERSION='1.2.84' quasar dev", + "dev": "PORT=8085 APP_VERSION='1.2.85' quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/scripts/_ALL_SITES/riso.app/package.json b/scripts/_ALL_SITES/riso.app/package.json index 3ba69a7e..49021218 100755 --- a/scripts/_ALL_SITES/riso.app/package.json +++ b/scripts/_ALL_SITES/riso.app/package.json @@ -1,6 +1,6 @@ { "name": "riso", - "version": "1.2.84", + "version": "1.2.85", "productName": "Riso 💚 - Rete Italiana Scambio orizzontale", "description": "Progetto RISO (Rete Italiana Scambio orizzontale) promuove una rete di comunità locali che favoriscono scambi di beni, servizi e ospitalità. Con l'App RISO, sviluppata per facilitare il baratto, il dono e l'uso di monete alternative come i RIS, il progetto crea legami autentici basati sulla fiducia e sostenibilità. Partecipa agli scambi e costruisci una comunità più consapevole e autosufficiente.", "author": "Surya", @@ -9,11 +9,11 @@ "license": "MIT", "type": "module", "scripts": { - "dev": "APP_VERSION='1.2.84' PORT=8084 quasar dev", + "dev": "APP_VERSION='1.2.85' PORT=8084 quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev", "build": "quasar build", - "buildpwa": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", - "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.84' quasar build -m pwa", + "buildpwa": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", + "buildpwatest": "NODE_ENV=production APP_VERSION='1.2.85' quasar build -m pwa", "type-check": "vue-tsc --noEmit", "type-check:watch": "vue-tsc --noEmit --watch", "buildspa": "quasar build -m spa", @@ -21,8 +21,8 @@ "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfileNoJS": "eslint --ext .ts,.vue --ignore-path .gitignore ./ > file.out.txt", "fix": "eslint -c ./eslint.config.js \"./src*/**/*.{ts,js,cjs,mjs,vue}\" --ignore-pattern .gitignore ./ --fix > file.out.txt", - "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.84' quasar dev -m pwa", - "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.84' quasar dev", + "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.85' quasar dev -m pwa", + "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.85' quasar dev", "debug": "quasar dev --mode debug", "test": "echo \"No test specified\" && exit 0", "generate-sw": "workbox generateSW workbox-config.js", diff --git a/src-pwa/custom-service-worker.js b/src-pwa/custom-service-worker.js index 3a21afc2..7276e87a 100755 --- a/src-pwa/custom-service-worker.js +++ b/src-pwa/custom-service-worker.js @@ -3,7 +3,7 @@ /* global workbox */ /* global cfgenv */ -const VITE_APP_VERSION = '1.2.84'; +const VITE_APP_VERSION = '1.2.85'; // Costanti di configurazione const DYNAMIC_CACHE = 'dynamic-cache-v2'; diff --git a/src/common/shared_vuejs.ts b/src/common/shared_vuejs.ts index 4af772ca..e73f269d 100755 --- a/src/common/shared_vuejs.ts +++ b/src/common/shared_vuejs.ts @@ -2447,6 +2447,8 @@ export const shared_consts = { 'profile.qualifica': 1, 'profile.note': 1, 'profile.da_contattare': 1, + 'profile.resid_comune': 1, + 'profile.resid_str_comune': 1, 'profile.resid_province': 1, 'profile.resid_card': 1, 'profile.username_telegram': 1, diff --git a/src/components/CFindUsers/CFindUsers.ts b/src/components/CFindUsers/CFindUsers.ts index d117c21b..6d3c78d1 100755 --- a/src/components/CFindUsers/CFindUsers.ts +++ b/src/components/CFindUsers/CFindUsers.ts @@ -220,6 +220,8 @@ export default defineComponent({ 'profile.qualifica': 1, 'profile.note': 1, 'profile.da_contattare': 1, + 'profile.resid_str_comune': 1, + 'profile.resid_comune': 1, 'profile.resid_province': 1, 'mycities.reg': 1, perm: 1, diff --git a/src/components/CMyCardService/CMyCardService.scss b/src/components/CMyCardService/CMyCardService.scss index 5d400273..dd14ed01 100644 --- a/src/components/CMyCardService/CMyCardService.scss +++ b/src/components/CMyCardService/CMyCardService.scss @@ -1,5 +1,5 @@ // ======================================== -// VARIABILI MODERNE (compatibili con Quasar) +// VARIABILI MODERNE CON GRADIENTI // ======================================== $primary-color: #1976d2; $primary-light: #42a5f5; @@ -27,13 +27,26 @@ $mobile-breakpoint: 768px; $small-breakpoint: 600px; // ======================================== -// PROFILE (già esistente - solo ottimizzato) +// GRADIENTI MODERNI +// ======================================== +$gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +$gradient-secondary: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); +$gradient-info: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); +$gradient-positive: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); +$gradient-card-light: linear-gradient(135deg, #fdfbfb 0%, #ebedee 100%); +$gradient-card-white: linear-gradient(to bottom, #ffffff 0%, #f8f9fa 100%); +$gradient-hover: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%); + +// ======================================== +// PROFILE (con gradiente) // ======================================== .profile { width: 100%; margin: 0 auto; max-width: 450px; padding: 6px; + background: $gradient-card-white; + border-radius: $border-radius-sm; @media (max-width: $mobile-breakpoint) { padding: 4px; @@ -41,7 +54,7 @@ $small-breakpoint: 600px; } // ======================================== -// MY ROW (già esistente - ottimizzato) +// MY ROW // ======================================== .myrow { display: flex; @@ -54,20 +67,38 @@ $small-breakpoint: 600px; } // ======================================== -// QUALIFICA (già esistente - modernizzato) +// QUALIFICA (con gradiente) // ======================================== .qualifica { - border: 2px solid $primary-light; + background: linear-gradient(135deg, rgba(38, 166, 154, 0.1) 0%, rgba(38, 166, 154, 0.05) 100%); + border: 2px solid rgba(38, 166, 154, 0.3); border-radius: $border-radius-sm; padding: 6px 10px; - background: rgba(65, 152, 239, 0.05); transition: all $transition-speed ease; font-weight: 500; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); + transition: left 0.5s ease; + } &:hover { - background: rgba(65, 152, 239, 0.1); - border-color: $primary-color; - transform: translateX(2px); + background: linear-gradient(135deg, rgba(38, 166, 154, 0.15) 0%, rgba(38, 166, 154, 0.08) 100%); + border-color: $secondary-color; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(38, 166, 154, 0.2); + + &::before { + left: 100%; + } } @media (max-width: $mobile-breakpoint) { @@ -76,15 +107,33 @@ $small-breakpoint: 600px; } // ======================================== -// TEXT BACHECA (già esistente - modernizzato) +// TEXT BACHECA (con gradiente) // ======================================== .text-bacheca { margin: 8px 0; - border: 2px solid $primary-light; + background: linear-gradient(135deg, rgba(79, 172, 254, 0.08) 0%, rgba(0, 242, 254, 0.08) 100%); + border: 2px solid rgba(79, 172, 254, 0.3); border-radius: $border-radius-sm; padding: 10px 12px; - background: rgba(65, 152, 239, 0.03); line-height: 1.6; + position: relative; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + top: -50%; + right: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); + opacity: 0; + transition: opacity 0.3s ease; + } + + &:hover::after { + opacity: 1; + } @media (max-width: $mobile-breakpoint) { margin: 6px 0; @@ -93,16 +142,17 @@ $small-breakpoint: 600px; } // ======================================== -// NOTE BACHECA (già esistente - modernizzato) +// NOTE BACHECA (con gradiente warning) // ======================================== .note-bacheca { - border: 2px solid $warning-color; + background: linear-gradient(135deg, rgba(242, 192, 55, 0.12) 0%, rgba(242, 192, 55, 0.06) 100%); + border: 2px solid rgba(242, 192, 55, 0.4); + border-left: 4px solid $warning-color; border-radius: $border-radius-sm; padding: 10px 12px; - background: rgba(242, 192, 55, 0.08); - border-left: 4px solid $warning-color; line-height: 1.6; margin: 8px 0; + box-shadow: 0 2px 8px rgba(242, 192, 55, 0.15); @media (max-width: $mobile-breakpoint) { padding: 8px 10px; @@ -111,7 +161,7 @@ $small-breakpoint: 600px; } // ======================================== -// IMG (già esistente - ottimizzato) +// IMG // ======================================== .img { margin: 0 auto; @@ -128,7 +178,7 @@ $small-breakpoint: 600px; } // ======================================== -// CALENDAR STYLES (già esistente - compatto) +// CALENDAR STYLES // ======================================== .cal { color: #1a1a1a; @@ -210,13 +260,15 @@ $small-breakpoint: 600px; } // ======================================== -// BADGE FAV/BOOK (già esistente - ottimizzato) +// BADGE FAV/BOOK (con gradiente) // ======================================== .badge-favbook { font-weight: 600; padding: 3px 8px; border-radius: 6px; font-size: 0.8125rem; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.7) 100%); + backdrop-filter: blur(4px); @media (max-width: $mobile-breakpoint) { padding: 2px 6px; @@ -225,7 +277,7 @@ $small-breakpoint: 600px; } // ======================================== -// BUTTONS FAV (già esistente - compatto) +// BUTTONS FAV // ======================================== .buttonsfav { display: flex; @@ -251,7 +303,7 @@ $small-breakpoint: 600px; } // ======================================== -// CONTAINER BUTTON (già esistente - ottimizzato) +// CONTAINER BUTTON // ======================================== .container_butt { display: flex; @@ -267,7 +319,7 @@ $small-breakpoint: 600px; } // ======================================== -// ANIMATIONS (già esistente) +// ANIMATIONS // ======================================== .expand-fade-enter-active, .expand-fade-leave-active { @@ -286,7 +338,7 @@ $small-breakpoint: 600px; } // ======================================== -// DIALOG POSITIONING (già esistente - ottimizzato) +// DIALOG POSITIONING // ======================================== .well-positioned-dialog { width: 50vw; @@ -312,37 +364,75 @@ $small-breakpoint: 600px; } // ======================================== -// MODERN CARD (nuovo - sostituisce my-card) +// MODERN CARD (con gradienti bellissimi!) // ======================================== .modern-card { + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 50%, #ffffff 100%); + border: 1px solid rgba(0, 0, 0, 0.06); border-radius: $border-radius; - box-shadow: $shadow-md; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); margin: 8px 0; transition: all $transition-speed ease; + position: relative; + overflow: hidden; + + // Effetto luce che scorre + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); + transition: left 0.6s ease; + } @media (max-width: $mobile-breakpoint) { margin: 6px 0; } &:hover { - box-shadow: $shadow-lg; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); + transform: translateY(-4px); + background: linear-gradient(135deg, #ffffff 0%, #f0f4f8 50%, #ffffff 100%); + border-color: rgba(25, 118, 210, 0.2); + + &::before { + left: 100%; + } } + // Variante con bordo colorato a sinistra - User &.clBorderUser { border-left: 4px solid $primary-color; + background: linear-gradient(to right, rgba(25, 118, 210, 0.03), #ffffff 10%, #f8f9fa 50%, #ffffff 100%); + + &:hover { + background: linear-gradient(to right, rgba(25, 118, 210, 0.06), #ffffff 10%, #f0f4f8 50%, #ffffff 100%); + box-shadow: 0 8px 24px rgba(25, 118, 210, 0.15); + } } + // Variante con bordo colorato a sinistra - Service &.clBorderService { border-left: 4px solid $secondary-color; + background: linear-gradient(to right, rgba(38, 166, 154, 0.03), #ffffff 10%, #f8f9fa 50%, #ffffff 100%); + + &:hover { + background: linear-gradient(to right, rgba(38, 166, 154, 0.06), #ffffff 10%, #f0f4f8 50%, #ffffff 100%); + box-shadow: 0 8px 24px rgba(38, 166, 154, 0.15); + } } } // ======================================== -// MODERN DIALOG (nuovo - sostituisce visudialog) +// MODERN DIALOG (con gradiente) // ======================================== .modern-dialog { max-height: 80vh; overflow-y: auto; + background: linear-gradient(to bottom, #ffffff 0%, #f8f9fa 100%); @media (max-width: $mobile-breakpoint) { max-height: 90vh; @@ -351,6 +441,7 @@ $small-breakpoint: 600px; &.no-padding { :deep(.q-card-section) { padding: 12px; + background: transparent; @media (max-width: $mobile-breakpoint) { padding: 10px; @@ -358,32 +449,35 @@ $small-breakpoint: 600px; } } - // Scrollbar styling + // Scrollbar styling con gradiente &::-webkit-scrollbar { width: 6px; } &::-webkit-scrollbar-track { - background: #f1f1f1; + background: linear-gradient(to bottom, #f1f1f1, #e0e0e0); border-radius: 10px; } &::-webkit-scrollbar-thumb { - background: $primary-light; + background: linear-gradient(135deg, $primary-light, $primary-color); border-radius: 10px; + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); &:hover { - background: $primary-color; + background: linear-gradient(135deg, $primary-color, $primary-dark); } } } // ======================================== -// TOOLBAR (già esistente - compatto) +// TOOLBAR (con gradiente) // ======================================== .q-toolbar { min-height: 48px; padding: 8px 12px; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.95), rgba(248, 249, 250, 0.95)); + backdrop-filter: blur(10px); @media (max-width: $mobile-breakpoint) { min-height: 44px; @@ -398,14 +492,28 @@ $small-breakpoint: 600px; font-size: 1rem; } } + + &.bg-primary { + background: $gradient-primary !important; + } + + &.bg-white { + background: linear-gradient(135deg, #ffffff, #f8f9fa) !important; + } } // ======================================== -// MENU STYLES (già esistente - modernizzato) +// MENU STYLES (con gradienti) // ======================================== .q-menu { + background: linear-gradient(to bottom, #ffffff, #f8f9fa); + backdrop-filter: blur(10px); + border: 1px solid rgba(0, 0, 0, 0.08); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + .q-list { padding: 6px; + background: transparent; @media (max-width: $mobile-breakpoint) { padding: 4px; @@ -417,10 +525,12 @@ $small-breakpoint: 600px; min-height: 40px; border-radius: $border-radius-sm; transition: all $transition-speed ease; + background: transparent; &:hover { - background: rgba(25, 118, 210, 0.08); - transform: translateX(2px); + background: linear-gradient(135deg, rgba(25, 118, 210, 0.08), rgba(25, 118, 210, 0.04)); + transform: translateX(4px); + box-shadow: 0 2px 8px rgba(25, 118, 210, 0.1); } @media (max-width: $mobile-breakpoint) { @@ -439,7 +549,7 @@ $small-breakpoint: 600px; } // ======================================== -// ABSOLUTE POSITIONING (già esistente - ottimizzato) +// ABSOLUTE POSITIONING // ======================================== .absolute-top-right { position: absolute; @@ -451,14 +561,27 @@ $small-breakpoint: 600px; top: 8px; right: 8px; } + + .q-btn { + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(8px); + transition: all $transition-speed ease; + + &:hover { + background: rgba(0, 0, 0, 0.7); + transform: scale(1.1) rotate(90deg); + } + } } // ======================================== -// INSET SHADOW (già esistente - ottimizzato) +// INSET SHADOW (con gradiente) // ======================================== .inset-shadow { + background: linear-gradient(to bottom, #fafafa, #f5f5f5); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.06); padding: 10px; + border-radius: $border-radius-sm; @media (max-width: $mobile-breakpoint) { padding: 8px; @@ -466,12 +589,14 @@ $small-breakpoint: 600px; } // ======================================== -// DIALOG CARD (già esistente - ottimizzato) +// DIALOG CARD (con gradiente) // ======================================== .dialog_card { max-width: 500px; width: 100%; border-radius: $border-radius; + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); @media (max-width: $mobile-breakpoint) { max-width: 100%; @@ -480,10 +605,22 @@ $small-breakpoint: 600px; } // ======================================== -// CLASSI ESISTENTI MANTENUTE +// CLASSI ESISTENTI CON GRADIENTI // ======================================== .clBorderService { border: 1px solid rgba($secondary-color, 0.3); + position: relative; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 4px; + height: 100%; + background: linear-gradient(to bottom, $secondary-color, rgba($secondary-color, 0.9)); + } &:hover { border-color: $secondary-color; @@ -492,6 +629,18 @@ $small-breakpoint: 600px; .clBorderUser { border: 1px solid rgba($primary-color, 0.3); + position: relative; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 4px; + height: 100%; + background: linear-gradient(to bottom, $primary-color, color-contrast($primary-color, -10%)); + } &:hover { border-color: $primary-color; @@ -501,6 +650,8 @@ $small-breakpoint: 600px; .clDescrEstesa { padding: 10px; line-height: 1.6; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.5), rgba(248, 249, 250, 0.5)); + border-radius: $border-radius-sm; @media (max-width: $mobile-breakpoint) { padding: 8px; @@ -509,7 +660,10 @@ $small-breakpoint: 600px; .accom_maxosp { font-weight: 600; - color: $primary-color; + background: linear-gradient(135deg, $primary-color, color-lighten($primary-color, 15%)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; margin-right: 4px; } @@ -518,6 +672,7 @@ $small-breakpoint: 600px; // ======================================== .q-item { padding: 10px 12px; + transition: all $transition-speed ease; @media (max-width: $mobile-breakpoint) { padding: 8px 10px; @@ -530,27 +685,59 @@ $small-breakpoint: 600px; .q-item__label { line-height: 1.5; } -} -// ======================================== -// Q-CHIP OTTIMIZZAZIONI -// ======================================== -.q-chip { - margin: 2px 4px 2px 0; - - &.glossy { - background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%); + &:hover { + background: linear-gradient(90deg, rgba(25, 118, 210, 0.03), transparent); } } // ======================================== -// Q-BTN OTTIMIZZAZIONI +// Q-CHIP OTTIMIZZAZIONI (con gradienti) +// ======================================== +.q-chip { + margin: 2px 4px 2px 0; + transition: all $transition-speed ease; + + &.glossy { + background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.05) 100%); + backdrop-filter: blur(4px); + } + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); + } +} + +// ======================================== +// Q-BTN OTTIMIZZAZIONI (con effetti) // ======================================== .q-btn { transition: all $transition-speed ease; - + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + border-radius: 50%; + background: rgba(255, 255, 255, 0.3); + transform: translate(-50%, -50%); + transition: width 0.6s ease, height 0.6s ease; + } + &:hover:not(.q-btn--disable) { - transform: scale(1.02); + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + + &::before { + width: 300px; + height: 300px; + } } &.q-btn--round { @@ -558,10 +745,21 @@ $small-breakpoint: 600px; transform: scale(1.1); } } + + &.q-btn--unelevated { + background: linear-gradient(135deg, currentColor, color-darken($primary-color, 5%)); + } } // ======================================== -// RESPONSIVE UTILITIES (già esistente - ottimizzato) +// Q-CARD SECTION (con gradiente sottile) +// ======================================== +.q-card-section { + background: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.01) 100%); +} + +// ======================================== +// RESPONSIVE UTILITIES // ======================================== @media (max-width: $mobile-breakpoint) { .q-pa-xs { @@ -611,8 +809,17 @@ $small-breakpoint: 600px; } } +@keyframes shimmer { + 0% { + background-position: -1000px 0; + } + 100% { + background-position: 1000px 0; + } +} + .modern-card { - animation: fadeIn 0.3s ease-out; + animation: fadeIn 0.4s ease-out; } // ======================================== @@ -620,8 +827,27 @@ $small-breakpoint: 600px; // ======================================== .q-separator { margin: 8px 0; + background: linear-gradient(to right, transparent, rgba(0, 0, 0, 0.1), transparent); @media (max-width: $mobile-breakpoint) { margin: 6px 0; } +} + +// ======================================== +// EXTRA: Effetti particolari +// ======================================== + +// Effetto glassmorphism +.glass-effect { + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); +} + +// Card evento "attending" +.is-attending { + border-left: 4px solid $positive-color; + background: linear-gradient(to right, rgba(33, 186, 69, 0.08), transparent 20%); + box-shadow: 0 2px 12px rgba(33, 186, 69, 0.1); } \ No newline at end of file diff --git a/src/components/CMyCardService/CMyCardService.ts b/src/components/CMyCardService/CMyCardService.ts index 4289313a..f09284fe 100644 --- a/src/components/CMyCardService/CMyCardService.ts +++ b/src/components/CMyCardService/CMyCardService.ts @@ -565,6 +565,8 @@ export default defineComponent({ 'profile.img': 1, 'profile.mygroups': 1, 'profile.qualifica': 1, + 'profile.resid_str_comune': 1, + 'profile.resid_comune': 1, 'profile.resid_province': 1, 'profile.resid_card': 1, 'mycities.reg': 1, diff --git a/src/components/CMyChipList/CMyChipList.scss b/src/components/CMyChipList/CMyChipList.scss index 32a61908..02fc51a0 100755 --- a/src/components/CMyChipList/CMyChipList.scss +++ b/src/components/CMyChipList/CMyChipList.scss @@ -1,6 +1,282 @@ -.clchip{ - display: flex; - justify-content: left; - //flex: 1; - //flex-direction: column; +// ======================================== +// CMyChipList - SCSS Moderno con Gradienti +// ======================================== + +$primary-color: #1976d2; +$primary-light: #42a5f5; +$secondary-color: #26a69a; +$positive-color: #21ba45; +$negative-color: #c10015; +$info-color: #31ccec; +$warning-color: #f2c037; + +@use 'sass:color'; + +$border-radius-sm: 8px; +$border-radius: 10px; +$transition-speed: 0.3s; +$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08); +$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1); + +$mobile-breakpoint: 768px; + +// ======================================== +// CONTAINER +// ======================================== +.q-mb-sm { + // Padding e margini ottimizzati + @media (max-width: $mobile-breakpoint) { + margin-bottom: 10px !important; + } } + +// ======================================== +// LABEL/TITLE (con gradiente sottile) +// ======================================== +.text-subtitle2 { + &.text-primary { + background: linear-gradient(135deg, $primary-color, lighten($primary-color, 15%)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-weight: 600; + letter-spacing: 0.02em; + margin-bottom: 8px; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.875rem; + margin-bottom: 6px; + } + } +} + +// ======================================== +// CHIPS CONTAINER +// ======================================== +.q-gutter-sm { + &.row.wrap { + gap: 8px; + + @media (max-width: $mobile-breakpoint) { + gap: 6px; + } + } +} + +// ======================================== +// SINGLE CHIP (con gradienti bellissimi!) +// ======================================== +.q-chip { + position: relative; + overflow: hidden; + transition: all $transition-speed cubic-bezier(0.4, 0, 0.2, 1); + border-radius: $border-radius !important; + font-weight: 500; + letter-spacing: 0.01em; + + // Effetto luce scorrevole + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); + transition: left 0.5s ease; + } + + // Shadow con gradiente + &.shadow-1 { + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12); + } + + // Padding compatto + &.q-px-sm { + padding-left: 10px !important; + padding-right: 10px !important; + + @media (max-width: $mobile-breakpoint) { + padding-left: 8px !important; + padding-right: 8px !important; + font-size: 0.8125rem !important; + } + } + + // Hover effect + &:hover { + transform: translateY(-2px) scale(1.02); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); + + &::before { + left: 100%; + } + } + + // Colori con gradienti + &[class*='bg-primary'], + &[class*='bg-blue'] { + background: linear-gradient(135deg, $primary-color, lighten($primary-color, 10%)) !important; + box-shadow: 0 2px 8px rgba($primary-color, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust($primary-color, $lightness: -5%), $primary-color) !important; + box-shadow: 0 4px 12px rgba($primary-color, 0.4); + } + } + + &[class*='bg-secondary'], + &[class*='bg-teal'] { + background: linear-gradient(135deg, $secondary-color, lighten($secondary-color, 10%)) !important; + box-shadow: 0 2px 8px rgba($secondary-color, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust($secondary-color, $lightness: -5%), $secondary-color) !important; + box-shadow: 0 4px 12px rgba($secondary-color, 0.4); + } + } + + &[class*='bg-positive'], + &[class*='bg-green'] { + background: linear-gradient(135deg, $positive-color, lighten($positive-color, 10%)) !important; + box-shadow: 0 2px 8px rgba($positive-color, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust($positive-color, $lightness: -5%), $positive-color) !important; + box-shadow: 0 4px 12px rgba($positive-color, 0.4); + } + } + + &[class*='bg-negative'], + &[class*='bg-red'] { + background: linear-gradient(135deg, $negative-color, color.adjust($negative-color, $lightness: 10%)) !important; + box-shadow: 0 2px 8px rgba($negative-color, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust($negative-color, $lightness: -5%), $negative-color) !important; + box-shadow: 0 4px 12px rgba($negative-color, 0.4); + } + } + + &[class*='bg-warning'], + &[class*='bg-orange'], + &[class*='bg-amber'] { + background: linear-gradient(135deg, $warning-color, lighten($warning-color, 10%)) !important; + box-shadow: 0 2px 8px rgba($warning-color, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust($warning-color, $lightness: -5%), $warning-color) !important; + box-shadow: 0 4px 12px rgba($warning-color, 0.4); + } + } + + &[class*='bg-info'], + &[class*='bg-cyan'] { + background: linear-gradient(135deg, $info-color, color.adjust($info-color, $lightness: 10%)) !important; + box-shadow: 0 2px 8px rgba($info-color, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust($info-color, $lightness: -5%), $info-color) !important; + box-shadow: 0 4px 12px rgba($info-color, 0.4); + } + } + + &[class*='bg-purple'] { + background: linear-gradient(135deg, #9c27b0, lighten(#9c27b0, 10%)) !important; + box-shadow: 0 2px 8px rgba(#9c27b0, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust(#9c27b0, $lightness: -5%), #9c27b0) !important; + box-shadow: 0 4px 12px rgba(#9c27b0, 0.4); + } + } + + &[class*='bg-pink'] { + background: linear-gradient(135deg, #e91e63, lighten(#e91e63, 10%)) !important; + box-shadow: 0 2px 8px rgba(#e91e63, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust(#e91e63, $lightness: -5%), #e91e63) !important; + box-shadow: 0 4px 12px rgba(#e91e63, 0.4); + } + } + + &[class*='bg-grey'], + &[class*='bg-gray'] { + background: linear-gradient(135deg, #757575, lighten(#757575, 10%)) !important; + box-shadow: 0 2px 8px rgba(#757575, 0.3); + + &:hover { + background: linear-gradient(135deg, color.adjust(#757575, $lightness: -5%), #757575) !important; + box-shadow: 0 4px 12px rgba(#757575, 0.4); + } + } + + // Icon dentro il chip + .q-icon { + transition: transform $transition-speed ease; + } + + &:hover .q-icon { + transform: scale(1.1) rotate(5deg); + } + + // Text color bianco con ombra sottile per leggibilità + &[class*='text-white'] { + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); + } +} + +// ======================================== +// DENSE VARIANT +// ======================================== +.q-chip--dense { + padding: 3px 8px !important; + font-size: 0.8125rem; + + @media (max-width: $mobile-breakpoint) { + padding: 2px 6px !important; + font-size: 0.75rem; + } +} + +// ======================================== +// ANIMATION +// ======================================== +@keyframes chipAppear { + from { + opacity: 0; + transform: scale(0.8) translateY(10px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +.q-chip { + animation: chipAppear 0.3s ease-out; + animation-fill-mode: both; + + // Stagger animation per chip multipli + @for $i from 1 through 20 { + &:nth-child(#{$i}) { + animation-delay: #{$i * 0.05}s; + } + } +} + +// ======================================== +// GLASSMORPHISM VARIANT (opzionale) +// ======================================== +.q-chip.glass-effect { + background: rgba(255, 255, 255, 0.2) !important; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + + &:hover { + background: rgba(255, 255, 255, 0.3) !important; + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15); + } +} \ No newline at end of file diff --git a/src/components/CMyFieldDb/CMyFieldDb-modern.scss b/src/components/CMyFieldDb/CMyFieldDb-modern.scss new file mode 100644 index 00000000..7172655f --- /dev/null +++ b/src/components/CMyFieldDb/CMyFieldDb-modern.scss @@ -0,0 +1,283 @@ +// ======================================== +// MODERN FIELD DB - COMPACT & PROFESSIONAL +// ======================================== + +// Container principale +.modern-field-container { + display: flex; + align-items: stretch; + gap: 12px; + padding: 8px 12px; + margin: 6px 0; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(250, 250, 252, 0.95) 100%); + border-radius: 12px; + border: 1px solid rgba(66, 165, 245, 0.15); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(66, 165, 245, 0.08), transparent); + transition: left 0.6s ease; + } + + &:hover { + border-color: rgba(66, 165, 245, 0.3); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.12); + transform: translateY(-1px); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + gap: 6px; + padding: 3px 5px; + margin: 4px 0; + border-radius: 10px; + } +} + +// Label/Titolo campo +.modern-field-label { + display: flex; + align-items: center; + justify-content: center; + min-width: 120px; + max-width: 140px; + padding: 10px 14px; + background: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%); + border-radius: 8px; + box-shadow: 0 2px 6px rgba(25, 118, 210, 0.25); + position: relative; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + top: -50%; + right: -50%; + width: 100%; + height: 200%; + background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.1), transparent); + transform: rotate(45deg); + animation: shimmer 3s infinite; + } + + .label-content { + display: flex; + flex-direction: column; + align-items: center; + gap: 6px; + z-index: 1; + } + + .label-icon { + width: 32px; + height: 32px; + object-fit: contain; + } + + .label-text { + color: white; + font-weight: 600; + font-size: 0.9rem; + text-align: center; + line-height: 1.3; + letter-spacing: 0.3px; + } + + @media (max-width: 599px) { + min-width: 80px; + max-width: 100px; + padding: 8px 8px; + border-radius: 6px; + + .label-icon { + width: 24px; + height: 24px; + } + + .label-text { + font-size: 0.8rem; + } + } +} + +// Valore campo (chip/display) +.modern-field-value { + flex: 1; + display: flex; + align-items: center; + padding: 8px 12px; + min-height: 48px; + cursor: pointer; + border-radius: 8px; + transition: all 0.3s ease; + position: relative; + + &:hover { + background: rgba(66, 165, 245, 0.05); + + .value-chip { + transform: scale(1.02); + box-shadow: 0 3px 10px rgba(102, 126, 234, 0.35); + } + } + + @media (max-width: 599px) { + padding: 6px 8px; + min-height: 40px; + } +} + +// Chip valore +.value-chip { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + font-weight: 500; + font-size: 0.95rem; + padding: 10px 16px; + border-radius: 20px; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + max-width: 100%; + word-break: break-word; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent); + transition: left 0.5s ease; + } + + &:hover::before { + left: 100%; + } + + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 8px 12px; + border-radius: 16px; + } +} + +// Stato vuoto +.value-empty { + color: #999; + font-style: italic; + font-size: 0.9rem; + padding: 10px 16px; + + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 8px 12px; + } +} + +// Wrapper per popup edit +.modern-popup-wrapper { + width: 100%; + + :deep(.q-field) { + margin-bottom: 0; + } + + :deep(.q-field__control) { + border-radius: 8px; + min-height: 44px; + + @media (max-width: 599px) { + min-height: 40px; + border-radius: 6px; + } + } + + :deep(.q-field__label) { + font-size: 0.9rem; + font-weight: 500; + + @media (max-width: 599px) { + font-size: 0.85rem; + } + } +} + +// Animazione shimmer +@keyframes shimmer { + 0% { + transform: translateX(-100%) rotate(45deg); + } + 100% { + transform: translateX(100%) rotate(45deg); + } +} + +// Stati disabilitati +.modern-field-container.disabled { + opacity: 0.6; + cursor: not-allowed; + pointer-events: none; + + .modern-field-label { + background: linear-gradient(135deg, #90a4ae 0%, #607d8b 100%); + } + + .value-chip { + background: linear-gradient(135deg, #b0bec5 0%, #90a4ae 100%); + } +} + +// Variante readonly (non clickable ma visibile) +.modern-field-container.readonly { + .modern-field-value { + cursor: default; + + &:hover { + background: transparent; + + .value-chip { + transform: none; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + } + } + } +} + +// LEGACY SUPPORT - mantiene classi esistenti +.colmodif { + cursor: pointer; + + &:hover { + background-color: rgba(168, 240, 255, 0.3); + } +} + +.colsel { + background-color: rgba(129, 184, 255, 0.3); +} + +.cldisable { + color: #999 !important; + opacity: 0.6; +} + +.clinput { + @media (max-width: 500px) { + display: flex; + flex-grow: 1; + } +} diff --git a/src/components/CMyFieldDb/CMyFieldDb.ts b/src/components/CMyFieldDb/CMyFieldDb.ts index 1555c618..5f0b5dec 100755 --- a/src/components/CMyFieldDb/CMyFieldDb.ts +++ b/src/components/CMyFieldDb/CMyFieldDb.ts @@ -14,7 +14,7 @@ import MixinBase from '@src/mixins/mixin-base' export default defineComponent({ name: 'CMyFieldDb', - emits: ['save'], + emits: ['save', 'savedInDb'], props: { title: { type: String, @@ -34,6 +34,16 @@ export default defineComponent({ required: false, default: '', }, + mysubkey_tosee: { + type: String, + required: false, + default: '', + }, + fieldsel_tosee: { + type: String, + required: false, + default: '', + }, specialField: { type: Object as PropType, required: false, @@ -149,12 +159,13 @@ export default defineComponent({ const { setValDb, getValDb } = MixinBase() - function showandsave(row: any, col: any, newval: any, valinitial: any) { + async function showandsave(row: any, col: any, newval: any, valinitial: any) { console.log('showandsave CMyFieldDb:', newval) console.log('subkey', props.mysubkey, 'sskey', props.mysubsubkey) - tools.saveInDBForTypes($q, props.mykey, newval, props.type, props.serv, props.table, props.mysubkey, props.id, props.indrec, props.mysubsubkey, props.specialField); + await tools.saveInDBForTypes($q, props.mykey, newval, props.type, props.serv, props.table, props.mysubkey, props.id, props.indrec, props.mysubsubkey, props.specialField); + emit('savedInDb') } function save(newval: any) { diff --git a/src/components/CMyFieldDb/CMyFieldDb.vue b/src/components/CMyFieldDb/CMyFieldDb.vue index cba39df5..63524279 100755 --- a/src/components/CMyFieldDb/CMyFieldDb.vue +++ b/src/components/CMyFieldDb/CMyFieldDb.vue @@ -1,75 +1,51 @@ @@ -78,5 +54,5 @@ diff --git a/src/components/CMyGroup/CMyGroup.scss b/src/components/CMyGroup/CMyGroup.scss index fc6d6911..6411182f 100755 --- a/src/components/CMyGroup/CMyGroup.scss +++ b/src/components/CMyGroup/CMyGroup.scss @@ -1,25 +1,524 @@ -.myflex{ - display: flex; - flex: 1; +// ======================================== +// CMyGroup - SCSS Moderno con Gradienti +// ======================================== + +$primary-color: #1976d2; +$primary-light: #42a5f5; +$primary-dark: #1565c0; +$secondary-color: #26a69a; +$positive-color: #21ba45; +$negative-color: #c10015; +$info-color: #31ccec; +$warning-color: #f2c037; + +$grey-text: #555; +$grey-light: #999; + +$border-radius-sm: 8px; +$border-radius: 12px; +$transition-speed: 0.3s; +$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08); +$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1); +$shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.15); + +$mobile-breakpoint: 768px; + +// Gradiente speciale per gruppi +$gradient-group-primary: linear-gradient(135deg, $secondary-color 0%, lighten($secondary-color, 15%) 100%); +$gradient-group-hover: linear-gradient(135deg, darken($secondary-color, 5%) 0%, $secondary-color 100%); + +// ======================================== +// Q-ITEM CONTAINER (con gradiente group-style) +// ======================================== +.q-item { + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 50%, #ffffff 100%); + border-radius: $border-radius; + padding: 10px 12px; + margin: 8px 0; + transition: all $transition-speed cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: $shadow-sm; + position: relative; + overflow: hidden; + border: 1px solid rgba(0, 0, 0, 0.06); + border-left: 4px solid transparent; + + // Effetto luce scorrevole + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); + transition: left 0.6s ease; + z-index: 0; + } + + // Gradiente sottile group-themed + &::after { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: linear-gradient(to right, rgba($secondary-color, 0.02), transparent 15%); + opacity: 0; + transition: opacity $transition-speed ease; + z-index: 0; + } + + @media (max-width: $mobile-breakpoint) { + padding: 8px 10px; + margin: 6px 0; + } + + // Hover effect + &.clickable:hover, + &[clickable]:hover { + background: linear-gradient(135deg, #ffffff 0%, #f0f4f8 50%, #ffffff 100%); + box-shadow: 0 4px 16px rgba($secondary-color, 0.15); + transform: translateY(-2px); + border-left-color: $secondary-color; + border-color: rgba($secondary-color, 0.15); + + &::before { + left: 100%; + } + + &::after { + opacity: 1; + } + } + + // Assicura che i contenuti siano sopra gli effetti + > * { + position: relative; + z-index: 1; + } } -.container{ - vertical-align: center; - padding: 5px; - font-size: 1.15rem; +// ======================================== +// AVATAR (con effetto glow group-themed) +// ======================================== +.q-avatar { + transition: all $transition-speed ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + border: 2px solid rgba(255, 255, 255, 0.8); + position: relative; + + &::after { + content: ''; + position: absolute; + inset: -2px; + border-radius: 50%; + background: $gradient-group-primary; + opacity: 0; + transition: opacity $transition-speed ease; + z-index: -1; + } + + .q-item:hover & { + transform: scale(1.05); + box-shadow: 0 4px 16px rgba($secondary-color, 0.3); + + &::after { + opacity: 0.3; + } + } + + @media (max-width: $mobile-breakpoint) { + width: 50px !important; + height: 50px !important; + } } -.element{ - font-weight: bold; - vertical-align: center; - padding: 5px; - font-size: 1.15rem; +// ======================================== +// PROFILE IMAGE +// ======================================== +.imgprofile { + border-radius: 50%; + object-fit: cover; } +// ======================================== +// GROUP TITLE (con gradiente) +// ======================================== +.q-item__label { + line-height: 1.5; + margin-bottom: 3px; -.title_param{ - font-size: 1.25rem; + &:last-child { + margin-bottom: 0; + } + + strong { + font-weight: 600; + background: $gradient-group-primary; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-size: 1rem; + transition: all $transition-speed ease; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.9375rem; + } + + .q-item:hover & { + background: $gradient-group-hover; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + } + + em { + font-style: italic; + color: $grey-text; + font-size: 0.875rem; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.8125rem; + } + } + + // Caption style + &[caption] { + color: $grey-light; + font-size: 0.8125rem; + margin-top: 2px; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.75rem; + } + } } -.iconcirc { - margin-right: 4px; + +// ======================================== +// GROUPNAME BADGE +// ======================================== +.q-item__label { + // Stile per (groupname) + &:has(strong) { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + + // Parentesi con groupname + > :not(strong) { + font-size: 0.875rem; + color: $grey-text; + padding: 2px 8px; + border-radius: 6px; + background: linear-gradient(135deg, rgba($secondary-color, 0.08), rgba($secondary-color, 0.04)); + border: 1px solid rgba($secondary-color, 0.2); + + @media (max-width: $mobile-breakpoint) { + font-size: 0.8125rem; + padding: 2px 6px; + } + } + } } + +// ======================================== +// ACTION BUTTONS (con gradienti) +// ======================================== +.q-btn { + transition: all $transition-speed ease; + position: relative; + overflow: hidden; + + // Rounded menu button + &[rounded] { + &.q-btn--round { + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(8px); + box-shadow: $shadow-sm; + border: 1px solid rgba(0, 0, 0, 0.06); + + &:hover { + background: rgba(255, 255, 255, 0.95); + box-shadow: $shadow-md; + transform: scale(1.1) rotate(90deg); + } + } + } + + // Send coins button (special gradient) + &[color='green'] { + background: linear-gradient(135deg, $positive-color, lighten($positive-color, 10%)) !important; + box-shadow: 0 2px 8px rgba($positive-color, 0.3); + + &:hover { + background: linear-gradient(135deg, darken($positive-color, 5%), $positive-color) !important; + box-shadow: 0 4px 12px rgba($positive-color, 0.4); + transform: translateY(-2px); + } + + &::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 0; + height: 0; + border-radius: 50%; + background: rgba(255, 255, 255, 0.4); + transform: translate(-50%, -50%); + transition: width 0.6s ease, height 0.6s ease; + } + + &:hover::before { + width: 300px; + height: 300px; + } + } +} + +// ======================================== +// MENU DROPDOWN (con gradienti) +// ======================================== +.q-menu { + background: linear-gradient(to bottom, #ffffff, #f8f9fa); + backdrop-filter: blur(10px); + border: 1px solid rgba(0, 0, 0, 0.08); + box-shadow: $shadow-lg; + border-radius: $border-radius-sm; + + .q-list { + padding: 6px; + background: transparent; + + @media (max-width: $mobile-breakpoint) { + padding: 4px; + } + } + + .q-item { + border-radius: $border-radius-sm; + margin: 2px 0; + background: transparent; + border: none; + box-shadow: none; + border-left: none; + padding: 10px 12px; + + &::before { + display: none; + } + + &::after { + display: none; + } + + &:hover { + background: linear-gradient(135deg, rgba($secondary-color, 0.08), rgba($secondary-color, 0.04)); + transform: translateX(4px) translateY(0); + box-shadow: 0 2px 8px rgba($secondary-color, 0.1); + } + + @media (max-width: $mobile-breakpoint) { + padding: 8px 10px; + } + } + + .q-item__section--avatar { + min-width: 36px; + + @media (max-width: $mobile-breakpoint) { + min-width: 32px; + } + + .q-icon { + transition: all $transition-speed ease; + } + + .q-item:hover & .q-icon { + transform: scale(1.1); + } + } +} + +// ======================================== +// COIN ICON (special styling) +// ======================================== +.q-btn { + [class*='img:'] { + transition: transform $transition-speed ease; + } + + &:hover [class*='img:'] { + transform: scale(1.1) rotate(10deg); + } +} + +// ======================================== +// DIALOG (con gradiente) +// ======================================== +.q-dialog { + .q-card { + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); + border-radius: $border-radius; + + @media (max-width: $mobile-breakpoint) { + border-radius: 0; + } + } + + .q-toolbar { + background: linear-gradient(135deg, $primary-color, $primary-dark) !important; + border-radius: $border-radius $border-radius 0 0; + padding: 12px 16px; + + @media (max-width: $mobile-breakpoint) { + padding: 10px 12px; + border-radius: 0; + } + + .q-toolbar-title { + font-weight: 600; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + } + } +} + +// ======================================== +// ANIMATIONS +// ======================================== +@keyframes groupItemAppear { + from { + opacity: 0; + transform: translateY(10px) scale(0.98); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.q-item { + animation: groupItemAppear 0.35s ease-out; +} + +// Coin icon rotation on hover +@keyframes coinRotate { + 0% { transform: rotateY(0deg); } + 100% { transform: rotateY(360deg); } +} + +.q-btn:hover [class*='img:'] { + animation: coinRotate 0.8s ease-in-out; +} + +// ======================================== +// RESPONSIVE ADJUSTMENTS +// ======================================== +@media (max-width: $mobile-breakpoint) { + .q-item-section { + padding: 0 4px; + } + + .q-item__label { + line-height: 1.4; + } + + .q-btn { + &[rounded] { + padding: 6px; + } + + &[dense] { + padding: 4px 8px; + font-size: 0.875rem; + } + } +} + +// ======================================== +// UTILITY CLASSES +// ======================================== + +// Glass effect variant +.glass-group-item { + .q-item { + background: rgba(255, 255, 255, 0.7) !important; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); + + &:hover { + background: rgba(255, 255, 255, 0.85) !important; + } + } +} + +// Highlighted group (admin) +.admin-group { + .q-item { + border-left: 4px solid $warning-color; + background: linear-gradient(to right, rgba($warning-color, 0.05), transparent 20%); + + &:hover { + background: linear-gradient(to right, rgba($warning-color, 0.08), transparent 20%); + box-shadow: 0 4px 16px rgba($warning-color, 0.15); + } + } +} + +// Featured group +.featured-group { + .q-item { + border: 2px solid transparent; + background: linear-gradient(white, white) padding-box, + $gradient-group-primary border-box; + + &:hover { + box-shadow: 0 6px 20px rgba($secondary-color, 0.25); + } + } +} + +// Active group indicator +.active-group-indicator { + position: absolute; + top: 8px; + right: 8px; + width: 10px; + height: 10px; + border-radius: 50%; + background: $gradient-group-primary; + box-shadow: 0 0 8px rgba($secondary-color, 0.6); + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0%, 100% { + box-shadow: 0 0 8px rgba($secondary-color, 0.6); + } + 50% { + box-shadow: 0 0 16px rgba($secondary-color, 0.9); + } +} + +// Member count badge (opzionale) +.member-count-badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border-radius: 12px; + background: linear-gradient(135deg, rgba($info-color, 0.1), rgba($info-color, 0.05)); + border: 1px solid rgba($info-color, 0.3); + color: darken($info-color, 15%); + font-size: 0.75rem; + font-weight: 600; + margin-left: 8px; + + .q-icon { + font-size: 0.875rem; + } +} \ No newline at end of file diff --git a/src/components/CMyPopupEdit/CMyPopupEdit-modern.scss b/src/components/CMyPopupEdit/CMyPopupEdit-modern.scss new file mode 100644 index 00000000..c56fe2b1 --- /dev/null +++ b/src/components/CMyPopupEdit/CMyPopupEdit-modern.scss @@ -0,0 +1,437 @@ +// ======================================== +// MODERN POPUP EDIT - ENHANCED DISPLAY +// ======================================== + +// Sovrascrive e aggiunge agli stili esistenti + +// Display del valore quando non in modifica +.modern-value-display { + width: 100%; + + // Chip per valori stringa/generici + .value-chip-display { + display: inline-flex; + align-items: center; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + font-weight: 500; + font-size: 0.95rem; + padding: 10px 18px; + border-radius: 20px; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + max-width: 100%; + word-break: break-word; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent); + transition: left 0.5s ease; + } + + &:hover { + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 8px 14px; + border-radius: 16px; + } + } + + // Link button + .value-link-btn { + background: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%); + color: white; + padding: 10px 18px; + border-radius: 20px; + box-shadow: 0 2px 8px rgba(25, 118, 210, 0.3); + transition: all 0.3s ease; + text-decoration: none; + display: inline-flex; + align-items: center; + gap: 8px; + font-weight: 500; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; + } + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + padding: 8px 14px; + border-radius: 16px; + font-size: 0.85rem; + gap: 6px; + } + } + + // Toggle migliorato + .value-toggle { + :deep(.q-toggle) { + padding: 4px 0; + + .q-toggle__track { + width: 48px; + height: 24px; + border-radius: 12px; + transition: all 0.3s ease; + } + + .q-toggle__thumb { + width: 20px; + height: 20px; + transition: all 0.3s ease; + } + + &.q-toggle--truthy { + .q-toggle__track { + background: linear-gradient(135deg, #4caf50 0%, #2e7d32 100%); + box-shadow: 0 2px 6px rgba(76, 175, 80, 0.3); + } + } + + &.q-toggle--falsy { + .q-toggle__track { + background: linear-gradient(135deg, #e0e0e0 0%, #bdbdbd 100%); + } + } + + @media (max-width: 599px) { + .q-toggle__track { + width: 42px; + height: 22px; + } + + .q-toggle__thumb { + width: 18px; + height: 18px; + } + } + } + } +} + +// Enhanced chip_shadow per user items +.chip_shadow { + :deep(.q-chip) { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + transition: all 0.3s ease; + border: none; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; + } + + &:hover { + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); + transform: translateY(-1px); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + font-size: 0.85rem; + } + } +} + +// User card migliorata +.user-item-card { + padding: 10px 12px; + margin: 6px 0; + border-radius: 12px; + transition: all 0.3s ease; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(250, 250, 252, 0.95) 100%); + border: 1px solid rgba(66, 165, 245, 0.15); + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(66, 165, 245, 0.08), transparent); + transition: left 0.6s ease; + } + + &:hover { + background: linear-gradient(135deg, rgba(255, 255, 255, 1) 0%, rgba(245, 248, 252, 1) 100%); + border-color: rgba(66, 165, 245, 0.3); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.15); + transform: translateY(-1px); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + padding: 8px 10px; + margin: 4px 0; + border-radius: 10px; + } + + .q-item-section { + &.avatar { + padding-right: 12px; + + @media (max-width: 599px) { + padding-right: 8px; + } + } + } + + .q-avatar { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + border: 2px solid rgba(255, 255, 255, 0.8); + transition: all 0.3s ease; + } + + &:hover .q-avatar { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + transform: scale(1.05); + } + + .q-badge { + font-size: 0.7rem; + padding: 3px 8px; + font-weight: 600; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); + + @media (max-width: 599px) { + font-size: 0.65rem; + padding: 2px 6px; + } + } + + .q-item-label { + font-weight: 500; + color: #2c3e50; + + &.caption { + color: #7f8c8d; + font-size: 0.85rem; + + @media (max-width: 599px) { + font-size: 0.8rem; + } + } + } +} + +// Input states durante editing +.popup-edit-wrapper { + :deep(.q-field) { + padding-bottom: 6px; + + @media (max-width: 599px) { + padding-bottom: 4px; + } + } + + :deep(.q-field__control) { + min-height: 44px; + border-radius: 8px; + transition: all 0.3s ease; + + &:hover { + background: rgba(66, 165, 245, 0.03); + } + + &:focus-within { + background: rgba(66, 165, 245, 0.05); + box-shadow: 0 0 0 2px rgba(66, 165, 245, 0.2); + } + + @media (max-width: 599px) { + min-height: 40px; + border-radius: 6px; + } + } + + :deep(.q-field__label) { + font-size: 0.9rem; + font-weight: 500; + color: #1976d2; + + @media (max-width: 599px) { + font-size: 0.85rem; + } + } + + :deep(.q-field__native) { + font-size: 0.95rem; + color: #2c3e50; + padding: 8px 12px; + + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 6px 10px; + } + } + + :deep(.q-input), + :deep(.q-select) { + margin: 2px 0; + + @media (max-width: 599px) { + margin: 1px 0; + } + } +} + +// Stato focus su editor +.editor { + border: 1px solid rgba(66, 165, 245, 0.3); + border-radius: 8px; + padding: 8px; + min-height: 60px; + transition: all 0.3s ease; + background: white; + + &:hover { + border-color: rgba(66, 165, 245, 0.5); + background: rgba(66, 165, 245, 0.02); + } + + &:focus-within { + border-color: #42a5f5; + box-shadow: 0 0 0 2px rgba(66, 165, 245, 0.15); + background: white; + } + + @media (max-width: 599px) { + padding: 6px; + min-height: 50px; + border-radius: 6px; + } +} + +// Textarea compatta +:deep(textarea.myinput-area) { + padding: 10px; + border-radius: 8px; + min-height: 60px; + line-height: 1.5; + font-size: 0.95rem; + color: #2c3e50; + transition: all 0.3s ease; + + &:focus { + background: rgba(66, 165, 245, 0.02); + } + + @media (max-width: 599px) { + padding: 8px; + min-height: 50px; + font-size: 0.85rem; + } +} + +// Bottoni migliorati +.popup-button { + padding: 8px 16px; + margin: 4px 8px; + border-radius: 20px; + transition: all 0.3s ease; + background: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%); + color: white; + font-weight: 500; + box-shadow: 0 2px 6px rgba(25, 118, 210, 0.3); + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; + } + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + padding: 6px 12px; + margin: 3px 6px; + border-radius: 16px; + } +} + +// Extra field modernizzato +.extrafield { + font-size: 0.9rem; + padding: 6px 12px; + color: #5e6e7f; + font-weight: 500; + margin-bottom: 6px; + display: inline-block; + background: linear-gradient(135deg, rgba(66, 165, 245, 0.08) 0%, rgba(66, 165, 245, 0.05) 100%); + border-radius: 8px; + border: 1px solid rgba(66, 165, 245, 0.15); + + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 4px 10px; + margin-bottom: 4px; + border-radius: 6px; + } +} \ No newline at end of file diff --git a/src/components/CMyPopupEdit/CMyPopupEdit.scss b/src/components/CMyPopupEdit/CMyPopupEdit.scss index a2977857..2bb4b0d7 100755 --- a/src/components/CMyPopupEdit/CMyPopupEdit.scss +++ b/src/components/CMyPopupEdit/CMyPopupEdit.scss @@ -1,362 +1,449 @@ // ======================================== -// VARIABILI +// MODERN POPUP EDIT - ENHANCED DISPLAY // ======================================== -$primary-color: #1976d2; -$primary-light: #42a5f5; -$grey-color: #666; -$border-radius: 8px; -$border-radius-sm: 6px; -$transition-speed: 0.3s; +// Sovrascrive e aggiunge agli stili esistenti -$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08); -$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1); +// Display del valore quando non in modifica +.modern-value-display { + width: 100%; -$mobile-breakpoint: 768px; + // Chip per valori stringa/generici + .value-chip-display { + display: inline-flex; + align-items: center; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + font-weight: 500; + font-size: 0.95rem; + padding: 10px 18px; + border-radius: 20px; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + max-width: 100%; + word-break: break-word; -// ======================================== -// EDITOR -// ======================================== -.editor { - border: 1px solid rgba(25, 118, 210, 0.3); - border-radius: $border-radius-sm; - padding: 6px; - min-height: 60px; - transition: all $transition-speed ease; - background: white; - - &:hover { - border-color: $primary-light; - } - - &:focus-within { - border-color: $primary-color; - box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.1); - } - - @media (max-width: $mobile-breakpoint) { - padding: 4px; - min-height: 50px; - } -} - -// ======================================== -// POPUP EDIT CONTAINER -// ======================================== -.popup-edit-wrapper { - :deep(.q-popup-edit) { - padding: 8px; - border-radius: $border-radius; - box-shadow: $shadow-md; - - @media (max-width: $mobile-breakpoint) { - padding: 6px; + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent); + transition: left 0.5s ease; } - } -} - -// ======================================== -// FIELD WRAPPERS -// ======================================== -.field-wrapper { - padding: 4px 0; - margin: 3px 0; - - @media (max-width: $mobile-breakpoint) { - padding: 3px 0; - margin: 2px 0; - } -} - -// ======================================== -// EXTRA FIELD -// ======================================== -.extrafield { - font-size: 0.9375rem; - padding: 4px 6px; - color: $grey-color; - font-weight: 500; - margin-bottom: 4px; - display: inline-block; - background: rgba(0, 0, 0, 0.03); - border-radius: $border-radius-sm; - - @media (max-width: $mobile-breakpoint) { - font-size: 0.875rem; - padding: 3px 4px; - margin-bottom: 3px; - } -} - -// ======================================== -// TOGGLE ENHANCED -// ======================================== -.toggle-enhanced { - padding: 4px 0; - - :deep(.q-toggle__label) { - font-size: 0.9375rem; - margin-left: 6px; - - @media (max-width: $mobile-breakpoint) { - font-size: 0.875rem; - margin-left: 4px; - } - } - - :deep(.q-toggle__inner) { - transition: all $transition-speed ease; - } -} - -// ======================================== -// CHIP SHADOW -// ======================================== -.chip_shadow { - :deep(.q-chip) { - box-shadow: $shadow-sm; - transition: all $transition-speed ease; &:hover { - box-shadow: $shadow-md; transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 8px 14px; + border-radius: 16px; + } + } + + // Link button + .value-link-btn { + background: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%); + color: white; + padding: 10px 18px; + border-radius: 20px; + box-shadow: 0 2px 8px rgba(25, 118, 210, 0.3); + transition: all 0.3s ease; + text-decoration: none; + display: inline-flex; + align-items: center; + gap: 8px; + font-weight: 500; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; + } + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + padding: 8px 14px; + border-radius: 16px; + font-size: 0.85rem; + gap: 6px; + } + } + + // Toggle migliorato + .value-toggle { + :deep(.q-toggle) { + padding: 4px 0; + + .q-toggle__track { + width: 48px; + height: 24px; + border-radius: 12px; + transition: all 0.3s ease; + } + + .q-toggle__thumb { + width: 20px; + height: 20px; + transition: all 0.3s ease; + } + + &.q-toggle--truthy { + .q-toggle__track { + background: linear-gradient(135deg, #4caf50 0%, #2e7d32 100%); + box-shadow: 0 2px 6px rgba(76, 175, 80, 0.3); + } + } + + &.q-toggle--falsy { + .q-toggle__track { + background: linear-gradient(135deg, #e0e0e0 0%, #bdbdbd 100%); + } + } + + @media (max-width: 599px) { + .q-toggle__track { + width: 42px; + height: 22px; + } + + .q-toggle__thumb { + width: 18px; + height: 18px; + } + } } } } -// ======================================== -// USER CARD IN POPUP -// ======================================== -.user-item-card { - padding: 6px 8px; - margin: 4px 0; - border-radius: $border-radius; - transition: all $transition-speed ease; - background: white; - border: 1px solid rgba(0, 0, 0, 0.08); +// Enhanced chip_shadow per user items +.chip_shadow { + :deep(.q-chip) { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); + transition: all 0.3s ease; + border: none; + position: relative; + overflow: hidden; - &:hover { - background: rgba(25, 118, 210, 0.05); - border-color: rgba(25, 118, 210, 0.2); - box-shadow: $shadow-sm; + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; + } + + &:hover { + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4); + transform: translateY(-1px); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + font-size: 0.85rem; + } + } +} + +// User card migliorata +.user-item-card { + padding: 10px 12px; + margin: 6px 0; + border-radius: 12px; + transition: all 0.3s ease; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(250, 250, 252, 0.95) 100%); + border: 1px solid rgba(66, 165, 245, 0.15); + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(66, 165, 245, 0.08), transparent); + transition: left 0.6s ease; } - @media (max-width: $mobile-breakpoint) { - padding: 4px 6px; - margin: 3px 0; + &:hover { + background: linear-gradient(135deg, rgba(255, 255, 255, 1) 0%, rgba(245, 248, 252, 1) 100%); + border-color: rgba(66, 165, 245, 0.3); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.15); + transform: translateY(-1px); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + padding: 8px 10px; + margin: 4px 0; + border-radius: 10px; } .q-item-section { &.avatar { - padding-right: 8px; + padding-right: 12px; - @media (max-width: $mobile-breakpoint) { - padding-right: 6px; + @media (max-width: 599px) { + padding-right: 8px; } } } .q-avatar { - box-shadow: $shadow-sm; - border: 2px solid rgba(0, 0, 0, 0.05); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + border: 2px solid rgba(255, 255, 255, 0.8); + transition: all 0.3s ease; + } + + &:hover .q-avatar { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + transform: scale(1.05); } .q-badge { - font-size: 0.6875rem; - padding: 2px 6px; + font-size: 0.7rem; + padding: 3px 8px; font-weight: 600; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); - @media (max-width: $mobile-breakpoint) { - font-size: 0.625rem; - padding: 1px 4px; + @media (max-width: 599px) { + font-size: 0.65rem; + padding: 2px 6px; + } + } + + .q-item-label { + font-weight: 500; + color: #2c3e50; + + &.caption { + color: #7f8c8d; + font-size: 0.85rem; + + @media (max-width: 599px) { + font-size: 0.8rem; + } } } } -// ======================================== -// INPUT OVERRIDES (Compact) -// ======================================== +// Input states durante editing .popup-edit-wrapper { :deep(.q-field) { - padding-bottom: 8px; + padding-bottom: 6px; - @media (max-width: $mobile-breakpoint) { - padding-bottom: 6px; + @media (max-width: 599px) { + padding-bottom: 4px; } } :deep(.q-field__control) { min-height: 44px; + border-radius: 8px; + transition: all 0.3s ease; - @media (max-width: $mobile-breakpoint) { + &:hover { + background: rgba(66, 165, 245, 0.03); + } + + &:focus-within { + background: rgba(66, 165, 245, 0.05); + box-shadow: 0 0 0 2px rgba(66, 165, 245, 0.2); + } + + @media (max-width: 599px) { min-height: 40px; + border-radius: 6px; } } :deep(.q-field__label) { - font-size: 0.9375rem; + font-size: 0.9rem; + font-weight: 500; + color: #1976d2; - @media (max-width: $mobile-breakpoint) { - font-size: 0.875rem; + @media (max-width: 599px) { + font-size: 0.85rem; } } - :deep(.q-input) { - margin: 3px 0; + :deep(.q-field__native) { + font-size: 0.95rem; + color: #2c3e50; + padding: 8px 12px; - @media (max-width: $mobile-breakpoint) { - margin: 2px 0; + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 6px 10px; } } + :deep(.q-input), :deep(.q-select) { - margin: 3px 0; - - @media (max-width: $mobile-breakpoint) { - margin: 2px 0; - } - } -} - -// ======================================== -// TEXTAREA COMPACT -// ======================================== -:deep(textarea) { - &.myinput-area { - padding: 8px; - border-radius: $border-radius-sm; - min-height: 60px; - line-height: 1.4; - - @media (max-width: $mobile-breakpoint) { - padding: 6px; - min-height: 50px; - } - } -} - -// ======================================== -// BUTTON IN POPUP -// ======================================== -.popup-button { - padding: 6px 12px; - margin: 3px 6px; - border-radius: $border-radius-sm; - transition: all $transition-speed ease; - - &:hover { - transform: translateY(-1px); - box-shadow: $shadow-sm; - } - - @media (max-width: $mobile-breakpoint) { - padding: 4px 8px; - margin: 2px 4px; - } -} - -// ======================================== -// DATE PICKER COMPACT -// ======================================== -.date-picker-compact { - :deep(.q-date) { - padding: 4px; - - @media (max-width: $mobile-breakpoint) { - padding: 3px; - } - } - - :deep(.q-date__header) { - padding: 6px; - - @media (max-width: $mobile-breakpoint) { - padding: 4px; - } - } - - :deep(.q-date__calendar-item) { - padding: 3px; - - @media (max-width: $mobile-breakpoint) { - padding: 2px; - } - } -} - -// ======================================== -// COLOR PICKER -// ======================================== -.color-select-wrapper { - :deep(.q-select) { - min-width: 150px; - - @media (max-width: $mobile-breakpoint) { - min-width: 120px; - } - } -} - -// ======================================== -// LEGACY SUPPORT -// ======================================== -.clpopupVisuCard { - border-radius: $border-radius; - padding: 4px; - margin: 3px 0; - - @media (max-width: $mobile-breakpoint) { - padding: 3px; margin: 2px 0; + + @media (max-width: 599px) { + margin: 1px 0; + } } } -// ======================================== -// DISABLED STATE -// ======================================== -.disabled { - opacity: 0.5; - cursor: not-allowed; - pointer-events: none; -} - -// ======================================== -// CURSOR POINTER -// ======================================== -.cursor-pointer { - cursor: pointer; - transition: opacity $transition-speed ease; +// Stato focus su editor +.editor { + border: 1px solid rgba(66, 165, 245, 0.3); + border-radius: 8px; + padding: 8px; + min-height: 60px; + transition: all 0.3s ease; + background: white; &:hover { - opacity: 0.8; + border-color: rgba(66, 165, 245, 0.5); + background: rgba(66, 165, 245, 0.02); + } + + &:focus-within { + border-color: #42a5f5; + box-shadow: 0 0 0 2px rgba(66, 165, 245, 0.15); + background: white; + } + + @media (max-width: 599px) { + padding: 6px; + min-height: 50px; + border-radius: 6px; } } -// ======================================== -// FLEX HELPERS (Compact) -// ======================================== -.flex { - display: flex; - gap: 6px; +// Textarea compatta +:deep(textarea.myinput-area) { + padding: 10px; + border-radius: 8px; + min-height: 60px; + line-height: 1.5; + font-size: 0.95rem; + color: #2c3e50; + transition: all 0.3s ease; - @media (max-width: $mobile-breakpoint) { - gap: 4px; + &:focus { + background: rgba(66, 165, 245, 0.02); + } + + @media (max-width: 599px) { + padding: 8px; + min-height: 50px; + font-size: 0.85rem; } } -.justify-center { - justify-content: center; +// Bottoni migliorati +.popup-button { + padding: 8px 16px; + margin: 4px 8px; + border-radius: 20px; + transition: all 0.3s ease; + background: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%); + color: white; + font-weight: 500; + box-shadow: 0 2px 6px rgba(25, 118, 210, 0.3); + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; + } + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(25, 118, 210, 0.4); + + &::before { + left: 100%; + } + } + + @media (max-width: 599px) { + padding: 6px 12px; + margin: 3px 6px; + border-radius: 16px; + } } -.items-center { - align-items: center; -} +// Extra field modernizzato +.extrafield { + font-size: 0.9rem; + padding: 6px 12px; + color: #5e6e7f; + font-weight: 500; + margin-bottom: 6px; + display: inline-block; + background: linear-gradient(135deg, rgba(66, 165, 245, 0.08) 0%, rgba(66, 165, 245, 0.05) 100%); + border-radius: 8px; + border: 1px solid rgba(66, 165, 245, 0.15); -// ======================================== -// REQUIRED INDICATOR -// ======================================== -.required-indicator { - color: #c10015; - font-weight: 600; - margin-left: 2px; + @media (max-width: 599px) { + font-size: 0.85rem; + padding: 4px 10px; + margin-bottom: 4px; + border-radius: 6px; + } +} +.modern-chip-container { + min-width: 350px; + + @media (max-width: 599px) { + width: 100%; + min-width: unset; + } + + .modern-chip { + width: 100%; + } } \ No newline at end of file diff --git a/src/components/CMyPopupEdit/CMyPopupEdit.ts b/src/components/CMyPopupEdit/CMyPopupEdit.ts index 8580d711..de2f0a36 100755 --- a/src/components/CMyPopupEdit/CMyPopupEdit.ts +++ b/src/components/CMyPopupEdit/CMyPopupEdit.ts @@ -121,6 +121,21 @@ export default defineComponent({ required: false, default: '', }, + label_trans: { + type: String, + required: false, + default: '', + }, + subfield_to_see: { + type: String, + required: false, + default: '', + }, + fieldsel_tosee: { + type: String, + required: false, + default: '', + }, subfield2: { type: String, required: false, @@ -261,6 +276,7 @@ export default defineComponent({ const userStore = useUserStore(); const globalStore = useGlobalStore(); + const myvaltosee = ref(null as any); const myvalue = ref(null as any); const myvalue2 = ref(null as any); const myvalueprec = ref('false'); @@ -276,6 +292,7 @@ export default defineComponent({ const $router = useRouter(); const loaded = ref(false); + const modeEdit = ref(false); const myColor = ref('#FF00AA55'); // Colore con trasparenza iniziale @@ -357,6 +374,7 @@ export default defineComponent({ } } col.value.jointable = props.jointable; + col.value.label_trans = props.label_trans; if (props.filter) col.value.filter = props.filter; col.value.fieldtype = props.type; @@ -519,7 +537,7 @@ export default defineComponent({ } function changevalRecOrig(newval: any, subcol: string = '') { - console.log('changevalRec', newval) + console.log('changevalRec', newval); // if (!props.insertMode || (props.insertMode && col.value.fieldtype !== costanti.FieldType.multioption)) { if (col.value && col.value.allowchar === costanti.ALLOWCHAR_CODE) { newval = tools.removespaces_slash(newval); @@ -537,7 +555,7 @@ export default defineComponent({ } if (props.type === costanti.FieldType.imgfile_sfuso) { - newval = newval?.imagefile + newval = newval?.imagefile; } if (props.notAllowAtChar) { @@ -635,8 +653,11 @@ export default defineComponent({ note: '', }; } - } catch (e) { } + } catch (e) {} + if (props.subfield_to_see) { + myvaltosee.value = myrow.value[props.field][props.subfield_to_see]; + } // console.log('popupedit: myvalue.value', myvalue.value) @@ -740,7 +761,6 @@ export default defineComponent({ } } - if (col.value.fieldtype === costanti.FieldType.verifica) { newVal.username = userStore.my.username; newVal.data = tools.getDateNow(); @@ -793,6 +813,11 @@ export default defineComponent({ } } + if (props.fieldsel_tosee) { + const mystrcol = props.fieldsel_tosee; + myvaltosee.value = copynewval[mystrcol]; + } + console.log('SaveValueInt', newVal, valinitial); emit('save', newVal, valinitial, copynewval.which!); @@ -836,6 +861,25 @@ export default defineComponent({ ); } } + async function savefieldtosee(value: any, initialval: any, myq: any) { + if (!props.insertMode) { + let ret = null; + myvalue2.value = value; + return tools.saveInDBForTypes( + myq, + props.field2, + myvalue2.value, + props.type, + props.serv, + props.table, + props.fieldsel_tosee, + props.id, + props.indrec, + props.mysubsubkey, + props.specialField + ); + } + } function annulla(val: any) { emit('annulla', true); @@ -889,7 +933,7 @@ export default defineComponent({ myvalue.value = ''; } else { myvalue.value = newVal.imagefile; - newVal = tools.getDirUpload() + mypath.value + myvalue.value + newVal = tools.getDirUpload() + mypath.value + myvalue.value; } } else if (col.value.fieldtype === costanti.FieldType.imgcard) { console.log('newVal.imagefile', newVal); @@ -1204,6 +1248,8 @@ export default defineComponent({ colorPicker, myColor, hoverPreview, + myvaltosee, + modeEdit, }; }, }); diff --git a/src/components/CMyPopupEdit/CMyPopupEdit.vue b/src/components/CMyPopupEdit/CMyPopupEdit.vue index 27172bc7..017a8cbc 100755 --- a/src/components/CMyPopupEdit/CMyPopupEdit.vue +++ b/src/components/CMyPopupEdit/CMyPopupEdit.vue @@ -1282,15 +1282,19 @@
- +
+ +
diff --git a/src/components/CMyProfileTutorial/CMyProfileTutorial.ts b/src/components/CMyProfileTutorial/CMyProfileTutorial.ts index 8c51244c..7ea8cc0c 100755 --- a/src/components/CMyProfileTutorial/CMyProfileTutorial.ts +++ b/src/components/CMyProfileTutorial/CMyProfileTutorial.ts @@ -130,7 +130,7 @@ export default defineComponent({ const arrStep = ref([ - { + /*{ indstep: 0, step: STEP_CITY, title: t('tutorial.step_residence_title'), @@ -140,6 +140,17 @@ export default defineComponent({ checkOkReal: function (): boolean { return this.checkOk() }, icon: 'house', required: true, + },*/ + { + indstep: 0, + step: STEP_CITY, + title: t('tutorial.step_residence_comune_title'), + extratitle: function () { return ': ' + (contact.value!.profile.resid_str_comune ? contact.value!.profile.resid_str_comune : '') }, + label: t('tutorial.step_residence_comune'), + checkOk: function (): boolean { return contact.value ? !!contact.value.profile.resid_str_comune && contact.value.profile.resid_str_comune !== '' && contact.value.profile.resid_str_comune !== '0' : false }, + checkOkReal: function (): boolean { return this.checkOk() }, + icon: 'house', + required: true, }, /*{ step: STEP_NAME_SURNAME, // 2 @@ -343,8 +354,8 @@ export default defineComponent({ username.value = props.mycontact.username } } - if (contact.value && contact.value.profile && contact.value.profile.resid_province === '0') { - contact.value.profile.resid_province = '' + if (contact.value && contact.value.profile && contact.value.profile.resid_str_comune === '0') { + contact.value.profile.resid_str_comune = '' } mylistcircuits.value = circuitStore.getCircuitsNameByProvince(strProv.value) diff --git a/src/components/CMySelect/CMySelect.ts b/src/components/CMySelect/CMySelect.ts index 881051da..6e9c15c1 100755 --- a/src/components/CMySelect/CMySelect.ts +++ b/src/components/CMySelect/CMySelect.ts @@ -1,15 +1,15 @@ import type { PropType } from 'vue'; -import { computed, defineComponent, onMounted, ref, toRef, watch } from 'vue' -import { useI18n } from 'vue-i18n' -import { useUserStore } from '@store/UserStore' -import { useGlobalStore } from '@store/globalStore' -import { useQuasar } from 'quasar' -import { costanti } from '@costanti' -import { fieldsTable } from '@store/Modules/fieldsTable' -import { shared_consts } from '@src/common/shared_vuejs' +import { computed, defineComponent, onMounted, ref, toRef, watch } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useUserStore } from '@store/UserStore'; +import { useGlobalStore } from '@store/globalStore'; +import { useQuasar } from 'quasar'; +import { costanti } from '@costanti'; +import { fieldsTable } from '@store/Modules/fieldsTable'; +import { shared_consts } from '@src/common/shared_vuejs'; import type { IColGridTable } from 'model'; -import { IOperators } from 'model' -import { tools } from '@tools' +import { IOperators } from 'model'; +import { tools } from '@tools'; import { useProducts } from 'app/src/store/Products'; export default defineComponent({ @@ -39,12 +39,12 @@ export default defineComponent({ myclass: { type: String, required: false, - default: '' + default: '', }, tablesel: { type: String, required: false, - default: '' + default: '', }, type_out: { type: Number, @@ -54,35 +54,40 @@ export default defineComponent({ type: Object, required: false, default: () => { - return {} + return {}; }, }, col: { type: Object as PropType, required: false, default: () => { - return { name: '' } + return { name: '' }; }, }, filter_table: { type: String, required: false, - default: '' + default: '', }, filter_field: { type: String, required: false, - default: '' + default: '', }, filter_extra: { type: [Object, String], required: false, - default: null + default: null, }, value_extra: { type: [String, Number], required: false, - default: '' + default: '', + }, + myvaltosee: { + type: [String, Number], + required: false, + default: '', }, optlab: [String, Function], optval: { @@ -92,37 +97,37 @@ export default defineComponent({ useinput: { type: Boolean, required: false, - default: true + default: true, }, pickup: { type: Boolean, required: false, - default: false + default: false, }, addall: { type: Boolean, required: false, - default: false + default: false, }, addnone: { type: Boolean, required: false, - default: false + default: false, }, addlast: { type: Boolean, required: false, - default: false + default: false, }, dense: { type: Boolean, required: false, - default: true + default: true, }, multiple: { type: Boolean, required: false, - default: false + default: false, }, newvaluefunc: { type: Function, @@ -161,294 +166,300 @@ export default defineComponent({ }, components: {}, setup(props, { emit }) { - const $q = useQuasar() - const { t } = useI18n() - const userStore = useUserStore() - const globalStore = useGlobalStore() + const $q = useQuasar(); + const { t } = useI18n(); + const userStore = useUserStore(); + const globalStore = useGlobalStore(); - const optFiltered = ref([]) - const valori = ref([]) + const optFiltered = ref([]); + const valori = ref([]); - const myvalue = ref('') - const myarrvalue = ref([]) - const arrtempOpt = ref([]) + const myvalue = ref(''); + const myarrvalue = ref([]); + const arrtempOpt = ref([]); - const optionsreal: any = [] + const optionsreal: any = []; - const selectMultiServer = ref(null) - const selectPickup = ref(null) - const selectMultiple = ref(null) - const selectGeneric = ref(null) + const selectMultiServer = ref(null); + const selectPickup = ref(null); + const selectMultiple = ref(null); + const selectGeneric = ref(null); - const productStore = useProducts() + const productStore = useProducts(); - const mystr = ref('') + const mystr = ref(''); + const myval_tosee = ref(''); const valoriload = computed(() => { - return updateArrOptions() - }) + return updateArrOptions(); + }); - watch(() => props.options, (value: any, oldval: any) => { - if (!props.multiselect_by_server) { - valori.value = valoriload.value - } else { - // console.log('@@@ VALORI CHANGED (1)', valori.value) + watch( + () => props.options, + (value: any, oldval: any) => { + if (!props.multiselect_by_server) { + valori.value = valoriload.value; + } else { + // console.log('@@@ VALORI CHANGED (1)', valori.value) + } } - }, - ) - watch(() => props.value, (value: any, oldval: any) => { - update() - }, - ) + ); + watch( + () => props.value, + (value: any, oldval: any) => { + update(); + } + ); - watch(() => props.arrvalue, (value: any, oldval: any) => { - // console.log(' MODIF props.arrvalue', props.arrvalue) - update() - }, - ) + watch( + () => props.arrvalue, + (value: any, oldval: any) => { + // console.log(' MODIF props.arrvalue', props.arrvalue) + update(); + } + ); function saveOptInCookie(arrval: any) { // console.log('saveOptInCookie') if (arrval) { for (const id of arrval) { - const trovato = arrtempOpt.value.find((rec) => rec._id === id) + const trovato = arrtempOpt.value.find((rec) => rec._id === id); if (!trovato) { - const rec = valori.value.find((rec: any) => rec._id === id) + const rec = valori.value.find((rec: any) => rec._id === id); if (rec) { // console.log('SAVE OPT rec', rec) - const obj: any = {} - obj[`${props.optval}`] = id - obj[`${props.optlab}`] = rec[`${props.optlab}`] - arrtempOpt.value.push(obj) - let num = localStorage.getItem(props.tablesel + 'NUM') || 0 + const obj: any = {}; + obj[`${props.optval}`] = id; + obj[`${props.optlab}`] = rec[`${props.optlab}`]; + arrtempOpt.value.push(obj); + let num = localStorage.getItem(props.tablesel + 'NUM') || 0; try { if (!num) { - num = 0 + num = 0; } else { - num = parseInt(num.toString(), 10) + num = parseInt(num.toString(), 10); } } catch (e) { - num = 0 + num = 0; } // console.log('----------- valori.value', valori.value) // console.log('----------- arrtempOpt.value', arrtempOpt.value) - tools.localStSetItem(props.tablesel + num + props.optval, id) - const mysaved = tools.getValueByFunzOrVal(rec, props.optlab) - tools.localStSetItem(props.tablesel + num + props.optlab, mysaved) + tools.localStSetItem(props.tablesel + num + props.optval, id); + const mysaved = tools.getValueByFunzOrVal(rec, props.optlab); + tools.localStSetItem(props.tablesel + num + props.optlab, mysaved); - console.log(' SAVED: ', props.tablesel + num + props.optlab, '=', mysaved) + console.log( + ' SAVED: ', + props.tablesel + num + props.optlab, + '=', + mysaved + ); - num += 1 - tools.localStSetItem(props.tablesel + 'NUM', num.toString()) + num += 1; + tools.localStSetItem(props.tablesel + 'NUM', num.toString()); } } } } } - function changeval(newval: any) { // console.log(' ½½½½½½½ changeval', newval) if (props.multiple || props.multiselect_by_server) { // tools.localStSetItem(props.tablesel + '_' + newval, valori.value[newval]) if (props.type_out === costanti.FieldType.object) { - const arrout = [] + const arrout = []; for (const val of newval) { - const obj: any = {} + const obj: any = {}; if (typeof val !== 'object') { - obj[props.optval] = val - arrout.push(obj) + obj[props.optval] = val; + arrout.push(obj); } else { - arrout.push(val) + arrout.push(val); } } - myarrvalue.value = arrout + myarrvalue.value = arrout; } else { - myarrvalue.value = newval && newval['arrvalue'] ? newval['arrvalue'] : newval + myarrvalue.value = newval && newval['arrvalue'] ? newval['arrvalue'] : newval; } - saveOptInCookie(newval) - - console.log(' ----- Myselect changeval Arrvalue', myarrvalue.value) - emit('update:arrvalue', myarrvalue.value) - emit('changeval', myarrvalue.value) - + saveOptInCookie(newval); + console.log(' ----- Myselect changeval Arrvalue', myarrvalue.value); + emit('update:arrvalue', myarrvalue.value); + emit('changeval', myarrvalue.value); } else { - if (props.tablesel === shared_consts.TAB_COUNTRY) - myvalue.value = newval && newval['value'] ? newval['value'] : newval + myvalue.value = newval && newval['value'] ? newval['value'] : newval; else if (props.tablesel === shared_consts.TAB_CITIES) - myvalue.value = newval && newval['value'] ? newval['value'] : newval + myvalue.value = newval && newval['value'] ? newval['value'] : newval; else if (props.tablesel === shared_consts.TAB_PHONES) - myvalue.value = newval && newval['code'] ? newval['code'] : newval - else - myvalue.value = newval + myvalue.value = newval && newval['code'] ? newval['code'] : newval; + else myvalue.value = newval; // console.log('Myselect changeval', myvalue.value) if (myvalue.value && JSON.stringify(myvalue.value)) { - saveLastOpt(props.optval, JSON.stringify(myvalue.value)) + saveLastOpt(props.optval, JSON.stringify(myvalue.value)); } - saveOptInCookie([myvalue.value]) + saveOptInCookie([myvalue.value]); - emit('update:value', myvalue.value) - emit('changeval', myvalue.value) + emit('update:value', myvalue.value); + emit('changeval', myvalue.value); } } function saveLastOpt(key: string, myval: any) { - - let ind = 9 + let ind = 9; // get free number for (let i = 0; i < 10; i++) { - let myoldval = tools.getItemLS(props.tablesel + 'last_VAL' + i.toString()) - myoldval = tools.strToObj(myoldval) + let myoldval = tools.getItemLS(props.tablesel + 'last_VAL' + i.toString()); + myoldval = tools.strToObj(myoldval); if (myoldval && myoldval[key]) { if (myoldval[key] === myval) { // already exist - return + return; } // if (myoldval[key] !== myval) { if (!myoldval[key]) { - ind = i - break + ind = i; + break; } } else { - ind = i - break + ind = i; + break; } } // console.log('saveLastOpt', ind, 'key', key, 'myval', myval) - tools.localStSetItem(props.tablesel + 'last_OPT' + ind.toString(), key) - tools.localStSetItem(props.tablesel + 'last_VAL' + ind.toString(), myval) + tools.localStSetItem(props.tablesel + 'last_OPT' + ind.toString(), key); + tools.localStSetItem(props.tablesel + 'last_VAL' + ind.toString(), myval); } function mounted() { // console.log('CMYSELECT: mounted') - optionsreal.value = props.options + myval_tosee.value = props.myvaltosee + optionsreal.value = props.options; if (props.focus) { - focusVisibleSelect() + focusVisibleSelect(); } - update() - + update(); } function focusVisibleSelect() { - try { if (selectMultiServer.value && props.multiselect_by_server) { - selectMultiServer.value.focus() + selectMultiServer.value.focus(); } else if (selectPickup.value && props.pickup) { - selectPickup.value.focus() + selectPickup.value.focus(); } else if (selectMultiple.value && props.multiple) { - selectMultiple.value?.focus() + selectMultiple.value?.focus(); } else { - if (selectGeneric.value) - selectGeneric.value?.focus() + if (selectGeneric.value) selectGeneric.value?.focus(); } } catch (e) { - console.error('Err', e) + console.error('Err', e); } } function update() { - console.log('update', props.value, props) + console.log('update', props.value, props); // console.log(' #### mounted myselect', props.options, 'arrvalue', myarrvalue.value) - let rec: any + let rec: any; if (optionsreal.value) { if (!props.multiselect_by_server) { - rec = optionsreal.value.find((myrec: any) => myrec[`${props.optval}`] === props.value) + rec = optionsreal.value.find( + (myrec: any) => myrec[`${props.optval}`] === props.value + ); } } if (props.multiselect_by_server) { - const num = parseInt(localStorage.getItem(props.tablesel + 'NUM')!, 10) + const num = parseInt(localStorage.getItem(props.tablesel + 'NUM')!, 10); // console.log('num LOADED ', num) - arrtempOpt.value = [] + arrtempOpt.value = []; if (props.addall) { - let myobj: any = {} + let myobj: any = {}; if (typeof props.optlab === 'string') { - myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)') - myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI) + myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)'); + myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI); } - arrtempOpt.value.push(myobj) + arrtempOpt.value.push(myobj); } if (props.addnone) { - const myobj: any = {} + const myobj: any = {}; if (typeof props.optlab === 'string') { - myobj[props.optlab] = '[Nessuno]' - myobj[props.optval] = costanti.FILTER_NESSUNO + myobj[props.optlab] = '[Nessuno]'; + myobj[props.optval] = costanti.FILTER_NESSUNO; } - arrtempOpt.value = [myobj, ...arrtempOpt.value] + arrtempOpt.value = [myobj, ...arrtempOpt.value]; } for (let i = 0; i < num; i++) { - const itemId = parseInt(localStorage.getItem(props.tablesel + i + props.optval)!, 10) - const itemlab = localStorage.getItem(props.tablesel + i + props.optlab) + const itemId = parseInt( + localStorage.getItem(props.tablesel + i + props.optval)!, + 10 + ); + const itemlab = localStorage.getItem(props.tablesel + i + props.optlab); if (itemId) { - const obj: any = {} - obj[`${props.optval}`] = itemId - obj[`${props.optlab}`] = itemlab + const obj: any = {}; + obj[`${props.optval}`] = itemId; + obj[`${props.optlab}`] = itemlab; if (!arrtempOpt.value.find((rec) => rec._id === itemId)) - arrtempOpt.value.push(obj) + arrtempOpt.value.push(obj); } } // Check if exist other array: if (props.col) { - if (props.col.remote_table && props.col.remote_key && props.col.remote_field) { - try { - const myarrremote = props.row[props.col.remote_table] + const myarrremote = props.row[props.col.remote_table]; for (const myrec of myarrremote) { - const myidkey = myrec[props.col.remote_key] + const myidkey = myrec[props.col.remote_key]; if (!arrtempOpt.value.includes(myidkey)) { - const myobj: any = {} - myobj[props.col.remote_key] = myidkey + const myobj: any = {}; + myobj[props.col.remote_key] = myidkey; if (props.col.remote_field === 'comune' && !!myrec['prov']) { - myobj[props.col.remote_field] = myrec[props.col.remote_field] + ' (' + myrec['prov'] + ')' + myobj[props.col.remote_field] = + myrec[props.col.remote_field] + ' (' + myrec['prov'] + ')'; } else { - myobj[props.col.remote_field] = myrec[props.col.remote_field] + myobj[props.col.remote_field] = myrec[props.col.remote_field]; } - arrtempOpt.value.push(myobj) + arrtempOpt.value.push(myobj); } } - - } catch (e) { } - + } catch (e) {} } } - myarrvalue.value = [] - const myarr = props.arrvalue + myarrvalue.value = []; + const myarr = props.arrvalue; if (tools.isArray(myarr)) { for (const val of myarr) { - rec = arrtempOpt.value.find((myrec: any) => val === (myrec[`${props.optval}`])) + rec = arrtempOpt.value.find((myrec: any) => val === myrec[`${props.optval}`]); if (rec) { - myarrvalue.value.push(rec[`${props.optval}`]) + myarrvalue.value.push(rec[`${props.optval}`]); } else { - myarrvalue.value.push(val) + myarrvalue.value.push(val); } } } } else { if (props.addnone) { - const myobj: any = {} + const myobj: any = {}; if (typeof props.optlab === 'string') { - myobj[props.optlab] = '[Nessuno]' - myobj[props.optval] = costanti.FILTER_NESSUNO + myobj[props.optlab] = '[Nessuno]'; + myobj[props.optval] = costanti.FILTER_NESSUNO; } - myarrvalue.value = [myobj, ...myarrvalue.value] + myarrvalue.value = [myobj, ...myarrvalue.value]; } } @@ -457,43 +468,41 @@ export default defineComponent({ } if (props.multiple) { - - const arrrec = [] - let myarr = props.arrvalue + const arrrec = []; + let myarr = props.arrvalue; if (myarr && !tools.isArray(myarr)) { - myarr = [myarr] + myarr = [myarr]; } if (myarr) { for (const val of myarr) { - rec = optionsreal.value.find((myrec: any) => val === (myrec[`${props.optval}`])) + rec = optionsreal.value.find( + (myrec: any) => val === myrec[`${props.optval}`] + ); if (rec) { - arrrec.push(rec[`${props.optval}`]) + arrrec.push(rec[`${props.optval}`]); } } } if (arrrec.length > 0) { - if (props.funcgetvaluebyid) - myarrvalue.value = props.funcgetvaluebyid(arrrec) - else - myarrvalue.value = arrrec + if (props.funcgetvaluebyid) myarrvalue.value = props.funcgetvaluebyid(arrrec); + else myarrvalue.value = arrrec; } else { if (props.arrvalue) { - myarrvalue.value = props.arrvalue + myarrvalue.value = props.arrvalue; } } } else { if (rec) { if (props.funcgetvaluebyid) - myvalue.value = props.funcgetvaluebyid(rec[`${props.optval}`]) - else - myvalue.value = tools.getValueByFunzOrVal(rec, props.optlab) + myvalue.value = props.funcgetvaluebyid(rec[`${props.optval}`]); + else myvalue.value = tools.getValueByFunzOrVal(rec, props.optlab); } else { // if (!props.useinput) { if (props.value) { - myvalue.value = props.value + myvalue.value = props.value; } else { - myvalue.value = '' + myvalue.value = ''; } // } } @@ -502,99 +511,97 @@ export default defineComponent({ } if (props.multiselect_by_server) { - valori.value = arrtempOpt.value + valori.value = arrtempOpt.value; } else { - valori.value = valoriload.value + valori.value = valoriload.value; } // console.log('cmyselect: myvalue.value', myvalue.value) } function updateArrOptions() { - - let myarr: any = [] + let myarr: any = []; // console.log(props.col.jointable, props.filter) if (props && props.col && props.col.jointable) { - optionsreal.value = globalStore.getTableJoinByName(props.col.jointable, props.col.addall, props.col.addnone, props.filter) + optionsreal.value = globalStore.getTableJoinByName( + props.col.jointable, + props.col.addall, + props.col.addnone, + props.filter + ); // console.log('optionsreal.value', optionsreal.value) } else { - optionsreal.value = props.options + optionsreal.value = props.options; } // console.log('optionsreal.value', optionsreal.value) - myarr = optionsreal.value + myarr = optionsreal.value; if (!fieldsTable.tableRemotePickup.includes(props.tablesel)) { - - const needle: any = props.value_extra + const needle: any = props.value_extra; // console.log('needle', needle, 'props.multiple', props.multiple) if (props.filter_table) { // console.log(' FILTERTABLE', props.filter_field, myarr) if (props.multiple) { - myarr = myarr.filter((rec: any) => rec[props.filter_field] === needle) + myarr = myarr.filter((rec: any) => rec[props.filter_field] === needle); } else { - myarr = myarr.filter((rec: any) => { if (tools.isArray(rec[props.filter_field])) - return rec[props.filter_field].includes(needle) - else - return false - }) + return rec[props.filter_field].includes(needle); + else return false; + }); } // console.log(' RISSSSSSSSS: ', myarr) } } if (props.addall) { - let myobj: any = {} + let myobj: any = {}; // if (typeof props.optlab === 'string') { - myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)') - myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI) + myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)'); + myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI); // } - if (myarr && !tools.isObjectEmpty(myobj)) - myarr = [myobj, ...myarr] + if (myarr && !tools.isObjectEmpty(myobj)) myarr = [myobj, ...myarr]; } if (props.addnone) { - const myobj: any = {} + const myobj: any = {}; if (typeof props.optlab === 'string') { - myobj[props.optlab] = '[Nessuno]' - myobj[props.optval] = costanti.FILTER_NESSUNO + myobj[props.optlab] = '[Nessuno]'; + myobj[props.optval] = costanti.FILTER_NESSUNO; } - if (myarr) - myarr = [myobj, ...myarr] + if (myarr) myarr = [myobj, ...myarr]; } if (props.addlast) { - myarr = getLastInserted(myarr) + myarr = getLastInserted(myarr); } // console.log(' myarr: ', myarr) - return myarr + return myarr; } function getLastInserted(myarr: any) { for (let ind = 0; ind < 10; ind++) { - const optlab = tools.getItemLS(props.tablesel + 'last_OPT' + ind.toString()) - let optval = tools.getItemLS(props.tablesel + 'last_VAL' + ind.toString()) - if (optval) - optval = JSON.parse(optval) + const optlab = tools.getItemLS(props.tablesel + 'last_OPT' + ind.toString()); + let optval = tools.getItemLS(props.tablesel + 'last_VAL' + ind.toString()); + if (optval) optval = JSON.parse(optval); // console.log(ind, '¶¶¶¶¶¶¶¶¶¶ optlab', optlab, 'optval', optval) - const myobj2: any = {} + const myobj2: any = {}; if (typeof props.optlab === 'string') { if (optval && !!optval['comune']) { - myobj2[props.optlab] = optval['comune'] - myobj2[props.optval] = optval[optlab] - myarr = [...myarr, myobj2] + myobj2[props.optlab] = optval['comune']; + myobj2[props.optval] = optval[optlab]; + myarr = [...myarr, myobj2]; } } } - return myarr + return myarr; } function filterFn(val: any, update: any, abort: any) { @@ -604,47 +611,47 @@ export default defineComponent({ // console.log('props.filter_extra', props.filter_extra) // console.log('valori.value', valori.value) - let myarr: any = [] + let myarr: any = []; - mystr.value = val.toLocaleLowerCase() + mystr.value = val.toLocaleLowerCase(); - myarr = updateArrOptions() + myarr = updateArrOptions(); if (!fieldsTable.tableRemotePickup.includes(props.tablesel)) { if (myarr && myarr.length > 0) { - valori.value = myarr + valori.value = myarr; } else { if (props.filter_table) { - valori.value = [] + valori.value = []; } } if (!props.multiple && !props.multiselect_by_server) { - if (val === '') { - valori.value = myarr + valori.value = myarr; } else { - const optlab: any = props.optlab ? '' + props.optlab : '' + const optlab: any = props.optlab ? '' + props.optlab : ''; if (optlab) { valori.value = myarr.filter((v: any) => { - const mioval = tools.getRecordByField(optlab, v) - if (mioval) - return mioval?.toLowerCase().indexOf(mystr.value) > -1 - else - return false - - }) + const mioval = tools.getRecordByField(optlab, v); + if (mioval) return mioval?.toLowerCase().indexOf(mystr.value) > -1; + else return false; + }); } } } - return + return; } - - if (val.length <= 1 && !(fieldsTable.tableRemotePickup.includes(props.tablesel) && props.filter_extra)) { - console.log('@@@ LENGTH <= 1') - abort() - return + if ( + val.length <= 1 && + !( + fieldsTable.tableRemotePickup.includes(props.tablesel) && props.filter_extra + ) + ) { + console.log('@@@ LENGTH <= 1'); + abort(); + return; } // console.log('props.tablesel', props.tablesel) @@ -652,8 +659,8 @@ export default defineComponent({ if (fieldsTable.tableRemotePickup.includes(props.tablesel)) { try { // myarr = optionsreal.value - myarr = [] - if (mystr.value !== '' || props.filter_extra) + myarr = []; + if (mystr.value !== '' || props.filter_extra) { // myarr = [{_id:1, prov: 'RN', descr: 'Rimini'}] /* if (val === '1') { @@ -663,102 +670,113 @@ export default defineComponent({ myarr.push({ _id: 1, comune: 'PROVA 2', prov: 'AL' }) myarr.push({ _id: 2, comune: 'PROVA 2B', prov: 'AL' }) - }*/ { // @ts-ignore - myarr = await globalStore.loadPickup({ table: props.tablesel, search: mystr.value.trim(), filter: props.filter_extra }) + }*/ // @ts-ignore + myarr = await globalStore.loadPickup({ + table: props.tablesel, + search: mystr.value.trim(), + filter: props.filter_extra, + }); } if (myarr === null) { - console.log('@@@ VALORI VALUE XXX', valori.value) - valori.value = arrtempOpt.value + console.log('@@@ VALORI VALUE XXX', valori.value); + valori.value = arrtempOpt.value; } } catch (e) { - console.log('@@@ VALORI VALUE XXX', valori.value) - valori.value = arrtempOpt.value + console.log('@@@ VALORI VALUE XXX', valori.value); + valori.value = arrtempOpt.value; } // const needle = val.toLocaleLowerCase() // optFiltered.value = optFiltered.value.filter((v: any) => v.toLocaleLowerCase().indexOf(needle) > -1) if (props.addall) { - let myobj: any = {} + let myobj: any = {}; if (typeof props.optlab === 'string') { - myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)') - myobj = tools.setRecordByField(props.optval, myobj, costanti.FILTER_TUTTI) + myobj = tools.setRecordByField(props.optlab, myobj, '(Tutti)'); + myobj = tools.setRecordByField( + props.optval, + myobj, + costanti.FILTER_TUTTI + ); } - myarr = [myobj, ...myarr] + myarr = [myobj, ...myarr]; } if (props.addnone) { - const myobj: any = {} + const myobj: any = {}; if (typeof props.optlab === 'string') { - myobj[props.optlab] = '[Nessuno]' - myobj[props.optval] = costanti.FILTER_NESSUNO + myobj[props.optlab] = '[Nessuno]'; + myobj[props.optval] = costanti.FILTER_NESSUNO; } - myarr = [myobj, ...myarr] + myarr = [myobj, ...myarr]; } if (props.addlast) { - myarr = getLastInserted(myarr) + myarr = getLastInserted(myarr); } } if (myarr && myarr.length > 0) { - valori.value = myarr + valori.value = myarr; if (props.multiselect_by_server) { // console.log('@@@ VALORI CHANGED (3)', valori.value) } } else { - valori.value = [] + valori.value = []; } - console.log('*** OUT: tablesel', props.tablesel, 'filterFn', myarr) + console.log('*** OUT: tablesel', props.tablesel, 'filterFn', myarr); }, // "ref" is the Vue reference to the QSelect (ref: any) => { if (!props.useinput) { // console.log('ref.options', ref.options) if (val !== '' && ref.options.length > 0) { - ref.setOptionIndex(-1) // reset optionIndex in case there is something selected - ref.moveOptionSelection(1, true) // focus the first selectable option and do not update the input-value + ref.setOptionIndex(-1); // reset optionIndex in case there is something selected + ref.moveOptionSelection(1, true); // focus the first selectable option and do not update the input-value } } } - ) + ); } function abortFilterFn() { - console.log('delayed filter aborted') + console.log('delayed filter aborted'); } function checkIfShowRec(rec: any) { - return (rec._id > 0 && typeof rec._id === 'number') || rec._id !== 'number' + return (rec._id > 0 && typeof rec._id === 'number') || rec._id !== 'number'; } async function newvaluefuncfirst(value: any, done: any) { if (props.newvaluefunc && props.col) { - const fieldval = fieldsTable.getLabelByTable(props.col.jointable) + const fieldval = fieldsTable.getLabelByTable(props.col.jointable); // console.log('fieldval', fieldval, 'optionsreal.value', optionsreal.value) // Se esiste già, non crearlo const esiste = optionsreal.value.find((rec: any) => { // console.log('rec[fieldval]',rec[fieldval], value.toLowerCase()) - return rec[fieldval]?.toLowerCase() === value.toLowerCase() && (rec[props.filter_field] === props.value_extra) - }) - console.log('esiste', esiste) + return ( + rec[fieldval]?.toLowerCase() === value.toLowerCase() && + rec[props.filter_field] === props.value_extra + ); + }); + console.log('esiste', esiste); if (!esiste || (esiste && esiste.length === 0)) { // console.log('non esiste, lo creo ! ', value) - const newrec = await props.newvaluefunc(tools.CapitalizeAllWords(value)) + const newrec = await props.newvaluefunc(tools.CapitalizeAllWords(value)); if (newrec) { if (props.col && props.col.jointable) { // Reload // console.log(' A1', optionsreal.value) // valori.value = valoriload.value // optionsreal.value = valori.value - console.log('DOPO', optionsreal.value) + console.log('DOPO', optionsreal.value); } - console.log('newrec', newrec) - const myid = fieldsTable.getKeyByTable(props.col.jointable) - const recfound = valori.value.find((rec: any) => rec[myid] === newrec[myid]) + console.log('newrec', newrec); + const myid = fieldsTable.getKeyByTable(props.col.jointable); + const recfound = valori.value.find((rec: any) => rec[myid] === newrec[myid]); if (!recfound) { - done(newrec, 'add-unique') + done(newrec, 'add-unique'); } // console.log('myid', myid, optionsreal.value) @@ -790,12 +808,11 @@ export default defineComponent({ } function getIcon() { - if (props.icon_alternative) - return props.icon_alternative + if (props.icon_alternative) return props.icon_alternative; if (props.col && props.col['icon']) { - return props.col['icon'] + return props.col['icon']; } - return '' + return ''; } function selectText(event: any) { @@ -804,14 +821,14 @@ export default defineComponent({ } function getLabelValue(opt: any): string { - const collabel = props.optlab + const collabel = props.optlab; if (typeof collabel === 'function') { // Se collabel è una funzione, chiamala con opt - return collabel(opt) + return collabel(opt); } else if (typeof collabel === 'string') { // Se collabel è una stringa, usa il valore della proprietà corrispondente - return opt[collabel] || 'N/A' + return opt[collabel] || 'N/A'; } // Fallback generico @@ -820,39 +837,48 @@ export default defineComponent({ function getOptionLabel(option: any): string { // console.log('getOptionLabel', option) + let lab = ''; if (typeof props.optlab === 'function') { - return props.optlab(option); // Se optlab è una funzione, chiamala + lab = props.optlab(option); // Se optlab è una funzione, chiamala } else { - return option[props.optlab]; // Se optlab è una stringa, usa la proprietà corrispondente + if (typeof option === "object") { + lab = option[props.optlab]; // Se optlab è una stringa, usa la proprietà corrispondente + } else { + lab = myval_tosee.value ? myval_tosee.value : ''; + } } + if (!lab) { + // console.log('⚠️ LAB NON PRESENTE !'); + } + + return lab; } function clear() { - emit('clear') - myvalue.value = '' - mystr.value = '' + emit('clear'); + myvalue.value = ''; + mystr.value = ''; + myval_tosee.value = ''; } function searchOnGM(mystr: string) { - emit('searchOnGM', mystr) + emit('searchOnGM', mystr); } function applyLabelColorBasedOnProductStatus(myrec: any) { - let classi = '' + let classi = ''; if (props.tablesel === 'products') { if (productStore.isNonVendibile(myrec)) { - classi = 'bg-grey' + classi = 'bg-grey'; } if (!productStore.isDisponibile(myrec)) { - classi = 'bg-red-1' + classi = 'bg-red-1'; } } - return classi + return classi; } - - onMounted(mounted) - + onMounted(mounted); return { changeval, @@ -873,7 +899,6 @@ export default defineComponent({ mystr, searchOnGM, applyLabelColorBasedOnProductStatus, - } - } -}) - + }; + }, +}); diff --git a/src/components/CMySelect/CMySelect.vue b/src/components/CMySelect/CMySelect.vue index 41737225..1d1f08e2 100755 --- a/src/components/CMySelect/CMySelect.vue +++ b/src/components/CMySelect/CMySelect.vue @@ -39,7 +39,7 @@ @@ -108,7 +108,7 @@ :input-class="myclass" :options="valori" :option-value="optval" - :option-label="getOptionLabel" + :option-label="(opt) => getOptionLabel(opt)" :use-chips="tools.isValueNotEmpty(myvalue)" stack-label clearable @@ -130,7 +130,7 @@ diff --git a/src/components/CMyUser/CMyUser.scss b/src/components/CMyUser/CMyUser.scss index b892863a..04c8c91b 100755 --- a/src/components/CMyUser/CMyUser.scss +++ b/src/components/CMyUser/CMyUser.scss @@ -1,4 +1,439 @@ -.myflex{ - display: flex; - flex: 1; +// ======================================== +// CMyUser - SCSS Moderno con Gradienti +// ======================================== + +$primary-color: #1976d2; +$primary-light: #42a5f5; +$primary-dark: #1565c0; +$secondary-color: #26a69a; +$positive-color: #21ba45; +$negative-color: #c10015; +$info-color: #31ccec; +$warning-color: #f2c037; + +$grey-text: #555; +$grey-light: #999; + +$border-radius-sm: 8px; +$border-radius: 12px; +$transition-speed: 0.3s; +$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08); +$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1); +$shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.15); + +$mobile-breakpoint: 768px; + +// ======================================== +// Q-ITEM CONTAINER (con gradiente) +// ======================================== +.q-item { + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 50%, #ffffff 100%); + border-radius: $border-radius; + padding: 10px 12px; + margin: 8px 0; + transition: all $transition-speed cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: $shadow-sm; + position: relative; + overflow: hidden; + border: 1px solid rgba(0, 0, 0, 0.06); + + // Effetto luce scorrevole + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); + transition: left 0.6s ease; + z-index: 0; + } + + @media (max-width: $mobile-breakpoint) { + padding: 8px 10px; + margin: 6px 0; + } + + // Hover effect + &.clickable:hover, + &[clickable]:hover { + background: linear-gradient(135deg, #ffffff 0%, #f0f4f8 50%, #ffffff 100%); + box-shadow: $shadow-md; + transform: translateY(-2px); + border-color: rgba($primary-color, 0.15); + + &::before { + left: 100%; + } + } + + // Assicura che i contenuti siano sopra l'effetto luce + >* { + position: relative; + z-index: 1; + } } + +// ======================================== +// AVATAR (con effetto glow) +// ======================================== +.q-avatar { + transition: all $transition-speed ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + border: 2px solid rgba(255, 255, 255, 0.8); + position: relative; + + &::after { + content: ''; + position: absolute; + inset: -2px; + border-radius: 50%; + background: linear-gradient(135deg, $primary-light, $secondary-color); + opacity: 0; + transition: opacity $transition-speed ease; + z-index: -1; + } + + .q-item:hover & { + transform: scale(1.05); + box-shadow: 0 4px 16px rgba($primary-color, 0.3); + + &::after { + opacity: 0.3; + } + } + + @media (max-width: $mobile-breakpoint) { + width: 50px !important; + height: 50px !important; + } +} + +// ======================================== +// PROFILE IMAGE +// ======================================== +.imgprofile { + border-radius: 50%; + object-fit: cover; +} + +// ======================================== +// USERNAME (con gradiente) +// ======================================== +.username { + font-weight: 600; + background: linear-gradient(135deg, $primary-color, rgba($primary-color, 0.85)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-size: 1rem; + transition: all $transition-speed ease; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.9375rem; + } + + .q-item:hover & { + background: linear-gradient(135deg, color-darken($primary-color, 5%), $primary-color); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } +} + +// ======================================== +// PROVINCE DISPLAY (con gradiente) +// ======================================== +.show_province_title, +.show_comune_title { + font-style: italic; + text-align: right; + font-size: 0.8125rem; + color: $grey-text; + margin-top: 4px; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.75rem; + } +} + +.show_province, +.show_comune { + font-weight: 600; + padding: 2px 8px; + border-radius: 6px; + background: linear-gradient(135deg, rgba($info-color, 0.1), rgba($info-color, 0.05)); + border: 1px solid rgba($info-color, 0.3); + color: color-darken($info-color, 15%); + transition: all $transition-speed ease; + + &:hover { + background: linear-gradient(135deg, rgba($info-color, 0.15), rgba($info-color, 0.08)); + border-color: $info-color; + } +} + +// ======================================== +// Q-ITEM LABEL +// ======================================== +.q-item__label { + line-height: 1.5; + margin-bottom: 3px; + + &:last-child { + margin-bottom: 0; + } + + strong { + font-weight: 600; + color: color-darken($grey-text, 10%); + } + + em { + font-style: italic; + color: $grey-text; + font-size: 0.875rem; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.8125rem; + } + } + + // Caption style + &[caption] { + color: $grey-light; + font-size: 0.8125rem; + margin-top: 2px; + + @media (max-width: $mobile-breakpoint) { + font-size: 0.75rem; + } + } +} + +// ======================================== +// MENU BUTTON (con glassmorphism) +// ======================================== +.q-btn { + transition: all $transition-speed ease; + + &[rounded] { + &.q-btn--round { + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(8px); + box-shadow: $shadow-sm; + border: 1px solid rgba(0, 0, 0, 0.06); + + &:hover { + background: rgba(255, 255, 255, 0.95); + box-shadow: $shadow-md; + transform: scale(1.1) rotate(90deg); + } + } + } +} + +// ======================================== +// MENU DROPDOWN (con gradienti) +// ======================================== +.q-menu { + background: linear-gradient(to bottom, #ffffff, #f8f9fa); + backdrop-filter: blur(10px); + border: 1px solid rgba(0, 0, 0, 0.08); + box-shadow: $shadow-lg; + border-radius: $border-radius-sm; + + .q-list { + padding: 6px; + background: transparent; + + @media (max-width: $mobile-breakpoint) { + padding: 4px; + } + } + + .q-item { + border-radius: $border-radius-sm; + margin: 2px 0; + background: transparent; + border: none; + box-shadow: none; + + &::before { + display: none; + } + + &:hover { + background: linear-gradient(135deg, rgba($primary-color, 0.08), rgba($primary-color, 0.04)); + transform: translateX(4px) translateY(0); + box-shadow: 0 2px 8px rgba($primary-color, 0.1); + } + + @media (max-width: $mobile-breakpoint) { + padding: 8px 10px; + } + } + + .q-item__section--avatar { + min-width: 36px; + + @media (max-width: $mobile-breakpoint) { + min-width: 32px; + } + + .q-icon { + transition: all $transition-speed ease; + } + + .q-item:hover & .q-icon { + transform: scale(1.1); + } + } +} + +// ======================================== +// STATUS INDICATORS +// ======================================== + +// Reported user +[style*='color: red'] { + &[style*='font-weight: bold'] { + background: linear-gradient(135deg, rgba($negative-color, 0.12), rgba($negative-color, 0.06)); + padding: 4px 8px; + border-radius: 6px; + border-left: 3px solid $negative-color; + display: inline-block; + margin: 4px 0; + } +} + +// Facilitator note +[style*='color: blue'] { + em { + background: linear-gradient(135deg, rgba($primary-color, 0.08), rgba($primary-color, 0.04)); + padding: 3px 6px; + border-radius: 6px; + border-left: 2px solid $primary-color; + } +} + +// ======================================== +// DIALOG (con gradiente) +// ======================================== +.q-dialog { + .q-card { + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); + border-radius: $border-radius; + + @media (max-width: $mobile-breakpoint) { + border-radius: 0; + } + } + + .q-toolbar { + background: linear-gradient(135deg, $primary-color, $primary-dark) !important; + border-radius: $border-radius $border-radius 0 0; + padding: 12px 16px; + + @media (max-width: $mobile-breakpoint) { + padding: 10px 12px; + border-radius: 0; + } + + .q-toolbar-title { + font-weight: 600; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + } + } +} + +// ======================================== +// ANIMATIONS +// ======================================== +@keyframes userItemAppear { + from { + opacity: 0; + transform: translateY(10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.q-item { + animation: userItemAppear 0.3s ease-out; +} + +// ======================================== +// RESPONSIVE ADJUSTMENTS +// ======================================== +@media (max-width: $mobile-breakpoint) { + .q-item-section { + padding: 0 4px; + } + + .q-item__label { + line-height: 1.4; + } + + .q-btn { + &[rounded] { + padding: 6px; + } + } +} + +// ======================================== +// UTILITY CLASSES +// ======================================== + +// Glass effect variant +.glass-user-item { + .q-item { + background: rgba(255, 255, 255, 0.7) !important; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.3); + + &:hover { + background: rgba(255, 255, 255, 0.85) !important; + } + } +} + +// Highlighted user +.highlighted-user { + .q-item { + border-left: 4px solid $primary-color; + background: linear-gradient(to right, rgba($primary-color, 0.05), transparent 20%); + } +} + +// Online indicator (opzionale) +.online-indicator { + position: absolute; + bottom: 2px; + right: 2px; + width: 12px; + height: 12px; + border-radius: 50%; + background: linear-gradient(135deg, $positive-color, rgba($positive-color, 0.9)); + border: 2px solid white; + box-shadow: 0 0 8px rgba($positive-color, 0.6); + animation: pulse 2s infinite; +} + +@keyframes pulse { + + 0%, + 100% { + box-shadow: 0 0 8px rgba($positive-color, 0.6); + } + + 50% { + box-shadow: 0 0 16px rgba($positive-color, 0.9); + } +} \ No newline at end of file diff --git a/src/components/CMyUser/CMyUser.vue b/src/components/CMyUser/CMyUser.vue index ad679064..c41dd836 100755 --- a/src/components/CMyUser/CMyUser.vue +++ b/src/components/CMyUser/CMyUser.vue @@ -1,6 +1,9 @@ - + diff --git a/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.scss b/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.scss index 54c3a472..6619655d 100755 --- a/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.scss +++ b/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.scss @@ -251,7 +251,6 @@ $transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .step-completed & { - text-decoration: line-through; opacity: 0.8; } } diff --git a/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.ts b/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.ts index 2d53c38e..c7588545 100755 --- a/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.ts +++ b/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.ts @@ -15,6 +15,7 @@ import type { ICircuit, IUserFields } from 'model'; import { costanti } from '@costanti'; import { shared_consts } from '@src/common/shared_vuejs'; +import { CMyFieldDb } from '@src/components/CMyFieldDb'; import { CMySelectCity } from '@src/components/CMySelectCity'; import { CMyCircuit } from '@src/components/CMyCircuit'; import { CMyUser } from '@src/components/CMyUser'; @@ -29,6 +30,7 @@ export default defineComponent({ CMySelectCity, CMyCircuit, CMyUser, + CMyFieldDb, }, props: { showAlsoIfSkipped: { @@ -68,7 +70,6 @@ export default defineComponent({ // ======================================== // TUTORIAL STATE // ======================================== - const contact = ref(null); const activeStep = ref('telegram'); const currentStepIndex = ref(0); // Indice step corrente per navigazione const nascondiavviso = ref(false); @@ -89,6 +90,14 @@ export default defineComponent({ return userStore.my?.profile?.telegram_verification_skipped; }); + const contact = computed(() => { + if (!props.mycontact) { + return userStore.my; + } else { + return props.mycontact; + } + }); + const isTelegramVerified = computed(() => { return ( !!(userStore.my?.profile?.username_telegram && userStore.my?.profile?.teleg_id) || @@ -121,6 +130,13 @@ export default defineComponent({ return ''; }); + const strComune = computed(() => { + if (contact.value && contact.value.profile.resid_str_comune) { + return contact.value.profile.resid_str_comune; + } + return ''; + }); + const card = computed(() => { if (contact.value && contact.value.profile.resid_card) { return contact.value.profile.resid_card; @@ -135,24 +151,24 @@ export default defineComponent({ // Step definitions const stepResidence = computed(() => ({ step: STEP_CITY, - title: t('tutorial.step_residence_title'), + title: t('tutorial.step_residence_comune_title'), extratitle: function () { - return contact.value?.profile.resid_province - ? ': ' + contact.value.profile.resid_province + return contact.value?.profile.resid_str_comune + ? ': ' + contact.value.profile.resid_str_comune : ''; }, label: t('tutorial.step_residence'), checkOk: function (): boolean { return contact.value - ? !!contact.value.profile.resid_province && - contact.value.profile.resid_province !== '' && - contact.value.profile.resid_province !== '0' + ? !!contact.value.profile.resid_str_comune && + contact.value.profile.resid_str_comune !== '' && + contact.value.profile.resid_str_comune !== '0' : false; }, checkOkReal: function (): boolean { return this.checkOk(); }, - icon: 'house', + icon: 'fas fa-map-marker-alt', required: true, })); @@ -215,7 +231,7 @@ export default defineComponent({ } return false; }, - icon: 'img: /images/1ris_rosso_100.png', + icon: 'flag-icon flag-icon-it', required: false, })); @@ -233,6 +249,14 @@ export default defineComponent({ step: 0, }); + // Step 2: Comune + steps.push({ + key: 'comune', + name: 'Comune di Residenza', + completed: stepResidence.value.checkOk(), + step: STEP_CITY, + }); + // Step 3: Circuito Locale (solo se disponibile) steps.push({ key: 'circuit', @@ -271,14 +295,43 @@ export default defineComponent({ badge: { color: isTelegramVerified.value ? 'positive' - : (isTelegramSkipped.value + : isTelegramSkipped.value ? 'red' - : 'orange'), + : 'orange', label: isTelegramVerified.value ? 'Fatto' - : (isTelegramSkipped.value + : isTelegramSkipped.value ? 'Saltato' - : 'Da fare'), + : 'Da fare', + }, + }, + { + key: 'comune', + visible: true, + disabled: false, + title: 'Comune Residenza', + description: + 'Seleziona il tuo comune di residenza, o dove vivi abitualmente, per connetterti con la Community Locale.', + completed: stepResidence.value.checkOk(), + avatar: { + color: stepResidence.value.checkOk() ? 'positive' : 'primary', + icon: stepResidence.value.checkOk() ? 'check' : stepResidence.value.icon, + isImage: false, + }, + caption: stepResidence.value.checkOk() + ? 'Completato: ' + stepResidence.value.extratitle() + ' (' + strProv.value + ')' + : stepResidence.value.extratitle(), + badge: { + color: stepResidence.value.checkOkReal() + ? 'positive' + : isSalta(STEP_CITY) + ? 'red' + : 'orange', + label: stepResidence.value.checkOkReal() + ? 'Fatto' + : isSalta(STEP_CITY) + ? 'Saltato' + : 'Da fare', }, }, { @@ -286,12 +339,11 @@ export default defineComponent({ visible: true, disabled: false, title: 'Circuito RIS Locale', - description: - 'Seleziona la tua provincia di residenza per connetterti con la community locale.', + description: 'Unisciti al circuito della tua zona', completed: stepCircuit.value.checkOk(), avatar: { - color: stepCircuit.value.checkOk() ? 'positive' : 'orange', - icon: stepCircuit.value.checkOk() ? 'check' : '', + color: stepCircuit.value.checkOk() ? 'positive' : 'primary', + icon: stepCircuit.value.checkOk() ? 'check' : stepCircuit.value.icon, isImage: !stepCircuit.value.checkOk(), imageSrc: '/images/1ris_rosso_100.png', }, @@ -301,14 +353,14 @@ export default defineComponent({ badge: { color: stepCircuit.value.checkOkReal() ? 'positive' - : (isSalta(STEP_CIRCUIT) + : isSalta(STEP_CIRCUIT) ? 'red' - : 'orange'), + : 'orange', label: stepCircuit.value.checkOkReal() ? 'Fatto' - : (isSalta(STEP_CIRCUIT) + : isSalta(STEP_CIRCUIT) ? 'Saltato' - : 'Da fare'), + : 'Da fare', }, }, { @@ -321,7 +373,9 @@ export default defineComponent({ completed: stepCircuitItalia.value.checkOk(), avatar: { color: stepCircuitItalia.value.checkOk() ? 'positive' : 'grey-6', - icon: stepCircuitItalia.value.checkOk() ? 'check' : '', + icon: stepCircuitItalia.value.checkOk() + ? 'check' + : stepCircuitItalia.value.icon, isImage: !stepCircuitItalia.value.checkOk(), imageSrc: '/images/1ris_rosso_100.png', }, @@ -383,6 +437,7 @@ export default defineComponent({ const totalSteps = computed(() => { let count = 0; count++; // Telegram + count++; // Comune count++; // Circuito Locale // if (mycircuit.value) if (circuititalia.value) count++; // Circuito Italia @@ -392,6 +447,7 @@ export default defineComponent({ const completedSteps = computed(() => { let count = 0; if (isTelegramVerified.value) count++; + if (stepResidence.value.checkOk()) count++; if (stepCircuit.value.checkOk()) count++; if (stepCircuitItalia.value.checkOk()) count++; return count; @@ -712,18 +768,14 @@ export default defineComponent({ // TUTORIAL METHODS // ======================================== const updateContact = () => { - if (!props.mycontact) { - contact.value = userStore.my; - } else { - contact.value = props.mycontact; - } + console.log('updateContact'); if ( contact.value && contact.value.profile && - contact.value.profile.resid_province === '0' + contact.value.profile.resid_str_comune === '0' ) { - contact.value.profile.resid_province = ''; + contact.value.profile.resid_str_comune = ''; } // Trova il primo step non completato e aprilo @@ -899,7 +951,10 @@ export default defineComponent({ userStore, globalStore, costanti, + strComune, t, + updateContact, + strProv, }; }, }); diff --git a/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.vue b/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.vue index 5f92b94a..aa6a7d82 100755 --- a/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.vue +++ b/src/components/CProfileCompletitionBanner/CProfileCompletitionBanner.vue @@ -1,6 +1,6 @@ diff --git a/src/components/editprofile/editprofile.vue b/src/components/editprofile/editprofile.vue index 6773cc86..034fe69d 100755 --- a/src/components/editprofile/editprofile.vue +++ b/src/components/editprofile/editprofile.vue @@ -1,5 +1,8 @@ - + -