- corretto componente CDateTime

- aggiunto componente CDateTimeStartEnd
This commit is contained in:
Surya Paolo
2025-10-05 23:58:57 +02:00
parent 58db59a751
commit 2f39d4f1d9
71 changed files with 1559 additions and 1642 deletions

View File

@@ -1,7 +1,7 @@
VITE_APP_ID="17" VITE_APP_ID="13"
VITE_APP_URL="https://localhost" VITE_APP_URL="https://localhost"
VITE_MONGODB_HOST="https://localhost:3000" VITE_MONGODB_HOST="https://localhost:3000"
VITE_LOGO_REG="piuchebuono-logo-full.png" VITE_LOGO_REG='riso-logo-full.png'
VITE_PUBLICKEY_PUSH='BDncvMiUZmjaCG2Kr1V9N0_33hOG-AuNSbHSvL24y2dzBiUjAxKm02emx5SeJvz2IGmtRf6YqCgopeQwCwUmZw8' VITE_PUBLICKEY_PUSH='BDncvMiUZmjaCG2Kr1V9N0_33hOG-AuNSbHSvL24y2dzBiUjAxKm02emx5SeJvz2IGmtRf6YqCgopeQwCwUmZw8'
VITE_DEBUG="1" VITE_DEBUG="1"
VITE_VUE_APP_ISTEST=0 VITE_VUE_APP_ISTEST=0

View File

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

View File

@@ -1,15 +1,15 @@
{ {
"name": "piuchebuono", "name": "riso",
"version": "1.2.71", "version": "1.2.71",
"description": "PiuCheBuono", "productName": "Riso 💚 - Rete Italiana Scambi Orizzontali",
"productName": "PiuCheBuono", "description": "Progetto RISO (Rete Italiana Scambi Orizzontali) 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", "author": "Surya",
"private": true, "private": true,
"keywords": [], "keywords": [],
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "PORT=8085 APP_VERSION='1.2.71' quasar dev", "dev": "APP_VERSION='1.2.71' PORT=8084 quasar dev",
"dev_noCheck": "SKIP_TSC=true quasar dev", "dev_noCheck": "SKIP_TSC=true quasar dev",
"build": "quasar build", "build": "quasar build",
"buildpwa": "NODE_ENV=production APP_VERSION='1.2.71' quasar build -m pwa", "buildpwa": "NODE_ENV=production APP_VERSION='1.2.71' quasar build -m pwa",
@@ -21,117 +21,117 @@
"lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt", "lintfile": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ./ > file.out.txt",
"lintfileNoJS": "eslint --ext .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", "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.71' quasar dev -m pwa", "pwa": "NODE_ENV=development PORT=8094 APP_VERSION='1.2.71' quasar dev -m pwa",
"spa": "NODE_ENV=development PORT=8085 APP_VERSION='1.2.71' quasar dev", "spa": "NODE_ENV=development PORT=8084 APP_VERSION='1.2.71' quasar dev",
"debug": "quasar dev --mode debug", "debug": "quasar dev --mode debug",
"test": "echo \"No test specified\" && exit 0", "test": "echo \"No test specified\" && exit 0",
"generate-sw": "workbox generateSW workbox-config.js", "generate-sw": "workbox generateSW workbox-config.js",
"postinstall": "quasar prepare" "postinstall": "quasar prepare"
}, },
"dependencies": { "dependencies": {
"@cubejs-client/core": "^1.2.26", "@cubejs-client/core": "^1.3.21",
"@quasar/extras": "^1.16.17", "@quasar/extras": "^1.17.0",
"@quasar/quasar-ui-qcalendar": "^4.1.2", "@quasar/quasar-ui-qcalendar": "^4.1.2",
"@types/jsbarcode": "^3.11.4", "@types/jsbarcode": "^3.11.4",
"@types/leaflet": "^1.9.17", "@types/leaflet": "^1.9.18",
"@vue/compat": "^3.5.13", "@vue/compat": "^3.5.16",
"@vue/compiler-sfc": "^3.5.13", "@vue/compiler-sfc": "^3.5.16",
"@vuelidate/core": "^2.0.3", "@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4", "@vuelidate/validators": "^2.0.4",
"acorn": "^8.14.1", "acorn": "^8.15.0",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"apexcharts": "^4.7.0",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",
"axios": "^1.8.4", "axios": "^1.9.0",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"chart.js": "^4.4.8", "chart.js": "^4.4.9",
"core-js": "^3.41.0", "core-js": "^3.43.0",
"crypto-browserify": "^3.12.1", "crypto-browserify": "^3.12.1",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"echarts": "5.6.0", "echarts": "5.6.0",
"eslint-plugin-n": "^17.16.2", "eslint-plugin-n": "^17.19.0",
"eslint-plugin-quasar": "^1.1.0", "eslint-plugin-quasar": "^1.1.0",
"graphql": "^16.10.0", "gsap": "^3.13.0",
"graphql-tag": "^2.12.6",
"gsap": "^3.12.7",
"html2pdf.js": "^0.10.3", "html2pdf.js": "^0.10.3",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"jsbarcode": "^3.11.6", "jsbarcode": "^3.12.1",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"leaflet-routing-machine": "^3.2.12", "leaflet-routing-machine": "^3.2.12",
"leaflet.markercluster": "^1.5.3", "leaflet.markercluster": "^1.5.3",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mongoose-paginate-v2": "^1.9.1",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^3.0.1", "pinia": "^3.0.3",
"qrcode-vue3": "^1.7.1",
"quasar": "^2.18.1", "quasar": "^2.18.1",
"quasar-extras": "^2.0.9", "quasar-extras": "^2.0.9",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"scrollreveal": "^4.0.9", "scrollreveal": "^4.0.9",
"typescript-eslint": "^8.27.0", "typescript-eslint": "^8.34.0",
"vee-validate": "^4.15.0", "vee-validate": "^4.15.1",
"vue": "^3.5.13", "vue": "^3.5.16",
"vue-class-component": "^8.0.0-rc.1", "vue-class-component": "^8.0.0-rc.1",
"vue-country-code": "^1.1.3", "vue-country-code": "^1.1.3",
"vue-echarts": "^7.0.3", "vue-echarts": "^7.0.3",
"vue-i18n": "^11.1.2", "vue-i18n": "^11.1.5",
"vue-idb": "^0.2.0", "vue-idb": "^0.2.0",
"vue-image-zoomer": "^2.4.4",
"vue-property-decorator": "^10.0.0-rc.3", "vue-property-decorator": "^10.0.0-rc.3",
"vue-router": "^4.5.0", "vue-router": "^4.5.1",
"vue-scroll-reveal": "^2.1.0", "vue-scroll-reveal": "^2.1.0",
"vue-social-sharing": "^4.0.0-alpha4", "vue-social-sharing": "^4.0.0-alpha4",
"vue-svgicon": "^4.0.0-alpha.3", "vue-svgicon": "^4.0.0-alpha.3",
"vue-timeago3": "^2.3.2", "vue-timeago3": "^2.3.2",
"vue2-dragula": "^2.5.5", "vue2-dragula": "^2.5.5",
"vue3-pdf-app": "^1.0.3", "vue3-apexcharts": "^1.8.0",
"vue3-qr-reader": "^1.0.0", "vue3-qr-reader": "^1.0.0",
"vuedraggable": "^4.1.0",
"vuex": "^4.1.0", "vuex": "^4.1.0",
"vuex-router-sync": "^6.0.0-rc.1", "vuex-router-sync": "^6.0.0-rc.1",
"workbox-core": "^7.3.0", "workbox-core": "^7.3.0",
"workbox-precaching": "^7.3.0", "workbox-precaching": "^7.3.0",
"workbox-routing": "^7.3.0", "workbox-routing": "^7.3.0",
"workbox-strategies": "^7.3.0", "workbox-strategies": "^7.3.0",
"workbox-window": "^7.3.0" "workbox-window": "^7.3.0",
"xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.23.0", "@eslint/js": "^9.28.0",
"@intlify/unplugin-vue-i18n": "^6.0.5", "@intlify/unplugin-vue-i18n": "^6.0.8",
"@quasar/app-vite": "^2.1.4", "@quasar/app-vite": "^2.2.1",
"@types/google.maps": "^3.58.1", "@types/google.maps": "^3.58.1",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/node": "^22.13.11", "@types/node": "^24.0.1",
"@types/nprogress": "^0.2.3", "@types/nprogress": "^0.2.3",
"@types/vue-tel-input": "^2.1.7", "@types/vue-tel-input": "^2.1.7",
"@types/vuelidate": "^0.7.22", "@types/vuelidate": "^0.7.22",
"@vue/devtools": "^7.7.2", "@vue/devtools": "^7.7.6",
"@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.5.0", "@vue/eslint-config-typescript": "^14.5.0",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",
"eslint": "9", "eslint": "9",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-vue": "^10.0.0", "eslint-plugin-vue": "^10.2.0",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"globals": "^16.0.0", "globals": "^16.2.0",
"http-proxy-middleware": "^3.0.3", "http-proxy-middleware": "^3.0.5",
"jest": "^29.7.0", "jest": "^30.0.0",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"nodemon": "^3.1.9", "nodemon": "^3.1.10",
"npm-check-updates": "^17.1.16", "npm-check-updates": "^18.0.1",
"parcel": "^2.14.1", "parcel": "^2.15.2",
"postcss": "^8.5.3", "postcss": "^8.5.5",
"postcss-loader": "^8.1.1", "postcss-loader": "^8.1.1",
"prettier": "3", "prettier": "3",
"strip-ansi": "=7.1.0", "strip-ansi": "=7.1.0",
"ts-jest": "^29.2.6", "ts-jest": "^29.4.0",
"typescript": "5.7.3", "typescript": "5.8.3",
"vite-plugin-checker": "^0.9.1", "vite-plugin-checker": "^0.9.3",
"vue-cli-plugin-element-ui": "^1.1.4", "vue-cli-plugin-element-ui": "^1.1.4",
"vue-eslint-parser": "^10.1.1", "vue-eslint-parser": "^10.1.3",
"vue-tsc": "^2.2.8", "vue-tsc": "^2.2.10",
"vueify": "^9.4.1", "vueify": "^9.4.1",
"workbox-build": "^7.3.0" "workbox-build": "^7.3.0"
}, },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 90 KiB

BIN
public/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -61,6 +61,7 @@
"leaflet.markercluster": "^1.5.3", "leaflet.markercluster": "^1.5.3",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mongoose-paginate-v2": "^1.9.1",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"pinia": "^3.0.3", "pinia": "^3.0.3",

View File

