Merge pull request #24 from paoloar77/Booking

Booking
This commit is contained in:
Paolo Arena
2019-10-05 20:09:44 +02:00
committed by GitHub
84 changed files with 4020 additions and 239 deletions

View File

@@ -1 +0,0 @@
cfg_freeplanet.app/

View File

@@ -28,12 +28,12 @@
"dependencies": {
"@babel/plugin-transform-runtime": "^7.4.0",
"@babel/runtime": "^7.0.0",
"@quasar/extras": "^1.1.2",
"@quasar/extras": "^1.3.2",
"@types/vuelidate": "^0.7.0",
"@vue/eslint-config-standard": "^4.0.0",
"acorn": "^6.0.0",
"autoprefixer": "^9.5.0",
"axios": "^0.18.0",
"axios": "^0.19.0",
"babel-eslint": "^10.0.1",
"bcrypt-nodejs": "0.0.3",
"bcryptjs": "^2.4.3",
@@ -44,13 +44,13 @@
"graphql": "^0.13.2",
"graphql-tag": "^2.8.0",
"gsap": "^2.0.2",
"jquery": "^3.3.1",
"jquery": "^3.4.1",
"js-cookie": "^2.2.0",
"localforage": "^1.7.3",
"normalize.css": "^8.0.0",
"npm": "^6.9.0",
"npm": "^6.10.1",
"nprogress": "^0.2.0",
"quasar": "^1.0.0-beta.21",
"quasar": "^1.1.6",
"quasar-extras": "^2.0.8",
"register-service-worker": "^1.0.0",
"vee-validate": "^2.1.2",
@@ -85,7 +85,8 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.4.2",
"@quasar/app": "^1.0.0-beta.22",
"@quasar/app": "^1.1.2",
"@quasar/quasar-app-extension-colorize": "^1.0.0-alpha.1",
"@quasar/quasar-app-extension-typescript": "^1.0.0-alpha.11",
"@types/dotenv": "^4.0.3",
"@types/jest": "^23.1.4",
@@ -98,8 +99,8 @@
"@vue/cli-plugin-e2e-cypress": "^3.0.1",
"@vue/cli-plugin-pwa": "^3.0.1",
"@vue/cli-plugin-typescript": "^3.0.1",
"@vue/cli-plugin-unit-jest": "^3.5.3",
"@vue/cli-service": "^3.0.1",
"@vue/cli-plugin-unit-jest": "^3.9.0",
"@vue/cli-service": "^3.9.2",
"@vue/test-utils": "^1.0.0-beta.20",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.5.0",

View File

@@ -134,11 +134,17 @@ module.exports = function (ctx) {
'QToolbarTitle',
'QBtn',
'QBtnDropdown',
'QColor',
'QIcon',
'QList',
'QItemLabel',
'QItem',
'QCard',
'QMarkupTable',
'QSpace',
'QDialog',
'QBadge',
'QForm',
'QCardSection',
'QCardActions',
'QField',
@@ -173,6 +179,12 @@ module.exports = function (ctx) {
'QImg',
'QSplitter',
'QRating',
'QParallax',
'QTab',
'QTabs',
'QTabPanels',
'QTabPanel',
'QTree',
'QSeparator'
],
directives: [

View File

@@ -1,3 +1,44 @@
body {
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #a7a7a7;
line-height: 1.5;
//font-size: 1rem;
}
html {
font-size: 100%; // default font size (browser 16) -> (10 62.5%)
}
p {
font-size: 125%; // default font size (browser 16) -> (10 62.5%)
margin: 0 0 8px;
}
$grayshadow: #555;
$graytext: #555;
$textcol: blue;
$textcol_scuro: darkblue;
$heightBtn: 100%;
.flex-item {
// background-color: #d5e2eb;
display: flex;
padding: 2px;
margin: 2px;
margin-left: 3px;
margin-right: 3px;
color: #000;
font-size: 1rem;
height: $heightBtn;
line-height: $heightBtn;
vertical-align: middle;
//flex: 0 0 100%;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .2s;
}
@@ -73,3 +114,201 @@
max-width: 22px;
}
}
.links, .links a {
text-shadow: 1px 1px 1px #555 !important;
// font-weight: bold;
color: cornflowerblue !important;
}
.links:hover {
color: white !important;
}
.text-subtitle1 {
font-size: 1.35rem;
font-weight: 400;
line-height: 1.75rem;
text-shadow: .25 .25rem .5rem $grayshadow;
letter-spacing: .00937em;
&.big {
font-size: 1.5rem;
}
}
.text-subtitle2 {
font-size: 1.15rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .25rem .25rem .5rem $grayshadow;
}
.text-subtitle3 {
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
}
@media (max-width: 718px) {
// PER VERSIONE MOBILE
p {
font-size: 100%; // default font size (browser 16) -> (10 62.5%)
font-family: "Abyssinica SIL", serif;
text-justify: auto;
margin: 0 0 4px;
}
.text-subtitle1 {
font-size: 1.25rem;
}
.text-subtitle2 {
font-size: 1rem;
}
.text-subtitle3 {
font-size: 0.75rem;
}
.cltexth3 {
font-size: 1.25rem;
}
.text-big{
font-size: 1.25rem;
}
}
.my-card {
width: 100%;
max-width: 350px;
min-width: 300px;
padding: 1rem 1rem;
box-shadow: none;
}
.text-trans {
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90);
}
.text-spacetrans {
padding: 0 !important;
background: rgba(0,0,0,0.3) !important;
border-radius: 30px !important;
}
.text-shadow {
text-shadow: .15rem .15rem .15rem $grayshadow;
}
.citazione{
font-size: 0.75rem;
font-family: "Lucida Calligraphy", serif;
}
.cltexth3, .cltexth2, .cltexth4 {
font-size: 1.25rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .01em;
text-align: center !important;
}
.cltexth4 {
font-size: 1rem;
}
.cltexth2 {
font-size: 1.5rem;
}
.boldhigh, .boldop, .text-big{
font-weight: 500;
text-shadow: .05rem .05rem .05rem $grayshadow;
}
.boldop{
color: darkblue;
}
.text-big{
font-size: 1.5rem;
}
.center_to_image{
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 100%;
text-align: center;
}
.center_img {
display: block;
margin-left: auto;
margin-right: auto;
}
.padding_cell {
padding: 0.75rem 0.5rem;
}
@media (max-width: 3000px) {
.q-parallax__media > img {
max-height: 550px !important;
min-width:inherit !important;
min-height: inherit !important;
}
}
@media (max-width: 1000px) {
.q-parallax__media > img {
max-height: 500px !important;
min-width:inherit !important;
min-height: inherit !important;
}
}
@media (max-width: 800px) {
.q-parallax__media > img {
max-height: 450px !important;
min-width:inherit !important;
min-height: inherit !important;
}
}
@media (max-width: 718px) {
.q-parallax__media > img {
max-height: 450px !important;
min-height: inherit !important;
min-width:100% !important;
}
}
// preloading images:
@media screen {
div#preloader {
position: absolute;
left: -9999px;
top: -9999px;
}
div#preloader img {
display: block;
}
}
@media print {
div#preloader,
div#preloader img {
visibility: hidden;
display: none;
}
}

View File

@@ -7,10 +7,14 @@ import { Header } from './components/Header'
import globalroutines from './globalroutines/index'
import { GlobalStore } from './store/Modules'
import { toolsext } from '@src/store/Modules/toolsext'
import { BannerCookies, CPreloadImages } from '@components'
import { static_data } from '@src/db/static_data'
@Component({
components: {
appHeader: Header
appHeader: Header,
BannerCookies, CPreloadImages
},
router
})
@@ -47,7 +51,7 @@ export default class App extends Vue {
// console.log('window.location.href', window.location.href)
let chiamaautologin = true
this.listaRoutingNoLogin.forEach(mystr => {
this.listaRoutingNoLogin.forEach((mystr) => {
if (window.location.href.includes(mystr)) {
chiamaautologin = false
}
@@ -59,9 +63,9 @@ export default class App extends Vue {
.then((loadstorage) => {
if (loadstorage) {
if (UserStore.state.lang !== '') {
if (toolsext.getLocale() !== '') {
// console.log('SETLOCALE :', this.$i18n.locale)
this.$i18n.locale = UserStore.state.lang // Set Lang
this.$i18n.locale = toolsext.getLocale() // Set Lang
} else {
UserStore.mutations.setlang(this.$i18n.locale)
}
@@ -81,5 +85,7 @@ export default class App extends Vue {
}
get static_data() {
return static_data
}
}

View File

@@ -5,6 +5,10 @@
<app-header></app-header>
<q-ajax-bar></q-ajax-bar>
<CPreloadImages :arrimg="static_data.preLoadImages">
</CPreloadImages>
<q-page-container>
<transition name="fade" mode="out-in">
<router-view/>
@@ -12,6 +16,7 @@
</q-page-container>
</q-layout>
</div>
<BannerCookies urlInfo="/policy"></BannerCookies>
</div>
</template>
<script lang="ts" src="./App.ts">

View File

@@ -0,0 +1,26 @@
// Animations
// slideFromBottom
.slideFromBottom-enter, .slideFromBottom-leave-to {
transform: translate(0px, 10em);
}
.slideFromBottom-enter-to, .slideFromBottom-leave {
transform: translate(0px, 0px);
}
.slideFromBottom-enter-active {
transition: transform .2s ease-out;
}
.slideFromBottom-leave-active {
transition: transform .2s ease-in;
}
.tothebottomfixed {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: -100%;
z-index: 1000;
}

View File

@@ -0,0 +1,128 @@
import Vue from 'vue'
import Component from 'vue-class-component'
import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import Quasar, { Screen } from 'quasar'
import { Prop } from 'vue-property-decorator'
@Component({
name: 'BannerCookies'
})
export default class BannerCookies extends Vue {
public $t: any
@Prop({ required: true }) public urlInfo: string
public elementId = 'id'
public disableDecline = true
public debug = false
public status = null
public supportsLocalStorage = true
public isOpen = false
public init() {
const visitedType = this.getCookieStatus()
if (visitedType && (visitedType === 'accept' || visitedType === 'decline' || visitedType === 'postpone')) {
this.isOpen = false
}
if (!visitedType) {
this.isOpen = true
}
if (!this.supportsLocalStorage)
this.isOpen = false
this.status = visitedType
this.$emit('status', visitedType)
}
public mounted() {
this.init()
}
public checkLocalStorageFunctionality() {
// Check for availability of localStorage
try {
const test = '__cookie-check-localStorage'
window.localStorage.setItem(test, test)
window.localStorage.removeItem(test)
} catch (e) {
console.error('Local storage is not supported, falling back to cookie use')
this.supportsLocalStorage = false
}
}
public setCookieStatus(type) {
if (this.supportsLocalStorage) {
if (type === 'accept') {
localStorage.setItem(`cookie-${this.elementId}`, 'accept')
}
if (type === 'decline') {
localStorage.setItem(`cookie-${this.elementId}`, 'decline')
}
if (type === 'postpone') {
localStorage.setItem(`cookie-${this.elementId}`, 'postpone')
}
} else {
/*if (type === 'accept') {
tinyCookie.set(`cookie-${this.elementId}`, 'accept')
}
if (type === 'decline') {
tinyCookie.set(`cookie-${this.elementId}`, 'decline')
}
if (type === 'postpone') {
tinyCookie.set(`cookie-${this.elementId}`, 'postpone')
}*/
}
}
public getCookieStatus() {
if (this.supportsLocalStorage) {
return localStorage.getItem(`cookie-${this.elementId}`)
} else {
// return tinyCookie.get(`cookie-${this.elementId}`)
}
}
public accept() {
if (!this.debug) {
this.setCookieStatus('accept')
}
this.status = 'accept'
this.isOpen = false
this.$emit('clicked-accept')
}
public decline() {
if (!this.debug) {
this.setCookieStatus('decline')
}
this.status = 'decline'
this.isOpen = false
this.$emit('clicked-decline')
}
public clickInfo() {
this.isOpen = false
}
public postpone() {
if (!this.debug) {
this.setCookieStatus('postpone')
}
this.status = 'postpone'
this.isOpen = false
this.$emit('clicked-postpone')
}
public removeCookie() {
localStorage.removeItem(`cookie-${this.elementId}`)
this.status = null
this.$emit('removed-cookie')
}
}

View File

@@ -0,0 +1,25 @@
<template>
<div v-if="isOpen" class="tothebottomfixed" role="dialog">
<div class="q-pa-md q-gutter-sm">
<transition appear name="slide-up" mode="out-in" :duration="2000">
<q-banner class="bg-primary text-white" transition-show="jump-down">
{{$t('cookies')}}
<template v-slot:action>
<q-btn v-if="disableDecline === false" flat color="white" label="Declina"
@click="decline"></q-btn>
<q-btn flat color="white" label="INFO" type="a" :href="urlInfo" @click="clickInfo"></q-btn>
<q-btn flat color="white" label="OK" @click="accept"></q-btn>
</template>
</q-banner>
</transition>
</div>
</div>
</template>
<script lang="ts" src="./BannerCookies.ts">
</script>
<style lang="scss" scoped>
@import './BannerCookies.scss';
</style>

View File

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

View File

@@ -0,0 +1,66 @@
$heightBtn: 100%;
$grayshadow: #555;
.text-subtitle-carica {
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
}
.text-subtitle-certificato {
font-size: 0.75rem;
line-height: 1rem;
}
@media (max-width: 718px) {
// PER VERSIONE MOBILE
.text-subtitle-carica {
font-size: 1rem;
}
}
.op {
text-align: center !important;
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
&__cell {
font-size: 1rem;
color: red;
}
&__email {
font-size: 1rem;
color: #3b5998;
}
&__email a {
text-decoration: none;
}
&__facebook a {
font-size: 1rem;
text-decoration: none;
}
&__storia {
margin-top: 1rem;
margin-bottom: 1rem;
text-align: justify;
}
}
.myimg {
border-radius: 300px !important;
}
.q-img {
&__image {
border-radius: 300px !important;
}
}

View File

@@ -0,0 +1,52 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { IPerson } from '../../model/GlobalStore'
@Component({
name: 'CBook',
filters: {
firstchars(value) {
return tools.firstchars(value, 250)
}
}
})
export default class CBook extends Vue {
@Prop({ required: true, default: 'one' }) public tab
public clicca() {
this.tab = 'two'
}
@Prop({ required: true }) public op: IPerson
get tools() {
return tools
}
get myop() {
if (!!this.op) {
return this.op
} else {
return {
index: 0,
tab: '',
name: '',
sub1: '',
sub2: '',
sub3: '',
img: '',
cell: '',
email: '',
paginaweb: '',
paginafb: '',
intro: '',
info: ''
}
}
}
}

View File

@@ -0,0 +1,47 @@
<template>
<q-card class="my-card text-center">
<q-img :src="myop.img" class="myimg">
<div class="absolute-bottom text-spacetrans text-shadow">
<div class="text-h6 text-trans">{{myop.name}}</div>
<div class="text-subtitle-carica text-trans">{{myop.sub1}}</div>
</div>
</q-img>
<q-tabs v-model="tab" class="text-teal">
<q-tab label="Info" name="one"></q-tab>
<q-tab label="Storia" name="two"></q-tab>
</q-tabs>
<q-separator></q-separator>
<q-tab-panels v-model="tab" animated>
<q-tab-panel name="one">
<div class="text-subtitle-carica">{{myop.sub2}}</div>
<div v-if="myop.sub3" class="text-subtitle-certificato">{{myop.sub3}}</div>
<div class="op__cell">
<q-icon class="flex-icon" name="mobile_friendly"></q-icon>
{{myop.cell}}
</div>
<div class="op__storia" v-html="myop.intro"></div>
<q-btn rounded size="sm" color="secondary" @click="clicca()">Continua ...</q-btn>
</q-tab-panel>
<q-tab-panel name="two">
<div class="op__storia" v-html="myop.info"></div>
</q-tab-panel>
</q-tab-panels>
<!--<q-card-section>-->
<!--<div class="text-subtitle3">{{myop.sub2}}</div>-->
<!--{{myop.info}}-->
<!--</q-card-section>-->
</q-card>
</template>
<script lang="ts" src="./CBook.ts">
</script>
<style lang="scss" scoped>
@import './CBook.scss';
</style>

View File

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

View File

@@ -0,0 +1,66 @@
$heightBtn: 100%;
$grayshadow: #555;
.text-subtitle-carica {
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
}
.text-subtitle-certificato {
font-size: 0.75rem;
line-height: 1rem;
}
@media (max-width: 718px) {
// PER VERSIONE MOBILE
.text-subtitle-carica {
font-size: 1rem;
}
}
.op {
text-align: center !important;
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: .1rem .1rem .1rem $grayshadow;
&__cell {
font-size: 1rem;
color: red;
}
&__email {
font-size: 1rem;
color: #3b5998;
}
&__email a {
text-decoration: none;
}
&__facebook a {
font-size: 1rem;
text-decoration: none;
}
&__storia {
margin-top: 1rem;
margin-bottom: 1rem;
text-align: justify;
}
}
.myimg {
border-radius: 300px !important;
}
.q-img {
&__image {
border-radius: 300px !important;
}
}

View File

@@ -0,0 +1,52 @@
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { IPerson } from '../../model/GlobalStore'
@Component({
name: 'CCard',
filters: {
firstchars(value) {
return tools.firstchars(value, 250)
}
}
})
export default class CCard extends Vue {
@Prop({ required: true, default: 'one' }) public tab
public clicca() {
this.tab = 'two'
}
@Prop({ required: true }) public op: IPerson
get tools() {
return tools
}
get myop() {
if (!!this.op) {
return this.op
} else {
return {
index: 0,
tab: '',
name: '',
sub1: '',
sub2: '',
sub3: '',
img: '',
cell: '',
email: '',
paginaweb: '',
paginafb: '',
intro: '',
info: ''
}
}
}
}

View File

@@ -0,0 +1,59 @@
<template>
<q-card class="my-card text-center">
<q-img :src="myop.img" class="myimg">
<div class="absolute-bottom text-spacetrans text-shadow">
<div class="text-h6 text-trans">{{myop.name}}</div>
<div class="text-subtitle-carica text-trans">{{myop.sub1}}</div>
</div>
</q-img>
<q-tabs v-model="tab" class="text-teal">
<q-tab label="Info" name="one"></q-tab>
<q-tab label="Storia" name="two"></q-tab>
</q-tabs>
<q-separator></q-separator>
<q-tab-panels v-model="tab" animated>
<q-tab-panel name="one">
<div class="text-subtitle-carica">{{myop.sub2}}</div>
<div v-if="myop.sub3" class="text-subtitle-certificato">{{myop.sub3}}</div>
<div class="op__cell">
<q-icon class="flex-icon" name="mobile_friendly"></q-icon>
{{myop.cell}}
</div>
<div class="op__email">
<q-icon class="flex-icon" name="contact_mail"> </q-icon>&nbsp;
<a :href="tools.getemailto(myop.email)" target="_blank">{{myop.email}}
</a>
</div>
<div class="op__facebook" v-if="myop.paginafb">
<a :href="myop.paginafb" target="_blank">
<i aria-hidden="true" class="q-icon fab fa-facebook-f icon_contact links"></i> Pagina Facebook
</a>
</div>
<div class="op__storia" v-html="myop.intro"></div>
<q-btn rounded size="sm" color="secondary" @click="clicca()">Continua ...</q-btn>
</q-tab-panel>
<q-tab-panel name="two">
<div class="op__storia" v-html="myop.info"></div>
</q-tab-panel>
</q-tab-panels>
<!--<q-card-section>-->
<!--<div class="text-subtitle3">{{myop.sub2}}</div>-->
<!--{{myop.info}}-->
<!--</q-card-section>-->
</q-card>
</template>
<script lang="ts" src="./CCard.ts">
</script>
<style lang="scss" scoped>
@import './CCard.scss';
</style>

View File

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

View File

@@ -0,0 +1,79 @@
.imgtext {
display: flex;
justify-content: space-between;
/* flex-flow: row nowrap; */
padding: 1rem 0 1rem 0;
margin: .125rem;
* {
width: 100%;
flex: 1;
margin-left: auto;
margin-right: auto;
}
&__img {
min-width: 250px;
}
&__imgh100 {
max-height: 100px;
}
&__imgh150 {
max-height: 150px;
}
&__imgw150 {
max-width: 150px;
}
&__imgw100 {
max-width: 100px;
}
}
@media (max-width: 1600px) {
.myclimg {
max-height: 550px !important;
width: 100%;
}
}
@media (max-width: 1000px) {
.myclimg {
max-height: 450px !important;
width: 100%;
}
}
@media (max-width: 800px) {
.myclimg {
max-height: 400px !important;
}
}
@media (max-width: 400px) {
.myclimg {
// height: inherit !important;
}
// PER VERSIONE MOBILE
.landing > section.padding_testo {
padding-top: 0.5rem;
padding-bottom: 0.1rem;
}
.imgtext {
padding: 0.25rem 0 0.25rem 0;
}
}
.landing > section.padding_testo {
padding-top: 1rem;
padding-bottom: 0.25rem;
}
.section_text {
padding: 10px;
}

View File

@@ -0,0 +1,31 @@
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import { GlobalStore, UserStore } from '@store'
import VueScrollReveal from 'vue-scroll-reveal'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { Screen } from 'quasar'
// Vue.use(VueScrollReveal, {
// class: 'v-scroll-reveal', // A CSS class applied to elements with the v-scroll-reveal directive; useful for animation overrides.
// duration: 1200,
// scale: 0.95,
// distance: '10px',
// rotate: {
// x: 0,
// y: 0,
// z: 0
// }
// // mobile: true
// })
@Component({
name: 'CImgText'
})
export default class CImgText extends Vue {
@Prop({ required: false, default: '' }) public src: string
@Prop({ required: false, default: '' }) public src2: string
@Prop({ required: false, default: 'myclimg' }) public class1: string
@Prop({ required: false, default: '' }) public style1: string
}

View File

@@ -0,0 +1,21 @@
<template>
<div>
<section class="padding_testo bg-white text-grey-10 text-justify" > <!-- v-scroll-reveal.reset -->
<div class="row items-start q-col-gutter-xs imgtext">
<div class="imgtext__img">
<img v-if="src" :src="src" class="myclimg" :style="style1">
<img v-if="src2" :src="src2" class="myclimg" :style="style1">
<div class="section_text">
<slot></slot>
</div>
</div>
</div>
</section>
</div>
</template>
<script lang="ts" src="./CImgText.ts">
</script>
<style lang="scss" scoped>
@import './CImgText.scss';
</style>

View File

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

View File

View File

@@ -0,0 +1,36 @@
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import { GlobalStore, UserStore } from '@store'
import { Logo } from '../../components/logo'
import { Footer } from '../../components/Footer'
import VueScrollReveal from 'vue-scroll-reveal'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { Screen } from 'quasar'
Vue.use(VueScrollReveal, {
class: 'v-scroll-reveal', // A CSS class applied to elements with the v-scroll-reveal directive; useful for animation overrides.
duration: 1200,
scale: 0.95,
distance: '10px',
rotate: {
x: 0,
y: 0,
z: 0
}
// mobile: true
})
@Component({
name: 'CPage',
components: { Logo, Footer }
})
export default class CPage extends Vue {
@Prop({ required: true }) public imghead: string = ''
@Prop({ required: true }) public headtitle: string = ''
@Prop({ required: true }) public img1: string = ''
@Prop({ required: true }) public text1: string = ''
}

View File

@@ -0,0 +1,28 @@
<template>
<q-page class="text-white">
<div class="landing">
<CTitle :src="imghead" :title="headtitle">
</CTitle>
<section class="padding_testo bg-white text-grey-10 text-center" v-scroll-reveal.reset>
<div class="landing__features row items-start q-col-gutter-xs intro">
<div class="intro__associazione">
<!--<img src="../../statics/images/scuolaopbenessere/16427623_404497389905092_1266178961781563443_n.jpg">-->
<img :src="img1">
{{text1}}
</div>
</div>
</section>
<Footer></Footer>
</div>
</q-page>
</template>
<script lang="ts" src="./CPage.ts">
</script>
<style lang="scss" scoped>
@import './CPage.scss';
</style>

View File

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

View File

@@ -0,0 +1,18 @@
.cltitlebg{
}
.titletext {
color: white;
font-size: 3rem;
font-weight: 500;
line-height: 3rem;
text-shadow: .25rem .25rem .5rem black;
letter-spacing: .00937em;
}
.q-img__content > div{
background: rgba(0,0,0,0.17) !important;
}

View File

@@ -0,0 +1,29 @@
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import { GlobalStore, UserStore } from '@store'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { Screen } from 'quasar'
@Component({
name: 'CTitle'
})
export default class CTitle extends Vue {
@Prop({ required: false, default: '' }) public imgbackground: string
@Prop({ required: false, default: '' }) public imghead: string
@Prop({ required: false, default: '' }) public sizes: string
@Prop({ required: true }) public headtitle: string
get tools() {
return tools
}
get getsrc() {
// return this.src
const filefull = tools.getimgFullpathbysize(this.imgbackground)
return tools.getimgbysize(filefull.path, filefull.file)
}
}

View File

@@ -0,0 +1,27 @@
<template>
<div>
<q-img v-if="imgbackground" :src="getsrc"
:style="tools.styles_imgtitle(sizes)">
<div class="absolute-bottom text-body1 text-center">
<h2 class="titletext">{{headtitle}}</h2>
</div>
</q-img>
<!--
<q-parallax :height="tools.myheight_imgtitle()" :width="tools.mywidth_imgtitle()">
<template v-slot:media>
<img :src="imgbackground" class="cltitlebg">
</template>
<h2 class="titletext">{{headtitle}}</h2>
</q-parallax>
-->
</div>
</template>
<script lang="ts" src="./CTitle.ts">
</script>
<style lang="scss" scoped>
@import './CTitle.scss';
</style>

View File

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

View File

@@ -0,0 +1,185 @@
$grayshadow: #555;
$textcol: blue;
$textcol_scuro: darkblue;
.landing__footer {
//background: -webkit-gradient(linear, left top, left bottom, color-stop(65%, rgba(0, 0, 0, .1)), to(#000));
background: linear-gradient(180deg, rgba(0, 0, 0, .8) 95%, #FFF);
padding-top: 4.5rem !important;
padding-bottom: 4.5rem !important;
padding-left: 1.25rem;
padding-right: 1.25rem;
color: #9f9f9f;
}
.icon_contact:hover {
color: blue;
border-color: white;
border-width: .0625rem;
}
.landing__footer .doc-link {
color: $textcol;
}
.landing__footer .doc-link:hover {
opacity: .8
}
.landing__swirl-bg {
background-repeat: no-repeat !important;
background-position: top;
background-size: contain !important;
background-image: url(../../statics/images/landing_first_section.png) !important
}
.landing__footer-icons {
font-size: 1.75rem
}
.landing__footer-icons a {
margin: 0 .5rem .5rem;
text-decoration: none;
outline: 0;
color: $textcol;
transition: color .28s
}
.landing__footer-icons a:hover {
color: $textcol_scuro;
}
.doc-img {
max-width: 100%;
}
.mylist {
background: #3fdaff;
padding-left: 1.25rem;
}
.clgutter {
margin-top: 1.25rem;
padding: .62rem;
}
.carousel_img_3 {
//background-image: url(../../statics/images/cibo_sano.jpg);
background-size: cover !important;
background-position: 50% center !important;
background-repeat: no-repeat !important;
}
@media (max-width: 718px) {
// PER VERSIONE MOBILE
.landing__hero {
text-align: center
}
.landing__header {
height: 7vh
}
.clgutter {
margin-top: 0;
padding: 0;
}
.landing__hero .text-h1 {
font-size: 3rem;
line-height: 3.05rem;
margin-bottom: 1.5rem
}
.landing > section.padding {
padding: 2.5rem 1rem;
}
.landing > section.padding_testo {
padding-top: 1.25rem;
padding-bottom: 1rem;
}
.landing > section.padding_gallery {
padding-top: 3.125rem;
padding-bottom: 5.625rem;
}
.landing__features h4, .landing__features h6 {
margin: 1.25rem 0
}
h4 {
line-height: 1.4;
text-shadow: 0.25rem 0.25rem 0.5rem $grayshadow;
}
.landing .feature-item {
text-align: center;
margin-top: 1.25rem;
}
.landing__hero-content {
padding-bottom: 11.25rem;
}
.landing__hero-btns {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center
}
.q-col-gutter-sm {
padding: .625rem .315rem;
}
.text-vers{
font-size: 0.6rem;
}
.carousel_img_3 {
//background-image: url(../../statics/images/cibo_sano.jpg);
background-size: 620px 620px !important;
background-position: 50% top !important;
background-repeat: no-repeat !important;
}
}
.custom-caption {
text-align: center;
padding: .75rem;
color: $textcol;
background-color: rgba(0, 0, 0, .3);
}
.mycontacts {
color: gray;
letter-spacing: 0.078rem;
}
.copyrights {
color: gray;
letter-spacing: 0.078rem;
}
.mycontacts_title {
text-shadow: 0.125rem 0.125rem 0.125rem #555;
font-weight: bold;
color: #999;
letter-spacing: 0.125rem;
}
.mycontacts_text {
color: #999;
letter-spacing: normal !important;
}
.footer_link {
font-size: 1rem;
color:gray;
}
.footer_link:hover {
color:white;
}

View File

@@ -0,0 +1,49 @@
import Vue from 'vue'
import { GlobalStore, UserStore } from '@modules'
import { Logo } from '../logo'
import { Component, Prop } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { db_data } from '@src/db/db_data'
import { static_data } from '@src/db/static_data'
import Quasar from 'quasar'
import { FormNewsletter } from '../FormNewsletter'
@Component({
name: 'Footer',
components: { Logo, FormNewsletter }
})
export default class Footer extends Vue {
public $t
public $v
public $q
get tools() {
return tools
}
get mythis() {
return this
}
get TelegramSupport() {
return db_data.TELEGRAM_SUPPORT
}
get FBPage() {
return db_data.URL_FACEBOOK
}
get InstagramPage() {
return db_data.URL_INSTAGRAM
}
get static_data(){
return static_data
}
}

View File

@@ -0,0 +1,91 @@
<template>
<div>
<section class="landing__footer">
<div class="row justify-between items-start q-col-gutter-xs">
<div class="col-12 col-sm-4 ">
<p style="text-align: center">
<logo></logo>
</p>
<!--<span v-html="$t('homepage.footer.description')">-->
<!--</span>-->
<FormNewsletter v-if="static_data.functionality.SHOW_NEWSLETTER" :idwebsite="tools.appid()"
:locale="tools.getLocale()">
</FormNewsletter>
<!--<div class="q-mt-xs copyrights">-->
<!--<p class="mycontacts_text" v-html="$t('homepage.copyrights')"></p>-->
<!--</div>-->
</div>
<div class="col-12 col-sm-4">
<div class="text-center">
<div class="q-mt-xs mycontacts">
<p class="mycontacts_title">{{$t('homepage.titlecontatti')}}</p>
<p class="mycontacts_text" v-html="$t('homepage.contacts')"></p>
</div>
<div class="landing__footer-icons row flex-center">
<a v-if="!!FBPage" :href="FBPage" target="_blank">
<i aria-hidden="true" class="q-icon fab fa-facebook-f icon_contact links"> </i></a>
<a v-if="!!InstagramPage" :href="InstagramPage" target="_blank">
<i aria-hidden="true" class="q-icon fab fa-instagram icon_contact links"> </i></a>
<a v-if="!!TelegramSupport" :href="TelegramSupport" target="_blank">
<i aria-hidden="true" class="q-icon fab fa-telegram icon_contact links"></i></a>
<!--<a href="" target="_blank"><i aria-hidden="true" class="q-icon fab fa-github"> </i></a>-->
<!--<a href="https://twitter.com/" target="_blank"><i aria-hidden="true" class="q-icon fab fa-twitter"> </i></a>-->
<!--<a href="https://discord.gg/5TDhbDg" target="_blank"><i aria-hidden="true"-->
<!--class="q-icon fab fa-discord"> </i></a><a-->
<!--href="https://forum.quasar-framework.org/" target="_blank"><i aria-hidden="true"-->
<!--class="q-icon fas fa-comments"> </i></a><a-->
<!--href="https://www.patreon.com/quasarframework" target="_blank"><i aria-hidden="true"-->
<!--class="q-icon fab fa-patreon"> </i></a>-->
</div>
</div>
<p class="text-center">
<router-link v-if="static_data.functionality.SHOW_ONLY_POLICY" to="/policy"><span class="footer_link">{{$t('privacy_policy')}}</span></router-link>
</p>
</div>
<div class="col-12 col-sm-4 q-pa-md" v-for="">
<div v-for="myitemmenu in static_data.routes">
<div v-if="myitemmenu.infooter">
<div v-if="myitemmenu.solotitle">
<span class="footer_link">{{tools.getLabelByItem(myitemmenu, mythis)}}</span><br/>
</div>
<div v-else>
<router-link :to="myitemmenu.path">
<span class="footer_link"><span
v-if="myitemmenu.level_child > 0">&nbsp;&nbsp;&nbsp;</span>
{{tools.getLabelByItem(myitemmenu, mythis)}}</span><br/>
</router-link>
</div>
<!--<a :href="myitemmenu.path"><span class="footer_link">{{tools.getLabelByItem(myitemmenu, mythis)}}</span></a><br/>-->
</div>
</div>
</div>
</div>
</section>
<q-page-scroller position="bottom-right" :scroll-offset="850" :offset="[18, 18]" style="opacity: 0.3">
<q-btn fab icon="keyboard_arrow_up" color="accent"/>
</q-page-scroller>
</div>
</template>
<script lang="ts" src="./Footer.ts">
</script>
<style lang="scss" scoped>
@import './Footer.scss';
</style>

View File

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

View File

@@ -0,0 +1,30 @@
// Animations
// slideFromBottom
.slideFromBottom-enter, .slideFromBottom-leave-to {
transform: translate(0px, 10em);
}
.slideFromBottom-enter-to, .slideFromBottom-leave {
transform: translate(0px, 0px);
}
.slideFromBottom-enter-active {
transition: transform .2s ease-out;
}
.slideFromBottom-leave-active {
transition: transform .2s ease-in;
}
.news_title {
color: white;
font-size: 1rem;
}
.news_link {
color: gray;
}
.news_link:hover {
color: white;
}

View File

@@ -0,0 +1,96 @@
import Vue from 'vue'
import Component from 'vue-class-component'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import Quasar, { Screen } from 'quasar'
import { Prop } from 'vue-property-decorator'
import { Api } from '../../store'
import { serv_constants } from '../../store/Modules/serv_constants'
@Component({
name: 'FormNewsletter'
})
export default class FormNewsletter extends Vue {
public $t
public $q
public name: string = null
public surname: string = null
public email: string = null
public accept: boolean = false
@Prop() public idwebsite: string
@Prop() public locale: string
get tools() {
return tools
}
public async onSubmit() {
if (this.accept !== true) {
this.$q.notify({
color: 'red-5',
textColor: 'white',
icon: 'fas fa-exclamation-triangle',
message: this.$t('newsletter.license')
})
}
else {
const usertosend = {
email: this.email,
firstName: this.name,
lastName: this.surname,
idwebsite: this.idwebsite,
locale: this.locale
}
console.log(usertosend)
return await Api.SendReq('/signup_news', 'POST', usertosend, false)
.then((res) => {
if (res.data.result === serv_constants.RIS_SUBSCRIBED_OK) {
this.$q.notify({
color: 'green-4',
textColor: 'white',
icon: 'fas fa-check-circle',
// message: this.$t('newsletter.submitted')
message: res.data.msg
})
} else if (res.data.result === serv_constants.RIS_SUBSCRIBED_ALREADYEXIST) {
this.$q.notify({
color: 'orange-4',
textColor: 'white',
icon: 'fas fa-check-circle',
// message: this.$t('newsletter.submitted')
message: res.data.msg
})
} else {
this.$q.notify({
color: 'red-5',
textColor: 'white',
icon: 'fas fa-exclamation-triangle',
message: res.data.msg
})
}
})
.catch((error) => {
console.error(error)
// UserStore.mutations.setErrorCatch(error)
return false
})
}
}
public onReset() {
this.name = null
this.surname = null
this.email = null
this.accept = false
}
}

View File

@@ -0,0 +1,63 @@
<template>
<div>
<div class="q-pa-md q-gutter-sm text-white">
<p class="news_title">{{$t('newsletter.title')}}</p>
<q-form
@submit="onSubmit"
@reset="onReset"
class="q-gutter-md"
>
<q-input
filled
name="firstName"
dark standout
v-model="name"
:label="$t('newsletter.name') + `*`"
:hint="$t('newsletter.namehint')"
lazy-rules
:rules="[ val => val && val.length > 0 || $t('newsletter.typesomething')]">
</q-input>
<q-input
filled
dark standout
v-model="surname"
name="lastName"
:label="$t('newsletter.surname') + `*`"
:hint="$t('newsletter.surnamehint')"
lazy-rules
:rules="[ val => val && val.length > 0 || $t('newsletter.typesomething')]">
</q-input>
<q-input
filled
dark standout
v-model="email"
:label="$t('newsletter.email') + `*`"
lazy-rules
:rules="[ val => val && val.length > 6 || $t('newsletter.typesomething')]">
</q-input>
<router-link to="/policy"><span class="news_link">{{$t('privacy_policy')}}</span></router-link>
<q-toggle dark v-model="accept" :label="$t('newsletter.acceptlicense')"/>
<div>
<q-btn :label="$t('newsletter.submit')" type="submit" color="primary"/>
<q-btn :label="$t('newsletter.reset')" type="reset" color="primary" flat class="q-ml-sm"/>
</div>
</q-form>
</div>
</div>
</template>
<script lang="ts" src="./FormNewsletter.ts">
</script>
<style lang="scss" scoped>
@import './FormNewsletter.scss';
</style>

View File

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

View File

@@ -286,3 +286,12 @@ canvas {
display: inline-block;
padding: 4px 2px;
}
.text-user {
text-shadow: .05rem .05rem .15rem #fff;
background-color: limegreen;
border-radius: 1rem !important;
text-align: center;
margin: 1px;
margin-bottom: 5px;
}

View File

@@ -11,6 +11,7 @@ import { tools } from '../../store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import Quasar, { Screen } from 'quasar'
import { static_data } from '../../db/static_data'
@Component({
name: 'Header',
@@ -37,12 +38,6 @@ export default class Header extends Vue {
public photo = ''
public visuimg: boolean = true
public selectOpLang = [
{ label: 'English', icon: 'fa-flag-us', value: 'enUs', image: '../statics/images/gb.png', short: 'EN' },
{ label: 'Español', icon: 'fa-flag-es', value: 'es', image: '../statics/images/es.png', short: 'ES' },
{ label: 'Italiano', icon: 'fa-facebook', value: 'it', image: '../statics/images/it.png', short: 'IT' }
// { label: 'German', icon: 'fa-flag-de', value: 'de', image: '../statics/images/de.png', short: 'DE' },
]
get getappname(){
if (Screen.width < 400) {
@@ -73,12 +68,12 @@ export default class Header extends Vue {
}
// -------------------------------------------------------------------------
// QUASAR Example using event to open drawer from another component or page
// QUASAR Example using myevent to open drawer from another component or page
// -------------------------------------------------------------------------
// (1) This code is inside layout file that have a drawer
// if this.leftDrawerOpen is true, drawer is displayed
// (2) Listen for an event in created
// (2) Listen for an myevent in created
/* created(){
this.$root.$on("openLeftDrawer", this.openLeftDrawercb);
},
@@ -90,7 +85,7 @@ export default class Header extends Vue {
}
}
// (4) In another component or page, emit the event!
// (4) In another component or page, emit the myevent!
// Call the method when clicking button etc.
methods: {
openLeftDrawer() {
@@ -165,14 +160,17 @@ export default class Header extends Vue {
const color = (value === 'online') ? 'positive' : 'warning'
if (!!oldValue) {
tools.showNotif(this.$q, this.$t('connection') + ` ${value}`, {
color,
icon: 'wifi'
})
}
if (this.static_data.functionality.SHOW_IF_IS_SERVER_CONNECTION) {
this.changeIconConn()
if (!!oldValue) {
tools.showNotif(this.$q, this.$t('connection') + ` ${value}`, {
color,
icon: 'wifi'
})
}
this.changeIconConn()
}
}
}
@@ -203,10 +201,10 @@ export default class Header extends Vue {
}
public setshortlang(lang) {
for (const indrec in this.selectOpLang) {
if (this.selectOpLang[indrec].value === lang) {
// console.log('this.selectOpLang[indrec].short', this.selectOpLang[indrec].short, this.selectOpLang[indrec].value)
this.langshort = this.selectOpLang[indrec].short
for (const indrec in static_data.lang_available) {
if (static_data.lang_available[indrec].value === lang) {
// console.log('static_data.lang_available[indrec].short', static_data.lang_available[indrec].short, static_data.lang_available[indrec].value)
this.langshort = static_data.lang_available[indrec].short
return
}
}
@@ -218,7 +216,7 @@ export default class Header extends Vue {
}
public setLangAtt(mylang) {
console.log('MYLL=', mylang)
console.log('LANG =', mylang)
// console.log('PRIMA this.$q.lang.isoName', this.$q.lang.isoName)
// dynamic import, so loading on demand only
@@ -316,6 +314,12 @@ export default class Header extends Vue {
get Username() {
return UserStore.state.username
}
get Name() {
return UserStore.state.name
}
get Surname() {
return UserStore.state.surname
}
get Verificato() {
return UserStore.state.verified_email
@@ -337,4 +341,8 @@ export default class Header extends Vue {
tools.showNotif(this.$q, this.$t('logout.uscito'), {icon: 'exit_to_app'})
})
}
get static_data(){
return static_data
}
}

View File

@@ -1,6 +1,6 @@
<template>
<div>
<q-header reveal elevated class="bg-primary text-white">
<q-header reveal elevated class="bg-primary">
<q-toolbar
color="primary"
:glossy="$q.theme === 'mat'"
@@ -58,7 +58,7 @@
-->
<q-btn
v-if="!isonline"
v-if="!isonline && static_data.functionality.SHOW_IF_IS_SERVER_CONNECTION"
flat
dense
round
@@ -72,6 +72,7 @@
<q-btn-dropdown
stretch
v-if="static_data.lang_available.length > 1"
flat
:label="langshort"
auto-close
@@ -79,7 +80,7 @@
<q-list bordered>
<q-item clickable v-ripple
v-for="langrec in selectOpLang" :key="langrec.value"
v-for="langrec in static_data.lang_available" :key="langrec.value"
@click="lang = langrec.value">
<q-item-section avatar>
<img :src="langrec.image" class="flagimg">
@@ -101,7 +102,8 @@
<label>{{ $t('msg.hello') }}</label> <span v-model="prova"></span> !
</div>-->
<q-btn dense flat round icon="menu" @click="right = !right"/>
<q-btn v-if="static_data.functionality.SHOW_USER_MENU" dense flat round icon="menu" @click="right = !right">
</q-btn>
</q-toolbar>
@@ -119,16 +121,16 @@
</q-drawer>
<q-drawer v-model="right" side="right" overlay bordered>
<q-drawer v-if="static_data.functionality.SHOW_USER_MENU" v-model="right" side="right" overlay bordered>
<div id="profile">
<q-img class="absolute-top" src="https://cdn.quasar-framework.org/img/material.png"
<q-img class="absolute-top" src="../../statics/images/landing_first_section.png"
style="height: 150px">
<div class="absolute-bottom bg-transparent">
<div class="absolute-bottom bg-transparent text-black center_img">
<q-avatar class="q-mb-sm">
<q-avatar class="q-mb-sm center_img">
<img src="../../statics/images/avatar-1.svg">
</q-avatar>
<div v-if="Username" class="text-weight-bold">{{ Username }}</div>
<div v-if="Username" class="text-weight-bold text-user">{{ Username }} - {{ Name }}</div>
<div v-else class="text-italic">{{ $t('user.loggati') }}</div>
<!--<span class="text-white" v-if="Verificato"> {{$t('reg.verificato')}} </span>-->

View File

@@ -0,0 +1,11 @@
$grayshadow: #555;
$textcol: blue;
$textcol_scuro: darkblue;
p {
color: black;
margin: 0 0 1rem;
//text-shadow: .125rem .125rem .25rem $grayshadow;
}

View File

@@ -0,0 +1,28 @@
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { Screen } from 'quasar'
import { ICategory } from '../../model'
import { Footer } from '../../components/Footer/index'
@Component({
name: 'PagePolicy',
components: { Footer }
})
export default class PagePolicy extends Vue {
@Prop({required: true}) public owneremail: string
@Prop({required: true}) public SiteName: string
@Prop({required: true}) public ownerDataName: string
@Prop({required: true}) public managerData: string
@Prop({required: true}) public includeData: string
@Prop({required: true}) public url: string
@Prop({required: true}) public lastdataupdate: string
@Prop({required: true}) public country: string
get toolsext() {
return toolsext
}
}

View File

@@ -0,0 +1,275 @@
<template>
<q-page class="q-pa-md">
<div v-if="toolsext.isLang('it')">
<p class="text-subtitle1">Privacy Policy di {{url}}</p>
<p class="text-subtitle1">Informativa sul trattamento dei dati personali ai sensi dellart. 13 del
Regolamento
(UE) n. 2016/679</p>
<p>Ai sensi dellart. 13 del Regolamento (UE) n. 2016/679, anche denominato General Data Protection
Regulation
(di
seguito il GDPR), {{SiteName}} La informa che i Suoi dati personali (di seguito i Dati),
saranno trattati nel rispetto di quanto previsto dal GDPR e di ogni normativa applicabile in riferimento
al
trattamento dei dati personali in conformità allinformativa che segue.</p>
<p><span class="text-subtitle2">1. Titolare del trattamento</span><br/>
{{ownerDataName}}</p>
<p><span class="boldhigh">Responsabile trattamento e protezione dati:</span><br/>
{{managerData}}
</p>
<p class="text-subtitle2">2. Categorie di Dati</p>
<p>I Dati trattati dal Titolare includono: {{includeData}}.</p>
<p class="text-subtitle2">3. Finalità e base giuridica del trattamento. Legittimo interesse.</p>
<p>I Dati saranno trattati per ladempimento di finalità informative, commerciali e amministrative ad
obblighi
di
legge, ai sensi dellart. 6, comma 1, lettera b) e c) del GDPR, nonché il perseguimento del legittimo
interesse
del Titolare, allart. 6, comma 1, lettera f del GDPR, in riferimento a:
rispetto di procedure amministrative interne e adempimento di obblighi di legge o regolamenti vigenti in
{{this.country}};
linvio di comunicazioni di natura informativa, commerciale e promozionale.</p>
<p>In ogni caso, il trattamento dei Suoi Dati effettuato sulla base del proprio legittimo interesse del
Titolare
avviene, oltre che nel rispetto di quanto previsto allart. 6, comma 1, lettera f del GDPR, anche in
conformità
a quanto disposto al considerando n. 47 e allOpinion n. 6/2014 Article 29 Data Protection Working
Party,
par.
III.3.1.</p>
<p class="text-subtitle2">4. Modalità del trattamento.</p>
<p>I Suoi Dati sono raccolti e registrati in modo lecito e secondo correttezza per le finalità sopra
indicate e
sono trattati anche con lausilio di strumenti elettronici e automatizzati, anche mediante linserimento
e
lorganizzazione in banche dati, in conformità a quanto disposto dal GDPR in materia di misure di
sicurezza,
e,
comunque, in modo tale da garantire la sicurezza e la riservatezza dei Dati stessi.</p>
<p class="text-subtitle2">5. Destinatari o categorie di destinatari.</p>
<p>I Dati potranno essere resi accessibili, portati a conoscenza di o comunicati ai seguenti soggetti, i
quali
saranno nominati dal Titolare, a seconda dei casi, quali responsabili la cui lista è disponibile
presso la
sede del Titolare o incaricati:
dipendenti e/o collaboratori a qualsivoglia titolo del Titolare;
soggetti pubblici o privati, persone fisiche o giuridiche, di cui il Titolare si avvalga per lo
svolgimento
delle attività strumentali al raggiungimento della finalità di cui sopra o a cui il Titolare sia tenuto
a
comunicare i Dati in forza di obblighi legali o contrattuali.</p>
<p>In ogni caso, i Dati non saranno diffusi.</p>
<p class="text-subtitle2">6. Luogo</p>
<p>I Dati sono trattati presso le sedi operative del Titolare ed in ogni altro luogo in cui le parti
coinvolte
nel
trattamento siano localizzate. Per ulteriori informazioni, contattare il Titolare agli estremi riportati
in
apertura.</p>
<p class="text-subtitle2">7. Periodo di conservazione.</p>
<p>I Dati saranno conservati per un periodo di tempo non superiore a 10 (dieci) anni per finalità
amministrative
e,
comunque, per il tempo strettamente necessario al perseguimento dellinteresse legittimo del
Titolare.</p>
<p class="text-subtitle2">8. Diritti di accesso, cancellazione, limitazione e portabilità.</p>
<p>Il Titolare La informa che Le sono riconosciuti i diritti di cui agli artt. da 15 a 20 del GDPR. A titolo
esemplificativo, inviando specifica richiesta allindirizzo email {{owneremail}}, Lei potrà:
ottenere la conferma che sia o meno in corso un trattamento di dati personali che La riguardano;
qualora un trattamento sia in corso, ottenere laccesso ai dati e alle informazioni relative al
trattamento,
nonché richiedere una copia dei dati stessi;
ottenere la rettifica dei dati inesatti e lintegrazione dei dati personali incompleti;
ottenere, qualora sussista una delle condizioni previste dallart. 17 del GDPR, la cancellazione dei
Dati
che La
riguardano;
ottenere, nei casi previsti dallart. 18 del GDPR, la limitazione del trattamento dei Dati che La
riguardano;
ricevere i Dati che La riguardano in un formato strutturato, di uso comune e leggibile da dispositivo
automatico
e richiedere la loro trasmissione ad un altro titolare, se tecnicamente fattibile.</p>
<p class="text-subtitle2">9. Diritto di opposizione.</p>
<p>Ai sensi dellart. 21 del GDPR, Lei godrà altresì del diritto di opporsi in qualsiasi momento al
trattamento
dei
propri Dati effettuato per il perseguimento del legittimo interesse del Titolare scrivendo allindirizzo
email
{{owneremail}}. In caso di opposizione, i Dati non saranno più oggetto di trattamento, sempre che non
sussistano motivi legittimi per procedere al trattamento che prevalgono sugli interessi, sui diritti e
sulle
libertà degli interessati, oppure per laccertamento, lesercizio o la difesa di un diritto in sede
giudiziaria.</p>
<p class="text-subtitle2">Responsabile della protezione dei dati</p>
<p>Il titolare ha provveduto a nominare il responsabile della protezione dei dati che è contattabile alla
seguente
casella di posta elettronica {{owneremail}}.</p>
<p class="text-subtitle2">10. Diritto di proporre reclamo al Garante.</p>
<p>Il Titolare La informa altresì che potrà proporre reclamo al Garante per la Protezione dei Dati Personali
nel
caso in cui ritenga che siano stati violati i diritti di cui è titolare ai sensi del GDPR o di qualsiasi
altra
normativa applicabile, secondo le modalità indicate sul sito internet del Garante per la Protezione dei
Dati
Personali accessibile allindirizzo: <a href="http://www.garanteprivacy.it" target="_blank">www.garanteprivacy.it</a>.
</p>
<p>Ultimo aggiornamento: {{lastdataupdate}}</p>
</div>
<div v-if="toolsext.isLang('es')">
<p class="text-subtitle1">Política de privacidad de {{url}}</p>
<p class="text-subtitle1">Información sobre el procesamiento de datos personales de conformidad con el art.
13 del Reglamento (UE) n. 2016/679</p>
<p>Según el art. 13 del Reglamento (UE) n. 2016/679, también llamado Reglamento general de protección de
datos (de seguido del "RGPD"), {{SiteName}} le informa que sus datos personales (en adelante, los
"Datos"), será tratado de conformidad con las disposiciones del GDPR y cualquier legislación
aplicable con referencia a procesamiento de datos personales de acuerdo con la siguiente
información.</p>
<p><span class="text-subtitle2">1. Controlador de datos</span><br/>
{{ownerDataName}}</p>
<p><span class="boldhigh">Gerente de procesamiento y protección de datos:</span><br/>
{{managerData}}
</p>
<p>El administrador de protección de datos puede ser contactado por correo electrónico:
{{owneremail}} para obtener información sobre el procesamiento de los datos comunicados o recopilados en
el transcurso de
navegación en este sitio, de conformidad con la legislación vigente sobre privacidad.</p>
<p class="text-subtitle2"> 2. Categorías de datos </p>
<p>Los datos procesados por el propietario incluyen: {{includeData}}. </p>
<p class="text-subtitle2"> 3. Finalidad y fundamento jurídico del procesamiento. Interés legítimo. </p>
            <p>Los datos serán procesados para el cumplimiento de fines informativos, comerciales y
administrativos.
obligaciones de ley, de conformidad con el art. 6, párrafo 1, letra b) yc) del GDPR, así
como la búsqueda de lo legítimo interés
del titular, en el art. 6, párrafo 1, letra f del RGPD, con referencia a:
cumplimiento de procedimientos administrativos internos y cumplimiento de obligaciones
legales o regulaciones vigentes en
{{this.country}};
envío de información, comunicaciones comerciales y promocionales. </p>
            <p>En cualquier caso, el procesamiento de sus datos se basa en su interés legítimo
titular se produce, así como en cumplimiento de lo dispuesto en el art. 6, párrafo 1, letra
f del
RGPD, también en conformidad a lo dispuesto en el considerando n. 47 y la opinión n. 6/2014 Artículo 29
Protección de
datos de trabajo partido, par. III.3.1. </p>
            <p class="text-subtitle2"> 4. Métodos de procesamiento. </p>
            <p>Sus datos se recopilan y registran de manera legal y correcta para los fines anteriores
indicado y También se procesan con la ayuda de herramientas electrónicas y automatizadas,
también a través de la inserción y la organización en bases de datos, de conformidad con las disposiciones
del GDPR
sobre medidas de seguridad y, sin embargo, de tal manera que garantice la seguridad y confidencialidad de
los
Datos. </p>
            <p class="text-subtitle2"> 5. Destinatarios o categorías de destinatarios. </p>
            <p>Los datos se pueden hacer accesibles, señalar o comunicar a los siguientes sujetos, i
que
serán designados por el controlador de datos, según sea el caso, como controladores de
datos, cuya lista está disponible
en el
sede del propietario - o personas a cargo:
empleados y / o colaboradores en cualquier capacidad del controlador de datos;
sujetos públicos o privados, personas físicas o jurídicas, para las cuales el controlador de datos hace uso de progreso de actividades instrumentales para el logro de los propósitos antes mencionados o para las cuales se requiere el controlador de datos para comunicar los datos en virtud de obligaciones legales o contractuales. </p>
            <p>En cualquier caso, los datos no serán revelados. </p>
            <p class="text-subtitle2"> 6. Localización </p>
            <p>Los datos se procesan en las oficinas operativas del controlador de datos y en cualquier otro lugar donde las partes involucrado en
Los tratamientos son localizados. Para obtener más información, póngase en contacto con el propietario en los detalles anteriores. en apertura. </p>
            <p class="text-subtitle2"> 7. Período de retención. </p>
            <p>Los Datos se conservarán por un período de tiempo que no exceda los 10 (diez) años para fines
administrativo y, sin embargo, por el tiempo estrictamente necesario para perseguir el interés legítimo del Propietario. </p>
            <p class="text-subtitle2"> 8. Derechos de acceso, cancelación, limitación y portabilidad. </p>
            <p>El propietario le informa que tiene derecho a los derechos establecidos en los artículos del
15 al 20 del GDPR. En nombre de
Por ejemplo, al enviar una solicitud específica a la dirección de correo electrónico
{{owneremail}}, puede:
obtener confirmación de que sus datos personales se están procesando o no;
Si un tratamiento está en curso, obtenga acceso a los datos e información relacionados con
tratamiento así como solicitar una copia de los datos;
obtener la corrección de datos inexactos y la integración de datos personales incompletos;
obtener, si alguna de las condiciones establecidas por el art. 17 del RGPD, la cancelación
de datos que te concierne;
obtener, en los casos previstos por el art. 18 del RGPD, la limitación del procesamiento de
los Datos que te concierne;
recibir los datos que le conciernen en un formato estructurado, comúnmente utilizado y
legible por dispositivo automático
y solicite su transmisión a otro propietario, si es técnicamente posible. </p>
<p class="text-subtitle2"> 9. Oposición a la derecha. </p>
            <p>Según el art. 21 del RGPD, también disfrutará del derecho de objetar en cualquier momento
procesamiento de datos propios llevado a cabo para la búsqueda del interés legítimo del propietario
escribiendo a la dirección
correo electrónico {{owneremail}}. En caso de oposición, los datos ya no se procesarán, a menos que se
Hay razones legítimas para proceder con el procesamiento que prevalecen sobre los intereses, derechos y
sobre las libertades de las partes interesadas, o para la determinación, el ejercicio o la defensa de un
derecho en
sede judicial. </p>
            <p class="text-subtitle2"> Oficial de protección de datos </p>
            <p>El propietario ha designado al responsable de protección de datos con el que puede contactar
siguiente dirección de correo electrónico {{owneremail}}. </p>
            <p class="text-subtitle2"> 10. Derecho a presentar una queja ante el Garante. </p>
            <p>El controlador de datos también le informa que puede presentar una queja ante el garante para
la protección de datos personales en caso de que crea que los derechos que posee bajo el GDPR o de han sido
violados cualquier otra legislación aplicable, de la manera indicada en el sitio web del Garante para
Protección de datos personales accesibles en la dirección: <a
href="https://www.garante.es/politica-de-privacidad/" target="_blank">https://www.garante.es/politica-de-privacidad/</a>.
            </p>
            <p>Última actualización: {{lastdataupdate}} </p>
</div>
<Footer></Footer>
</q-page>
</template>
<script lang="ts" src="./PagePolicy.ts">
</script>
<style lang="scss" scoped>
@import './PagePolicy.scss';
</style>

View File

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

View File

@@ -3,8 +3,12 @@ export * from './todos'
export * from './logo'
export * from './CProgress'
export * from './CCard'
export * from './CBook'
export * from './CPage'
export * from './CTitle'
export * from './CImgText'
export * from './CImgTitle'
export * from './CPreloadImages'
export * from './CDate'
export * from './BannerCookies'
export * from './PagePolicy'

View File

@@ -17,7 +17,7 @@
}
#logoimg {
height: 150px;
height: 50px;
width: auto;
@media screen and (max-width: 600px) {
}

84
src/db/db_data.js Normal file
View File

@@ -0,0 +1,84 @@
import { IEvents } from "../model";
export const db_data = {
URL_FACEBOOK: "https://www.facebook.com/associazioneshen",
events: [
{
title: 'Scambi Reiki',
details: 'Nelle serate esperienziali è possibile <span class="boldhigh">Dare e Ricevere</span> un trattamento completo.<br />' +
'Possono partecipare le persone che hanno già preso parte al <span class="boldhigh">seminario di 1° livello</span>, ma anche <span class="boldhigh">tutti quelli che hanno il desiderio di conoscere il Reiki</span> e sperimentarlo per la prima volta: in questo caso invitiamo gli interessati a contattarci per un appuntamento prima dellinizio della serata per ricevere le informazioni pratiche.',
date: '2019-07-11',
time: '21:00',
duration: 120,
side: 'left',
bgcolor: 'orange',
icon: 'fas fa-praying-hands',
img: 'images/reiki/reikisfondo.jpg',
where: 'Centro Shen',
// whereicon: 'shen.png',
teacher: 'Cristina Barattoni',
avatar: 'cristina.png',
infoextra: '',
linkpdf: 'files/eventi/Reiki_aMICHI.pdf',
},
{
title: 'Scambi Reiki',
details: 'Nelle serate esperienziali è possibile <span class="boldhigh">Dare e Ricevere</span> un trattamento completo.<br />' +
'Possono partecipare le persone che hanno già preso parte al <span class="boldhigh">seminario di 1° livello</span>, ma anche <span class="boldhigh">tutti quelli che hanno il desiderio di conoscere il Reiki</span> e sperimentarlo per la prima volta: in questo caso invitiamo gli interessati a contattarci per un appuntamento prima dellinizio della serata per ricevere le informazioni pratiche.',
date: '2019-07-20',
time: '21:00',
duration: 120,
side: 'left',
bgcolor: 'orange',
icon: 'fas fa-praying-hands',
img: 'images/reiki/reikisfondo.jpg',
where: 'Centro Shen',
// whereicon: 'shen.png',
teacher: 'Cristina Barattoni',
avatar: 'cristina.png',
infoextra: '',
linkpdf: '',
},
{
title: 'Seminario Reiki 1° Livello',
details: 'I seminari vengono organizzati volutamente in gruppi poco numerosi.\n' +
'Si crea così un ambiente accogliente e tranquillo con un atmosfera conviviale.<br />' +
'' +
'Per info vedi <a href="reiki/seminari">Seminari Reiki</a>',
date: '2019-07-22',
days: 2,
time: '9:00',
side: 'left',
bgcolor: 'red',
icon: 'fas fa-chalkboard-teacher',
img: 'images/reiki/reikisfondo.jpg',
where: 'Centro Shen',
// whereicon: 'shen.png',
teacher: 'Cristina Barattoni',
avatar: 'cristina.png',
teacher2: 'Elisa Ghizzardi',
avatar2: 'elisa.png',
infoextra: 'sabato e domenica dalle 10.00 alle 18.00',
linkpdf: '',
},
{
title: 'Presentazione Corsi per Operatori del Massaggio del Benessere',
details: 'Vieni alla presentazione dei Corsi!<br>10 settembre a Ravenna, 17 settembre a Lugo',
date: '2019-09-10',
time: '20:30',
duration: 120,
side: 'left',
bgcolor: 'blue',
icon: 'fas fa-praying-hands',
img: 'images/scuolaopbenessere/img1.jpg',
where: 'Centro Shen',
// whereicon: 'shen.png',
teacher: 'Operatori',
avatar: 'cristina.png',
avatar2: 'elisa.png',
infoextra: '',
linkpdf: '',
},
]
}

59
src/db/static_data.ts Normal file
View File

@@ -0,0 +1,59 @@
import { Todos, Projects, UserStore } from '@store'
import globalroutines from '../globalroutines/index'
import Quasar, { date, Screen } from 'quasar'
import { IListRoutes, ILang, IMenuList, IProject, ITodo, Privacy, IPerson, IFunctionality } from '../model/index'
import { RouteNames } from '../router/route-names'
const ds_operatori: IPerson[] = [
{
index: 0,
name: 'Elisa Ghizzardi',
sub1: 'Presidente',
sub2: 'Reiki Master, Naturopata e Operatrice Olistica',
img: '../../statics/images/direttivo/elisa.jpg',
cell: '338-9344724',
email: 'elisa.ghizzardi@yahoo.com',
paginaweb: '',
paginafb: '',
intro: 'Il mio incontro con le discipline olistiche è iniziato nel 2000, in un momento di grossi cambiamenti che mi hanno spinta a pormi delle domande sullesistenza e sul percorso di vita che tocca a ciascuno di noi... <br>',
info: 'Il mio incontro con le discipline olistiche è iniziato nel 2000, in un momento di grossi cambiamenti che mi hanno spinta a pormi delle domande sullesistenza e sul percorso di vita che tocca a ciascuno di noi.<br>' +
'In mio aiuto sono arrivati i Fiori di Bach, che ho utilizzato per diverso tempo e grazie ai quali ho cominciato a prendere contatto con una parte di me che non conoscevo e che ha cominciato ad emergere sempre di più.<br><br>' +
'Qualche anno dopo ho conosciuto la Via del Reiki, attraverso la quale ho compreso che lessere umano ha un potenziale enorme, dimenticato, ma che può essere ritrovato ed alimentato grazie al collegamento con la potente Energia Universale, grazie al collegamento con la scintilla divina che alberga in ognuno di noi. Ho desiderato allora completare il percorso per diventare insegnante e poter far conoscere anche ad altri la magnifica via del Reiki per riscoprire questo grande dono che abbiamo dentro di noi e per ritrovare la connessione con lEsistenza, lAmore e la Gioia profonda.<br><br>' +
'Grazie a delle meravigliose sincronicità ho incontrato persone con cui condividere il percorso, partecipare attivamente alla conduzione di unassociazione culturale per la divulgazione delle discipline olistiche e questo percorso che sempre più chiaramente si è mostrato essere “ciò che volevo fare da grande”. Gli interessi si sono così trasformati in percorsi formativi professionali per diventare Operatrice Olistica e Naturopata.<br><br>' +
'Insieme a Cristina e Kathryna nel 2019 abbiamo deciso di fondare Lassociazione SHEN per creare un centro di formazione sia per chi desidera intraprendere una professione in ambito olistico sia per chi desidera fare un percorso di crescita personale.<br><br>' +
'E di certo il cammino non è ancora finito cè così tanto da conoscere e sperimentare...<br><br>' +
'<span class="citazione">I due giorni più importanti della vita sono quello in cui sei nato e quello in capisci perché. (Mark Twain)</span>',
}]
const arrLangUsed = [
'it',
'enUs',
'es'
]
const lang_available: ILang[] = [
{ label: 'Italiano', icon: 'fa-flag-it', value: 'it', image: '../statics/images/it.png', short: 'IT' },
{ label: 'English', icon: 'fa-flag-us', value: 'enUs', image: '../statics/images/gb.png', short: 'EN' },
{ label: 'Español', icon: 'fa-flag-es', value: 'es', image: '../statics/images/es.png', short: 'ES' }
// { label: 'Français', icon: 'fa-facebook', value: 'fr', image: '../statics/images/fr.png', short: 'FR' }
// { label: 'German', icon: 'fa-flag-de', value: 'de', image: '../statics/images/de.png', short: 'DE' },
]
const functionality: IFunctionality = {
SHOW_USER_MENU: true,
SHOW_IF_IS_SERVER_CONNECTION: false,
ENABLE_TODOS_LOADING: true,
ENABLE_PROJECTS_LOADING: true,
SHOW_NEWSLETTER: false,
SHOW_ONLY_POLICY: false,
EVENTS_CAN_BOOKING: false
}
export const static_data = {
functionality,
ds_operatori,
lang_available,
arrLangUsed
}

View File

@@ -52,6 +52,7 @@
}
.my-menu, .my-menu > i{
min-height: 40px;
min-width: 26px;
font-size: 1rem;
}
@@ -63,7 +64,7 @@
.my-menu-icon > i{
min-width: 26px;
font-size: 1.5rem;
font-size: 1.25rem;
}
.clexpansion{

View File

@@ -2,6 +2,8 @@ import Vue from 'vue'
import { Watch } from 'vue-property-decorator'
import { GlobalStore } from '../../store/Modules'
import Component from 'vue-class-component'
import { static_data } from '../../db/static_data'
import { tools } from '../../store/Modules/tools'
export default class MenuOne extends Vue {
@@ -16,20 +18,21 @@ export default class MenuOne extends Vue {
// return this.$route.path
// }
get tools() {
return tools
}
get mythis() {
return this
}
get getmenu() {
return GlobalStore.getters.getmenu
}
public getLabelByItem(item) {
if (!!item.name)
return this.$t(item.name)
else
return item.text
}
public setParentVisibilityBasedOnRoute(parent) {
parent.routes.forEach((item) => {
if (this.$route.path === item.route) {
if (this.$route.path === item.path) {
parent.show = true
return
}
@@ -43,4 +46,8 @@ export default class MenuOne extends Vue {
return text
}
get static_data(){
return static_data
}
}

View File

@@ -3,12 +3,12 @@
<q-list class="rounded-borders text-primary">
<template v-for="(parent, index) in getmenu">
<!--<div class="q-list-header">{{replaceUnderlineToSpace(index)}}</div>-->
<div v-for="myitemmenu in parent.routes">
<div v-if="!!myitemmenu.routes2">
<div v-for="myitemmenu in static_data.routes">
<div v-if="!!myitemmenu.routes2 && myitemmenu.inmenu">
<q-expansion-item
:header-inset-level="myitemmenu.level_parent"
:content-inset-level="myitemmenu.level_parent"
:label="getLabelByItem(myitemmenu)"
:label="tools.getLabelByItem(myitemmenu, mythis)"
:icon="myitemmenu.materialIcon"
expand-icon-class="my-menu-separat"
header-class="my-menu"
@@ -16,17 +16,17 @@
<q-expansion-item v-for="(child2, index) in myitemmenu.routes2"
:key="index"
:to="child2.route"
:to="child2.path"
:header-inset-level="child2.level_child"
:duration="300"
:icon="child2.materialIcon"
active-class="my-menu-active"
expand-icon-class="my-menu-icon-none"
class="item item-link drawer-closer cursor-pointer my-menu"
:label="getLabelByItem(child2)">
:label="tools.getLabelByItem(child2, mythis)">
<q-expansion-item v-if="!!child2.routes2" v-for="(child3, index) in child2.routes2"
:key="index"
:to="child3.route"
:to="child3.path"
:header-inset-level="child3.level_child"
:duration="300"
:icon="child3.materialIcon"
@@ -34,7 +34,7 @@
expand-icon-class="my-menu-separat"
active-class="my-menu-active"
class="item item-link drawer-closer cursor-pointer my-menu"
:label="getLabelByItem(child3)">
:label="tools.getLabelByItem(child3, mythis)">
</q-expansion-item>
</q-expansion-item>
@@ -42,18 +42,19 @@
</q-expansion-item>
</div>
<div v-else>
<q-slide-transition :duration=200>
<div v-show="true">
<q-expansion-item
:to="myitemmenu.route"
:header-inset-level="myitemmenu.level_parent"
:content-inset-level="myitemmenu.level_parent"
:label="getLabelByItem(myitemmenu)"
:icon="myitemmenu.materialIcon"
expand-icon="none"
header-class="my-menu"
active-class="my-menu-active">
</q-expansion-item>
<div v-if="myitemmenu.inmenu && !myitemmenu.submenu">
<q-slide-transition :duration=200>
<div v-show="true">
<q-expansion-item
:to="myitemmenu.path"
:header-inset-level="myitemmenu.level_parent"
:content-inset-level="myitemmenu.level_parent"
:label="tools.getLabelByItem(myitemmenu, mythis)"
:icon="myitemmenu.materialIcon"
expand-icon="none"
header-class="my-menu"
active-class="my-menu-active">
</q-expansion-item>
<!--
@@ -72,8 +73,9 @@
</q-item-section>
</q-item>
-->
</div>
</q-slide-transition>
</div>
</q-slide-transition>
</div>
</div>
</div>
</template>

60
src/model/Calendar.ts Normal file
View File

@@ -0,0 +1,60 @@
export interface IEvents {
_id?: any
time?: string
duration?: number
duration2?: number
title?: string
details?: string
date?: string
side?: string
bgcolor?: string
days?: number
icon?: string
img?: string
where?: string
teacher?: string
teacher2?: string
avatar?: string
avatar2?: string
infoextra?: string
linkpdf?: string
nobookable?: boolean
}
export interface IBookedEvent {
id_bookedevent?: any
numpeople: number
infoevent: string
msgbooking: string
datebooked?: Date
booked: boolean
}
export interface ICalendarState {
editable: boolean
eventlist: IEvents[]
bookedevent: IBookedEvent[]
// ---------------
titlebarHeight: number
locale: string,
maxDays: number,
fiveDayWorkWeek: boolean,
shortMonthLabel: boolean,
showDayOfYearLabel: boolean,
shortWeekdayLabel: boolean,
shortIntervalLabel: boolean,
hour24Format: boolean,
hideHeader: boolean,
noScroll: boolean,
showMonthLabel: boolean,
showWorkWeeks: boolean,
intervalRange: {min: number, max: number},
intervalRangeStep: number,
intervalHeight: number,
resourceHeight: number,
resourceWidth: number,
dayHeight: number,
enableThemes: boolean,
theme: {}
}

18
src/model/Estimate.ts Normal file
View File

@@ -0,0 +1,18 @@
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
export interface IEstimate {
id?: number
title: string
advanced?: boolean
description?: string
viewlist?: number[]
listsel?: number
qtaName?: string
icon?: string
numpag?: number
qta?: number
price?: number
pricebase?: number
checksel?: boolean
}

View File

@@ -1,4 +1,5 @@
import { IAction } from '@src/model/Projects'
import { Component } from 'vue-router/types/router'
export interface IPost {
title: string
@@ -72,12 +73,124 @@ export interface IMenuList {
}
export interface IListRoutes {
route: string
faIcon?: string
materialIcon?: string
path: string
name: string
materialIcon?: string
component?: Component
reqauth?: boolean
inmenu?: boolean
solotitle?: boolean
infooter?: boolean
submenu?: boolean
// ------------------------
faIcon?: string
text?: string
routes2?: IListRoutes[]
level_parent?: number
level_child?: number
}
export interface IPerson {
index?: number
tab?: string
name: string
sub1: string
sub2?: string
sub3?: string
img: string
cell?: string
email?: string
paginaweb?: string
paginafb?: string
intro?: string
info?: string
vario?: string
}
export interface IPreloadImages {
imgname: string
mobile: boolean
}
export interface ILang {
label: string
icon: string
value: string
image: string
short: string
}
export interface IAllLang {
es?: string
enUs?: string
fr?: string
de?: string
it?: string
}
export interface ITimeLineEntry {
date: string
title: string
description: IAllLang
description2?: IAllLang
description3?: IAllLang
icon: string
image: string
image2?: string
image3?: string
image4?: string
video?: string
side: string
link_url?: string
link_url_lang?: IAllLang
link_text?: IAllLang
ingallery?: boolean
}
export interface ITimeLineMain {
titlemain: IAllLang
body: ITimeLineEntry[]
}
export interface IGallery {
title: string
subtitle?: IAllLang
img: string
width?: number
height?: number
ingallery?: boolean
inexibitions?: boolean
}
export interface IColl {
title: IAllLang
date: string
subtitle?: IAllLang
img: string
img2?: string
linkagg?: string
linkagg_type?: number
width?: number
height?: number
}
export interface ICollaborations {
withwhom_title: IAllLang
list: IColl[]
}
export interface IParamDialog {
param1?: any
param2?: any
param3?: any
}
export interface IFunctionality {
SHOW_USER_MENU?: boolean
SHOW_IF_IS_SERVER_CONNECTION?: boolean
ENABLE_TODOS_LOADING?: boolean
ENABLE_PROJECTS_LOADING?: boolean
SHOW_NEWSLETTER?: boolean
SHOW_ONLY_POLICY?: boolean
EVENTS_CAN_BOOKING?: false
}

View File

@@ -3,6 +3,8 @@ import { IToken } from 'model/other'
export const DefaultUser = <IUserState>{
email: '',
username: '',
name: '',
surname: '',
password: '',
lang: 'it'
}
@@ -11,6 +13,8 @@ export interface IUserState {
userId?: string
email?: string
username?: string
name?: string
surname?: string
password?: string
lang?: string
repeatPassword?: string

View File

@@ -1,3 +1,5 @@
import { IBookingState } from '@src/model/BookingStore'
export * from './UserStore'
export * from './GlobalStore'
export * from './signin-option'
@@ -10,3 +12,5 @@ export * from './Todos'
export * from './Projects'
export * from './Calendar'
export * from './Estimate'
export * from './BookingStore'

View File

@@ -2,6 +2,8 @@
export interface ISignupOptions {
email?: string
username: string
name?: string
surname?: string
password?: string
lang?: string
repeatPassword?: string

View File

@@ -1,13 +1,3 @@
body {
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #a7a7a7;
line-height: 1.5;
//font-size: 1rem;
}
$grayshadow: #555;
.testo-banda {
//background: -webkit-gradient(linear, left top, left bottom, from(#3144f0), to(transparent));
@@ -15,9 +5,18 @@ $grayshadow: #555;
//background: rgba(0, 0, 0, .6)
}
$grayshadow: #555;
$textcol: blue;
$textcol_scuro: darkblue;
p {
margin: 0 0 16px;
text-shadow: 2px 2px 4px $grayshadow;
margin: 0 0 1.25rem;
//text-shadow: .125rem .125rem .25rem $grayshadow;
}
h4 {
font-size: 1.25rem;
}
.mycard {
@@ -28,7 +27,7 @@ p {
}
.landing_background {
background: #000 url(../../statics/images/cover.jpg) no-repeat 50% fixed;
background: #000 url(../../statics/images/foto1.jpg) no-repeat 50% fixed;
background-size: cover
}
@@ -42,8 +41,51 @@ p {
//padding: 0 16px
}
.intro {
display: flex;
justify-content: space-between;
align-items: stretch;
/* flex-flow: row nowrap; */
padding: 1.25rem 0 1.25rem 0;
margin: .125rem;
* {
width: 100%;
flex: 1;
margin-left: auto;
margin-right: auto;
}
&__associazione {
min-width: 350px;
}
&__comeassociarsi{
min-width: 350px;
}
}
.subtitle {
font-weight: 600;
text-align: center;
letter-spacing: 0.125rem;
text-transform: uppercase;
font-size: 1rem;
}
.landing > section.padding {
padding: 90px 16px
padding: 5.62rem 1rem;
}
.landing > section.padding_testo {
padding-top: 1.25rem;
padding-bottom: 1rem;
}
.landing > section.padding_gallery {
padding-top: 3.125rem;
padding-bottom: 5.625rem;
}
.landing > section > div {
@@ -59,7 +101,7 @@ p {
}
.landing__toolbar .q-btn {
border-radius: 0 0 5px 5px;
border-radius: 0 0 .315rem .315rem;
-ms-flex-item-align: stretch;
align-self: stretch
}
@@ -73,7 +115,7 @@ p {
}
.landing__arrow {
bottom: 25px;
bottom: 1.5rem;
opacity: .4
}
@@ -83,24 +125,24 @@ p {
}
.landing__logo {
width: 150px;
height: 150px;
margin-top: 21px;
width: 9.40rem;
height: 9.40rem;
margin-top: 1.315rem;
//-webkit-animation: logo-rotate 240s linear infinite;
//animation: logo-rotate 240s linear infinite
}
.landing__features .q-icon {
font-size: 64px
font-size: 4rem
}
h4 {
line-height: 1.5;
text-shadow: 4px 4px 8px $grayshadow;
text-shadow: .25rem .25rem .5rem $grayshadow;
}
.landing__features h4, .landing__features h6 {
margin: 26px 0
margin: 1rem 0
}
.landing__features p {
@@ -111,19 +153,22 @@ h4 {
.landing__footer {
//background: -webkit-gradient(linear, left top, left bottom, color-stop(65%, rgba(0, 0, 0, .1)), to(#000));
background: linear-gradient(180deg, rgba(0, 0, 0, .8) 75%, #FFF);
padding-top: 72px !important;
padding-bottom: 72px !important
background: linear-gradient(180deg, rgba(0, 0, 0, .8) 95%, #FFF);
padding-top: 4.5rem !important;
padding-bottom: 4.5rem !important;
padding-left: 1.25rem;
padding-right: 1.25rem;
color: #9f9f9f;
}
.icon_contact:hover {
color: blue;
border-color: white;
border-width: 1px;
border-width: .0625rem;
}
.landing__footer .doc-link {
color: #fff
color: $textcol;
}
.landing__footer .doc-link:hover {
@@ -147,7 +192,7 @@ h4 {
}
.q-col-gutter-sm {
padding: 50px 50px;
padding: 3.125rem 3.125rem;
//margin-left: -48px
}
@@ -187,7 +232,7 @@ body.mobile .landing:before {
.home {
//background-color: rgb(250, 250, 250);
padding: 5px;
padding: 3.125rem;
display: flex;
//flex-wrap: nowrap;
flex-direction: column;
@@ -196,17 +241,17 @@ body.mobile .landing:before {
}
.btn-start {
margin: 5px;
margin: 3.125rem;
}
.shadow {
//color: white;
text-shadow: 2px 2px 4px $grayshadow;
text-shadow: 0.125rem 0.125rem 0.25rem $grayshadow;
}
.shadow-max {
//color: white;
text-shadow: 4px 4px 8px $grayshadow;
text-shadow: .25rem .25rem .5rem $grayshadow;
}
.text-h1 {
@@ -227,45 +272,26 @@ body.mobile .landing:before {
font-weight: 700;
}
.text-subtitle1 {
font-size: 1.35rem;
font-weight: 400;
line-height: 1.75rem;
text-shadow: 4px 4px 8px $grayshadow;
letter-spacing: .00937em;
&.big {
font-size: 1.5rem;
}
}
.text-subtitle2 {
font-size: 1.15rem;
.text-vers{
font-size: 0.75rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: 4px 4px 8px $grayshadow;
}
.text-subtitle3 {
font-size: 1rem;
font-weight: 400;
line-height: 1.75rem;
letter-spacing: .00937em;
text-shadow: 2px 2px 4px $grayshadow;
text-shadow: .25rem .25rem .5rem $grayshadow;
}
.homep-cover-img-1 {
background: #000 url(../../statics/images/cover.jpg) no-repeat 50% fixed;
background: #000 url(../../statics/images/foto1.jpg) no-repeat 50% fixed;
//transition: background-image 1s ease-in-out;
}
.homep-cover-img-2 {
background: #000 url(../../statics/images/hand_people.jpg) no-repeat 50% fixed;
background: #000 url(../../statics/images/foto2.jpg) no-repeat 50% fixed;
//transition: background-image 1s ease-in-out;
}
.homep-cover-img-3 {
background: #000 url(../../statics/images/cibo_sano.jpg) no-repeat 50% fixed;
background: #000 url(../../statics/images/foto3.jpg) no-repeat 50% fixed;
//transition: background-image 1s ease-in-out;
}
@@ -274,19 +300,19 @@ body.mobile .landing:before {
}
.landing__footer-icons {
font-size: 28px
font-size: 1.75rem
}
.landing__footer-icons a {
margin: 0 8px 8px;
margin: 0 .5rem .5rem;
text-decoration: none;
outline: 0;
color: #fff;
color: $textcol;
transition: color .28s
}
.landing__footer-icons a:hover {
color: #e0e0e0
color: $textcol_scuro;
}
.doc-img {
@@ -295,12 +321,12 @@ body.mobile .landing:before {
.mylist {
background: #3fdaff;
padding-left: 20px;
padding-left: 1.25rem;
}
.clgutter {
margin-top: 20px;
padding: 10px;
margin-top: 1.25rem;
padding: .62rem;
}
.carousel_img_3 {
@@ -321,35 +347,44 @@ body.mobile .landing:before {
height: 7vh
}
.clgutter {
margin-top: 0px;
padding: 0px;
margin-top: 0;
padding: 0;
}
.landing__hero .text-h1 {
font-size: 3rem;
line-height: 3.05rem;
margin-bottom: 24px
margin-bottom: 1.5rem
}
.landing > section.padding {
padding: 40px 16px
//padding-bottom: 90px
padding: 2.5rem 1rem;
}
.landing > section.padding_testo {
padding-top: 1.25rem;
padding-bottom: 1rem;
}
.landing > section.padding_gallery {
padding-top: 3.125rem;
padding-bottom: 5.625rem;
}
.landing__features h4, .landing__features h6 {
margin: 20px 0
margin: 1.25rem 0
}
h4 {
line-height: 1.4;
text-shadow: 4px 4px 8px $grayshadow;
text-shadow: 0.25rem 0.25rem 0.5rem $grayshadow;
}
.landing .feature-item {
text-align: center;
margin-top: 20px;
margin-top: 1.25rem;
}
.landing__hero-content {
padding-bottom: 180px
padding-bottom: 11.25rem;
}
.landing__hero-btns {
-webkit-box-pack: center;
@@ -358,17 +393,14 @@ body.mobile .landing:before {
}
.q-col-gutter-sm {
padding: 10px 5px;
padding: .625rem .315rem;
}
.text-subtitle1 {
font-size: 1.25rem;
}
.text-subtitle2 {
font-size: 1rem;
}
.text-subtitle3 {
font-size: 0.75rem;
.text-vers{
font-size: 0.6rem;
}
.carousel_img_3 {
@@ -382,8 +414,25 @@ body.mobile .landing:before {
.custom-caption {
text-align: center;
padding: 12px;
color: white;
padding: .75rem;
color: $textcol;
background-color: rgba(0, 0, 0, .3);
}
.mycontacts {
color: gray;
letter-spacing: 0.078rem;
}
.mycontacts_title {
text-shadow: 0.125rem 0.125rem 0.125rem #555;
font-weight: bold;
color: #999;
letter-spacing: 0.125rem;
}
.mycontacts_text {
color: #999;
letter-spacing: 0.093rem;
}

View File

@@ -4,8 +4,12 @@ import { GlobalStore, UserStore } from '@store'
import { Logo } from '../../components/logo'
import { Footer } from '../../components/Footer'
import VueScrollReveal from 'vue-scroll-reveal'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { Screen } from 'quasar'
Vue.use(VueScrollReveal, {
class: 'v-scroll-reveal', // A CSS class applied to elements with the v-scroll-reveal directive; useful for animation overrides.
@@ -21,7 +25,7 @@ Vue.use(VueScrollReveal, {
})
@Component({
components: { Logo }
components: { Logo, Footer }
})
export default class Home extends Vue {
public text: string = ''

View File

@@ -402,6 +402,8 @@
<q-page-scroller position="bottom-right" :scroll-offset="850" :offset="[18, 18]" style="opacity: 0.3">
<q-btn fab icon="keyboard_arrow_up" color="accent" />
</q-page-scroller>
<Footer></Footer>
</div>
</q-page>

View File

@@ -7,6 +7,7 @@ import { ProgressBar } from '@src/store/Modules/Interface'
import { isEqual } from 'lodash'
import { UserStore } from '@store'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
Vue.use(VueRouter)
/*
@@ -16,7 +17,7 @@ Vue.use(VueRouter)
const Router = new VueRouter({
scrollBehavior: () => ({ x: 0, y: 0 } as PositionResult),
routes: cfgrouter.routes,
routes: cfgrouter.getmenu(),
// Leave these as is and change from quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode

View File

@@ -1,11 +1,13 @@
import { RouteConfig, Route, RouteRecord } from 'vue-router/types'
import { tools } from '@src/store/Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import auth from '../middleware/auth'
import { GlobalStore, Projects, Todos, UserStore } from '@store'
import { RouteNames } from '@src/router/route-names'
import { IListRoutes, IMenuList } from '@src/model'
import { static_data } from '@src/db/static_data'
interface IMyMeta {
title?: string,
@@ -88,6 +90,11 @@ export const cfgrouter = {
name: 'Categories',
component: () => import('@/views/admin/testp1/testp1.vue')
},
{
path: '/estimate',
name: 'Estimate',
component: () => import('@/views/pages/estimate/estimate.vue')
},
{
path: '/offline',
name: 'Offline',

View File

@@ -1,4 +1,4 @@
import msg_website from './i18n_website'
import msg_website from '../db/i18n_website'
const msgglobal = {
it: {
@@ -9,6 +9,7 @@ const msgglobal = {
delete: 'Elimina',
cancel: 'Annulla',
today: 'Oggi',
book: 'Prenota',
msg: {
titledeleteTask: 'Elimina Task',
deleteTask: "Vuoi Eliminare {mytodo}?"
@@ -44,10 +45,13 @@ const msgglobal = {
loggati: 'Utente non loggato'
},
reg: {
page_title: 'Registrazione',
incorso: 'Registrazione in corso...',
richiesto: 'Campo Richiesto',
email: 'Email',
username: 'Nome Utente',
name: 'Nome',
surname: 'Cognome',
username_login: 'Nome Utente o email',
password: 'Password',
repeatPassword: 'Ripeti password',
@@ -79,6 +83,7 @@ const msgglobal = {
}
},
login: {
page_title: 'Login',
incorso: 'Login in corso',
enter: 'Login',
errato: "Username o password errata. Riprovare",
@@ -149,6 +154,14 @@ const msgglobal = {
themebgcolor: 'Tema Colore Sfondo'
},
cal: {
booked: 'Prenotato',
booked_error: 'Prenotazione non avvenuta. Riprovare più tardi',
booking: 'Prenota Evento',
titlebooking: 'Prenotazione',
cancelbooking: 'Cancella Prenotazione',
canceledbooking: 'Prenotazione Cancellata',
cancelederrorbooking: 'Cancellazione non effettuata, Riprovare più tardi',
event: 'Evento',
starttime: 'Dalle',
endtime: 'alle',
duration: 'Durata',
@@ -161,11 +174,18 @@ const msgglobal = {
infoextra: 'Date e Ora Extra:',
alldayevent: 'Tutto il giorno',
eventstartdatetime: 'Data e Ora Inizio Evento',
enterEndDateTime: 'Data e Ora Fine Evento'
enterEndDateTime: 'Data e Ora Fine Evento',
selnumpeople: 'Partecipanti',
msgbooking: 'Messaggio da inviare',
bookingtextdefault: 'Mi prenoto all\'evento',
bookingtextdefault_of: 'di'
},
newsletter: {
title: 'Desideri ricevere la nostra Newsletter?',
name: 'Il tuo Nome',
namehint: 'Nome e Cognome',
surname: 'Il tuo Cognome',
namehint: 'Nome',
surnamehint: 'Cognome',
email: 'La tua Email',
submit: 'Iscriviti',
reset: 'Cancella',
@@ -173,9 +193,11 @@ const msgglobal = {
acceptlicense: 'Accetto la licenza e i termini',
license: 'Devi prima accettare la licenza e i termini',
submitted: 'Iscritto'
}
},
privacy_policy:'Privacy Policy',
cookies: 'Usiamo i Cookie per una migliore prestazione web.'
},
'es': {
es: {
dialog: {
ok: 'Vale',
yes: 'Sí',
@@ -183,6 +205,7 @@ const msgglobal = {
delete: 'Borrar',
cancel: 'Cancelar',
today: 'Hoy',
book: 'Reserva',
msg: {
titledeleteTask: 'Borrar Tarea',
deleteTask: 'Quieres borrar {mytodo}?'
@@ -218,10 +241,13 @@ const msgglobal = {
loggati: 'Usuario no ha iniciado sesión'
},
reg: {
page_title: 'Registro',
incorso: 'Registro en curso...',
richiesto: 'Campo requerido',
email: 'Email',
username: 'Nombre usuario',
name: 'Nombre',
surname: 'Apellido',
username_login: 'Nombre usuario o email',
password: 'contraseña',
repeatPassword: 'Repetir contraseña',
@@ -246,6 +272,7 @@ const msgglobal = {
}
},
login: {
page_title: 'Login',
incorso: 'Login en curso',
enter: 'Entra',
errato: "Nombre de usuario, correo o contraseña incorrectos. inténtelo de nuevo",
@@ -317,6 +344,14 @@ const msgglobal = {
themebgcolor: 'Tema Colores Fondo'
},
cal: {
booked: 'Reservado',
booked_error: 'Reserva fallida. Intenta nuevamente más tarde',
booking: 'Reserva Evento',
titlebooking: 'Reserva',
cancelbooking: 'Cancelar Reserva',
canceledbooking: 'Reserva Cancelada',
cancelederrorbooking: 'Cancelación no realizada, intente nuevamente más tarde',
event: 'Evento',
starttime: 'Inicio',
endtime: 'fin',
duration: 'Duración',
@@ -329,11 +364,18 @@ const msgglobal = {
infoextra: 'Fecha y Hora Extras:',
alldayevent: 'Todo el dia',
eventstartdatetime: 'Evento de inicio de fecha y hora',
enterEndDateTime: 'Fecha y hora del evento final'
enterEndDateTime: 'Fecha y hora del evento final',
selnumpeople: 'Partecipantes',
msgbooking: 'Mensaje para enviar',
bookingtextdefault: 'Reservo el evento',
bookingtextdefault_of: 'de',
},
newsletter: {
title: '¿Desea recibir nuestro boletín informativo?',
name: 'Tu Nombre',
namehint: 'Nombre y Apellido',
surname: 'Tu Apellido',
namehint: 'Nombre',
surnamehint: 'Apellido',
email: 'tu correo',
submit: 'Subscribete',
reset: 'Reiniciar',
@@ -341,9 +383,200 @@ const msgglobal = {
acceptlicense: 'Acepto la licencia y los términos',
license: 'Necesitas aceptar la licencia y los términos primero',
submitted: 'Subscrito'
}
},
privacy_policy:'Política de privacidad',
cookies: 'Utilizamos cookies para un mejor rendimiento web.'
},
'enUs': {
fr: {
dialog: {
ok: 'Bien',
yes: 'Oui',
no: 'Non',
delete: 'Supprimer',
cancel: 'annuler',
today: 'Aujourd\'hui',
book: 'Réserve',
msg: {
titledeleteTask: 'Supprimer la tâche',
deleteTask: 'Voulez-vous supprimer {mytodo}?'
}
},
comp: {
Conta: "Conta",
},
components: {
authentication: {
login: {
facebook: 'Facebook'
},
email_verification: {
title: 'Créer un compte',
introduce_email: 'entrez votre adresse email',
email: 'Email',
invalid_email: 'Votre email n\'est pas valide',
verify_email: 'Vérifiez votre email',
go_login: 'Retour à la connexion',
incorrect_input: 'Entrée correcte.',
link_sent: 'Pour confirmer lenregistrement, lisez votre boîte aux lettres et cliquez sur "Vérifier le courrier électronique".".\n' + 'Si vous ne le trouvez pas, regardez dans le dossier Spam.'
}
}
},
fetch: {
errore_generico: 'Erreur générique',
errore_server: 'Le serveur n\'est pas accessible. Essayez encore, Merci',
error_doppiologin: 'Re-connexion Accès ouvert par un autre appareil.',
},
user: {
notregistered: 'Vous devez vous inscrire auprès du service avant de pouvoir stocker les données.',
loggati: 'L\'utilisateur n\'est pas connecté'
},
reg: {
incorso: 'Inscription en cours...',
richiesto: 'Champ obligatoire',
email: 'Email',
username: 'Nom d\'utilisateur',
name: 'Nom',
surname: 'Prénom',
username_login: 'Nom d\'utilisateur ou email',
password: 'mot de passe',
repeatPassword: 'Répéter le mot de passe',
terms: "J'accepte les termes et conditions",
submit: "S'inscrire",
title_verif_reg: "Vérifier l'inscription",
verificato: "Vérifié",
non_verificato: "Non vérifié",
forgetpassword: "Vous avez oublié votre mot de passe?",
err: {
required: 'c\'est nécessaire',
email: 'Ce doit être un email valide.',
errore_generico: 'S\'il vous plaît remplir les champs correctement',
atleast: 'ça doit être au moins long',
complexity: 'doit contenir au moins 1 minuscule, 1 majuscule et 1 chiffre',
notmore: 'il ne doit pas être plus long que',
char: 'caractères',
terms: 'Vous devez accepter les conditions, pour continuer..',
duplicate_email: 'L\'email a déjà été enregistré',
duplicate_username: 'Le nom d\'utilisateur a déjà été utilisé',
sameaspassword: 'Les mots de passe doivent être identiques',
}
},
login: {
page_title: 'Login',
incorso: 'Connexion en cours',
enter: 'Entrez',
errato: "Nom d'utilisateur, email ou mot de passe incorrect. réessayer",
completato: 'Connexion faite!',
},
reset: {
title_reset_pwd: "Réinitialiser votre mot de passe",
send_reset_pwd: 'Envoyer un mot de passe de réinitialisation',
incorso: 'Demander un nouvel email...',
email_sent: 'Email envoyé',
check_email: 'Vérifiez votre email, vous recevrez un message avec un lien pour réinitialiser votre mot de passe. Ce lien, pour des raisons de sécurité, expirera au bout de 4 heures.',
title_update_pwd: 'Mettez à jour votre mot de passe',
update_password: 'Mettre à jour le mot de passe',
},
logout: {
uscito: 'Vous êtes déconnecté',
},
errors: {
graphql: {
undefined: 'non défini'
}
},
todo: {
titleprioritymenu: 'Prioridad:',
inserttop: 'Ingrese una nueva Tarea arriba',
insertbottom: 'Ingrese una nueva Tarea abajo',
edit: 'Descripción Tarea:',
completed: 'Ultimos Completados',
usernotdefined: 'Atención, debes iniciar sesión para agregar una Tarea',
start_date: 'Fecha inicio',
status: 'Estado',
completed_at: 'Fecha de finalización',
expiring_at: 'Fecha de Caducidad',
phase: 'Fase',
},
notification: {
status: 'Etat',
ask: 'Activer les notifications',
waitingconfirm: 'Confirmer la demande de notification.',
confirmed: 'Notifications activées!',
denied: 'Notifications désactivées! Attention, vous ne verrez pas les messages arriver. Réhabilitez-les pour les voir.',
titlegranted: 'Notifications activées activées!',
statusnot: 'Notifications d\'état',
titledenied: 'Notifications autorisées désactivées!',
title_subscribed: 'Abonnement au Site Web!',
subscribed: 'Maintenant, vous pouvez recevoir des messages et des notifications.',
newVersionAvailable: 'Mise à jour'
},
connection: 'Connexion',
proj: {
newproj: 'Título Projecto',
newsubproj: 'Título Sub-Projecto',
insertbottom: 'Añadir nuevo Proyecto',
longdescr: 'Descripción',
hoursplanned: 'Horas Estimadas',
hoursleft: 'Horas Restantes',
hoursadded: 'Horas Adicional',
hoursworked: 'Horas Trabajadas',
begin_development: 'Comienzo desarrollo',
begin_test: 'Comienzo Prueba',
progresstask: 'Progresion',
actualphase: 'Fase Actual',
hoursweeky_plannedtowork: 'Horarios semanales programados',
endwork_estimate: 'Fecha estimada de finalización',
privacyread: 'Quien puede verlo:',
privacywrite: 'Quien puede modificarlo:',
totalphases: 'Fases totales',
themecolor: 'Tema Colores',
themebgcolor: 'Tema Colores Fondo'
},
cal: {
booked: 'Réservé',
booked_error: 'La réservation a échoué. Réessayez plus tard',
booking: 'Réserver l\'événement',
titlebooking: 'Réservation',
cancelbooking: 'Annuler la réservation',
canceledbooking: 'Réservation annulée',
cancelederrorbooking: 'Annulation non effectuée, réessayez plus tard',
event: 'événement',
starttime: 'Accueil',
endtime: 'fin',
duration: 'Durée',
hours: 'Le temps',
when: 'Quand',
where: 'Où',
teacher: 'Avec',
enterdate: 'Entrez la date',
details: 'Les détails',
infoextra: 'Extras Date et heure:',
alldayevent: 'Toute la journée',
eventstartdatetime: 'Date de début et heure de l\'événement',
enterEndDateTime: 'Date et heure de l\'événement final',
selnumpeople: 'Participants',
msgbooking: 'Message à envoyer',
bookingtextdefault: 'Je réserve l\'événement',
bookingtextdefault_of: 'du',
},
newsletter: {
title: 'Souhaitez-vous recevoir notre newsletter?',
name: 'Ton nom',
surname: 'Tu prénom',
namehint: 'Nom',
surnamehint: 'Prénom',
email: 'votre e-mail',
submit: 'S\'abonner',
reset: 'Redémarrer',
typesomething: 'Remplir le champ',
acceptlicense: 'J\'accepte la licence et les termes',
license: 'Vous devez d\'abord accepter la licence et les termes',
submitted: 'Abonné'
},
privacy_policy:'Politique de confidentialité',
cookies: 'Nous utilisons des cookies pour améliorer les performances Web.'
},
enUs: {
dialog: {
ok: 'Ok',
yes: 'Yes',
@@ -351,6 +584,7 @@ const msgglobal = {
delete: 'Delete',
cancel: 'Cancel',
today: 'Today',
book: 'Book',
msg: {
titledeleteTask: 'Delete Task',
deleteTask: 'Delete Task {mytodo}?'
@@ -391,6 +625,8 @@ const msgglobal = {
email: 'Email',
username_login: 'Username or email',
username: 'Username',
name: 'Name',
surname: 'Surname',
password: 'Password',
repeatPassword: 'Repeat password',
terms: "I agree with the terms and conditions",
@@ -485,6 +721,14 @@ const msgglobal = {
themebgcolor: 'Theme Color Background'
},
cal: {
booked: 'Booked',
booked_error: 'Reservation failed. Try again later',
booking: 'Book the Event',
titlebooking: 'Reservation',
cancelbooking: 'Cancel Reservation',
canceledbooking: 'Booking cancelled',
cancelederrorbooking: 'Cancellation unsuccessfully, try again later',
event: 'Event',
starttime: 'From',
endtime: 'to',
duration: 'Duration',
@@ -495,13 +739,20 @@ const msgglobal = {
enterdate: 'Enter date',
details: 'Details',
infoextra: 'Extra Info DateTime',
alldayevent: 'All-Day event',
alldayevent: 'All-Day myevent',
eventstartdatetime: 'Event start date and time',
enterEndDateTime: 'Event end date and time'
enterEndDateTime: 'Event end date and time',
selnumpeople: 'Participants',
msgbooking: 'Message to send',
bookingtextdefault: 'I book the event',
bookingtextdefault_of: 'of',
},
newsletter: {
title: 'Would you like to receive our Newsletter?',
name: 'Your name',
namehint: 'Name and surname',
surname: 'Your surname',
namehint: 'Name',
surnamehint: 'Surname',
email: 'Your email',
submit: 'Subscribe',
reset: 'Reset',
@@ -509,32 +760,239 @@ const msgglobal = {
acceptlicense: 'I accept the license and terms',
license: 'You need to accept the license and terms first',
submitted: 'Subscribed'
}
},
privacy_policy:'Privacy Policy',
cookies: 'We use cookies for better web performance.'
},
de: {
dialog: {
ok: 'Ok',
yes: 'Yes',
no: 'No',
delete: 'Delete',
cancel: 'Cancel',
today: 'Today',
book: 'Book',
msg: {
titledeleteTask: 'Delete Task',
deleteTask: 'Delete Task {mytodo}?'
}
},
comp: {
Conta: "Count",
},
components: {
authentication: {
login: {
facebook: 'Facebook'
},
email_verification: {
title: 'Begin your registration',
introduce_email: 'Enter your email',
email: 'Email',
invalid_email: 'Your email is invalid',
verify_email: 'Verify your email',
go_login: 'Back to Login',
incorrect_input: 'Incorrect input.',
link_sent: 'To confirm the Registration, read your mailbox and click on "Verify email".\nIf you can not find it check your junk mail or spam.'
}
}
},
fetch: {
errore_generico: 'Generic Error',
errore_server: 'Unable to access to the Server. Retry. Thank you.',
error_doppiologin: 'Signup again. Another access was made with another device.',
},
user: {
notregistered: 'You need first to SignUp before storing data',
loggati: 'User not logged in'
},
reg: {
page_title: 'Registration',
incorso: 'Registration please wait...',
richiesto: 'Field Required',
email: 'Email',
username_login: 'Username or email',
username: 'Username',
name: 'Name',
surname: 'Surname',
password: 'Password',
repeatPassword: 'Repeat password',
terms: "I agree with the terms and conditions",
submit: "Submit",
title_verif_reg: "Verify Registration",
verificato: "Verified",
non_verificato: "Not Verified",
forgetpassword: "Forget Password?",
err: {
required: 'is required',
email: 'must be a valid email',
errore_generico: 'Please review fields again',
atleast: 'must be at least',
complexity: 'must contains at least 1 lowercase letter, 1 uppercase letter, and 1 digit',
notmore: 'must not be more than',
char: 'characters long',
terms: 'You need to agree with the terms & conditions.',
duplicate_email: 'Email was already registered',
duplicate_username: 'Username is already taken',
sameaspassword: 'Passwords must be identical',
}
},
login: {
page_title: 'Login',
incorso: 'Login...',
enter: 'Login',
errato: "Username or password wrong. Please retry again",
completato: 'Login successfully!',
},
reset: {
title_reset_pwd: "Reset your Password",
send_reset_pwd: 'Send password request',
incorso: 'Request New Email...',
email_sent: 'Email sent',
check_email: 'Check your email for a message with a link to update your password. This link will expire in 4 hours for security reasons.',
title_update_pwd: 'Update your password',
update_password: 'Update Password',
},
logout: {
uscito: 'Logout successfully',
},
errors: {
graphql: {
undefined: 'undefined'
}
},
todo: {
titleprioritymenu: 'Priority:',
inserttop: 'Insert Task at the top',
insertbottom: 'Insert Task at the bottom',
edit: 'Task Description:',
completed: 'Lasts Completed',
usernotdefined: 'Attention, you need to be Signed In to add a new Task',
start_date: 'Start Date',
status: 'Status',
completed_at: 'Completition Date',
expiring_at: 'Expiring Date',
phase: 'Phase',
},
notification: {
status: 'Status',
ask: 'Enable Notification',
waitingconfirm: 'Confirm the Request Notification',
confirmed: 'Notifications Enabled!',
denied: 'Notifications Disabled! Attention, you will not see your messages incoming. Reenable it for see it',
titlegranted: 'Notification Permission Granted!',
statusnot: 'status Notification',
titledenied: 'Notification Permission Denied!',
title_subscribed: 'Subscribed to FreePlanet.app!',
subscribed: 'You can now receive Notification and Messages.',
newVersionAvailable: 'Upgrade'
},
connection: 'Conexión',
proj: {
newproj: 'Project Title',
newsubproj: 'SubProject Title',
insertbottom: 'Insert New Project',
longdescr: 'Description',
hoursplanned: 'Estimated Hours',
hoursleft: 'Left Hours',
hoursadded: 'Additional Hours',
hoursworked: 'Worked Hours',
begin_development: 'Start Dev',
begin_test: 'Start Test',
progresstask: 'Progression',
actualphase: 'Actual Phase',
hoursweeky_plannedtowork: 'Scheduled weekly hours',
endwork_estimate: 'Estimated completion date',
privacyread: 'Who can see it:',
privacywrite: 'Who can modify if:',
totalphases: 'Total Phase',
themecolor: 'Theme Color',
themebgcolor: 'Theme Color Background'
},
cal: {
booked: 'Booked',
booked_error: 'Reservation failed. Try again later',
booking: 'Book the Event',
titlebooking: 'Reservation',
cancelbooking: 'Cancel Reservation',
canceledbooking: 'Booking cancelled',
cancelederrorbooking: 'Cancellation unsuccessfully, try again later',
event: 'Event',
starttime: 'From',
endtime: 'to',
duration: 'Duration',
hours: 'Hours',
when: 'When',
where: 'Where',
teacher: 'With',
enterdate: 'Enter date',
details: 'Details',
infoextra: 'Extra Info DateTime',
alldayevent: 'All-Day myevent',
eventstartdatetime: 'Event start date and time',
enterEndDateTime: 'Event end date and time',
selnumpeople: 'Participants',
msgbooking: 'Message to send',
bookingtextdefault: 'I book the event',
bookingtextdefault_of: 'of',
},
newsletter: {
title: 'Would you like to receive our Newsletter?',
name: 'Your name',
surname: 'Your surname',
namehint: 'Name',
surnamehint: 'Surname',
email: 'Your email',
submit: 'Subscribe',
reset: 'Reset',
typesomething: 'Please type something',
acceptlicense: 'I accept the license and terms',
license: 'You need to accept the license and terms first',
submitted: 'Subscribed'
},
privacy_policy:'Privacy Policy',
cookies: 'Wir verwenden Cookies für eine bessere Webleistung.'
},
};
const msgit = { ...msg_website.it, ...msgglobal.it }
const msgde = { ...msg_website.de, ...msgglobal.de }
const msgfr = { ...msg_website.fr, ...msgglobal.fr }
const msges = { ...msg_website.es, ...msgglobal.es }
const msgenUs = { ...msg_website.enUs, ...msgglobal.enUs }
const messages = {
it: { ...msgit,
it: {
...msgit,
pages: { ...msg_website.it.pages, ...msgglobal.it.pages },
msg: { ...msg_website.it.msg, ...msgglobal.it.msg },
homepage: { ...msg_website.it.homepage, ...msgglobal.it.homepage },
homepage: { ...msg_website.it.homepage, ...msgglobal.it.homepage }
},
es: { ...msges ,
es: {
...msges,
pages: { ...msg_website.es.pages, ...msgglobal.es.pages },
msg: { ...msg_website.es.msg, ...msgglobal.es.msg },
homepage: { ...msg_website.es.homepage, ...msgglobal.es.homepage }
},
enUs: { ...msgenUs ,
enUs: {
...msgenUs,
pages: { ...msg_website.enUs.pages, ...msgglobal.enUs.pages },
msg: { ...msg_website.enUs.msg, ...msgglobal.enUs.msg },
homepage: { ...msg_website.enUs.homepage, ...msgglobal.enUs.homepage }
},
fr: {
...msgfr,
pages: { ...msg_website.fr.pages, ...msgglobal.fr.pages },
msg: { ...msg_website.fr.msg, ...msgglobal.fr.msg },
homepage: { ...msg_website.fr.homepage, ...msgglobal.fr.homepage },
},
de: {
...msgde,
pages: { ...msg_website.de.pages, ...msgglobal.de.pages },
msg: { ...msg_website.de.msg, ...msgglobal.de.msg },
homepage: { ...msg_website.de.homepage, ...msgglobal.de.homepage },
}
}
export default messages;

View File

@@ -341,6 +341,10 @@ namespace Actions {
return
}
if (UserStore.state.userId === undefined || UserStore.state.tokens[0] === undefined) {
return
}
// console.log('saveSubscriptionToServer: ', newSub)
// console.log('context', context)
@@ -432,7 +436,7 @@ namespace Actions {
}
async function loadAfterLogin(context) {
console.log('loadAfterLogin')
// console.log('loadAfterLogin')
actions.clearDataAfterLoginOnlyIfActiveConnection()
state.arrConfig = await globalroutines(null, 'readall', 'config', null)

View File

@@ -14,6 +14,7 @@ import { costanti } from '@src/store/Modules/costanti'
import { RouteNames } from '@src/router/route-names'
import * as Types from '@src/store/Api/ApiTypes'
import { serv_constants } from '@src/store/Modules/serv_constants'
import { static_data } from '@src/db/static_data'
const nametable = 'projects'
@@ -273,6 +274,9 @@ namespace Actions {
async function dbLoad(context, { checkPending, onlyiffirsttime }) {
if (!static_data.functionality.ENABLE_PROJECTS_LOADING)
return null
if (onlyiffirsttime) {
if (stateglob.projects.length > 0) {
// if already set, then exit.
@@ -438,7 +442,6 @@ namespace Actions {
modify: b.dispatch(modify),
ActionCutPaste: b.dispatch(ActionCutPaste)
}
}
// Module

View File

@@ -0,0 +1,189 @@
import Api from '@api'
import { IBookedEvent, ICalendarState, IEvents } from 'model'
import { ILinkReg, IResult, IIdToken, IToken } from 'model/other'
import { storeBuilder } from '../Store'
import { serv_constants } from '../../serv_constants'
import { tools } from '../../tools'
import translate from '../../../../globalroutines/util'
import * as Types from '../../../Api/ApiTypes'
import { db_data } from '@src/db/db_data'
import { UserStore } from '@store'
// State
const state: ICalendarState = {
editable: false,
eventlist: [],
bookedevent: [],
// ---------------
titlebarHeight: 0,
locale: 'it-IT',
maxDays: 1,
fiveDayWorkWeek: false,
shortMonthLabel: false,
showDayOfYearLabel: false,
shortWeekdayLabel: true,
shortIntervalLabel: false,
hour24Format: true,
hideHeader: false,
noScroll: false,
showMonthLabel: false,
showWorkWeeks: false,
intervalRange: { min: 9, max: 23 },
intervalRangeStep: 1,
intervalHeight: 35,
resourceHeight: 60,
resourceWidth: 100,
dayHeight: 100,
enableThemes: false,
theme: {}
}
const b = storeBuilder.module<ICalendarState>('CalendarModule', state)
const stateGetter = b.state()
namespace Getters {
const findEventBooked = b.read((mystate: ICalendarState) => (myevent: IEvents, isconfirmed: boolean) => {
return mystate.bookedevent.find((bookedevent) => (bookedevent.id_bookedevent === myevent._id) && ((isconfirmed && bookedevent.booked) || (!isconfirmed)))
}, 'findEventBooked')
export const getters = {
get findEventBooked() {
return findEventBooked()
}
}
}
namespace Mutations {
// function authUser(state: ICalendarState, data: ICalendarState) {
// state.userId = data.userId
// }
//
// export const mutations = {
// authUser: b.commit(authUser),
// }
}
namespace Actions {
async function loadAfterLogin(context) {
// Load local data
state.editable = db_data.userdata.calendar_editable
state.eventlist = db_data.events
// state.bookedevent = db_data.userdata.bookedevent
// Load local data
console.log('CALENDAR loadAfterLogin', 'userid=', UserStore.state.userId)
let ris = null
ris = await Api.SendReq('/booking/' + UserStore.state.userId + '/' + process.env.APP_ID, 'GET', null)
.then((res) => {
if (res.data.bookedevent) {
state.bookedevent = res.data.bookedevent
} else {
state.bookedevent = []
}
})
.catch((error) => {
console.log('error dbLoad', error)
// UserStore.mutations.setErrorCatch(error)
return new Types.AxiosError(serv_constants.RIS_CODE_ERR, null, tools.ERR_GENERICO, error)
})
return ris
}
function getparambyevent(bookevent) {
return {
id_bookedevent: bookevent.id_bookedevent,
infoevent: bookevent.infoevent,
numpeople: bookevent.numpeople,
msgbooking: bookevent.msgbooking,
datebooked: bookevent.datebooked,
userId: UserStore.state.userId,
booked: bookevent.booked,
}
}
async function BookEvent(context, bookevent: IBookedEvent) {
console.log('BookEvent', bookevent)
const param = getparambyevent(bookevent)
return await Api.SendReq('/booking', 'POST', param)
.then((res) => {
if (res.status === 200) {
if (res.data.code === serv_constants.RIS_CODE_OK) {
state.bookedevent.push(bookevent)
return true
}
}
return false
})
.catch((error) => {
console.error(error)
return false
})
}
async function CancelBookingEvent(context, event: IEvents) {
console.log('CALSTORE: CancelBookingEvent', event)
const myeventtoCancel = state.bookedevent.find((eventbooked) => (eventbooked.id_bookedevent === event._id))
const param = getparambyevent(myeventtoCancel)
param.booked = false // Cancel Booking
return await Api.SendReq('/booking', 'POST', param)
.then((res) => {
if (res.status === 200) {
if (res.data.code === serv_constants.RIS_CODE_OK) {
state.bookedevent = state.bookedevent.filter((eventbooked) => (eventbooked.id_bookedevent !== event._id))
return true
}
}
return false
})
.catch((error) => {
console.error(error)
// UserStore.mutations.setErrorCatch(error)
return false
})
}
export const actions = {
loadAfterLogin: b.dispatch(loadAfterLogin),
BookEvent: b.dispatch(BookEvent),
CancelBookingEvent: b.dispatch(CancelBookingEvent)
}
// async function resetpwd(context, paramquery: ICalendarState) {
// }
//
// export const actions = {
// autologin_FromLocalStorage: b.dispatch(autologin_FromLocalStorage)
// }
}
// Module
const CalendarModule = {
get state() {
return stateGetter()
},
actions: Actions.actions,
getters: Getters.getters
// mutations: Mutations.mutations
}
export default CalendarModule

View File

@@ -15,6 +15,7 @@ import objectId from '@src/js/objectId'
import { costanti } from '@src/store/Modules/costanti'
import { IAction } from '@src/model'
import * as Types from '@src/store/Api/ApiTypes'
import { static_data } from '@src/db/static_data'
const nametable = 'todos'
@@ -217,7 +218,7 @@ namespace Mutations {
ApiTables.removeitemfromarray(stateparam.todos[indcat], ind)
}
async function movemyitem(stateparam: ITodosState, { myitemorig, myitemdest } ) {
async function movemyitem(stateparam: ITodosState, { myitemorig, myitemdest }) {
const indcat = stateparam.categories.indexOf(myitemorig.category)
const indorig = tools.getIndexById(stateparam.todos[indcat], myitemorig._id)
@@ -251,13 +252,19 @@ namespace Mutations {
namespace Actions {
async function dbLoad(context, { checkPending }) {
if (!static_data.functionality.ENABLE_PROJECTS_LOADING)
return null
console.log('dbLoad', nametable, checkPending, 'userid=', UserStore.state.userId)
// if (UserStore.state.userId === '') {
// return new Types.AxiosError(0, null, 0, '')
// }
const ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null)
let ris = null
ris = await Api.SendReq('/todos/' + UserStore.state.userId, 'GET', null)
.then((res) => {
if (res.data.todos) { // console.log('RISULTANTE CATEGORIES DAL SERVER = ', res.data.categories)
state.todos = res.data.todos

View File

@@ -7,9 +7,11 @@ import router from '@router'
import { serv_constants } from '../Modules/serv_constants'
import { tools } from '../Modules/tools'
import { toolsext } from '@src/store/Modules/toolsext'
import { GlobalStore, UserStore, Todos, Projects } from '@store'
import { GlobalStore, UserStore, Todos, Projects, BookingStore, CalendarStore } from '@store'
import globalroutines from './../../globalroutines/index'
import { static_data } from '@src/db/static_data'
import translate from './../../globalroutines/util'
import * as Types from '@src/store/Api/ApiTypes'
@@ -20,6 +22,8 @@ const state: IUserState = {
userId: '',
email: '',
username: '',
name: '',
surname: '',
password: '',
lang: process.env.LANG_DEFAULT,
repeatPassword: '',
@@ -108,6 +112,8 @@ namespace Mutations {
function authUser(state: IUserState, data: IUserState) {
state.userId = data.userId
state.username = data.username
state.name = data.name
state.surname = data.surname
if (data.verified_email) {
state.verified_email = data.verified_email
}
@@ -176,6 +182,8 @@ namespace Mutations {
function clearAuthData(state: IUserState) {
state.userId = ''
state.username = ''
state.name = ''
state.surname = ''
resetArrToken(state.tokens)
state.x_auth_token = ''
state.verified_email = false
@@ -221,7 +229,6 @@ namespace Mutations {
setErrorCatch: b.commit(setErrorCatch),
getMsgError: b.commit(getMsgError)
}
}
namespace Actions {
@@ -318,6 +325,8 @@ namespace Actions {
email: authData.email,
password: String(hashedPassword),
username: authData.username,
name: authData.name,
surname: authData.surname,
}
console.log(usertosend)
@@ -336,6 +345,8 @@ namespace Actions {
if (res.status === 200) {
const userId = newuser._id
const username = authData.username
const name = authData.name
const surname = authData.surname
if (process.env.DEV) {
console.log('USERNAME = ' + username)
console.log('IDUSER= ' + userId)
@@ -344,6 +355,8 @@ namespace Actions {
Mutations.mutations.authUser({
userId,
username,
name,
surname,
verified_email: false
})
@@ -353,6 +366,8 @@ namespace Actions {
localStorage.setItem(tools.localStorage.lang, state.lang)
localStorage.setItem(tools.localStorage.userId, userId)
localStorage.setItem(tools.localStorage.username, username)
localStorage.setItem(tools.localStorage.name, name)
localStorage.setItem(tools.localStorage.surname, surname)
localStorage.setItem(tools.localStorage.token, state.x_auth_token)
localStorage.setItem(tools.localStorage.expirationDate, expirationDate.toString())
localStorage.setItem(tools.localStorage.verified_email, String(false))
@@ -438,11 +453,15 @@ namespace Actions {
if (myuser) {
const userId = myuser.userId
const username = authData.username
const name = myuser.name
const surname = myuser.surname
const verified_email = myuser.verified_email
Mutations.mutations.authUser({
userId,
username,
name,
surname,
verified_email
})
@@ -452,6 +471,8 @@ namespace Actions {
localStorage.setItem(tools.localStorage.lang, state.lang)
localStorage.setItem(tools.localStorage.userId, userId)
localStorage.setItem(tools.localStorage.username, username)
localStorage.setItem(tools.localStorage.name, name)
localStorage.setItem(tools.localStorage.surname, surname)
localStorage.setItem(tools.localStorage.token, state.x_auth_token)
localStorage.setItem(tools.localStorage.expirationDate, expirationDate.toString())
localStorage.setItem(tools.localStorage.isLogged, String(true))
@@ -486,6 +507,8 @@ namespace Actions {
localStorage.removeItem(tools.localStorage.token)
localStorage.removeItem(tools.localStorage.userId)
localStorage.removeItem(tools.localStorage.username)
localStorage.removeItem(tools.localStorage.name)
localStorage.removeItem(tools.localStorage.surname)
localStorage.removeItem(tools.localStorage.isLogged)
// localStorage.removeItem(rescodes.localStorage.leftDrawerOpen)
localStorage.removeItem(tools.localStorage.verified_email)
@@ -512,26 +535,33 @@ namespace Actions {
}
async function setGlobal(isLogged: boolean) {
state.isLogged = true
console.log('state.isLogged')
// console.log('setGlobal')
// state.isLogged = true
state.isLogged = isLogged
if (isLogged) {
console.log('state.isLogged')
GlobalStore.mutations.setleftDrawerOpen(localStorage.getItem(tools.localStorage.leftDrawerOpen) === 'true')
GlobalStore.mutations.setCategorySel(localStorage.getItem(tools.localStorage.categorySel))
GlobalStore.actions.checkUpdates()
}
return await GlobalStore.actions.loadAfterLogin()
.then(() => {
return Todos.actions.dbLoad({ checkPending: true })
}).then(() => {
return Projects.actions.dbLoad({ checkPending: true, onlyiffirsttime: true })
})
const p = await BookingStore.actions.loadAfterLogin()
const p2 = await CalendarStore.actions.loadAfterLogin()
const p3 = await GlobalStore.actions.loadAfterLogin()
if (static_data.functionality.ENABLE_TODOS_LOADING)
await Todos.actions.dbLoad({ checkPending: true })
if (static_data.functionality.ENABLE_PROJECTS_LOADING)
await Projects.actions.dbLoad({ checkPending: true, onlyiffirsttime: true })
}
async function autologin_FromLocalStorage(context) {
try {
console.log('*** autologin_FromLocalStorage ***')
// console.log('*** autologin_FromLocalStorage ***')
// INIT
let isLogged = false
@@ -546,6 +576,8 @@ namespace Actions {
if (now < expirationDate) {
const userId = String(localStorage.getItem(tools.localStorage.userId))
const username = String(localStorage.getItem(tools.localStorage.username))
const name = String(localStorage.getItem(tools.localStorage.name))
const surname = String(localStorage.getItem(tools.localStorage.surname))
const verified_email = localStorage.getItem(tools.localStorage.verified_email) === 'true'
GlobalStore.state.wasAlreadySubOnDb = localStorage.getItem(tools.localStorage.wasAlreadySubOnDb) === 'true'
@@ -557,6 +589,8 @@ namespace Actions {
Mutations.mutations.authUser({
userId,
username,
name,
surname,
verified_email
})
@@ -566,7 +600,7 @@ namespace Actions {
await setGlobal(isLogged)
console.log('autologin userId STATE ', state.userId)
// console.log('autologin userId STATE ', state.userId)
return true
} catch (e) {

View File

@@ -10,5 +10,9 @@ export const costanti = {
CONFIG_ID_STATE_CONN: '2',
CONFIG_ID_SHOW_TYPE_TODOS: '3',
FuncDialog: {
CANCEL_BOOKING: 1
},
MAX_PHASES: 5,
}

View File

@@ -1,5 +1,6 @@
export {storeBuilder} from './Store/Store'
export {default as GlobalStore} from './GlobalStore'
export {default as BookingStore} from './BookingStore'
export {default as UserStore} from './UserStore'
export {default as Todos} from './Todos'
export {default as Projects} from './Projects'

View File

@@ -11,6 +11,10 @@ export const serv_constants = {
RIS_CODE_OK: 1,
RIS_CODE_LOGIN_OK: 1,
RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN: 403
RIS_CODE__HTTP_FORBIDDEN_INVALID_TOKEN: 403,
RIS_SUBSCRIBED_OK: 1,
RIS_SUBSCRIBED_ALREADYEXIST: 2,
RIS_SUBSCRIBED_ERR: -1
}

View File

@@ -1,16 +1,17 @@
import { Todos, Projects, UserStore } from '@store'
import { Todos, Projects, UserStore, CalendarStore } from '@store'
import globalroutines from './../../globalroutines/index'
import { costanti } from './costanti'
import { toolsext } from './toolsext'
import { translation } from './translation'
import Quasar, { date, Screen } from 'quasar'
import { IListRoutes, IMenuList, IProject, ITodo, Privacy } from '@src/model'
import { ICollaborations, IListRoutes, IMenuList, IParamDialog, IProject, ITodo, Privacy } from '@src/model'
import * as ApiTables from '@src/store/Modules/ApiTables'
import translate from '@src/globalroutines/util'
import { RouteNames } from '@src/router/route-names'
import { lists } from './lists'
import { shen } from '@src/database/shen'
import { static_data } from '@src/db/static_data'
import { IColl, ITimeLineEntry, ITimeLineMain } from '@src/model/GlobalStore'
export interface INotify {
color?: string | 'primary'
@@ -30,6 +31,8 @@ export const tools = {
DUPLICATE_EMAIL_ID: 11000,
DUPLICATE_USERNAME_ID: 11100,
TYPE_AUDIO: 1,
NUMSEC_CHECKUPDATE: 20000,
FIRST_PROJ: '5ca8f17fcd40dc5012f53346',
@@ -38,7 +41,7 @@ export const tools = {
WHAT_TODO: 1,
WHAT_PROJECT: 2,
arrLangUsed: ['enUs', 'it', 'es'],
languageid: 5,
SERVKEY_VERS: 'vers',
@@ -52,6 +55,8 @@ export const tools = {
userId: 'uid',
token: 'tk',
username: 'uname',
name: 'nm',
surname: 'sn',
lang: 'lg'
},
@@ -67,6 +72,35 @@ export const tools = {
COMPLETED: 10
},
SelectListNumPeople: [
{
id: 1,
label: '1',
value: 1
},
{
id: 2,
label: '2',
value: 2
},
{
id: 3,
label: '3',
value: 3
},
{
id: 4,
label: '4',
value: 4
},
{
id: 5,
label: '5',
value: 5
},
]
,
selectPhase: {
it: [
{
@@ -1264,8 +1298,48 @@ export const tools = {
result.push(json[key])
})
return result
}
,
},
executefunc(myself: any, myfunc: number, par: IParamDialog) {
if (myfunc === costanti.FuncDialog.CANCEL_BOOKING) {
console.log(' ENTRATO ! CancelBookingEvent ')
CalendarStore.actions.CancelBookingEvent(par.param1).then(ris => {
if (ris)
tools.showPositiveNotif(myself.$q, myself.$t('cal.canceledbooking') + ' "' + par.param1.title + '"')
else
tools.showNegativeNotif(myself.$q, myself.$t('cal.cancelederrorbooking'))
})
}
},
async askConfirm($q: any, mytitle, mytext, ok, cancel, myself: any, funcok: number, funccancel: number, par: IParamDialog) {
return $q.dialog({
message: mytext,
ok: {
label: ok,
push: true
},
title: mytitle,
cancel: true,
persistent: false
}).onOk(() => {
console.log('OK')
tools.executefunc(myself, funcok, par)
return true
}).onCancel(() => {
console.log('CANCEL')
tools.executefunc(myself, funccancel, par)
return false
})
},
showPositiveNotif(q: any, msg) {
tools.showNotif(q, msg, { color: 'positive', icon: 'notifications' })
},
showNegativeNotif(q: any, msg) {
tools.showNotif(q, msg, { color: 'negative', icon: 'notifications' })
},
showNotif(q: any, msg, data ?: INotify | null
) {
@@ -1310,7 +1384,7 @@ export const tools = {
,
checkLangPassed(mylang) {
console.log('checkLangPassed')
// console.log('checkLangPassed')
const mybrowserLang = Quasar.lang.isoName
@@ -1321,10 +1395,16 @@ export const tools = {
if ((mylang.toLowerCase() === 'es') || (mylang.toLowerCase() === 'es-es') || (mylang.toLowerCase() === 'eses')) {
mylang = 'es'
}
if ((mylang.toLowerCase() === 'fr') || (mylang.toLowerCase() === 'fr-fr') || (mylang.toLowerCase() === 'frfr')) {
mylang = 'fr'
}
if ((mylang.toLowerCase() === 'it') || (mylang.toLowerCase() === 'it-it') || (mylang.toLowerCase() === 'itit')) {
mylang = 'it'
}
if (!(tools.arrLangUsed.includes(mylang))) {
if (!(static_data.arrLangUsed.includes(mylang))) {
console.log('non incluso ', mylang)
mylang = tools.arrLangUsed[0]
mylang = static_data.arrLangUsed[0]
// Metti Inglese come default
UserStore.mutations.setlang(mylang)
@@ -1339,7 +1419,7 @@ export const tools = {
UserStore.mutations.setlang(mylang)
}
console.log('mylang calc : ', mylang)
// console.log('mylang calc : ', mylang)
return mylang
},
@@ -1519,6 +1599,14 @@ export const tools = {
return ''
}
,
getstrMMMDate(mytimestamp) {
// console.log('getstrDate', mytimestamp)
if (!!mytimestamp)
return date.formatDate(mytimestamp, 'DD MMM YYYY')
else
return ''
}
,
getstrYYMMDDDate(mytimestamp) {
return date.formatDate(mytimestamp, 'YYYY-MM-DD')
}
@@ -1589,26 +1677,26 @@ export const tools = {
return '/' + tipoproj + '/'
},
convertMenuListInListRoutes(arrlista: IMenuList[]) {
const lista = []
if (arrlista === undefined)
return lista
for (const elem of arrlista) {
const item: IListRoutes = {
faIcon: 'fa fa-list-alt',
materialIcon: elem.icon,
name: elem.nametranslate,
text: elem.description,
route: tools.getUrlByTipoProj(false, elem.urlroute) + elem.idelem,
routes2: tools.convertMenuListInListRoutes(elem.routes2),
level_parent: elem.level_parent,
level_child: elem.level_child
}
lista.push(item)
}
return lista
},
// convertMenuListInListRoutes(arrlista: IMenuList[]) {
// const lista = []
// if (arrlista === undefined)
// return lista
// for (const elem of arrlista) {
// const item: IListRoutes = {
// faIcon: 'fa fa-list-alt',
// materialIcon: elem.icon,
// name: elem.nametranslate,
// text: elem.description,
// path: tools.getUrlByTipoProj(false, elem.urlroute) + elem.idelem,
// routes2: tools.convertMenuListInListRoutes(elem.routes2),
// level_parent: elem.level_parent,
// level_child: elem.level_child
//
// }
// lista.push(item)
// }
// return lista
// },
getprivacyreadbytipoproj(tipoproj) {
if (tipoproj === RouteNames.myprojects)
@@ -1721,14 +1809,51 @@ export const tools = {
}
},
myheight_imgtitle() {
if (Screen.width < 400) {
return '250'
} else if (Screen.width < 600) {
return '350'
myheight_imgtitle(myheight?, myheightmobile?) {
let maxheight = 0
if (!!myheight) {
maxheight = myheight
if (myheight > 0) {
if (myheight > 1000) {
maxheight = 1000
} else {
maxheight = parseInt(myheight, 10)
}
}
} else {
return '350'
maxheight = 500
}
let maxh2 = 0
if (Screen.width < 400) {
maxh2 = 350
} else if (Screen.width < 600) {
maxh2 = 400
} else if (Screen.width < 800) {
maxh2 = 450
} else if (Screen.width < 1000) {
maxh2 = 500
} else {
maxh2 = 500
}
console.log('maxh2', maxh2)
console.log('maxheight', maxheight)
let ris = 0
if (maxh2 < maxheight)
ris = maxh2
else
ris = maxheight
if (!!myheightmobile) {
if (this.isMobile() && maxh2 > myheightmobile)
ris = parseInt(myheightmobile, 10)
}
console.log('ris', ris)
return ris
},
myheight_dialog() {
@@ -1741,11 +1866,15 @@ export const tools = {
}
},
styles_imgtitle() {
if (Screen.width < 400) {
return 'max-height: 250px'
styles_imgtitle(sized?: string) {
if (!!sized) {
return sized
} else {
return 'max-height: 350px'
if (Screen.width < 400) {
return 'max-height: 250px'
} else {
return 'max-height: 350px'
}
}
},
@@ -1783,6 +1912,10 @@ export const tools = {
}
},
isMobile() {
return (Screen.width < 400)
},
mywidth_imgtitle() {
if (Screen.width < 400) {
return '250'
@@ -1829,6 +1962,118 @@ export const tools = {
addDays(mydate, days) {
return date.addToDate(mydate, { days })
},
gettitlemain(datamain: ITimeLineMain) {
if (datamain.titlemain[toolsext.getLocale()])
return datamain.titlemain[toolsext.getLocale()]
else {
return datamain.titlemain[static_data.arrLangUsed[0]]
}
},
getwwithwhocoll(datamain: ICollaborations) {
if (datamain.withwhom_title[toolsext.getLocale()])
return datamain.withwhom_title[toolsext.getLocale()]
else {
return datamain.withwhom_title[static_data.arrLangUsed[0]]
}
},
gettextcoll(data: IColl) {
if (data.subtitle[toolsext.getLocale()])
return data.subtitle[toolsext.getLocale()]
else {
return data.subtitle[static_data.arrLangUsed[0]]
}
},
gettitlecoll(data: IColl) {
if (data.title[toolsext.getLocale()])
return data.title[toolsext.getLocale()]
else {
return data.title[static_data.arrLangUsed[0]]
}
},
gettextdescr(data: ITimeLineEntry, numdescr = 'description') {
if (!!data[numdescr]) {
if (data[numdescr][toolsext.getLocale()])
return data[numdescr][toolsext.getLocale()]
else {
return data[numdescr][static_data.arrLangUsed[0]]
}
} else {
return ''
}
},
getlink(data: ITimeLineEntry) {
if (data.link_text[toolsext.getLocale()])
return data.link_text[toolsext.getLocale()]
else {
return data.link_text[static_data.arrLangUsed[0]]
}
},
getlinkurl(data: ITimeLineEntry) {
if (data.link_url_lang) {
if (data.link_url_lang[toolsext.getLocale()]) {
return data.link_url_lang[toolsext.getLocale()]
} else {
return data.link_url
}
} else {
return data.link_url
}
},
appid() {
return process.env.APP_ID
},
getLabelByItem(item, mythis) {
if (!!item.name)
return mythis.$t(item.name)
else
return item.text
},
getimgbysize(dir: string, file: string) {
const myimage = dir + file
// console.log('includes = ', static_data.preLoadImages.map((a) => a.imgname).includes(myimage), myimage)
let ris = ''
if (this.isMobile() && (static_data.preLoadImages.map((a) => a.imgname).includes(myimage))) {
ris = dir + 'mobile/' + file
} else {
ris = myimage
}
// console.log('getimgbysize', ris)
return ris
},
getimgFullpathbysize(fileimg: string) {
const ind = fileimg.lastIndexOf('/')
if (ind > 0) {
return { path: fileimg.substring(0, ind + 1) , file: fileimg.substring(ind + 1) }
} else {
return { path: '', file: fileimg }
}
},
convertHTMLtoText(myhtml) {
let msg = myhtml
msg = msg.replace('&quot;', '"')
msg = msg.replace('&gt;', '>')
msg = msg.replace('&lt;', '<')
msg = msg.replace('&amp;', '&')
msg = msg.replace('<br>', '\n')
return msg
}
// getLocale() {

View File

@@ -0,0 +1,52 @@
import { UserStore } from '@store'
export const toolsext = {
getLocale(vero?: boolean) {
if (UserStore) {
if (UserStore.state) {
return UserStore.state.lang
}
}
return process.env.LANG_DEFAULT
},
isLang(whichlang) {
const loc = func_tools.getLocale()
return (loc === whichlang)
}
}
export const func_tools = {
getLocale(vero?: boolean) {
if (UserStore) {
if (UserStore.state) {
return UserStore.state.lang
}
}
return ''
},
getDateStr(mydate) {
const DateFormatter = new Intl.DateTimeFormat(func_tools.getLocale() || void 0, {
weekday: 'short',
day: 'numeric',
month: 'long',
year: 'numeric'
// timeZone: 'UTC'
})
if (DateFormatter) {
const date = new Date(mydate)
return DateFormatter.format(date)
}
return mydate
}
}
// export const costanti_tools = {
// DateFormatter: new Intl.DateTimeFormat(func_tools.getLocale() || void 0, {
// weekday: 'long',
// day: 'numeric',
// month: 'long',
// year: 'numeric'
// // timeZone: 'UTC'
// })
// }

View File

@@ -9,7 +9,7 @@ import { IProgressState } from '@types'
export interface RootState {
GlobalModule: IGlobalState
route: Route
path: Route
}
Vue.use(Vuex)

View File

@@ -0,0 +1,90 @@
/* eslint-disable */
export default {
Digitalizer: `<g>
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M259.476,280.364V247.5c0-12.958-10.542-23.5-23.5-23.5s-23.5,10.542-23.5,23.5v29.672 c0,35.757-13.173,70.087-37.094,96.665l-32.981,36.646c-2.771,3.079-2.521,7.821,0.558,10.593c3.078,2.771,7.82,2.521,10.592-0.558 l32.981-36.646c26.403-29.338,40.944-67.231,40.944-106.7V247.5c0-4.687,3.813-8.5,8.5-8.5s8.5,3.813,8.5,8.5v32.864 c0,44.003-16.301,86.167-45.901,118.727l-32.149,35.364c-2.786,3.064-2.56,7.809,0.505,10.595c1.437,1.307,3.242,1.95,5.042,1.95 c2.04,0,4.072-0.827,5.552-2.455l32.148-35.364C241.789,373.854,259.476,328.106,259.476,280.364z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M291.476,247.5c0-30.603-24.897-55.5-55.5-55.5s-55.5,24.897-55.5,55.5v29.672c0,27.839-10.256,54.566-28.879,75.258 l-23.447,26.053c-2.771,3.079-2.521,7.821,0.558,10.593c3.079,2.771,7.82,2.519,10.592-0.558l23.447-26.053 c21.106-23.451,32.73-53.742,32.73-85.293V247.5c0-22.332,18.168-40.5,40.5-40.5c22.332,0,40.5,18.168,40.5,40.5v32.864 c0,51.979-19.256,101.789-54.223,140.252l-27.125,29.839c-2.787,3.064-2.561,7.809,0.504,10.595c1.437,1.307,3.242,1.95,5.042,1.95 c2.04,0,4.072-0.827,5.552-2.455l27.126-29.839c37.481-41.23,58.123-94.622,58.123-150.342V247.5z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M323.476,247.5c0-48.248-39.252-87.5-87.5-87.5s-87.5,39.252-87.5,87.5v29.672c0,19.92-7.339,39.045-20.665,53.851 l-21.112,23.458c-2.771,3.079-2.521,7.821,0.558,10.593c3.078,2.771,7.821,2.519,10.592-0.558l21.112-23.458 c15.809-17.565,24.515-40.254,24.515-63.886V247.5c0-39.977,32.523-72.5,72.5-72.5s72.5,32.523,72.5,72.5v32.864 c0,59.958-22.212,117.412-62.545,161.777l-7.507,8.258c-2.786,3.065-2.56,7.809,0.505,10.595c1.437,1.306,3.243,1.95,5.042,1.95 c2.04,0,4.072-0.827,5.552-2.455l7.506-8.258c42.848-47.133,66.446-108.169,66.446-171.867V247.5z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M116.476,247.5c0,4.143,3.358,7.5,7.5,7.5s7.5-3.357,7.5-7.5c0-25.255,9.169-49.651,25.819-68.695 c16.495-18.867,39.134-31.205,63.746-34.741c4.1-0.589,6.946-4.391,6.357-8.49c-0.589-4.1-4.394-6.942-8.49-6.357 c-28.16,4.046-54.052,18.15-72.906,39.716C126.962,190.71,116.476,218.613,116.476,247.5z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M131.476,277.172c0-4.143-3.358-7.5-7.5-7.5s-7.5,3.357-7.5,7.5c0,12.002-4.421,23.523-12.449,32.443l-18.779,20.867 c-2.771,3.078-2.521,7.82,0.558,10.592c1.434,1.29,3.227,1.925,5.015,1.925c2.052,0,4.097-0.838,5.577-2.483l18.779-20.866 C125.687,307.971,131.476,292.886,131.476,277.172z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M340.755,344.123c-4.009-1.044-8.105,1.351-9.155,5.357c-2.769,10.579-6.213,21.096-10.24,31.258 c-1.526,3.851,0.359,8.21,4.21,9.735c0.907,0.359,1.841,0.529,2.761,0.529c2.985,0,5.808-1.795,6.975-4.739 c4.249-10.725,7.884-21.822,10.806-32.986C347.16,349.271,344.761,345.172,340.755,344.123z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M315.791,158.632c-3.081-2.771-7.823-2.517-10.592,0.563s-2.517,7.822,0.563,10.591 c22.061,19.832,34.713,48.157,34.713,77.714v32.864c0,12.473-0.86,25.042-2.557,37.359c-0.565,4.104,2.303,7.888,6.406,8.453 c0.347,0.048,0.692,0.071,1.033,0.071c3.688,0,6.903-2.722,7.42-6.478c1.79-12.993,2.698-26.251,2.698-39.406V247.5 C355.476,213.695,341.011,181.304,315.791,158.632z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M280.729,153.076c1.041,0.496,2.138,0.73,3.219,0.73c2.803,0,5.492-1.579,6.777-4.278c1.781-3.739,0.192-8.215-3.547-9.995 c-10.806-5.145-22.291-8.616-34.136-10.317c-4.106-0.585-7.901,2.258-8.49,6.357s2.257,7.901,6.357,8.49 C261.257,145.55,271.289,148.582,280.729,153.076z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M235.976,96c-2.806,0-5.644,0.078-8.437,0.232c-4.136,0.228-7.304,3.766-7.076,7.901c0.229,4.136,3.763,7.321,7.902,7.075 c2.519-0.139,5.079-0.209,7.61-0.209c75.266,0,136.5,61.233,136.5,136.5v32.864c0,4.143,3.358,7.5,7.5,7.5s7.5-3.357,7.5-7.5V247.5 C387.476,163.963,319.513,96,235.976,96z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M153.972,136.693c1.477,0,2.97-0.436,4.275-1.343c12.478-8.677,26.182-15.155,40.733-19.258 c3.987-1.124,6.308-5.268,5.184-9.254s-5.269-6.304-9.254-5.184c-16.16,4.556-31.376,11.749-45.226,21.379 c-3.401,2.365-4.241,7.039-1.876,10.439C149.265,135.57,151.599,136.693,153.972,136.693z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M99.476,277.172V247.5c0-34.89,13.213-68.118,37.205-93.565c2.841-3.014,2.702-7.76-0.312-10.602 s-7.761-2.701-10.602,0.312C99.14,171.886,84.476,208.77,84.476,247.5v29.672c0,4.083-1.504,8.002-4.234,11.035l-9.248,10.275 c-2.771,3.079-2.521,7.821,0.558,10.592c1.433,1.291,3.227,1.926,5.015,1.926c2.052,0,4.096-0.837,5.577-2.482l9.248-10.275 C96.605,292.449,99.476,284.966,99.476,277.172z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M409.951,189.104c-8.226-24.446-21.299-46.531-38.856-65.642c-2.803-3.05-7.547-3.252-10.597-0.449 c-3.05,2.803-3.251,7.547-0.449,10.598c16.127,17.554,28.134,37.834,35.686,60.276c1.054,3.133,3.976,5.11,7.107,5.11 c0.793,0,1.6-0.127,2.393-0.394C409.16,197.282,411.272,193.029,409.951,189.104z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M295.247,73.822c-3.917-1.341-8.183,0.748-9.524,4.668c-1.341,3.919,0.749,8.183,4.668,9.523 c16.538,5.659,32.065,13.857,46.15,24.369c1.347,1.005,2.92,1.489,4.48,1.489c2.286,0,4.544-1.041,6.017-3.015 c2.478-3.319,1.794-8.019-1.525-10.496C330.176,88.916,313.264,79.986,295.247,73.822z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M119.442,125.908C150.991,95.659,192.377,79,235.976,79c8.096,0,16.237,0.583,24.196,1.731 c4.103,0.598,7.903-2.252,8.495-6.352c0.592-4.1-2.251-7.902-6.351-8.494C253.648,64.635,244.786,64,235.976,64 c-47.487,0-92.56,18.141-126.915,51.081c-34.248,32.838-54.277,76.905-56.397,124.084c-0.186,4.138,3.018,7.644,7.155,7.829 c0.115,0.006,0.229,0.008,0.343,0.008c3.987,0,7.306-3.14,7.487-7.163C69.594,196.527,87.988,156.066,119.442,125.908z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M235.976,32c-16.772,0-33.485,1.944-49.674,5.778c-4.031,0.954-6.524,4.996-5.57,9.026c0.955,4.03,4.997,6.524,9.027,5.569 C204.817,48.809,220.366,47,235.976,47c54.996,0,106.332,21.911,144.55,61.695c1.473,1.533,3.439,2.305,5.41,2.305 c1.869,0,3.741-0.694,5.195-2.091c2.987-2.87,3.083-7.618,0.213-10.604c-19.913-20.729-43.304-37.036-69.522-48.465 C294.666,38.002,265.783,32,235.976,32z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M67.507,125.404c1.372,1.074,3.001,1.595,4.619,1.595c2.227,0,4.431-0.987,5.91-2.876 c21.375-27.302,49.515-48.717,81.377-61.932c3.826-1.587,5.642-5.975,4.055-9.801s-5.977-5.644-9.801-4.055 c-34.241,14.201-64.478,37.21-87.441,66.539C63.672,118.137,64.246,122.851,67.507,125.404z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M131.983,38.725c1.094,0,2.205-0.24,3.255-0.748C166.816,22.73,200.709,15,235.976,15c18.378,0,36.682,2.162,54.401,6.426 c4.025,0.966,8.077-1.51,9.046-5.537c0.969-4.027-1.51-8.078-5.538-9.047C275.019,2.302,255.535,0,235.976,0 c-37.544,0-73.631,8.232-107.259,24.469c-3.73,1.801-5.294,6.285-3.493,10.015C126.517,37.163,129.195,38.725,131.983,38.725z" />
<path fill="none" stroke="#FFFFFF" stroke-width="6" d="M321.724,31.383c7.732,3.079,15.385,6.619,22.746,10.52c1.119,0.594,2.321,0.875,3.505,0.875 c2.688,0,5.287-1.449,6.633-3.99c1.939-3.66,0.545-8.199-3.115-10.139c-7.837-4.153-15.986-7.922-24.22-11.201 c-3.849-1.533-8.21,0.345-9.743,4.192C315.998,25.488,317.876,29.851,321.724,31.383z" />
</svg>`,
Keytronic:
`<g>
<g>
<path fill="none" stroke-width="6" d="M478.665,72c0-39.704-32.296-72-72-72c-19.704,0-38.496,8.184-52,22.288C341.161,8.184,322.369,0,302.665,0 c-39.704,0-72,32.296-72,72c0,24.752,12.456,47.36,33.376,60.688L275.353,144L134.665,284.688l-26.344-26.344 c-3.128-3.128-8.184-3.128-11.312,0l-32,32c-3.128,3.128-3.128,8.184,0,11.312L91.353,328l-12.688,12.688l-26.344-26.344 c-3.128-3.128-8.184-3.128-11.312,0l-33,33c-3.128,3.128-3.128,8.184,0,11.312L34.353,385L4.345,415.008 c-3.128,3.128-3.128,8.184,0,11.312l52,52c1.56,1.56,3.608,2.344,5.656,2.344s4.096-0.784,5.656-2.344l51.008-51.008 l26.344,26.344c3.128,3.128,8.184,3.128,11.312,0l40-40c3.128-3.128,3.128-8.184,0-11.312L169.977,376l168.688-168.688 l7.312,7.312C359.305,235.544,381.913,248,406.665,248c39.704,0,72-32.296,72-72c0-19.704-8.184-38.496-22.288-52 C470.481,110.496,478.665,91.704,478.665,72z M462.665,176c0,30.872-25.128,56-56,56c-19.488,0-37.272-9.944-47.584-26.6 c-0.328-0.52-0.712-1.008-1.152-1.448l-13.608-13.608c-3.128-3.128-8.184-3.128-11.312,0l-180,180 c-3.128,3.128-3.128,8.184,0,11.312L179.353,408l-28.688,28.688l-26.344-26.344c-3.128-3.128-8.184-3.128-11.312,0l-51.008,51.008 l-40.688-40.688l30.008-30.008c3.128-3.128,3.128-8.184,0-11.312L24.977,353l21.688-21.688l26.344,26.344 c3.128,3.128,8.184,3.128,11.312,0l24-24c3.128-3.128,3.128-8.184,0-11.312L81.977,296l20.688-20.688l26.344,26.344 c3.128,3.128,8.184,3.128,11.312,0l152-152c3.128-3.128,3.128-8.184,0-11.312l-17.608-17.608c-0.44-0.44-0.92-0.824-1.448-1.152 c-16.656-10.312-26.6-28.096-26.6-47.584c0-30.872,25.128-56,56-56c17.96,0,34.968,8.768,45.504,23.456c3,4.184,10,4.184,13,0 C371.697,24.768,388.705,16,406.665,16c30.872,0,56,25.128,56,56c0,17.96-8.768,34.968-23.456,45.504 c-2.096,1.504-3.336,3.92-3.336,6.496s1.24,5,3.336,6.496C453.897,141.032,462.665,158.04,462.665,176z" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<rect fill="none" stroke-width="6" x="173.811" y="228.009" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -91.1265 252.0189)" width="169.678" height="16" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<rect fill="none" stroke-width="6" x="163.35" y="311.983" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -175.1045 217.2252)" width="22.624" height="16" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<path fill="none" stroke-width="6" d="M406.665,40c-17.648,0-32,14.352-32,32s14.352,32,32,32s32-14.352,32-32S424.313,40,406.665,40z M406.665,88 c-8.824,0-16-7.176-16-16s7.176-16,16-16c8.824,0,16,7.176,16,16S415.489,88,406.665,88z" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<rect fill="none" stroke-width="6" x="310.663" y="92.674" transform="matrix(0.7071 -0.7071 0.7071 0.7071 19.8046 255.7854)" width="16" height="22.624" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<rect fill="none" stroke-width="6" x="342.661" y="124.674" transform="matrix(0.7071 -0.7071 0.7071 0.7071 6.5493 287.7842)" width="16" height="22.624" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<rect fill="none" stroke-width="6" x="374.659" y="156.674" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -6.706 319.7831)" width="16" height="22.624" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<path fill="none" stroke-width="6" d="M470.665,344h-14.032c-0.44-1.112-0.896-2.216-1.392-3.328l9.928-9.928c3.128-3.128,3.128-8.184,0-11.312l-33.936-33.936 c-3.128-3.128-8.184-3.128-11.312,0l-9.928,9.928c-1.112-0.496-2.216-0.952-3.328-1.392V280c0-4.424-3.576-8-8-8h-48 c-4.424,0-8,3.576-8,8v14.032c-1.112,0.44-2.216,0.896-3.328,1.392l-9.928-9.928c-3.128-3.128-8.184-3.128-11.312,0 l-33.936,33.936c-3.128,3.128-3.128,8.184,0,11.312l9.928,9.928c-0.496,1.112-0.952,2.216-1.392,3.328h-14.032 c-4.424,0-8,3.576-8,8v48c0,4.424,3.576,8,8,8h14.032c0.44,1.112,0.896,2.216,1.392,3.328l-9.928,9.928 c-3.128,3.128-3.128,8.184,0,11.312l33.936,33.936c3.128,3.128,8.184,3.128,11.312,0l9.928-9.928 c1.112,0.496,2.216,0.952,3.328,1.392V472c0,4.424,3.576,8,8,8h48c4.424,0,8-3.576,8-8v-14.032 c1.112-0.44,2.216-0.896,3.328-1.392l9.928,9.928c3.128,3.128,8.184,3.128,11.312,0l33.936-33.936 c3.128-3.128,3.128-8.184,0-11.312l-9.928-9.928c0.496-1.112,0.952-2.216,1.392-3.328h14.032c4.424,0,8-3.576,8-8v-48 C478.665,347.576,475.089,344,470.665,344z M462.665,392h-11.672c-3.496,0-6.576,2.264-7.632,5.592 c-1.216,3.864-2.856,7.8-4.88,11.672c-1.616,3.104-1.032,6.888,1.44,9.36l8.288,8.288l-22.624,22.624l-8.288-8.288 c-2.472-2.472-6.256-3.056-9.36-1.44c-3.872,2.024-7.808,3.664-11.672,4.88c-3.336,1.064-5.6,4.144-5.6,7.64V464h-32v-11.672 c0-3.496-2.264-6.576-5.592-7.632c-3.864-1.216-7.8-2.856-11.672-4.88c-3.104-1.616-6.88-1.032-9.36,1.44l-8.288,8.288 l-22.624-22.624l8.288-8.288c2.472-2.472,3.056-6.256,1.44-9.36c-2.024-3.872-3.664-7.808-4.88-11.672 c-1.064-3.336-4.144-5.6-7.64-5.6h-11.672v-32h11.672c3.496,0,6.576-2.264,7.632-5.592c1.216-3.864,2.856-7.8,4.88-11.672 c1.616-3.104,1.032-6.888-1.44-9.36l-8.288-8.288l22.624-22.624l8.288,8.288c2.48,2.48,6.256,3.048,9.36,1.44 c3.872-2.024,7.808-3.664,11.672-4.88c3.336-1.064,5.6-4.144,5.6-7.64V288h32v11.672c0,3.496,2.264,6.576,5.592,7.632 c3.864,1.216,7.8,2.856,11.672,4.88c3.104,1.608,6.888,1.04,9.36-1.44l8.288-8.288l22.624,22.624l-8.288,8.288 c-2.472,2.472-3.056,6.256-1.44,9.36c2.024,3.872,3.664,7.808,4.88,11.672c1.064,3.336,4.144,5.6,7.64,5.6h11.672V392z" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<path fill="none" stroke-width="6" d="M374.665,328c-26.472,0-48,21.528-48,48s21.528,48,48,48s48-21.528,48-48S401.137,328,374.665,328z M374.665,408 c-17.648,0-32-14.352-32-32s14.352-32,32-32s32,14.352,32,32S392.313,408,374.665,408z" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<path fill="none" stroke-width="6" d="M54.665,168h-16c0,13.232-10.768,24-24,24v16c13.232,0,24,10.768,24,24h16c0-13.232,10.768-24,24-24v-16 C65.433,192,54.665,181.232,54.665,168z M46.665,208.248c-2.336-3.144-5.104-5.912-8.248-8.248 c3.144-2.336,5.912-5.104,8.248-8.248c2.336,3.144,5.104,5.912,8.248,8.248C51.769,202.336,49.001,205.104,46.665,208.248z" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<path fill="none" stroke-width="6" d="M150.665,120h-16c0,13.232-10.768,24-24,24v16c13.232,0,24,10.768,24,24h16c0-13.232,10.768-24,24-24v-16 C161.433,144,150.665,133.232,150.665,120z M142.665,160.248c-2.336-3.144-5.104-5.912-8.248-8.248 c3.144-2.336,5.912-5.104,8.248-8.248c2.336,3.144,5.104,5.912,8.248,8.248C147.769,154.336,145.001,157.104,142.665,160.248z" stroke="#FFFFFF"/>
</g>
</g>
<g>
<g>
<path fill="none" stroke-width="6" d="M70.665,48h-16c0,13.232-10.768,24-24,24v16c13.232,0,24,10.768,24,24h16c0-13.232,10.768-24,24-24V72 C81.433,72,70.665,61.232,70.665,48z M62.665,88.248c-2.336-3.144-5.104-5.912-8.248-8.248c3.144-2.336,5.912-5.104,8.248-8.248 c2.336,3.144,5.104,5.912,8.248,8.248C67.769,82.336,65.001,85.104,62.665,88.248z" stroke="#FFFFFF"/>
</g>
</g>
`,
Molectron: `
<path stroke="#FFFFFF" fill="none" stroke-width="6" d="m398.559,166.02c-8.85-3.404-18.292-6.493-28.22-9.265 2.563-9.984 4.609-19.706 6.087-29.073 7.689-48.757-0.808-82.959-23.925-96.306-6.72-3.88-14.443-5.848-22.954-5.848-26.882,0-60.85,19.965-95.118,53.681-7.486-7.352-15.006-14.105-22.502-20.167-38.379-31.038-72.25-40.781-95.365-27.434-14.856,8.577-23.891,26.093-26.126,50.652-0.376,4.125 2.664,7.773 6.789,8.148 4.138,0.382 7.772-2.664 8.148-6.789 1.238-13.594 5.484-31.398 18.688-39.021 17.11-9.881 45.699-0.365 78.434,26.106 7.143,5.776 14.314,12.217 21.461,19.233-14.373,15.293-28.676,32.894-42.41,52.347-24.16,2.199-47.172,5.888-68.291,10.948-3.698-14.376-6.238-28.093-7.491-40.827-0.405-4.122-4.059-7.134-8.198-6.729-4.122,0.405-7.135,4.076-6.729,8.198 1.326,13.474 4.008,27.966 7.917,43.133-9.596,2.706-18.73,5.712-27.311,9.012-46.072,17.72-71.443,42.18-71.443,68.873s25.371,51.153 71.441,68.872c8.85,3.404 18.292,6.493 28.22,9.265-2.563,9.984-4.609,19.706-6.087,29.073-7.689,48.757 0.808,82.959 23.925,96.306 6.72,3.88 14.443,5.848 22.954,5.848 26.573,0 60.071-19.516 93.938-52.531 7.255,7.086 14.54,13.609 21.803,19.482 27.161,21.966 52.059,33.266 72.489,33.265 8.438-0.001 16.119-1.93 22.876-5.831 23.117-13.347 31.614-47.549 23.925-96.306-1.477-9.366-3.523-19.087-6.086-29.07 15.439-4.252 29.64-9.26 42.218-14.96 3.773-1.71 5.445-6.154 3.735-9.927-1.71-3.773-6.155-5.446-9.927-3.735-11.912,5.398-25.377,10.15-40.042,14.192-6.063-20.261-14.137-41.412-23.976-62.808 10.281-22.122 18.685-44.004 24.943-64.936 55.665,15.586 88.651,40.202 88.651,63.801 0,15.247-13.296,27.827-24.45,35.694-3.385,2.388-4.193,7.067-1.806,10.452 2.388,3.386 7.067,4.193 10.452,1.806 20.153-14.215 30.804-30.797 30.804-47.952 0-26.693-25.371-51.153-71.441-68.872zm-69.013-125.491c5.844,7.10543e-15 11.044,1.291 15.454,3.838 17.112,9.88 23.166,39.396 16.607,80.979-1.405,8.907-3.35,18.159-5.789,27.669-21.207-5.028-44.299-8.68-68.532-10.835-13.596-19.242-27.866-36.839-42.375-52.253 2.655-2.618 5.312-5.158 7.964-7.602 29.252-26.953 56.48-41.796 76.671-41.796zm-95.096,60.152c11.317,12.062 22.5,25.517 33.323,40.102-10.769-0.587-21.712-0.891-32.773-0.891-11.431,0-22.738,0.321-33.855,0.947 10.808-14.56 22.006-28.07 33.305-40.158zm-.053,269.657c-11.718-12.42-23.296-26.341-34.486-41.466 11.514,0.674 23.234,1.02 35.089,1.02 11.419,0 22.732-0.333 33.871-0.969-11.18,15.064-22.777,29.01-34.474,41.415zm.603-55.446c-16.115,0-31.578-0.624-46.314-1.784-8.277-12.076-16.284-24.78-23.907-37.984-7.503-12.995-14.405-26.107-20.657-39.155 6.49-13.661 13.707-27.412 21.596-41.077 7.64-13.232 15.75-26.063 24.177-38.307 14.374-1.099 29.429-1.693 45.105-1.693 15.273,0 29.956,0.564 43.994,1.609 8.434,12.267 16.59,25.185 24.349,38.623 7.85,13.597 15.034,27.279 21.5,40.873-6.219,12.942-13.091,25.957-20.56,38.894-7.625,13.207-15.72,26.015-24.13,38.239-14.716,1.158-29.83,1.762-45.153,1.762zm-65.615-3.655c-18.453-2.132-35.582-5.129-51.205-8.81 4.744-15.789 10.758-32.16 17.929-48.79 4.898,9.688 10.128,19.373 15.679,28.987 5.668,9.818 11.549,19.371 17.597,28.613zm1.19-152.829c-6.111,9.318-12.078,18.991-17.847,28.984-5.933,10.276-11.499,20.61-16.677,30.928-7.543-17.318-13.858-34.376-18.788-50.749 16.203-3.859 34.042-6.983 53.312-9.163zm-155.575,76.484c0-23.472 32.634-47.951 87.757-63.55 6.235,20.802 14.601,42.62 24.805,64.647-9.813,21.362-17.865,42.477-23.913,62.705-55.663-15.587-88.649-40.203-88.649-63.802zm125.454,194.363c-5.844,0-11.044-1.291-15.454-3.838-17.112-9.88-23.166-39.396-16.607-80.979 1.405-8.907 3.35-18.159 5.789-27.669 20.518,4.865 42.8,8.441 66.173,10.619 13.951,19.807 28.618,37.883 43.53,53.648-2.254,2.201-4.509,4.348-6.76,6.423-29.252,26.954-56.48,41.796-76.671,41.796zm220.214-84.584c6.559,41.583 0.505,71.099-16.607,80.979-17.113,9.879-45.699,0.364-78.434-26.106-6.893-5.574-13.814-11.767-20.712-18.499 14.761-15.578 29.462-33.603 43.563-53.579 23.432-2.151 45.822-5.697 66.389-10.509 2.445,9.526 4.394,18.793 5.801,27.714zm-9.83-42.153c-16.064,3.733-33.311,6.67-51.339,8.745 6.085-9.283 12.027-18.918 17.773-28.871 5.517-9.556 10.713-19.161 15.579-28.757 7.195,16.66 13.228,33.063 17.987,48.883zm-17.918-84.145c-5.152-10.259-10.688-20.532-16.587-30.749-5.818-10.078-11.859-19.878-18.077-29.348 19.355,2.146 37.276,5.243 53.564,9.081-4.955,16.493-11.302,33.623-18.9,51.016z"/>
<path stroke="#FFFFFF" fill="none" stroke-width="6" d="m235,197.392c-20.678,0-37.5,16.822-37.5,37.5s16.822,37.5 37.5,37.5 37.5-16.822 37.5-37.5-16.822-37.5-37.5-37.5zm0,60c-12.406,0-22.5-10.094-22.5-22.5s10.094-22.5 22.5-22.5 22.5,10.094 22.5,22.5-10.094,22.5-22.5,22.5z"/>
`
}

View File

@@ -19,6 +19,12 @@ export const validations = {
registereduser,
required
},
name: {
required
},
surname: {
required
},
email: {
email,
registeredemail,

View File

@@ -30,9 +30,11 @@ export default class Signup extends Vue {
public signup: ISignupOptions = {
email: process.env.TEST_EMAIL || '',
username: process.env.TEST_USERNAME || '',
name: process.env.TEST_NAME || '',
surname: process.env.TEST_SURNAME || '',
password: process.env.TEST_PASSWORD || '',
repeatPassword: process.env.TEST_PASSWORD || '',
terms: process.env.PROD ? false : true
terms: !process.env.PROD
}
public created() {
@@ -107,6 +109,9 @@ export default class Signup extends Vue {
} else if (cosa === 'username') {
// console.log(item);
if (!item.isUnique) { return this.$t('reg.err.duplicate_username') }
} else if ((cosa === 'name') || (cosa === 'surname')) {
// console.log(item);
}
if (!item.complexity) { return this.$t('reg.err.complexity') }

View File

@@ -41,6 +41,38 @@
</q-input>
<q-input
v-model="signup.name"
rounded outlined
@blur="$v.signup.name.$touch"
:error="$v.signup.name.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('name', $v.signup.name)"
:label="$t('reg.name')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.surname"
rounded outlined
@blur="$v.signup.surname.$touch"
:error="$v.signup.surname.$error"
bottom-slots
debounce="1000"
:error-message="errorMsg('surname', $v.signup.surname)"
:label="$t('reg.surname')">
<template v-slot:prepend>
<q-icon name="person"/>
</template>
</q-input>
<q-input
v-model="signup.password"
type="password"

View File

@@ -0,0 +1,26 @@
.est{
margin: 5px;
padding: 5px;
&__price {
color: blue;
}
&__totale_text {
padding: 2px;
font-size: 1.15rem;
color: blue;
}
&__totale_numpag {
padding: 2px;
font-size: 1.15rem;
color: red;
}
&__totale_price {
padding: 2px;
font-size: 1.15rem;
color: green;
}
}

View File

@@ -0,0 +1,217 @@
import Vue from 'vue'
import { Component, Watch } from 'vue-property-decorator'
import { IEstimate } from '@src/model'
import { tools } from '@src/store/Modules/tools'
@Component({})
export default class Estimate extends Vue {
public arrEstimate: IEstimate[] = []
public features: IEstimate[] = [
{
title: '5 pagine principali: 1) Home principale con testo + slideshow di immagini, 2) Chi siamo, 3) Dove Siamo, 4) Contatti, 5) Servizi',
icon: 'looks_5'
},
{
title: 'Ottimizzato con tecnologia Responsive, visualizzabile su cellulare',
icon: 'devices_other'
},
{
title: 'Possibilità di modificare, in maniera autonoma, i testi delle pagine esistenti (Sito Dinamico)',
icon: 'edit'
},
{
title: 'Galleria d\'immagini Slideshow',
icon: 'photo_album'
},
{
title: 'Certificato SSL / HTTPS di sicurezza incluso',
icon: 'https'
},
{
title: 'GDPR privacy e cookie',
icon: 'verified_user'
},
{
title: 'Posizionamento motori di ricerca (Google)',
icon: 'search'
},
{
title: 'Statistica Visualizzazioni sito web (Google Analytics)',
icon: 'search'
}
]
public arrEstimateit: IEstimate[] = [
{
id: 1,
title: 'Pagina Web Base', description: '',
price: 250,
advanced: false,
qta: 1,
icon: 'web',
numpag: 5,
viewlist: null,
checksel: true
},
{
id: 9,
title: 'Hosting Base Dominio WWW (Servizio Esterno)',
description: 'Servizio di Hosting linux base + Database Mysql + Servizio Mail + Dominio',
advanced: false,
icon: 'home',
price: 80,
qta: 1,
numpag: 0,
viewlist: null,
checksel: false
},
{
id: 2,
title: '+ 5 Pagine Aggiuntive',
description: 'Inserisci il numero di pagine che si vuole creare',
advanced: false,
price: 50,
qta: 1,
numpag: 5,
icon: 'description',
viewlist: null,
checksel: false
},
{
id: 3,
title: '+ 10 Pagine Aggiuntive',
description: 'pagine aggiuntive da creare',
price: 85,
qta: 1,
numpag: 10,
icon: 'description',
viewlist: null,
checksel: false
},
{
id: 4,
title: '+ 20 Pagine Aggiuntive',
description: 'pagine aggiuntive da creare',
advanced: false,
price: 140,
qta: 1,
numpag: 20,
icon: 'description',
viewlist: null,
checksel: false
},
{
id: tools.languageid,
title: '+ 1 Lingua Aggiuntiva (con testi già tradotti)',
description: 'Inserimento di 1 lingua straniera nel sito. Comprende le pagine selezionate',
advanced: false,
icon: 'language',
price: 10,
pricebase: 50,
qta: 1,
numpag: 0,
viewlist: null,
checksel: false
},
{
id: 8,
title: 'Gestione Newsletter integrata con MailChimp',
advanced: true,
description: 'All\'interno del sito l\'utente potrà lasciare la propria email e nome, e verrà inviata a MailChimp (Account Gratuito)',
icon: 'contact_mail',
price: 50,
qta: 1,
numpag: 0,
viewlist: null,
checksel: false
},
{
id: 6,
title: 'Calendario Eventi',
advanced: true,
description: 'Visualizzazione Mensile e Settimanale di un calendario Eventi Personalizzato',
icon: 'event',
price: 100,
qta: 1,
numpag: 0,
viewlist: null,
checksel: false
},
{
id: 7,
title: 'Galleria Immagini Personalizzata',
advanced: true,
description: 'Possibilità di aggiungere/eliminare foto autonomamente dalla galleria Immagini (Richiede Hosting Base)',
icon: 'perm_media',
price: 100,
qta: 1,
numpag: 0,
viewlist: null,
checksel: false
}
// {
// id: 7,
// title: 'Servizio di Assistenza e modifica pagine (dal 2° anno)',
// description: '',
// icon: 'perm_media',
// price: 100,
// qta: 1,
// numpag: 0,
// viewlist: null,
// checksel: false
// },
]
public mounted() {
this.arrEstimate = this.arrEstimateit
}
public getPrice(rec: IEstimate) {
let myprice = 0
if (rec.id === tools.languageid) {
myprice = (rec.price * this.getNumpagTotal()) + rec.pricebase
} else {
myprice = rec.price
}
return myprice
}
public getNumpagTotal() {
let numpag = 0
let rec: IEstimate = null
for (rec of this.arrEstimateit) {
if (rec.checksel) {
numpag += rec.numpag
}
}
return numpag
}
public getTotal() {
let tot = 0
let rec: IEstimate = null
const numpagtot = this.getNumpagTotal()
for (rec of this.arrEstimateit) {
if (rec.checksel)
tot += this.getPrice(rec) * rec.qta
}
return tot
}
public getColor(rec) {
if (rec.advanced) {
return 'red'
} else {
return 'blue'
}
}
}

View File

@@ -0,0 +1,74 @@
<template>
<div>
<q-list bordered padding>
<q-item-label header class="text-subtitle1 text-blue text-center text-bold">Preventivo Sito Web
</q-item-label>
<p class="q-ml-md">
<q-chip color="primary" text-color="white" icon="">
Funzionalità Incluse
</q-chip>
</p>
<!--<q-item-label header class="text-subtitle1 text-blue">Funzionalità Incluse</q-item-label>-->
<q-item tag="label" v-for="rec in features" :key="rec.title">
<q-item-section avatar top>
<q-avatar :icon="rec.icon" color="green" text-color="white"/>
</q-item-section>
<q-item-section>
<q-item-label>{{rec.title}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
<q-list bordered padding>
<p class="q-ml-md">
<q-chip color="orange" text-color="white" icon="">
Funzionalità Aggiuntive
</q-chip>
</p>
<div style="text-align: right;">
<span class="est__totale_text">Pagine:</span>
<span class="est__totale_numpag">{{getNumpagTotal()}}</span>
<span style="margin-left: 20px;"></span>
<span class="est__totale_text">Totale:</span>
<span class="est__totale_price">{{getTotal()}} </span>
</div>
<q-item tag="label" v-for="rec in arrEstimateit" :key="rec.title">
<q-item-section avatar top>
<q-avatar :icon="rec.icon" :color="getColor(rec)" text-color="white"/>
</q-item-section>
<q-item-section>
<q-item-label>{{rec.title}}</q-item-label>
<q-item-label caption v-html="rec.description"></q-item-label>
<q-item-label>
<span class="est__price">{{getPrice(rec)}} </span>
</q-item-label>
</q-item-section>
<q-item-section side top>
<q-checkbox v-model="rec.checksel"/>
</q-item-section>
</q-item>
</q-list>
<div class="q-ml-md">
<span class="est__totale_text">Pagine:</span>
<span class="est__totale_numpag">{{getNumpagTotal()}}</span>
<span style="padding-left: 20px;"></span>
<span class="est__totale_text">Totale:</span>
<span class="est__totale_price">{{getTotal()}} </span>
</div>
</div>
</template>
<script lang="ts" src="./estimate.ts">
</script>
<style lang="scss" scoped>
@import './estimate';
</style>

View File

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