@@ -1,7 +1,7 @@
{ {
"name": "PiuCheBuono", "name": "Riso",
"short_name": "PiuCheBuono", "short_name": "Riso",
"description": "PiuCheBuono è un GAS e Bottega", "description": "Siamo la Rete Italiana di Scambio Orizzontale, abbiamo creato questa piattaforma per metterla al servizio di chi vuole riscoprire il valore della condivisione e della cooperazione. Valori semplici e profondi che ci aiutano a ritrovare il Senso della Vita, perduto in questa società consumista, e riporti quei Sani Pricìpi Naturali ed Umani di Fratellanza che intere popolazioni antiche conoscevano bene.",
"display": "standalone", "display": "standalone",
"orientation": "portrait", "orientation": "portrait",
"background_color": "#fff", "background_color": "#fff",
@@ -11,47 +11,47 @@
"start_url": "/?homescreen=1", "start_url": "/?homescreen=1",
"icons": [ "icons": [
{ {
"src:": "/images/pcb-android-icon-512x512.png", "src:": "/images/riso-android-icon-512x512.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-android-icon-384x384.png", "src:": "/images/riso-android-icon-384x384.png",
"sizes": "384x384", "sizes": "384x384",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-android-icon-192x192.png", "src:": "/images/riso-android-icon-192x192.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-android-icon-144x144.png", "src:": "/images/riso-android-icon-144x144.png",
"sizes": "144x144", "sizes": "144x144",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-android-icon-96x96.png", "src:": "/images/riso-android-icon-96x96.png",
"sizes": "96x96", "sizes": "96x96",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-apple-icon-120x120.png", "src:": "/images/riso-apple-icon-120x120.png",
"sizes": "120x120", "sizes": "120x120",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-apple-icon-144x144.png", "src:": "/images/riso-apple-icon-144x144.png",
"sizes": "144x144", "sizes": "144x144",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-apple-icon-152x152.png", "src:": "/images/riso-apple-icon-152x152.png",
"sizes": "152x152", "sizes": "152x152",
"type": "image/png" "type": "image/png"
}, },
{ {
"src:": "/images/pcb-apple-icon-180x180.png", "src:": "/images/riso-apple-icon-180x180.png",
"sizes": "180x180", "sizes": "180x180",
"type": "image/png" "type": "image/png"
} }

View File

@@ -1,32 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>
<%= productName %>
</title>
<meta charset="utf-8">
<meta name="description" content="<%= productDescription %>">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="version" content="1.2.2">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>">
<!-- Aggiungi le intestazioni di controllo della cache -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
<link rel="icon" type="image/ico" href="favicon.ico">
</head>
<body>
<!-- DO NOT touch the following DIV -->
<div id="q-app"></div>
</body>
</html>

View File

@@ -1,10 +1,87 @@
.calendar_comp{ /* ====== Config ====== */
max-width: 170px; :root {
@media (max-width: 400px) { --picker-actions-h: 56px; /* altezza footer azioni */
max-width: 400px; }
/* Per device piccolissimi riduciamo l'altezza */
@media (max-width: 360px) {
:root { --picker-actions-h: 48px; }
}
/* ====== Campo visualizzazione valore (nel q-field) ====== */
.cdt-display {
min-height: 1.5rem;
line-height: 1.5rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* ====== Contenitori popup/dialog del picker ====== */
.picker-popup,
.picker-sheet {
display: flex;
flex-direction: column;
overflow: hidden;
.picker-toolbar {
position: sticky;
top: 0;
z-index: 2;
background: var(--q-color-white);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.picker-body {
flex: 1 1 auto;
overflow: auto;
padding: 0.5rem;
/* spazio per non coprire il contenuto col footer */
padding-bottom: calc(var(--picker-actions-h) + 0.5rem);
}
.picker-actions {
position: sticky;
bottom: 0;
z-index: 2;
background: var(--q-color-white);
border-top: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
display: flex;
justify-content: flex-end;
align-items: center;
gap: 0.5rem;
min-height: var(--picker-actions-h);
padding: 0.5rem;
.row {
flex-wrap: wrap;
}
.q-btn {
min-width: 0; /* evita overflow su schermi stretti */
}
} }
} }
.calendar_comp { /* ====== Stile responsive del contenitore input ====== */
vertical-align: center; .calendar_comp {
width: 100%;
max-width: 320px; /* dimensione confortevole su desktop stretti */
display: flex;
align-items: center; /* allinea testo/icone verticalmente */
vertical-align: middle; /* per elementi inline-block eventualmente ereditati */
@media (max-width: 400px) {
max-width: 100%; /* su mobile usa tutta la larghezza disponibile */
}
}
/* ====== Micro-tweak tipografici per bottoni, se serve compattezza ====== */
@media (max-width: 360px) {
.picker-actions .q-btn {
padding: 0 0.5rem;
font-size: 0.85rem;
}
} }

View File

@@ -1,190 +1,173 @@
import { defineComponent, ref, toRef, watch } from 'vue' import { defineComponent, ref, watch, computed } from 'vue';
import { tools } from '@src/store/Modules/tools' import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar' import { tools } from '@src/store/Modules/tools';
import { useCalendarStore } from '@store/CalendarStore' import { toolsext } from '@store/Modules/toolsext';
import { useI18n } from 'vue-i18n'
import { toolsext } from '@store/Modules/toolsext'
export default defineComponent({ export default defineComponent({
name: 'CDate', name: 'CDate',
emits: ['update:value', 'savetoclose', 'show', 'clear'],
props: { props: {
value: { value: { type: [String, null] as unknown as () => string | null, default: null },
type: String, valueDate: { type: String, default: '' },
required: false, data_class: { type: String, default: '' },
default: '', canEdit: { type: Boolean, default: true },
}, label: { type: String, required: true, default: 'Val:' },
valueDate: { disable: { type: Boolean, default: false },
type: String, bgcolor: { type: String, default: '' },
required: false, dense: { type: Boolean, default: false },
default: '', view: { type: String as () => 'date-time' | 'date' | 'time', default: 'date-time' },
}, addstrrequired: { type: String, default: '' },
data_class: { nullable: { type: Boolean, default: true },
type: String, nullText: { type: String, default: '—' },
required: false, clearIcon: { type: String, default: 'fas fa-ban' },
default: '', calendarIcon: { type: String, default: 'fas fa-calendar-day' },
}, clockIcon: { type: String, default: 'fas fa-clock' },
canEdit: {
type: Boolean,
required: false,
default: true,
},
label: {
type: String,
required: true,
default: 'Val:',
},
disable: {
type: Boolean,
required: false,
default: false,
},
bgcolor: {
type: String,
required: false,
default: '',
},
dense: {
type: Boolean,
required: false,
default: false,
},
view: {
type: String,
required: false,
default: 'date-time',
},
addstrrequired: {
type: String,
required: false,
default: '',
},
}, },
components: {},
setup(props, { emit }) { setup(props, { emit }) {
const $q = useQuasar() const $q = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
const showDateTimeScroller = ref(false) const isMobile = computed(() => $q.screen.lt.sm);
const saveit = ref(false) const isDesktop = computed(() => $q.screen.gt.sm)
const myvalue = ref('')
const mydate = ref(false) // LABEL RESPONSIVE per il bottone di conferma
const mytime = ref(false) const confirmLabelDate = computed(() =>
const valueprec = ref('') isMobile.value
// const myvalueDate = toRef(props, 'valueDate') ? t('common.set') || 'Imposta'
: `Imposta a ${tools.getstrDateLong(myvalue.value)}`
);
const confirmLabelTime = computed(() =>
isMobile.value
? t('common.set') || 'Imposta'
: `Imposta a ${tools.getstrTime(myvalue.value)}`
);
const showDateTimeScroller = ref(false); // desktop popup v-model
const saveit = ref(false);
const myvalue = ref<string | null>(null);
const mydate = ref(false);
const mytime = ref(false);
const valueprec = ref<string | null>(null);
// mobile dialog state
const dateDialog = ref(false);
const timeDialog = ref(false);
const dateDesktopDialog = ref(false)
const timeDesktopDialog = ref(false)
const hasValue = computed(() => !!myvalue.value);
function getclass() { function getclass() {
return 'calendar_comp ' + props.data_class return 'calendar_comp ' + props.data_class;
} }
function Opening() { function Opening() {
console.log('Opening', 'myvalue', myvalue.value) saveit.value = false;
saveit.value = false valueprec.value = myvalue.value;
valueprec.value = myvalue.value if (!myvalue.value) myvalue.value = tools.getstrYYMMDDDateTime(new Date());
if (myvalue.value === '') { emit('show');
// myvalueDate.value = tools.getstrYYMMDDDateTime(new Date())
myvalue.value = tools.getstrYYMMDDDateTime(new Date())
}
// console.log('Opening', myvalueDate, myvalue)
emit('show')
} }
function Closing() { function Closing() {
mydate.value = false mydate.value = false;
mytime.value = false mytime.value = false;
// console.log('Closing') if (!saveit.value && myvalue.value !== valueprec.value) {
if (!saveit.value) { myvalue.value = valueprec.value;
if (myvalue.value !== valueprec.value) { tools.showNeutralNotif($q, t('db.reccanceled'));
myvalue.value = valueprec.value
tools.showNeutralNotif($q, t('db.reccanceled'))
}
} }
} }
watch(() => props.value, (value, oldval) => { watch(
if (value) { () => props.value,
myvalue.value = tools.getstrYYMMDDDateTime(value) (val) => {
// myvalueDate.value = myvalue.value if (val === null || val === '') myvalue.value = null;
console.log('myvalue Date = ', myvalue.value) else myvalue.value = tools.getstrYYMMDDDateTime(val);
} },
{ immediate: true }
}) );
function savetoclose() { function savetoclose() {
// console.log('Close')
saveit.value = true saveit.value = true
showDateTimeScroller.value = false showDateTimeScroller.value = false
// chiudi mobile
dateDialog.value = false
timeDialog.value = false
// chiudi desktop
dateDesktopDialog.value = false
timeDesktopDialog.value = false
emit('savetoclose', myvalue.value, valueprec.value) emit('savetoclose', myvalue.value, valueprec.value)
} }
function scrollerPopupStyle280() { function scrollerPopupStyle280() {
if ($q.screen.lt.sm) { return { maxHeight: '420px', height: '420px', width: '320px' };
return {
width: '100vw',
height: '100vh',
}
} else {
return {
maxHeight: '400px',
height: '400px',
width: '280px',
}
}
} }
function created() { function changeval(newval: string | Date) {
if (props.value !== null) { const out =
myvalue.value = tools.getstrYYMMDDDateTime(props.value) typeof newval === 'string' ? newval : tools.getstrYYMMDDDateTime(newval);
} myvalue.value = out;
emit('update:value', out);
// console.log('created myvalue', myvalue) saveit.value = true;
emit('savetoclose', out, valueprec.value);
} }
function changeval(newval: Date) { function replacevalue() {
// console.log('changeval', newval, 'value=', value, 'myvalue=', myvalue) emit('update:value', valueprec.value as unknown as string)
emit('update:value', newval)
saveit.value = true
emit('savetoclose', myvalue.value, valueprec.value)
}
function replacevalue() {
// console.log('changeval', newval, 'value=', value, 'myvalue=', myvalue)
if (valueprec.value) {
emit('update:value', valueprec.value)
saveit.value = true
showDateTimeScroller.value = false
emit('savetoclose', valueprec.value, valueprec.value)
}
}
function mystyle() {
if (props.label !== '')
return ''
else
return ''
}
function getstrDate(mydate: Date | string) {
if (props.view === 'date-time') {
return tools.getstrDateTime(mydate)
} else {
return tools.getstrDate(mydate)
}
}
function azzera() {
saveit.value = true saveit.value = true
showDateTimeScroller.value = false showDateTimeScroller.value = false
emit('savetoclose', null, valueprec.value)
// chiudi mobile
dateDialog.value = false
timeDialog.value = false
// chiudi desktop
dateDesktopDialog.value = false
timeDesktopDialog.value = false
emit('savetoclose', valueprec.value, valueprec.value)
}
function clearDate() {
saveit.value = true
showDateTimeScroller.value = false
dateDialog.value = false
timeDialog.value = false
dateDesktopDialog.value = false
timeDesktopDialog.value = false
myvalue.value = null
emit('update:value', null as unknown as string)
emit('savetoclose', null, valueprec.value)
emit('clear')
tools.showNeutralNotif($q, t('common.cleared') || 'Valore rimosso')
}
function openDate() {
if (isMobile.value) { Opening(); dateDialog.value = true }
else { Opening(); dateDesktopDialog.value = true }
}
function openTime() {
if (isMobile.value) { Opening(); timeDialog.value = true }
else { Opening(); timeDesktopDialog.value = true }
}
function getstrDate(myd: string | Date | null) {
if (!myd) return props.nullText;
if (props.view === 'date-time') return tools.getstrDateTime(myd);
if (props.view === 'date') return tools.getstrDate(myd);
return tools.getstrTime(myd);
} }
created()
return { return {
toolsext, toolsext,
changeval, changeval,
scrollerPopupStyle280, scrollerPopupStyle280,
mystyle,
getstrDate, getstrDate,
savetoclose, savetoclose,
Closing, Closing,
@@ -196,7 +179,20 @@ export default defineComponent({
mydate, mydate,
mytime, mytime,
tools, tools,
azzera, clearDate,
} hasValue,
// responsive
isMobile,
dateDialog,
timeDialog,
openDate,
openTime,
valueprec,
confirmLabelDate,
confirmLabelTime,
isDesktop,
dateDesktopDialog,
timeDesktopDialog,
};
}, },
}) });

View File

@@ -1,5 +1,6 @@
<template> <template>
<div class="" :style="mystyle()"> <div>
<!-- input nascosto per compatibilità -->
<q-input <q-input
v-model="myvalue" v-model="myvalue"
v-show="false" v-show="false"
@@ -15,8 +16,7 @@
debounce="500" debounce="500"
@update:model-value="changeval" @update:model-value="changeval"
:input-class="getclass()" :input-class="getclass()"
> />
</q-input>
<q-field <q-field
:label="label" :label="label"
@@ -28,117 +28,202 @@
:bg-color="bgcolor" :bg-color="bgcolor"
debounce="500" debounce="500"
:input-class="getclass()" :input-class="getclass()"
:disable="disable"
> >
<template #control>
<template v-slot:control> <div
<div style=""> class="self-center full-width no-outline cdt-display"
<div tabindex="0"
class="self-center full-width no-outline" >
:style="mystyle()" {{ getstrDate(myvalue) }}
tabindex="0"
>
{{ getstrDate(myvalue) }}
</div>
</div> </div>
</template> </template>
<template v-slot:append>
<template #append>
<!-- Disattiva -->
<q-btn <q-btn
v-if="canEdit && nullable"
dense
flat
:icon="clearIcon"
:title="$t('common.clear') || 'Disattiva'"
@click="clearDate"
class="q-mr-xs"
/>
<!-- Apri Date -->
<q-btn
v-if="canEdit"
dense dense
color="primary" color="primary"
v-if="canEdit" :icon="calendarIcon"
icon="fas fa-calendar-day"
class="cursor-pointer" class="cursor-pointer"
@click="mydate = !mydate" @click="openDate"
> />
</q-btn>
<!-- Apri Time -->
<q-btn <q-btn
v-if="canEdit"
dense dense
color="primary" color="primary"
v-if="canEdit" :icon="clockIcon"
icon="fas fa-clock"
class="cursor-pointer" class="cursor-pointer"
@click="mytime = !mytime" @click="openTime"
> />
</q-btn>
<q-popup-proxy
v-if="mydate"
transition-show="flip-up"
v-model="showDateTimeScroller"
@before-show="Opening"
@before-hide="Closing"
>
<q-card class="justify-center">
<div class="q-gutter-md justify-center">
<q-date
v-model="myvalue"
mask="YYYY-MM-DD HH:mm"
color="purple"
@update:model-value="changeval"
@close="
() => {
savetoclose();
}
"
/>
</div>
<q-card-actions align="center">
<q-btn icon="fas fa-trash"
@click="azzera"></q-btn>
<div class="row justify-center">
<q-btn
:label="$t('dialog.cancel')"
@click="replacevalue"
></q-btn>
<q-btn
:label="'Imposta a ' + tools.getstrDateLong(myvalue)"
color="primary"
v-close-popup
></q-btn>
</div>
</q-card-actions>
</q-card>
</q-popup-proxy>
<q-popup-proxy
v-if="mytime"
transition-show="flip-up"
v-model="showDateTimeScroller"
@before-show="Opening"
@before-hide="Closing"
>
<q-card class="justify-center">
<div class="q-gutter-md justify-center">
<q-time
v-model="myvalue"
mask="YYYY-MM-DD HH:mm"
color="purple"
@update:model-value="changeval"
@close="
() => {
savetoclose();
}
"
/>
<div class="row justify-center">
<q-btn
:label="$t('dialog.cancel')"
@click="replacevalue"
></q-btn>
<q-btn
:label="'Imposta a ' + tools.getstrTime(myvalue)"
color="primary"
v-close-popup
></q-btn>
</div>
</div>
</q-card>
</q-popup-proxy>
</template> </template>
</q-field> </q-field>
<!-- ===== Desktop: Dialog centrati e limitati ===== -->
<!-- DATE (desktop) -->
<q-dialog
v-model="dateDesktopDialog"
transition-show="fade"
transition-hide="fade"
>
<q-card class="picker-modal-desktop">
<q-toolbar class="picker-toolbar">
<div class="text-subtitle2">{{ label }}</div>
<q-space />
<q-btn
v-if="nullable"
flat dense :icon="clearIcon"
:label="$t('common.clear') || 'Disattiva'"
color="negative"
@click="clearDate"
/>
</q-toolbar>
<div class="picker-body">
<q-date
v-model="myvalue"
mask="YYYY-MM-DD HH:mm"
color="purple"
class="fit"
@update:model-value="changeval"
/>
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="replacevalue" />
<q-btn :label="confirmLabelDate" color="primary" @click="savetoclose" />
</div>
</q-card>
</q-dialog>
<!-- TIME (desktop) -->
<q-dialog
v-model="timeDesktopDialog"
transition-show="fade"
transition-hide="fade"
>
<q-card class="picker-modal-desktop">
<q-toolbar class="picker-toolbar">
<div class="text-subtitle2">{{ label }}</div>
<q-space />
</q-toolbar>
<div class="picker-body">
<q-time
v-model="myvalue"
mask="YYYY-MM-DD HH:mm"
color="purple"
class="fit"
@update:model-value="changeval"
/>
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="replacevalue" />
<q-btn :label="confirmLabelTime" color="primary" @click="savetoclose" />
</div>
</q-card>
</q-dialog>
<!-- ===== Mobile: Dialog full screen ===== -->
<q-dialog
v-model="dateDialog"
maximized
transition-show="slide-up"
transition-hide="slide-down"
>
<q-card class="picker-sheet">
<q-toolbar class="picker-toolbar">
<q-btn
flat round dense icon="arrow_back"
@click="replacevalue"
/>
<div class="text-subtitle1 q-ml-sm">{{ label }}</div>
<q-space />
<q-btn
v-if="nullable"
flat dense :icon="clearIcon"
:label="$t('common.clear') || 'Disattiva'"
color="negative"
@click="clearDate"
/>
</q-toolbar>
<div class="picker-body">
<q-date
v-model="myvalue"
mask="YYYY-MM-DD HH:mm"
color="purple"
class="fit"
@update:model-value="changeval"
/>
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="replacevalue" />
<q-btn :label="confirmLabelDate" color="primary" @click="savetoclose" />
</div>
</q-card>
</q-dialog>
<q-dialog
v-model="timeDialog"
maximized
transition-show="slide-up"
transition-hide="slide-down"
>
<q-card class="picker-sheet">
<q-toolbar class="picker-toolbar">
<q-btn
flat round dense icon="arrow_back"
@click="replacevalue"
/>
<div class="text-subtitle1 q-ml-sm">{{ label }}</div>
<q-space />
<q-btn
v-if="nullable"
flat dense :icon="clearIcon"
:label="$t('common.clear') || 'Disattiva'"
color="negative"
@click="clearDate"
/>
</q-toolbar>
<div class="picker-body">
<q-time
v-model="myvalue"
mask="YYYY-MM-DD HH:mm"
color="purple"
class="fit"
@update:model-value="changeval"
/>
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="replacevalue" />
<q-btn :label="confirmLabelTime" color="primary" @click="savetoclose" />
</div>
</q-card>
</q-dialog>
</div> </div>
</template> </template>
<script lang="ts" src="./CDateTime.ts"> <script lang="ts" src="./CDateTime.ts"></script>
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './CDateTime.scss'; @import './CDateTime.scss';

View File

@@ -0,0 +1,95 @@
:root { --picker-actions-h: 56px; }
@media (max-width: 360px) { :root { --picker-actions-h: 48px; } }
.cdt-display {
min-height: 1.5rem;
line-height: 1.5rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.calendar_comp {
width: 100%;
max-width: 320px;
display: flex;
align-items: center;
vertical-align: middle;
@media (max-width: 400px) { max-width: 100%; }
}
/* Desktop dialog centrato */
.picker-modal-desktop {
width: clamp(420px, 56vw, 720px);
max-height: min(80vh, 640px);
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: 16px;
.picker-toolbar {
position: sticky; top: 0; z-index: 2;
background: var(--q-color-white);
border-bottom: 1px solid rgba(0,0,0,.08);
}
.picker-body {
flex: 1 1 auto;
overflow: auto;
padding: .5rem;
padding-bottom: calc(var(--picker-actions-h) + .5rem);
}
.picker-actions {
position: sticky; bottom: 0; z-index: 2;
background: var(--q-color-white);
border-top: 1px solid rgba(0,0,0,.08);
box-shadow: 0 -2px 8px rgba(0,0,0,.06);
display: flex; justify-content: flex-end; align-items: center;
gap: .5rem; min-height: var(--picker-actions-h); padding: .5rem;
.q-btn { min-width: 0; }
}
}
/* Mobile full-screen */
.picker-sheet {
display: flex; flex-direction: column; height: 100vh; overflow: hidden;
.picker-toolbar {
position: sticky; top: 0; z-index: 2;
background: var(--q-color-white);
border-bottom: 1px solid rgba(0,0,0,.08);
}
.picker-body {
flex: 1 1 auto; overflow: auto; padding: .5rem;
padding-bottom: calc(var(--picker-actions-h) + .5rem);
}
.picker-actions {
position: sticky; bottom: 0; z-index: 2;
background: var(--q-color-white);
border-top: 1px solid rgba(0,0,0,.08);
box-shadow: 0 -2px 8px rgba(0,0,0,.06);
display: flex; justify-content: flex-end; align-items: center;
gap: .5rem; min-height: var(--picker-actions-h); padding: .5rem;
.q-btn { min-width: 0; }
}
}
/* Dark mode */
.body--dark .picker-modal-desktop,
.q-dark .picker-modal-desktop,
.body--dark .picker-sheet,
.q-dark .picker-sheet {
.picker-toolbar, .picker-actions {
background: var(--q-color-dark) !important;
border-color: rgba(255,255,255,.12);
box-shadow: 0 -2px 8px rgba(0,0,0,.4);
}
}
@media (max-width: 360px) {
.picker-actions .q-btn { padding: 0 .5rem; font-size: .85rem; }
}

View File

@@ -0,0 +1,363 @@
import { defineComponent, ref, watch, computed } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { tools } from '@src/store/Modules/tools';
import { toolsext } from '@store/Modules/toolsext';
function toTS(s: string | null): number | null {
if (!s) return null;
const iso = s.includes('T') ? s : s.replace(' ', 'T');
const ts = Date.parse(iso);
return Number.isNaN(ts) ? null : ts;
}
export default defineComponent({
name: 'CDateTimeStartEnd',
emits: [
'update:startValue',
'update:endValue',
'show',
'savetoclose',
'clear-start',
'clear-end',
],
props: {
startValue: { type: [String, null] as unknown as () => string | null, default: null },
endValue: { type: [String, null] as unknown as () => string | null, default: null },
startLabel: { type: String, default: 'Inizio' },
endLabel: { type: String, default: 'Fine' },
data_class: { type: String, default: '' },
canEdit: { type: Boolean, default: true },
disable: { type: Boolean, default: false },
bgcolor: { type: String, default: '' },
dense: { type: Boolean, default: false },
view: { type: String as () => 'date-time' | 'date' | 'time', default: 'date-time' },
nullableStart: { type: Boolean, default: true },
nullableEnd: { type: Boolean, default: true },
nullText: { type: String, default: '—' },
calendarIcon: { type: String, default: 'fas fa-calendar-day' },
clockIcon: { type: String, default: 'fas fa-clock' },
clearIcon: { type: String, default: 'fas fa-ban' },
optionalText: { type: String, default: 'opzionale' },
enableEndText: { type: String, default: 'Attiva' },
},
setup(props, { emit }) {
const $q = useQuasar();
const { t } = useI18n();
const isMobile = computed(() => $q.screen.lt.sm);
// local state
const startVal = ref<string | null>(null);
const endVal = ref<string | null>(null);
const startPrev = ref<string | null>(null);
const endPrev = ref<string | null>(null);
// dialog states
const startDateDialog = ref(false);
const startTimeDialog = ref(false);
const endDateDialog = ref(false);
const endTimeDialog = ref(false);
const startDateDesktopDialog = ref(false);
const startTimeDesktopDialog = ref(false);
const endDateDesktopDialog = ref(false);
const endTimeDesktopDialog = ref(false);
const endError = ref<string>('');
// sync props -> local
watch(
() => props.startValue,
(v) => {
startVal.value = v ? tools.getstrYYMMDDDateTime(v) : null;
},
{ immediate: true }
);
watch(
() => props.endValue,
(v) => {
endVal.value = v ? tools.getstrYYMMDDDateTime(v) : null;
validateRange();
},
{ immediate: true }
);
function getstrDate(val: string | Date | null) {
if (!val) return props.nullText;
if (props.view === 'date-time') return tools.getstrDateTime(val);
if (props.view === 'date') return tools.getstrDate(val);
return tools.getstrTime(val);
}
function opening(kind: 'start' | 'end') {
if (kind === 'start') {
startPrev.value = startVal.value;
if (!startVal.value) startVal.value = tools.getstrYYMMDDDateTime(new Date());
} else {
endPrev.value = endVal.value;
if (!endVal.value)
endVal.value = startVal.value || tools.getstrYYMMDDDateTime(new Date());
}
endError.value = '';
emit('show');
}
function cancelStart() {
startVal.value = startPrev.value;
closeAllStart();
}
function cancelEnd() {
endVal.value = endPrev.value;
endError.value = '';
closeAllEnd();
}
function saveStart() {
const currStart = startVal.value;
const prevStart = startPrev.value;
// salva start
emit('update:startValue', currStart as unknown as string);
emit('savetoclose', { which: 'start', current: currStart, prev: prevStart });
// Se esiste end e l'intervallo è invalido, riallinea fine preservando l'ora originale
if (endVal.value) {
const tsStart = toTS(currStart);
const tsEnd = toTS(endVal.value);
if (tsStart !== null && tsEnd !== null && tsEnd < tsStart) {
endVal.value = buildEndWithStartDatePreservingEndTime(tsStart, tsEnd);
endError.value = '';
emit('update:endValue', endVal.value as unknown as string);
emit('savetoclose', { which: 'end', current: endVal.value, prev: endPrev.value });
tools.showNeutralNotif(
$q,
t('date.rangeFixed') || 'Fine allineata allinizio mantenendo lora originale'
);
}
}
closeAllStart();
}
/**
* Costruisce una nuova data di fine usando:
* - data (Y/M/D) = quella di start
* - ora (h:m:s:ms) = quella di end originale
* Se il risultato è ancora < start, sposta end al giorno successivo mantenendo la stessa ora.
*/
function buildEndWithStartDatePreservingEndTime(
tsStart: number,
tsEnd: number
): string {
// Se il componente è solo 'date', non c'è ora da preservare: end = start
if (props.view === 'date') {
return tools.getstrYYMMDDDateTime(new Date(tsStart));
}
const dStart = new Date(tsStart);
const dEnd = new Date(tsEnd);
// Ricostruisci end: data = start, ora = end originale
const newEnd = new Date(
dStart.getFullYear(),
dStart.getMonth(),
dStart.getDate(),
dEnd.getHours(),
dEnd.getMinutes(),
dEnd.getSeconds(),
dEnd.getMilliseconds()
);
// Se così è ancora < start (es. end 08:00, start 10:00 stesso giorno) → bump di 1 giorno
if (newEnd.getTime() < tsStart) {
newEnd.setDate(newEnd.getDate() + 1);
}
return tools.getstrYYMMDDDateTime(newEnd);
}
function saveEnd() {
if (!validateRange(true)) {
// blocco il salvataggio se ancora invalida
return;
}
emit('update:endValue', endVal.value as unknown as string);
emit('savetoclose', { which: 'end', current: endVal.value, prev: endPrev.value });
closeAllEnd();
}
function onStartChange(v: string | Date) {
startVal.value = typeof v === 'string' ? v : tools.getstrYYMMDDDateTime(v);
}
function onEndChange(v: string | Date) {
endVal.value = typeof v === 'string' ? v : tools.getstrYYMMDDDateTime(v);
validateRange();
}
function clearStart() {
startVal.value = null;
emit('update:startValue', null as unknown as string);
emit('savetoclose', { which: 'start', current: null, prev: startPrev.value });
// se non c'è inizio, rimuovo anche fine per coerenza
if (endVal.value) {
endVal.value = null;
emit('update:endValue', null as unknown as string);
emit('savetoclose', { which: 'end', current: null, prev: endPrev.value });
}
emit('clear-start');
tools.showNeutralNotif($q, t('common.cleared') || 'Valore rimosso');
closeAllStart();
}
function clearEnd() {
endVal.value = null;
emit('update:endValue', null as unknown as string);
emit('clear-end');
tools.showNeutralNotif($q, t('common.cleared') || 'Valore rimosso');
endError.value = '';
closeAllEnd();
}
function enableEnd() {
endVal.value = startVal.value || tools.getstrYYMMDDDateTime(new Date());
validateRange(true);
emit('update:endValue', endVal.value as unknown as string);
}
function openStartDate() {
opening('start');
if (isMobile.value) startDateDialog.value = true;
else startDateDesktopDialog.value = true;
}
function openStartTime() {
opening('start');
if (isMobile.value) startTimeDialog.value = true;
else startTimeDesktopDialog.value = true;
}
function openEndDate() {
opening('end');
if (isMobile.value) endDateDialog.value = true;
else endDateDesktopDialog.value = true;
}
function openEndTime() {
opening('end');
if (isMobile.value) endTimeDialog.value = true;
else endTimeDesktopDialog.value = true;
}
function closeAllStart() {
startDateDialog.value = false;
startTimeDialog.value = false;
startDateDesktopDialog.value = false;
startTimeDesktopDialog.value = false;
}
function closeAllEnd() {
endDateDialog.value = false;
endTimeDialog.value = false;
endDateDesktopDialog.value = false;
endTimeDesktopDialog.value = false;
}
function validateRange(showMsg = false): boolean {
endError.value = '';
const tsStart = toTS(startVal.value);
const tsEnd = toTS(endVal.value);
if (tsStart != null && tsEnd != null && tsEnd < tsStart) {
endError.value =
t('date.invalidRange') || 'La data di fine non può precedere linizio';
if (showMsg) tools.showNeutralNotif($q, endError.value);
return false;
}
return true;
}
const confirmLabelStartDate = computed(() =>
isMobile.value
? t('common.set') || 'Imposta'
: `Imposta a ${tools.getstrDateLong(startVal.value)}`
);
const confirmLabelStartTime = computed(() =>
isMobile.value
? t('common.set') || 'Imposta'
: `Imposta a ${tools.getstrTime(startVal.value)}`
);
const confirmLabelEndDate = computed(() =>
isMobile.value
? t('common.set') || 'Imposta'
: `Imposta a ${tools.getstrDateLong(endVal.value)}`
);
const confirmLabelEndTime = computed(() =>
isMobile.value
? t('common.set') || 'Imposta'
: `Imposta a ${tools.getstrTime(endVal.value)}`
);
const canEditEnd = computed(() => !!endVal.value || !props.nullableEnd);
return {
toolsext,
tools,
// values & labels
startVal,
endVal,
startLabel: computed(() => props.startLabel),
endLabel: computed(() => props.endLabel),
// ui flags
dense: props.dense,
bgcolor: props.bgcolor,
disable: props.disable,
data_class: props.data_class,
canEdit: props.canEdit,
nullableStart: props.nullableStart,
nullableEnd: props.nullableEnd,
nullText: props.nullText,
optionalText: props.optionalText,
enableEndText: props.enableEndText,
calendarIcon: props.calendarIcon,
clockIcon: props.clockIcon,
clearIcon: props.clearIcon,
// dialogs
startDateDialog,
startTimeDialog,
endDateDialog,
endTimeDialog,
startDateDesktopDialog,
startTimeDesktopDialog,
endDateDesktopDialog,
endTimeDesktopDialog,
// methods
getstrDate,
openStartDate,
openStartTime,
openEndDate,
openEndTime,
cancelStart,
cancelEnd,
saveStart,
saveEnd,
onStartChange,
onEndChange,
clearStart,
clearEnd,
enableEnd,
// helpers
confirmLabelStartDate,
confirmLabelStartTime,
confirmLabelEndDate,
confirmLabelEndTime,
isMobile,
canEditEnd,
endError,
};
},
});

View File

@@ -0,0 +1,271 @@
<template>
<div class="dtse">
<!-- ===== RIGA CAMPO INIZIO ===== -->
<q-field
:label="startLabel"
:stack-label="!!startLabel"
:value="startVal"
standout
:dense="dense"
label-color="blue-6"
:bg-color="bgcolor"
:disable="disable"
:input-class="'calendar_comp ' + data_class"
>
<template #control>
<div class="self-center full-width no-outline cdt-display" tabindex="0">
{{ getstrDate(startVal) }}
</div>
</template>
<template #append>
<!-- Disattiva INIZIO -->
<q-btn
v-if="canEdit && nullableStart && startVal"
dense flat :icon="clearIcon"
:title="$t('common.clear') || 'Disattiva'"
@click="clearStart"
class="q-mr-xs"
/>
<!-- Apri Date INIZIO -->
<q-btn
v-if="canEdit"
dense color="primary"
:icon="calendarIcon"
class="cursor-pointer"
@click="openStartDate"
/>
<!-- Apri Time INIZIO -->
<q-btn
v-if="canEdit"
dense color="primary"
:icon="clockIcon"
class="cursor-pointer"
@click="openStartTime"
/>
</template>
</q-field>
<!-- ===== RIGA CAMPO FINE ===== -->
<q-field
:label="endLabel + ' ' + (endVal ? '' : '(' + (optionalText || 'opzionale') + ')')"
:stack-label="!!endLabel"
:value="endVal"
standout
:dense="dense"
label-color="blue-6"
:bg-color="bgcolor"
:disable="disable"
:error="!!endError"
:error-message="endError"
:input-class="'calendar_comp ' + data_class"
class="q-mt-sm"
>
<template #control>
<div class="self-center full-width no-outline cdt-display" tabindex="0">
{{ endVal ? getstrDate(endVal) : nullText }}
</div>
</template>
<template #append>
<!-- Attiva/Disattiva FINE -->
<q-btn
v-if="canEdit && !endVal && nullableEnd"
dense flat icon="add"
:label="enableEndText || 'Attiva'"
@click="enableEnd"
class="q-mr-xs"
/>
<q-btn
v-if="canEdit && endVal && nullableEnd"
dense flat :icon="clearIcon"
:title="$t('common.clear') || 'Disattiva'"
@click="clearEnd"
class="q-mr-xs"
/>
<!-- Apri Date FINE -->
<q-btn
v-if="canEdit"
dense color="primary"
:icon="calendarIcon"
class="cursor-pointer"
@click="openEndDate"
:disable="!canEditEnd"
/>
<!-- Apri Time FINE -->
<q-btn
v-if="canEdit"
dense color="primary"
:icon="clockIcon"
class="cursor-pointer"
@click="openEndTime"
:disable="!canEditEnd"
/>
</template>
</q-field>
<!-- ===== DESKTOP: Dialog centrati ===== -->
<!-- START DATE (desktop) -->
<q-dialog v-model="startDateDesktopDialog" transition-show="fade" transition-hide="fade">
<q-card class="picker-modal-desktop">
<q-toolbar class="picker-toolbar">
<div class="text-subtitle2">{{ startLabel }}</div>
<q-space />
<q-btn v-if="nullableStart && startVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearStart" />
</q-toolbar>
<div class="picker-body">
<q-date v-model="startVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onStartChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelStart" />
<q-btn :label="confirmLabelStartDate" color="primary" @click="saveStart" />
</div>
</q-card>
</q-dialog>
<!-- START TIME (desktop) -->
<q-dialog v-model="startTimeDesktopDialog" transition-show="fade" transition-hide="fade">
<q-card class="picker-modal-desktop">
<q-toolbar class="picker-toolbar">
<div class="text-subtitle2">{{ startLabel }}</div>
<q-space />
<q-btn v-if="nullableStart && startVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearStart" />
</q-toolbar>
<div class="picker-body">
<q-time v-model="startVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onStartChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelStart" />
<q-btn :label="confirmLabelStartTime" color="primary" @click="saveStart" />
</div>
</q-card>
</q-dialog>
<!-- END DATE (desktop) -->
<q-dialog v-model="endDateDesktopDialog" transition-show="fade" transition-hide="fade">
<q-card class="picker-modal-desktop">
<q-toolbar class="picker-toolbar">
<div class="text-subtitle2">{{ endLabel }}</div>
<q-space />
<q-btn v-if="nullableEnd && endVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearEnd" />
</q-toolbar>
<div class="picker-body">
<q-date v-model="endVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onEndChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelEnd" />
<q-btn :label="confirmLabelEndDate" color="primary" @click="saveEnd" :disable="!!endError" />
</div>
</q-card>
</q-dialog>
<!-- END TIME (desktop) -->
<q-dialog v-model="endTimeDesktopDialog" transition-show="fade" transition-hide="fade">
<q-card class="picker-modal-desktop">
<q-toolbar class="picker-toolbar">
<div class="text-subtitle2">{{ endLabel }}</div>
<q-space />
<q-btn v-if="nullableEnd && endVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearEnd" />
</q-toolbar>
<div class="picker-body">
<q-time v-model="endVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onEndChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelEnd" />
<q-btn :label="confirmLabelEndTime" color="primary" @click="saveEnd" :disable="!!endError" />
</div>
</q-card>
</q-dialog>
<!-- ===== MOBILE: Full-screen ===== -->
<!-- START DATE -->
<q-dialog v-model="startDateDialog" maximized transition-show="slide-up" transition-hide="slide-down">
<q-card class="picker-sheet">
<q-toolbar class="picker-toolbar">
<q-btn flat round dense icon="arrow_back" @click="cancelStart" />
<div class="text-subtitle1 q-ml-sm">{{ startLabel }}</div>
<q-space />
<q-btn v-if="nullableStart && startVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearStart" />
</q-toolbar>
<div class="picker-body">
<q-date v-model="startVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onStartChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelStart" />
<q-btn :label="confirmLabelStartDate" color="primary" @click="saveStart" />
</div>
</q-card>
</q-dialog>
<!-- START TIME -->
<q-dialog v-model="startTimeDialog" maximized transition-show="slide-up" transition-hide="slide-down">
<q-card class="picker-sheet">
<q-toolbar class="picker-toolbar">
<q-btn flat round dense icon="arrow_back" @click="cancelStart" />
<div class="text-subtitle1 q-ml-sm">{{ startLabel }}</div>
<q-space />
<q-btn v-if="nullableStart && startVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearStart" />
</q-toolbar>
<div class="picker-body">
<q-time v-model="startVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onStartChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelStart" />
<q-btn :label="confirmLabelStartTime" color="primary" @click="saveStart" />
</div>
</q-card>
</q-dialog>
<!-- END DATE -->
<q-dialog v-model="endDateDialog" maximized transition-show="slide-up" transition-hide="slide-down">
<q-card class="picker-sheet">
<q-toolbar class="picker-toolbar">
<q-btn flat round dense icon="arrow_back" @click="cancelEnd" />
<div class="text-subtitle1 q-ml-sm">{{ endLabel }}</div>
<q-space />
<q-btn v-if="nullableEnd && endVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearEnd" />
</q-toolbar>
<div class="picker-body">
<q-date v-model="endVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onEndChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelEnd" />
<q-btn :label="confirmLabelEndDate" color="primary" @click="saveEnd" :disable="!!endError" />
</div>
</q-card>
</q-dialog>
<!-- END TIME -->
<q-dialog v-model="endTimeDialog" maximized transition-show="slide-up" transition-hide="slide-down">
<q-card class="picker-sheet">
<q-toolbar class="picker-toolbar">
<q-btn flat round dense icon="arrow_back" @click="cancelEnd" />
<div class="text-subtitle1 q-ml-sm">{{ endLabel }}</div>
<q-space />
<q-btn v-if="nullableEnd && endVal" flat dense :icon="clearIcon" :label="$t('common.clear') || 'Disattiva'"
color="negative" @click="clearEnd" />
</q-toolbar>
<div class="picker-body">
<q-time v-model="endVal" mask="YYYY-MM-DD HH:mm" color="purple" class="fit" @update:model-value="onEndChange" />
</div>
<div class="picker-actions q-pa-sm">
<q-btn flat :label="$t('dialog.cancel')" @click="cancelEnd" />
<q-btn :label="confirmLabelEndTime" color="primary" @click="saveEnd" :disable="!!endError" />
</div>
</q-card>
</q-dialog>
</div>
</template>
<script lang="ts" src="./CDateTimeStartEnd.ts"></script>
<style lang="scss" scoped>
@import './CDateTimeStartEnd.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CDateTimeStartEnd} from './CDateTimeStartEnd.vue'

View File

@@ -1876,14 +1876,19 @@ export default defineComponent({
newRecord.value = {}; newRecord.value = {};
} }
function SaveValue(newVal: any, valinitial: any) { function SaveValue(newVal: any, valinitial: any, which?: string) {
// console.log('SaveValue', newVal) // console.log('SaveValue', newVal)
// console.log('rowsel', rowsel, 'colsel', colsel.value) // console.log('rowsel', rowsel, 'colsel', colsel.value)
let myfield = ''; let myfield = '';
let subf = ''; let subf = '';
if (colsel.value) { if (colsel.value) {
myfield = colsel.value.field!; if (which === 'end') {
subf = colsel.value.subfield!; myfield = colsel.value.field2!;
subf = colsel.value.subfield2!;
} else {
myfield = colsel.value.field!;
subf = colsel.value.subfield!;
}
} }
let myrec = rowsel.value; let myrec = rowsel.value;
@@ -2159,8 +2164,8 @@ export default defineComponent({
}; };
if (col.action === lists.MenuAction.CAN_EDIT_TABLE) { if (col.action === lists.MenuAction.CAN_EDIT_TABLE) {
canEditPrec.value = canEdit.value canEditPrec.value = canEdit.value;
canEdit.value = true canEdit.value = true;
// console.log('Edit', item); // console.log('Edit', item);
selItem(item, col); selItem(item, col);
recModif.value = { ...item }; recModif.value = { ...item };
@@ -2713,8 +2718,8 @@ export default defineComponent({
const check = tools.checkIfShowField(col, tipovis, visulabel, value); const check = tools.checkIfShowField(col, tipovis, visulabel, value);
let valuePresent = let valuePresent =
colVisib.value.includes(col.field! + (col.subfield ? ('.' + col.subfield) : '')) || colVisib.value.includes(col.field! + (col.subfield ? '.' + col.subfield : '')) ||
colVisib.value.includes(col.field + (col.subfield ? ('.' + col.subfield) : '')) colVisib.value.includes(col.field + (col.subfield ? '.' + col.subfield : ''));
if (valuePresent && col.visibleif! > 0 && record) { if (valuePresent && col.visibleif! > 0 && record) {
if (col.visib_field) { if (col.visib_field) {
@@ -2944,7 +2949,7 @@ export default defineComponent({
function hidewindowEdit() { function hidewindowEdit() {
annulla(0); annulla(0);
canEdit.value = canEditPrec.value canEdit.value = canEditPrec.value;
} }
function clickMarker(id: any) { function clickMarker(id: any) {

View File

@@ -53,7 +53,7 @@
:disable="disabilita()" :disable="disabilita()"
:val="lists.MenuAction.CAN_EDIT_TABLE" :val="lists.MenuAction.CAN_EDIT_TABLE"
icon="fas fa-pencil-alt" icon="fas fa-pencil-alt"
:label="canEdit ? t('grid.edit_table') : t('grid.disable_edit_table')" :label="canEdit ? t('grid.edit_table') : ''"
@update:model-value="canEdit = !canEdit" @update:model-value="canEdit = !canEdit"
@click="canEdit = !canEdit" @click="canEdit = !canEdit"
> >
@@ -1142,6 +1142,8 @@
v-model:row="props.row" v-model:row="props.row"
:field="col.field" :field="col.field"
:subfield="col.subfield" :subfield="col.subfield"
:field2="col.field2"
:subfield2="col.subfield2"
minuteinterval="1" minuteinterval="1"
@save="SaveValue" @save="SaveValue"
@show="selItem(props.row, col)" @show="selItem(props.row, col)"
@@ -1278,6 +1280,8 @@
v-model:row="props.row" v-model:row="props.row"
:field="col.field" :field="col.field"
:subfield="col.subfield" :subfield="col.subfield"
:field2="col.field2"
:subfield2="col.subfield2"
minuteinterval="1" minuteinterval="1"
@save="SaveValue" @save="SaveValue"
@show="selItem(props.row, col)" @show="selItem(props.row, col)"
@@ -1484,6 +1488,8 @@
:tablesel="mycol.tablesel" :tablesel="mycol.tablesel"
:field="mycol.field" :field="mycol.field"
:subfield="mycol.subfield" :subfield="mycol.subfield"
:field2="mycol.field2"
:subfield2="mycol.subfield2"
@save="SaveValdb" @save="SaveValdb"
@show="selItem(rowclicksel, mycol)" @show="selItem(rowclicksel, mycol)"
@showandsave="showandsave" @showandsave="showandsave"
@@ -1552,6 +1558,7 @@
" "
> >
<div class=""> <div class="">
MODIF_B: {{col.field2}}
<CMyPopupEdit <CMyPopupEdit
:table="mytable" :table="mytable"
:canEdit="true" :canEdit="true"
@@ -1560,6 +1567,8 @@
v-model:row="newRecord" v-model:row="newRecord"
:field="col.field" :field="col.field"
:subfield="col.subfield" :subfield="col.subfield"
:field2="col.field2"
:subfield2="col.subfield2"
:tablesel="col.tablesel" :tablesel="col.tablesel"
:value_extra="getValueExtra(col, newRecord)" :value_extra="getValueExtra(col, newRecord)"
:isInModif="true" :isInModif="true"
@@ -1642,6 +1651,7 @@
class="tdclass" class="tdclass"
> >
<div> <div>
MODIF_C: {{col.field2}}
<CMyPopupEdit <CMyPopupEdit
:table="mytable" :table="mytable"
:canEdit="true" :canEdit="true"
@@ -1652,6 +1662,8 @@
v-model:row="recModif" v-model:row="recModif"
:field="col.field" :field="col.field"
:subfield="col.subfield" :subfield="col.subfield"
:field2="col.field2"
:subfield2="col.subfield2"
:dense="false" :dense="false"
:value_extra="getValueExtra(col, recModif)" :value_extra="getValueExtra(col, recModif)"
minuteinterval="1" minuteinterval="1"

View File

@@ -6,11 +6,11 @@
filled filled
:label="label || undefined" :label="label || undefined"
type="number" type="number"
inputmode="decimal"
:dense="dense" :dense="dense"
@focus="onFocus" @focus="onFocus"
@update:model-value="onInputChange" @update:model-value="onInputChange"
@keydown="onKeyDown" @keydown="onKeyDown"
@wheel.prevent
/> />
<!-- Mostra i bottoni solo se l'utente ha modificato il valore --> <!-- Mostra i bottoni solo se l'utente ha modificato il valore -->

View File

@@ -16,6 +16,7 @@ import type { IColGridTable, IImgGallery, ISpecialField } from 'model';
import { CMyChipList } from '../CMyChipList'; import { CMyChipList } from '../CMyChipList';
import { CDate } from '../CDate'; import { CDate } from '../CDate';
import { CDateTime } from '../CDateTime'; import { CDateTime } from '../CDateTime';
import { CDateTimeStartEnd } from '../CDateTimeStartEnd';
import { CLabel } from '../CLabel'; import { CLabel } from '../CLabel';
import { CMyToggleList } from '../CMyToggleList'; import { CMyToggleList } from '../CMyToggleList';
import { CMySelect } from '../CMySelect'; import { CMySelect } from '../CMySelect';
@@ -110,11 +111,21 @@ export default defineComponent({
required: false, required: false,
default: '', default: '',
}, },
field2: {
type: String,
required: false,
default: '',
},
subfield: { subfield: {
type: String, type: String,
required: false, required: false,
default: '', default: '',
}, },
subfield2: {
type: String,
required: false,
default: '',
},
mysubsubkey: { mysubsubkey: {
type: String, type: String,
required: false, required: false,
@@ -229,6 +240,7 @@ export default defineComponent({
components: { components: {
CMyChipList, CMyChipList,
CDateTime, CDateTime,
CDateTimeStartEnd,
CDate, CDate,
CMyToggleList, CMyToggleList,
CMySelect, CMySelect,
@@ -250,6 +262,7 @@ export default defineComponent({
const globalStore = useGlobalStore(); const globalStore = useGlobalStore();
const myvalue = ref(null as any); const myvalue = ref(null as any);
const myvalue2 = ref(null as any);
const myvalueprec = ref('false'); const myvalueprec = ref('false');
const countryname = ref(''); const countryname = ref('');
const visueditor = ref(false); const visueditor = ref(false);
@@ -391,6 +404,18 @@ export default defineComponent({
props.mysubsubkey, props.mysubsubkey,
props.specialField props.specialField
); );
myvalue2.value = getValDb(
props.field2,
props.serv,
'',
props.table,
props.subfield2,
props.id,
props.idmain,
props.indrec,
'',
props.specialField
);
} else { } else {
if (props.mycol && props.mycol.name) col.value = { ...props.mycol }; if (props.mycol && props.mycol.name) col.value = { ...props.mycol };
} }
@@ -591,11 +616,14 @@ export default defineComponent({
miorecord = myrow.value.arrvariazioni[0]; miorecord = myrow.value.arrvariazioni[0];
} }
if (props.field !== '') myvalue.value = miorecord[props.field]; if (props.field !== '') {
else { myvalue.value = miorecord[props.field];
// @ts-ignore } else {
myvalue.value = myrow.value; myvalue.value = myrow.value;
} }
if (props.field2 !== '') {
myvalue2.value = miorecord[props.field2];
}
} }
// console.log('props.field', props.field, 'props.subfield', props.subfield, 'myvalue: ', myvalue) // console.log('props.field', props.field, 'props.subfield', props.subfield, 'myvalue: ', myvalue)
} }
@@ -700,6 +728,19 @@ export default defineComponent({
async function SaveValueInt(newVal: any, valinitial: any) { async function SaveValueInt(newVal: any, valinitial: any) {
console.log('SaveValueInt', newVal, valinitial); console.log('SaveValueInt', newVal, valinitial);
let copynewval = { ...newVal };
let isEnd = false;
if (copynewval.which === 'start' || copynewval.which === 'end') {
newVal = copynewval.current;
valinitial = copynewval.prev;
if (copynewval.which === 'end') {
isEnd = true;
}
}
if (col.value.fieldtype === costanti.FieldType.verifica) { if (col.value.fieldtype === costanti.FieldType.verifica) {
newVal.username = userStore.my.username; newVal.username = userStore.my.username;
newVal.data = tools.getDateNow(); newVal.data = tools.getDateNow();
@@ -724,14 +765,25 @@ export default defineComponent({
console.log('newVal', newVal); console.log('newVal', newVal);
if (isFieldDb()) { if (isFieldDb()) {
await savefield(newVal, valinitial, $q); if (isEnd) {
} else { await savefield2(newVal, valinitial, $q);
// Update value in table memory
if (props.subfield !== '') {
if (myrow.value[props.field] === undefined) myrow.value[props.field] = {};
myrow.value[props.field][props.subfield] = newVal;
} else { } else {
if (props.field !== '') myrow.value[props.field] = newVal; await savefield(newVal, valinitial, $q);
}
} else {
let subfield = props.subfield;
let field = props.field;
if (isEnd) {
subfield = props.subfield2;
field = props.field2;
}
// Update value in table memory
if (subfield !== '') {
if (myrow.value[field] === undefined) myrow.value[field] = {};
myrow.value[field][subfield] = newVal;
} else {
if (field !== '') myrow.value[field] = newVal;
else { else {
if (!props.isrec) { if (!props.isrec) {
// @ts-ignore // @ts-ignore
@@ -743,11 +795,12 @@ export default defineComponent({
console.log('SaveValueInt', newVal, valinitial); console.log('SaveValueInt', newVal, valinitial);
emit('save', newVal, valinitial); emit('save', newVal, valinitial, copynewval.which!);
} }
async function savefield(value: any, initialval: any, myq: any) { async function savefield(value: any, initialval: any, myq: any) {
if (!props.insertMode) { if (!props.insertMode) {
let ret = null;
myvalue.value = value; myvalue.value = value;
return tools.saveInDBForTypes( return tools.saveInDBForTypes(
myq, myq,
@@ -764,6 +817,25 @@ export default defineComponent({
); );
} }
} }
async function savefield2(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.subfield2,
props.id,
props.indrec,
props.mysubsubkey,
props.specialField
);
}
}
function annulla(val: any) { function annulla(val: any) {
emit('annulla', true); emit('annulla', true);
@@ -1082,6 +1154,7 @@ export default defineComponent({
return { return {
myvalue, myvalue,
myvalue2,
countryname, countryname,
visueditor, visueditor,
visuhtml, visuhtml,

View File

@@ -22,7 +22,6 @@
<div v-if="isInModif"> <div v-if="isInModif">
<q-toggle <q-toggle
:disable="!isInModif || col.disable" :disable="!isInModif || col.disable"
dark
color="green" color="green"
v-model="myvalue" v-model="myvalue"
:label="title ? title : col.label" :label="title ? title : col.label"
@@ -31,8 +30,6 @@
</div> </div>
<div v-else> <div v-else>
<q-toggle <q-toggle
dark
color="green"
v-model="myvalue" v-model="myvalue"
:label="title" :label="title"
:disable=" :disable="
@@ -40,7 +37,12 @@
(!isInModif && !canModify && !canEdit) (!isInModif && !canModify && !canEdit)
" "
@update:model-value="Savedb" @update:model-value="Savedb"
></q-toggle> color="green"
checked-icon="check"
unchecked-icon="close"
keep-color
class="toggle-enhanced"
/>
</div> </div>
</div> </div>
<div v-else-if="col.fieldtype === costanti.FieldType.link"> <div v-else-if="col.fieldtype === costanti.FieldType.link">
@@ -995,6 +997,51 @@
<div v-else-if="canEdit"> <div v-else-if="canEdit">
<q-btn <q-btn
:dense="dense" :dense="dense"
:label="
col.label
? addstrrequired + col.label
: col.label_trans
? addstrrequired + t(col.label_trans)
: undefined
"
color="primary"
@click="OpenEditDateToday"
icon="fas fa-calendar-day"
/>
</div>
</div>
<div v-else-if="col.fieldtype === costanti.FieldType.date2startend">
<div v-if="myvalue">
<CDateTimeStartEnd
:label="
col.label
? addstrrequired + col.label
: col.label_trans
? addstrrequired + t(col.label_trans)
: undefined
"
:class="{ 'cursor-pointer': canEdit }"
v-model:startValue="myvalue"
v-model:endValue="myvalue2"
:readonly="false"
:dense="dense"
:canEdit="canEdit"
@savetoclose="SaveValueInt"
@show="OpenEdit"
:nullable-end="true"
>
</CDateTimeStartEnd>
</div>
<div v-else-if="canEdit">
<q-btn
:dense="dense"
:label="
col.label
? addstrrequired + col.label
: col.label_trans
? addstrrequired + t(col.label_trans)
: undefined
"
color="primary" color="primary"
@click="OpenEditDateToday" @click="OpenEditDateToday"
icon="fas fa-calendar-day" icon="fas fa-calendar-day"
@@ -1068,7 +1115,6 @@
</div> </div>
<!-- Show Value --> <!-- Show Value -->
<div v-else-if="col.fieldtype === costanti.FieldType.multiselect"> <div v-else-if="col.fieldtype === costanti.FieldType.multiselect">
<div v-if="isInModif"> <div v-if="isInModif">
<CMySelect <CMySelect
:type_out="col.field_outtype" :type_out="col.field_outtype"

View File

@@ -2778,3 +2778,38 @@ body.body--dark {
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05);
transition: transform 0.2s ease; transition: transform 0.2s ease;
} }
.toggle-enhanced {
/* Per migliorare contrasto dello stato OFF */
--q-toggle-thumb-color: var(--q-color-grey-4);
--q-toggle-track-color: rgba(255, 255, 255, 0.2);
&.q-toggle--dark {
--q-toggle-thumb-color: var(--q-color-grey-5);
--q-toggle-track-color: rgba(255, 255, 255, 0.25);
}
/* Colore quando attivo */
&.q-toggle--truthy {
--q-toggle-thumb-color: var(--q-color-green);
--q-toggle-track-color: rgba(0, 150, 0, 0.5);
}
/* Migliora leggibilità delletichetta */
.q-toggle__label {
font-weight: 500;
font-size: 0.9rem;
color: var(--q-color-grey-10);
margin-left: 0.5rem;
}
/* Hover/focus con leggero bagliore */
&:hover:not(.disabled) .q-toggle__inner {
filter: drop-shadow(0 0 3px rgba(0, 200, 0, 0.4));
}
/* Quando disabilitato */
&.disabled {
opacity: 0.6;
}
}

View File

@@ -8,8 +8,6 @@ const msg_website_enUs = {
products: { products: {
quantity: 'Quantità', quantity: 'Quantità',
quantityAvailable: 'Disponibili', quantityAvailable: 'Disponibili',
stockQty: 'In Magazzino',
stockBloccatiQty: 'Bloccati In Magazzino',
weight: 'Peso', weight: 'Peso',
stars: 'Voto', stars: 'Voto',
color: 'Colore', color: 'Colore',
@@ -38,7 +36,6 @@ const msg_website_enUs = {
productslist: 'Lista Prodotti', productslist: 'Lista Prodotti',
collabora: 'Collabora', collabora: 'Collabora',
storehouses: 'Magazzino', storehouses: 'Magazzino',
providers: 'Fornitori',
departments: 'Uffici', departments: 'Uffici',
orders: 'Ordini Ricevuti', orders: 'Ordini Ricevuti',
orders2: 'Ordini Ricevuti', orders2: 'Ordini Ricevuti',

View File

@@ -8,7 +8,6 @@ const msg_website_es = {
products: { products: {
quantity: 'Quantità', quantity: 'Quantità',
quantityAvailable: 'Disponibili', quantityAvailable: 'Disponibili',
stockQty: 'In Magazzino',
weight: 'Peso', weight: 'Peso',
stars: 'Voto', stars: 'Voto',
color: 'Colore', color: 'Colore',

View File

@@ -1,9 +1,9 @@
const msg_website_it = { const msg_website_it = {
ws: { ws: {
sitename: 'Più che Buono', sitename: 'RISO',
siteshortname: 'Più che Buono', siteshortname: 'RISO',
description: '', description: 'Siamo la Rete Italiana di Scambio Orizzontale, abbiamo creato questa piattaforma per metterla al servizio di chi vuole riscoprire il valore della condivisione e della cooperazione. Valori semplici e profondi che ci aiutano a ritrovare il Senso della Vita, perduto in questa società consumista, e riporti quei Sani Pricìpi Naturali ed Umani di Fratellanza che intere popolazioni antiche conoscevano bene.',
keywords: '', keywords: 'riso, piattaforma di scambio, rete italiana scambio orizzontale, riso app, riso piattaforma, scambio e baratto, momenta RIS',
}, },
hours: { hours: {
descr: 'Descrizione', descr: 'Descrizione',
@@ -16,35 +16,23 @@ const msg_website_it = {
pages: { pages: {
home: 'Home', home: 'Home',
profile: 'Profilo', profile: 'Profilo',
install_site: 'Installa Sito',
profile2: 'ProfiloU', profile2: 'ProfiloU',
mypage2: 'mypage2', mypage2: 'mypage2',
myservice2: 'myservice2', myservice2: 'myservice2',
myhosps2: 'myhosps2', myhosps2: 'myhosps2',
mygood2: 'mygood2', mygood2: 'mygood2',
catalogo: 'Catalogo',
fundraising: 'Sostieni il Progetto', fundraising: 'Sostieni il Progetto',
notifs: 'Configura le Notifiche', notifs: 'Configura le Notifiche',
unsubscribe: 'Disiscriviti', unsubscribe: 'Disiscriviti',
unsubscribe_user: 'Disiscriviti User',
test: 'Test', test: 'Test',
projects: 'Progetti', projects: 'Progetti',
report: 'Report Ore', report: 'Report Ore',
producer: 'Produttore', producer: 'Produttore',
orderinfo: 'Ordini Effettuati', orderinfo: 'Ordini Effettuati',
products: 'Prodotti', products: 'Prodotti',
cash: 'Cassa',
productInfos: 'Info Prodotti',
listinoprodotti: 'Listino Prodotti',
productslist: 'Lista Prodotti', productslist: 'Lista Prodotti',
collabora: 'Collabora', collabora: 'Collabora',
categories: 'Categorie',
storehouses: 'Magazzino', storehouses: 'Magazzino',
providers: 'Fornitori',
catprods: 'Categorie',
subcatprods: 'Sotto-Categorie',
gasordine: 'Gas Ordine',
scontisticas: 'Scontistica',
departments: 'Uffici', departments: 'Uffici',
orders: 'Ordini Ricevuti', orders: 'Ordini Ricevuti',
orders2: 'Ordini Ricevuti', orders2: 'Ordini Ricevuti',
@@ -133,11 +121,15 @@ const msg_website_it = {
only_residenti: 'Solo Residenti', only_residenti: 'Solo Residenti',
only_consiglio: 'Solo Consiglieri', only_consiglio: 'Solo Consiglieri',
color: 'Colore', color: 'Colore',
totaliordini: 'Totali Ordini GAS', mainMenu: 'Menu Principale',
gestoreordinigas: 'Gestore Ordini GAS', subtitle: 'Sottotitolo',
lang: 'Lingua',
keywords: 'Parole Chiave',
desctiption: 'Descrizione',
heightimg: 'Altezza Immagine',
}, },
msg: { msg: {
myAppName: 'Più che Buono', myAppName: 'Riso',
myAppDescription: 'Il primo Vero Social Libero, Equo e Solidale, dove Vive Consapevolezza e Aiuto Comunitario. Gratuito', myAppDescription: 'Il primo Vero Social Libero, Equo e Solidale, dove Vive Consapevolezza e Aiuto Comunitario. Gratuito',
underconstruction: 'App in costruzione...', underconstruction: 'App in costruzione...',
myDescriz: '', myDescriz: '',

View File

@@ -1,4 +1,4 @@
/* PIUCHEBUONO APP /* RISO APP
*/ */
import type { import type {
IListRoutes, IListRoutes,
@@ -8,6 +8,30 @@ import type {
} from '@model' } from '@model'
// const SHOW_PROJINTHEMENU = false
//
// let arrlistafavourite = []
// let arrlistaprojtutti = []
// let arrlistaprojmiei = []
// if (SHOW_PROJINTHEMENU) {
// arrlistaprojtutti = Projects.getters.listaprojects(RouteNames.projectsall)
// arrlistaprojmiei = Projects.getters.listaprojects(RouteNames.myprojects)
// arrlistafavourite = Projects.getters.listaprojects(RouteNames.favouriteprojects)
// }
// PROGETTI -> FAVORITI :
// if (arrlistafavourite.length > 0) {
// arrMenu.push({
// icon: 'favorite_border',
// nametranslate: 'pages.' + RouteNames.favouriteprojects,
// urlroute: RouteNames.favouriteprojects,
// level_parent: 0.0,
// level_child: 0.5,
// routes2: arrlistafavourite,
// idelem: ''
// })
// }
const firstPage = { const firstPage = {
active: true, active: true,
order: 5, order: 5,
@@ -41,12 +65,76 @@ function getDynamicPages(site: ISites): IListRoutes[] {
materialIcon: 'fas fa-test', materialIcon: 'fas fa-test',
name: 'mypages.test', name: 'mypages.test',
component: () => import('@src/views/testServer/testServer.vue'), component: () => import('@src/views/testServer/testServer.vue'),
inmenu: false,
infooter: false,
},
{
active: true,
order: 12,
path: '/goods',
materialIcon: 'fas fa-tshirt',
name: 'mypages.goods',
component: () => import('@src/root/goods/goods.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true,
order: 15,
path: '/services',
materialIcon: 'fas fa-house-user',
name: 'mypages.services',
component: () => import('@src/root/services/services.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true,
order: 15,
path: '/activities',
materialIcon: 'fas fa-house-user',
name: 'mypages.activities',
component: () => import('@src/root/activities/activities.vue'),
meta: { requiresAuth: true }, meta: { requiresAuth: true },
inmenu: false, inmenu: false,
infooter: false, infooter: false,
}, },
{
/*{ active: true,
order: 15,
path: '/provapao',
materialIcon: 'fas fa-house-user',
name: 'mypages.provapao',
component: () => import('@src/root/provapao/provapao.vue'),
meta: { requiresAuth: true },
inmenu: false,
infooter: false,
},
{
active: true,
order: 15,
path: '/hosps',
materialIcon: 'fas fa-bed',
name: 'mypages.hosp',
component: () => import('@src/root/hosp/hosp.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: site.confpages && site.confpages.enableCircuits,
order: 16,
path: '/circuits',
materialIcon: 'fas fa-coins',
name: 'mypages.circuits',
component: () => import('@src/views/user/mycircuits/mycircuits.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true, active: true,
order: 20, order: 20,
path: '/events', path: '/events',
@@ -56,17 +144,6 @@ function getDynamicPages(site: ISites): IListRoutes[] {
meta: { requiresAuth: true }, meta: { requiresAuth: true },
inmenu: true, inmenu: true,
infooter: true, infooter: true,
},*/
{
active: site.confpages && site.confpages.showProfile,
order: 120,
path: '/myprofile',
materialIcon: 'fas fa-user',
name: 'pages.profile',
component: () => import('@src/views/user/myprofile/myprofile.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
}, },
{ {
active: true, active: true,
@@ -79,6 +156,17 @@ function getDynamicPages(site: ISites): IListRoutes[] {
inmenu: false, inmenu: false,
infooter: false, infooter: false,
}, },
{
active: true,
order: 120,
path: '/myprofile',
materialIcon: 'fas fa-user',
name: 'pages.profile',
component: () => import('@src/views/user/myprofile/myprofile.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{ {
active: true, active: true,
order: 120, order: 120,
@@ -91,7 +179,7 @@ function getDynamicPages(site: ISites): IListRoutes[] {
infooter: false, infooter: false,
}, },
{ {
active: site.confpages && site.confpages.showiscrittiMenu, active: true,
order: 130, order: 130,
path: '/friends', path: '/friends',
materialIcon: 'fas fa-user-friends', materialIcon: 'fas fa-user-friends',
@@ -101,19 +189,6 @@ function getDynamicPages(site: ISites): IListRoutes[] {
inmenu: true, inmenu: true,
infooter: true, infooter: true,
}, },
{
active: site.confpages && site.confpages.enableCircuits,
order: 16,
path: '/circuits',
materialIcon: 'fas fa-coins',
name: 'mypages.circuits',
component: () => import('@src/views/user/mycircuits/mycircuits.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
onlyAdmin: true,
onlyManager: true,
},
{ {
active: site.confpages && site.confpages.enableGroups, active: site.confpages && site.confpages.enableGroups,
order: 132, order: 132,
@@ -124,8 +199,6 @@ function getDynamicPages(site: ISites): IListRoutes[] {
meta: { requiresAuth: true }, meta: { requiresAuth: true },
inmenu: true, inmenu: true,
infooter: false, infooter: false,
onlyAdmin: true,
onlyManager: true,
}, },
{ {
active: true, active: true,
@@ -204,7 +277,7 @@ function getDynamicPages(site: ISites): IListRoutes[] {
{ {
active: true, active: true,
order: 150, order: 150,
path: '/fundraising', path: '/sostieniilprogetto',
materialIcon: 'fas fa-hand-holding-heart', materialIcon: 'fas fa-hand-holding-heart',
name: 'pages.fundraising', name: 'pages.fundraising',
component: () => import('@src/root/fundraising/fundraising.vue'), component: () => import('@src/root/fundraising/fundraising.vue'),
@@ -229,7 +302,7 @@ function getDynamicPages(site: ISites): IListRoutes[] {
export function firstimagehome() { export function firstimagehome() {
let img = 'statics/images/background.jpg' const img = 'statics/images/background.jpg'
return img return img
} }

View File

@@ -1030,7 +1030,9 @@ export interface ISpecialField {
export interface IColGridTable { export interface IColGridTable {
name: string name: string
name2?: string
subfield?: string subfield?: string
subfield2?: string
required?: boolean required?: boolean
label?: string label?: string
label_trans?: string label_trans?: string
@@ -1039,6 +1041,7 @@ export interface IColGridTable {
visib_value?: any visib_value?: any
align?: string align?: string
field?: string field?: string
field2?: string
sortable?: boolean sortable?: boolean
visulabel?: boolean visulabel?: boolean
disable?: boolean disable?: boolean

View File

@@ -1,8 +1,8 @@
<template> <template>
<CMyPage :title="t('pages.gestoreordinigas')" imgbackground="/images/fornitori.jpg" sizes="max-height: 120px"> <CMyPage :title="t('mypages.gestoreordinigas')" imgbackground="/images/fornitori.jpg" sizes="max-height: 120px">
<span>{{ <span>{{
setmeta({ setmeta({
title: t('pages.gestoreordinigas'), title: t('mypages.gestoreordinigas'),
description: '', description: '',
keywords: '', keywords: '',
}) })
@@ -10,8 +10,8 @@
</span> </span>
<div class="q-ma-sm q-gutter-sm q-pa-xs"> <div class="q-ma-sm q-gutter-sm q-pa-xs">
<CTitleBanner :title="t('pages.gestoreordinigas')"></CTitleBanner> <CTitleBanner :title="t('mypages.gestoreordinigas')"></CTitleBanner>
<CGridTableRec prop_mytable="gasordines" :prop_mytitle="t('pages.gestoreordinigas')" :prop_mycolumns="colTableGasordine" <CGridTableRec prop_mytable="gasordines" :prop_mytitle="t('mypages.gestoreordinigas')" :prop_mycolumns="colTableGasordine"
prop_colkey="name" nodataLabel="Nessun Gas" prop_colkey="name" nodataLabel="Nessun Gas"
noresultLabel="Il filtro selezionato non ha trovato nessun GAS"> noresultLabel="Il filtro selezionato non ha trovato nessun GAS">

View File

@@ -1,8 +1,8 @@
<template> <template>
<CMyPage :title="t('pages.totaliordini')" imgbackground="/images/prodotti.jpg" sizes="max-height: 120px"> <CMyPage :title="t('mypages.totaliordini')" imgbackground="/images/prodotti.jpg" sizes="max-height: 120px">
<span>{{ <span>{{
setmeta({ setmeta({
title: t('pages.totaliordini'), title: t('mypages.totaliordini'),
description: '', description: '',
keywords: '', keywords: '',
}) })
@@ -11,8 +11,8 @@
<div class="q-ma-sm q-gutter-sm q-pa-xs"> <div class="q-ma-sm q-gutter-sm q-pa-xs">
<CTitleBanner :title="t('pages.totaliordini')"></CTitleBanner> <CTitleBanner :title="t('mypages.totaliordini')"></CTitleBanner>
<CGridTableRec prop_mytable="orders" :prop_mytitle="t('pages.totaliordini')" :prop_mycolumns="colTableGestoreOrdini" <CGridTableRec prop_mytable="orders" :prop_mytitle="t('mypages.totaliordini')" :prop_mycolumns="colTableGestoreOrdini"
:filtercustom="filtroOrdini" prop_colkey="name" nodataLabel="Nessun Totale Ordine" :filtercustom="filtroOrdini" prop_colkey="name" nodataLabel="Nessun Totale Ordine"
noresultLabel="Il filtro selezionato non ha trovato nessun risultato"> noresultLabel="Il filtro selezionato non ha trovato nessun risultato">

View File

@@ -75,7 +75,7 @@ function getRoutesEcomm(site: ISites) {
order: 30, order: 30,
path: '/admin/ecommerce/gasordini', path: '/admin/ecommerce/gasordini',
materialIcon: 'fas fa-file-alt', materialIcon: 'fas fa-file-alt',
name: 'pages.gestoreordinigas', name: 'mypages.gestoreordinigas',
component: () => import('@src/rootgen/admin/gasordini/gasordini.vue'), component: () => import('@src/rootgen/admin/gasordini/gasordini.vue'),
inmenu: true, inmenu: true,
submenu: true, submenu: true,
@@ -102,7 +102,7 @@ function getRoutesEcomm(site: ISites) {
order: 30, order: 30,
path: '/admin/ecommerce/gestoreordini', path: '/admin/ecommerce/gestoreordini',
materialIcon: 'fas fa-chart-pie', materialIcon: 'fas fa-chart-pie',
name: 'pages.totaliordini', name: 'mypages.totaliordini',
component: () => import('@src/views/admin/gestoreordini/gestoreordini.vue'), component: () => import('@src/views/admin/gestoreordini/gestoreordini.vue'),
inmenu: true, inmenu: true,
submenu: true, submenu: true,

View File

@@ -1270,6 +1270,8 @@ const msg_it = {
date_updated: 'Ult. Aggiornamento', date_updated: 'Ult. Aggiornamento',
}, },
mypages: { mypages: {
gestoreordinigas: 'Gestore Ordini GAS',
totaliordini: 'Totali Ordini GAS',
listadeigas: 'Lista dei GAS', listadeigas: 'Lista dei GAS',
catalogo_new: 'Vuoi andare al Catalogo "{title}" appena creato?', catalogo_new: 'Vuoi andare al Catalogo "{title}" appena creato?',
confirm_nav: 'Conferma Navigazione', confirm_nav: 'Conferma Navigazione',
@@ -1361,6 +1363,11 @@ const msg_it = {
reject_ask_friend: 'Rifiuta Amicizia', reject_ask_friend: 'Rifiuta Amicizia',
report_user: 'Segnala Utente', report_user: 'Segnala Utente',
}, },
common: {
clear: 'Disattiva',
cleared: 'Data rimossa',
set:'Imposta',
},
handshake: { handshake: {
strettadimano: 'Stretta di mano', strettadimano: 'Stretta di mano',
strettedimano: 'Strette di mano', strettedimano: 'Strette di mano',
@@ -2180,6 +2187,9 @@ const msg_it = {
date_extraction: 'Data Estrazione', date_extraction: 'Data Estrazione',
descrizione_lunga: 'Descrizione Lunga', descrizione_lunga: 'Descrizione Lunga',
}, },
date: {
rangeFixed: 'La data di fine è stata allineata alla data di inizio',
},
}, },
}; };

View File

@@ -493,6 +493,7 @@ export const costanti = {
verifica: 21000, verifica: 21000,
pickcolor: 22000, pickcolor: 22000,
username_telegram: 23000, username_telegram: 23000,
date2startend: 23050,
}, },
TypeMov: { TypeMov: {

View File

@@ -63,7 +63,9 @@ function AddCol(params: IColGridTable) {
visulabel: params.visulabel === undefined ? true : params.visulabel, visulabel: params.visulabel === undefined ? true : params.visulabel,
align: params.align === undefined ? 'left' : params.align, align: params.align === undefined ? 'left' : params.align,
field: params.field === undefined ? params.name : params.field, field: params.field === undefined ? params.name : params.field,
field2: params.name2 || '',
subfield: params.subfield === undefined ? '' : params.subfield, subfield: params.subfield === undefined ? '' : params.subfield,
subfield2: params.subfield2 === undefined ? '' : params.subfield2,
sortable: params.sortable === undefined ? true : params.sortable, sortable: params.sortable === undefined ? true : params.sortable,
disable: params.disable === undefined ? false : params.disable, disable: params.disable === undefined ? false : params.disable,
titlepopupedit: params.titlepopupedit === undefined ? '' : params.titlepopupedit, titlepopupedit: params.titlepopupedit === undefined ? '' : params.titlepopupedit,
@@ -3312,16 +3314,17 @@ export const colmyBachecas = [
}), }),
AddCol({ AddCol({
name: 'dateTimeStart', name: 'dateTimeStart',
name2: 'dateTimeEnd',
label_trans: 'event.dateTimeStart', label_trans: 'event.dateTimeStart',
// jointable: toolsext.TABCALALLDATE, // jointable: toolsext.TABCALALLDATE,
fieldtype: costanti.FieldType.date, fieldtype: costanti.FieldType.date2startend,
// fieldtype: costanti.FieldType.select, // fieldtype: costanti.FieldType.select,
// fieldtype_real: costanti.FieldType.onlydate, // fieldtype_real: costanti.FieldType.onlydate,
// fieldtype: costanti.FieldType.onlydate, // fieldtype: costanti.FieldType.onlydate,
icon: 'fas fa-calendar-day', icon: 'fas fa-calendar-day',
required: true, required: true,
}), }),
AddCol({ /*AddCol({
name: 'dateTimeEnd', name: 'dateTimeEnd',
label_trans: 'event.dateTimeEnd', label_trans: 'event.dateTimeEnd',
fieldtype: costanti.FieldType.date, fieldtype: costanti.FieldType.date,
@@ -3331,7 +3334,7 @@ export const colmyBachecas = [
icon: 'fas fa-calendar-day', icon: 'fas fa-calendar-day',
sortable: false, sortable: false,
required: true, required: true,
}), }),*/
AddCol({ AddCol({
name: 'idCity', name: 'idCity',
label_trans: 'skill.cityorprovince', label_trans: 'skill.cityorprovince',
@@ -4482,6 +4485,7 @@ export const colTableProdShort = [
label_trans: 'products.name', label_trans: 'products.name',
field: 'productInfo', field: 'productInfo',
subfield: 'name', subfield: 'name',
required: true,
}), }),
AddCol({ AddCol({
name: 'price', name: 'price',
@@ -4964,13 +4968,9 @@ const colTableEvents = [
}), }),
AddCol({ AddCol({
name: 'dateTimeStart', name: 'dateTimeStart',
name2: 'dateTimeEnd',
label_trans: 'event.dateTimeStart', label_trans: 'event.dateTimeStart',
fieldtype: costanti.FieldType.date, fieldtype: costanti.FieldType.date2startend,
}),
AddCol({
name: 'dateTimeEnd',
label_trans: 'event.dateTimeEnd',
fieldtype: costanti.FieldType.date,
}), }),
AddCol({ name: 'bgcolor', label_trans: 'event.bgcolor' }), AddCol({ name: 'bgcolor', label_trans: 'event.bgcolor' }),
AddCol({ name: 'icon', label_trans: 'event.icon' }), AddCol({ name: 'icon', label_trans: 'event.icon' }),
@@ -7117,7 +7117,7 @@ export const fieldsTable = {
{ {
value: 'products', value: 'products',
label: 'Prodotti', label: 'Prodotti',
columns: colTableProducts, columns: colTableProdShort,
colkey: '_id', colkey: '_id',
collabel: (rec: any) => `${rec.productInfo.name}`, collabel: (rec: any) => `${rec.productInfo.name}`,
}, },