- Aggiornate tutte le categorie ottimizzandole.

- Migrazione delle vecchie categ. con quelle nuove.
- Create le Categorie e sottocategorie degli Eventi (a parte).
- Aggiornato la card dell'Ospitalità
This commit is contained in:
Surya Paolo
2025-12-07 02:13:18 +01:00
parent 5d35930dc8
commit a4ca394e49
58 changed files with 2127 additions and 1119 deletions

View File

@@ -256,7 +256,11 @@ export default defineComponent({
if (recSector) {
tools.setCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + recSector.value, newval)
}
// setCategBySector('sectorgoods', table, newval)
} else if (table === toolsext.TABMYBACHECAS) {
const recSector = searchList.value.find((rec) => rec.table === toolsext.TABSECTORBACHECAS)
if (recSector) {
tools.setCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + recSector.value, newval)
}
}

View File

@@ -107,6 +107,13 @@
/>
<div class="row justify-center">
<q-btn
label="Annulla"
v-close-popup
color="primary"
flat
class="q-ml-sm"
/>
<q-btn
label="Aggiungi"
type="submit"
@@ -120,13 +127,6 @@
"
color="primary"
/>
<q-btn
label="Annulla"
v-close-popup
color="primary"
flat
class="q-ml-sm"
/>
</div>
</q-form>
</q-card-section>

View File

@@ -10,24 +10,48 @@
</div>-->
<div>
<!-- display an myevent -->
<q-dialog v-model="displayEvent" :maximized="$q.screen.lt.sm">
<q-card v-if="myevent" class="dialog_card">
<q-dialog
v-model="displayEvent"
:maximized="$q.screen.lt.sm"
>
<q-card
v-if="myevent"
class="dialog_card"
>
<q-toolbar class="bg-primary text-white">
<!--<q-toolbar :class="tools.displayClasses(myevent)"-->
<!--:style="tools.displayStyles(myevent) + ` min-width: `+ tools.myheight_dialog() + `px;`">-->
<q-toolbar-title>
{{ t('cal.event') }}
</q-toolbar-title>
<q-btn v-if="editable" flat round color="white" icon="fas fa-copy">
<q-menu transition-show="flip-right" transition-hide="flip-left">
<q-btn
v-if="editable"
flat
round
color="white"
icon="fas fa-copy"
>
<q-menu
transition-show="flip-right"
transition-hide="flip-left"
>
<q-list style="min-width: 100px">
<q-item clickable @click="duplicateEvent(myevent, 7)">
<q-item
clickable
@click="duplicateEvent(myevent, 7)"
>
<q-item-section>Tra 1 Settimana</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 14)">
<q-item
clickable
@click="duplicateEvent(myevent, 14)"
>
<q-item-section>Tra 2 Settimane</q-item-section>
</q-item>
<q-item clickable @click="duplicateEvent(myevent, 7, 4)">
<q-item
clickable
@click="duplicateEvent(myevent, 7, 4)"
>
<q-item-section>4 Eventi ogni Settimana</q-item-section>
</q-item>
</q-list>
@@ -86,7 +110,10 @@
:class="`cal__details` + ($q.dark.isActive ? `_darktheme` : ``)"
v-html="myevent.details"
></div>
<div v-if="myevent.teacher" class="cal__teacher">
<div
v-if="myevent.teacher"
class="cal__teacher"
>
<span class="cal__teacher-title"
>{{ t('cal.teacher') }}: <span class="margin_with"></span
></span>
@@ -96,16 +123,17 @@
<CMyTeacher :username="myevent.teacher3"></CMyTeacher>
<CMyTeacher :username="myevent.teacher4"></CMyTeacher>
</div>
<div v-if="myevent.wherecode" class="cal__where">
<div
v-if="myevent.wherecode"
class="cal__where"
>
<!--<span v-if="tools.isMobile()"><br/></span>-->
<span class="cal__where-title">{{ t('cal.where') }}: </span>
<span class="cal__where-content">
<q-chip>
<q-avatar v-if="getWhereIcon(myevent.wherecode)">
<img
:src="
`/images/avatar/` + getWhereIcon(myevent.wherecode)
"
:src="`/images/avatar/` + getWhereIcon(myevent.wherecode)"
alt="Località"
/>
</q-avatar>
@@ -129,17 +157,16 @@
>
<span class="cal__quota-title">{{ t('event.price') }}:</span>
<q-chip>
<span class="cal__quota-content">{{
getPrice(myevent)
}}</span>
<span class="cal__quota-content">{{ getPrice(myevent) }}</span>
</q-chip>
</div>
<div v-if="myevent.dateTimeStart" class="cal__when">
<div
v-if="myevent.dateTimeStart"
class="cal__when"
>
<span class="cal__where-title"
>{{ t('cal.when') }}:
<span
v-html="tools.getstrDateTimeEvent($t, myevent, true)"
></span>
<span v-html="tools.getstrDateTimeEvent($t, myevent, true)"></span>
</span>
</div>
<p
@@ -181,16 +208,33 @@
</q-dialog>
<!-- id_bookedeventadd/edit an myevent -->
<q-dialog v-model="addEvent" no-backdrop-dismiss persistent>
<q-card v-if="addEvent" class="dialog_card">
<q-dialog
v-model="addEvent"
no-backdrop-dismiss
persistent
>
<q-card
v-if="addEvent"
class="dialog_card"
>
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ addOrUpdateEvent() }} {{ t('cal.event') }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
<q-btn
flat
round
color="white"
icon="close"
v-close-popup
></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
<q-form v-if="contextDay" ref="myevent" class="q-gutter-sm">
<q-form
v-if="contextDay"
ref="myevent"
class="q-gutter-sm"
>
<CMySelect
:label="$t('event.typol')"
v-model:value="eventForm.typol"
@@ -254,7 +298,10 @@
/>
</q-tabs>
<q-tab-panels v-model="tabeditor" animated>
<q-tab-panels
v-model="tabeditor"
animated
>
<q-tab-panel name="details">
<div class="q-gutter-sm myflex">
<q-input
@@ -320,7 +367,10 @@
</CMyEditor>
</q-tab-panel>
<q-tab-panel name="settings" class="q-gutter-sm">
<q-tab-panel
name="settings"
class="q-gutter-sm"
>
<!--<q-checkbox v-model="eventForm.allday" :label="$t('cal.alldayevent')"></q-checkbox>-->
<div class="q-gutter-sm row myflex">
@@ -507,28 +557,40 @@
</q-form>
</q-card-section>
<q-card-actions align="right">
<q-btn
:label="$t('dialog.ok')"
color="primary"
@click="saveEvent"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
></q-btn>
<q-btn
:label="$t('dialog.ok')"
color="primary"
@click="saveEvent"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="bookEventpage.show" no-backdrop-dismiss>
<q-card v-if="bookEventpage.show" class="dialog_card">
<q-dialog
v-model="bookEventpage.show"
no-backdrop-dismiss
>
<q-card
v-if="bookEventpage.show"
class="dialog_card"
>
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ t('cal.booking') }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
<q-btn
flat
round
color="white"
icon="close"
v-close-popup
></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
@@ -548,16 +610,20 @@
>
{{ myevent.title }}
</q-chip>
<div v-if="myevent.dateTimeStart" class="cal__when">
<div
v-if="myevent.dateTimeStart"
class="cal__when"
>
<span class="cal__where-title"
>{{ t('cal.when') }}:
<span
v-html="tools.getstrDateTimeEvent($t, myevent, true)"
></span>
<span v-html="tools.getstrDateTimeEvent($t, myevent, true)"></span>
</span>
</div>
<div class="q-pa-xs">
<q-card class="text-white windowcol" style="display: block">
<q-card
class="text-white windowcol"
style="display: block"
>
<q-card-section class="q-pa-xs">
<div
style="display: inline-flex"
@@ -583,9 +649,7 @@
style="min-width: 140px"
>
<q-select
:behavior="
$q.platform.is.ios === true ? 'dialog' : 'menu'
"
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
rounded
outlined
v-model="bookEventForm.numpeople"
@@ -614,9 +678,7 @@
style="min-width: 140px; margin-left: 10px"
>
<q-select
:behavior="
$q.platform.is.ios === true ? 'dialog' : 'menu'
"
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
rounded
outlined
v-model="bookEventForm.numpeopleLunch"
@@ -647,9 +709,7 @@
style="min-width: 180px; margin-left: 10px"
>
<q-select
:behavior="
$q.platform.is.ios === true ? 'dialog' : 'menu'
"
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
rounded
outlined
v-model="bookEventForm.numpeopleDinner"
@@ -679,9 +739,7 @@
style="min-width: 180px; margin-left: 10px"
>
<q-select
:behavior="
$q.platform.is.ios === true ? 'dialog' : 'menu'
"
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
rounded
outlined
v-model="bookEventForm.numpeopleDinnerShared"
@@ -726,6 +784,13 @@
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
></q-btn>
<q-btn
v-if="bookEventpage.state === EState.Modifying"
flat
@@ -745,28 +810,31 @@
:label="getTitleBtnBooking()"
color="primary"
@click="saveBookEvent(myevent)"
:disable="
!(bookEventpage.state === EState.Creating || hasModifiedBooking)
"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
:disable="!(bookEventpage.state === EState.Creating || hasModifiedBooking)"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="askInfopage.show" no-backdrop-dismiss>
<q-card v-if="askInfopage.show" class="dialog_card">
<q-dialog
v-model="askInfopage.show"
no-backdrop-dismiss
>
<q-card
v-if="askInfopage.show"
class="dialog_card"
>
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ t('cal.booking') }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
<q-btn
flat
round
color="white"
icon="close"
v-close-popup
></q-btn>
</q-toolbar>
<q-card-section class="inset-shadow">
@@ -786,12 +854,13 @@
>
{{ myevent.title }}
</q-chip>
<div v-if="myevent.dateTimeStart" class="cal__when">
<div
v-if="myevent.dateTimeStart"
class="cal__when"
>
<span class="cal__where-title"
>{{ t('cal.when') }}:
<span
v-html="tools.getstrDateTimeEvent($t, myevent, true)"
></span>
<span v-html="tools.getstrDateTimeEvent($t, myevent, true)"></span>
</span>
</div>
<div class="q-pa-xs">
@@ -812,18 +881,17 @@
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
flat
:label="$t('dialog.sendmsg')"
color="primary"
@click="sendMsg(myevent)"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
></q-btn>
<q-btn
:label="$t('dialog.sendmsg')"
color="primary"
@click="sendMsg(myevent)"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
@@ -956,20 +1024,13 @@
class="q-ma-xs"
:class="badgeClasses(event, 'header')"
:style="badgeStyles(event, 'header')"
style="
width: 10px;
max-width: 10px;
height: 10px;
max-height: 10px;
"
style="width: 10px; max-width: 10px; height: 10px; max-height: 10px"
></q-badge>
</template>
</div>
</template>
<template
#day-body="{
scope: { timestamp, timeStartPos, timeDurationHeight },
}"
#day-body="{ scope: { timestamp, timeStartPos, timeDurationHeight } }"
>
<template
v-for="(event, index) in getEvents(timestamp.date)"
@@ -1012,12 +1073,7 @@
class="my-event-rel justify-center rounded-borders"
:class="badgeClasses(event, 'body')"
:style="
badgeStyles(
event,
'body',
timeStartPos,
timeDurationHeight
)
badgeStyles(event, 'body', timeStartPos, timeDurationHeight)
"
@click.stop.prevent="showEvent(event)"
:draggable="tools.isManager()"
@@ -1087,13 +1143,7 @@
<img
:src="getImgEvent(event)"
@click="selectEvent(event)"
class="
text-left
padding_cell
listaev__tdimg listaev__img
cursor-pointer
q-mx-sm
"
class="text-left padding_cell listaev__tdimg listaev__img cursor-pointer q-mx-sm"
:style="getStyleByEvent(event, event === myevent)"
:alt="event.title"
/>
@@ -1139,9 +1189,7 @@
clickable
@click="duplicateEvent(myevent, 7, 4)"
>
<q-item-section
>4 Eventi ogni Settimana</q-item-section
>
<q-item-section>4 Eventi ogni Settimana</q-item-section>
</q-item>
</q-list>
</q-menu>
@@ -1187,22 +1235,17 @@
</q-chip>
</div>
<div
class="
listaev__date listaev__align_center_mobile
text-center
"
>
<span
v-html="tools.getstrDateTimeEvent($t, event, true)"
></span>
<div class="listaev__date listaev__align_center_mobile text-center">
<span v-html="tools.getstrDateTimeEvent($t, event, true)"></span>
</div>
<div class="listaev__align_center_mobile">
<div style="margin: 10px"></div>
<div v-if="event.internal">
<q-chip color="blue" text-color="white"
<q-chip
color="blue"
text-color="white"
>Evento Interno:</q-chip
>
</div>
@@ -1247,17 +1290,15 @@
<div style="margin: 10px"></div>
<p
:class="
`listaev__details` + ($q.dark.isActive
? `_darktheme`
: ``)
"
:class="`listaev__details` + ($q.dark.isActive ? `_darktheme` : ``)"
v-html="event.details"
></p>
<div v-if="event.teacher" class="">
<div
v-if="event.teacher"
class=""
>
<span class="cal__teacher-title"
>{{ t('cal.teacher') }}:
<span class="margin_with"></span
>{{ t('cal.teacher') }}: <span class="margin_with"></span
></span>
<CMyTeacher :username="event.teacher"></CMyTeacher>
@@ -1265,18 +1306,17 @@
<CMyTeacher :username="event.teacher3"></CMyTeacher>
<CMyTeacher :username="event.teacher4"></CMyTeacher>
<span v-if="event.wherecode" class="">
<span
v-if="event.wherecode"
class=""
>
<span v-if="tools.isMobile()"><br /></span>
<span class="cal__where-title"
>{{ t('cal.where') }}:
</span>
<span class="cal__where-title">{{ t('cal.where') }}: </span>
<q-chip>
<q-avatar v-if="getWhereIcon(event.wherecode)">
<img
:src="
`/images/avatar/` + getWhereIcon(event.wherecode)
"
:src="`/images/avatar/` + getWhereIcon(event.wherecode)"
:alt="event.wherecode"
/>
</q-avatar>
@@ -1293,13 +1333,17 @@
</q-chip>
</span>
</div>
<div v-if="event.contribtype" class="">
<div
v-if="event.contribtype"
class=""
>
<span class="cal__quota-title"
>{{ t('event.price') }}:<span
class="margin_with"
></span
>{{ t('event.price') }}:<span class="margin_with"></span
></span>
<span v-if="!isShowPrice(event)" class="">
<span
v-if="!isShowPrice(event)"
class=""
>
<q-chip
class="glossy"
color="orange"
@@ -1318,9 +1362,7 @@
text-color="white"
icon-right="star"
>
<span class="cal__quota-content">{{
getPrice(event)
}}</span>
<span class="cal__quota-content">{{ getPrice(event) }}</span>
</q-chip>
</div>
@@ -1418,8 +1460,7 @@
</div>
</div>
</template>
<script lang="ts" src="./CEventsCalendar.ts">
</script>
<script lang="ts" src="./CEventsCalendar.ts"></script>
<style lang="scss" scoped>
@import './CEventsCalendar.scss';
</style>

View File

@@ -306,7 +306,7 @@ export default defineComponent({
}
function getFilterGoods(recGood: any, index: number, arr: any) {
const recsectorGoods: any = searchList.value.find((rec) => rec.table === 'sectorgoods')
const recsectorGoods: any = searchList.value.find((rec) => rec.table === toolsext.TABSECTORGOODS)
// console.log('getFilterSkills', recSkill.idSector, recsectors.value)
if (recsectorGoods && recGood.idSectorGood) {
return recGood.idSectorGood.includes(recsectorGoods.value)
@@ -314,6 +314,15 @@ export default defineComponent({
return true
}
}
function getFilterBachecas(recBacheca: any, index: number, arr: any) {
const recsectorBachecas: any = searchList.value.find((rec) => rec.table === toolsext.TABSECTORBACHECAS)
// console.log('getFilterSkills', recSkill.idSector, recsectors.value)
if (recsectorBachecas && recBacheca.idSectorBacheca) {
return recBacheca.idSectorBacheca.includes(recsectorBachecas.value)
} else {
return true
}
}
function getFilterSubSkills(recSubSkill: any, index: number, arr: any) {
const recskills: any = searchList.value.find((rec) => rec.table === 'skills')
@@ -614,9 +623,9 @@ export default defineComponent({
{
visible: true,
label: 'Settore',
table: toolsext.TABSECTORS,
key: 'idSector',
value: tools.getCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + toolsext.TABSECTORS, 0, true),
table: toolsext.TABSECTORBACHECAS,
key: 'idSectorBacheca',
value: tools.getCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + toolsext.TABSECTORBACHECAS, 0, true),
arrvalue: [],
type: costanti.FieldType.select,
filter: null,
@@ -624,6 +633,19 @@ export default defineComponent({
notinsearch: false,
useinput: false,
},
{
visible: true,
label: 'Categoria',
table: 'bachecas',
key: 'idBacheca',
value: tools.getCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + tools.getCookie(tools.COOK_SEARCH + toolsext.TABSECTORBACHECAS, costanti.FILTER_TUTTI), costanti.FILTER_TUTTI, true),
arrvalue: [],
type: costanti.FieldType.select,
addall: true,
filter: getFilterBachecas,
showcount: true,
useinput: false,
},
{
visible: true,
label: 'Data Inizio',
@@ -898,7 +920,7 @@ export default defineComponent({
{
visible: true,
label: 'Settore',
table: 'sectorgoods',
table: toolsext.TABSECTORGOODS,
key: 'idSectorGood',
value: tools.getCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + toolsext.TABSECTORGOODS, 0, true),
arrvalue: [],
@@ -911,7 +933,7 @@ export default defineComponent({
{
visible: true,
label: 'Categoria',
table: 'goods',
table: toolsext.TABGOODS,
key: 'idGood',
value: tools.getCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + props.table + costanti.FILTER_SEP + tools.getCookie(tools.COOK_SEARCH + toolsext.TABSECTORGOODS, costanti.FILTER_TUTTI), costanti.FILTER_TUTTI, true),
arrvalue: [],

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,3 @@
// ========================================
// BASE STYLES
// ========================================
$primary-color: #1976d2;
$border-radius: 10px;
$transition-speed: 0.3s;
$mobile-breakpoint: 768px;
@use 'sass:color';
$shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
$shadow-md: 0 2px 6px rgba(0, 0, 0, 0.08);
$shadow-hover: 0 4px 12px rgba(25, 118, 210, 0.15);
@@ -169,7 +158,7 @@ $shadow-hover: 0 4px 12px rgba(25, 118, 210, 0.15);
gap: 8px;
// Desktop: layout a griglia 2 colonne
@media (min-width: $mobile-breakpoint + 1) {
@media (min-width: $mobile-breakpoint) {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
@@ -178,7 +167,7 @@ $shadow-hover: 0 4px 12px rgba(25, 118, 210, 0.15);
// Desktop large: 3 colonne per schermi molto larghi
@media (min-width: 1400px) {
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}

View File

@@ -854,6 +854,8 @@ export default defineComponent({
setCategBySector(shared_consts.TABLES_MYSKILLS, table, newval);
} else if (table === toolsext.TABSECTORGOODS) {
setCategBySector(toolsext.TABGOODS, table, newval);
} else if (table === toolsext.TABSECTORBACHECAS) {
setCategBySector(toolsext.TABBACHECAS, table, newval);
} else if (table === toolsext.TABREGIONS) {
setProvinceByRegion(toolsext.TABPROVINCE, table, newval);
} else if (table === toolsext.TABGOODS) {
@@ -872,6 +874,22 @@ export default defineComponent({
newval
);
}
} else if (table === toolsext.TABBACHECAS) {
const recSector = searchList.value.find(
(rec) => rec.table === toolsext.TABSECTORBACHECAS
);
if (recSector) {
tools.setCookie(
tools.COOK_SEARCH +
costanti.FILTER_SEP +
mytable.value +
costanti.FILTER_SEP +
table +
costanti.FILTER_SEP +
recSector.value,
newval
);
}
} else if (table === shared_consts.TABLES_LISTA_EDITORI) {
const rec = searchList.value.find((rec) => rec.table === table);
if (rec) {
@@ -1029,12 +1047,14 @@ export default defineComponent({
let recSector = null;
let recSectorGood = null;
let recSectorBacheca = null;
let recCities = null;
let recRegion = null;
let recProvince = null;
let recSkill = null;
let idSector = 0;
let idSectorGood = 0;
let idSectorBacheca = 0;
let idProvince = 0;
let idRegion = 0;
let idSkill = 0;
@@ -1046,10 +1066,16 @@ export default defineComponent({
}
if (searchList.value) {
recSectorGood = searchList.value.find(
(item: ISearchList) => item.table === 'sectorgoods'
(item: ISearchList) => item.table === toolsext.TABSECTORGOODS
);
idSectorGood = recSectorGood ? recSectorGood.value : 0;
}
if (searchList.value) {
recSectorBacheca = searchList.value.find(
(item: ISearchList) => item.table === toolsext.TABSECTORBACHECAS
);
idSectorBacheca = recSectorBacheca ? recSectorBacheca.value : 0;
}
if (searchList.value) {
recProvince = searchList.value.find(
(item: ISearchList) => item.table === 'provinces'
@@ -1315,13 +1341,20 @@ export default defineComponent({
obj2.idSkill = idSkill;
filtersearch2.push(obj2);
}
} else if (item.table === 'goods' && item.value === costanti.FILTER_TUTTI) {
} else if (item.table === toolsext.TABGOODS && item.value === costanti.FILTER_TUTTI) {
const obj2: any = {};
if (idSectorGood > 0) {
// idSectorGood
obj2['sectorGood._id'] = idSectorGood;
filtersearch2.push(obj2);
}
} else if (item.table === toolsext.TABBACHECAS && item.value === costanti.FILTER_TUTTI) {
const obj2: any = {};
if (idSectorBacheca > 0) {
// idSectorBacheca
obj2['sectorBacheca._id'] = idSectorBacheca;
filtersearch2.push(obj2);
}
} else if (
item.table === 'subskills' &&
item.value === costanti.FILTER_TUTTI
@@ -1843,6 +1876,14 @@ export default defineComponent({
newRecord.value.idGood = item.idGood;
console.log('newRecord', newRecord);
}
} else if (col.jointable === toolsext.TABSECTORBACHECAS) {
// Sbianca la select della Categoria Eventi
if (tools.existProp(item, 'idBacheca')) {
item.idGood = costanti.FILTER_NESSUNO;
newRecord.value.idBacheca = item.idBacheca;
console.log('newRecord', newRecord);
}
}
rowsel.value = item;
idsel = item._id;
@@ -2800,7 +2841,7 @@ export default defineComponent({
return '';
}
function cmdExt(cmd: any, id: any, myrec: any) {
async function cmdExt(cmd: any, id: any, myrec: any) {
console.log('cmd', cmd);
if (cmd === costanti.CMD_CLONE) {
@@ -2817,9 +2858,11 @@ export default defineComponent({
}
if (cmd === costanti.CMD_SHOW_PAGE) {
visupagedialog.value = true;
visupagedialog.value = false;
await nextTick();
myrecdialog.value = myrec;
myIdRecDialog.value = id;
visupagedialog.value = true;
return true;
} else if (cmd === costanti.CMD_OPEN_PAGE) {
router.push(tools.getPathByTableAndRec(mytable.value, myrec));

View File

@@ -1318,6 +1318,7 @@
<q-dialog
v-model="showSearchDialog"
:seamless="$q.screen.gt.xs"
transition-show="slide-up"
transition-hide="slide-down"
class="q-dialog-fullscreen no-padding-dialog"
@@ -1404,6 +1405,7 @@
@hide="hidewindow"
:maximized="$q.screen.lt.sm"
:persistent="false"
:seamless="$q.screen.gt.xs"
:class="
'dialog_annunci ' + ($q.screen.lt.sm ? 'bottom-dialog' : ' right-align-dialog')
"
@@ -1504,6 +1506,7 @@
@hide="hidewindow"
class="dialog_class"
:persistent="true"
:seamless="$q.screen.gt.xs"
:maximized="$q.screen.lt.sm"
>
<q-card class="dialog_card">
@@ -1582,11 +1585,6 @@
</div>
</q-card-section>
<q-card-actions align="center">
<q-btn
:label="t('dialog.insert')"
color="primary"
@click="saveNewRecord"
></q-btn>
<q-btn
flat
:label="t('dialog.cancel')"
@@ -1594,12 +1592,18 @@
v-close-popup
@click="annulla"
></q-btn>
<q-btn
:label="t('dialog.insert')"
color="primary"
@click="saveNewRecord"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog
v-model="editRecordBool"
@hide="hidewindowEdit"
:seamless="$q.screen.gt.xs"
:maximized="$q.screen.lt.sm"
>
<q-card class="dialog_card">
@@ -1672,17 +1676,17 @@
</div>
</q-card-section>
<q-card-actions align="center">
<q-btn
:label="t('dialog.save')"
color="primary"
@click="saverecModif"
></q-btn>
<q-btn
flat
:label="t('dialog.cancel')"
color="primary"
@click="cancelrecModif"
></q-btn>
<q-btn
:label="t('dialog.save')"
color="primary"
@click="saverecModif"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>

View File

@@ -1,16 +1,3 @@
// ========================================
// VARIABILI
// ========================================
$primary-color: #1976d2;
$grey-color: #666;
$grey-light: #999;
$border-radius: 8px;
$border-radius-sm: 6px;
$transition-speed: 0.3s;
$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
$mobile-breakpoint: 768px;
// ========================================
// GRID CONTAINER

View File

@@ -593,6 +593,8 @@ export default defineComponent({
setCategBySector(shared_consts.TABLES_MYSKILLS, table, newval)
} else if (table === toolsext.TABSECTORGOODS) {
setCategBySector(toolsext.TABGOODS, table, newval)
} else if (table === toolsext.TABSECTORBACHECAS) {
setCategBySector(toolsext.TABBACHECAS, table, newval)
} else if (table === toolsext.TABREGIONS) {
setProvinceByRegion(toolsext.TABPROVINCE, table, newval)
} else if (table === toolsext.TABGOODS) {
@@ -600,7 +602,11 @@ export default defineComponent({
if (recSector) {
tools.setCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + mytable.value + costanti.FILTER_SEP + table + costanti.FILTER_SEP + recSector.value, newval)
}
// setCategBySector('sectorgoods', table, newval)
} else if (table === toolsext.TABBACHECAS) {
const recSector = searchList.value.find((rec) => rec.table === toolsext.TABSECTORBACHECAS)
if (recSector) {
tools.setCookie(tools.COOK_SEARCH + costanti.FILTER_SEP + mytable.value + costanti.FILTER_SEP + table + costanti.FILTER_SEP + recSector.value, newval)
}
} else if (table === shared_consts.TAB_CITIES) {
const rec = searchList.value.find((myrec) => myrec.table === shared_consts.TAB_CITIES) // check if exist
if (rec) {
@@ -722,12 +728,14 @@ export default defineComponent({
let recSector = null
let recSectorGood = null
let recSectorBacheca = null
let recCities = null
let recRegion = null
let recProvince = null
let recSkill = null
let idSector = 0
let idSectorGood = 0
let idSectorBacheca = 0
let idProvince = 0
let idRegion = 0
let idSkill = 0
@@ -736,9 +744,12 @@ export default defineComponent({
recSector = searchList.value.find((item: ISearchList) => item.table === toolsext.TABSECTORS)
idSector = recSector ? recSector.value : 0
recSectorGood = searchList.value.find((item: ISearchList) => item.table === 'sectorgoods')
recSectorGood = searchList.value.find((item: ISearchList) => item.table === toolsext.TABSECTORGOODS)
idSectorGood = recSectorGood ? recSectorGood.value : 0
recSectorBacheca = searchList.value.find((item: ISearchList) => item.table === toolsext.TABSECTORBACHECAS)
idSectorBacheca = recSectorBacheca ? recSectorBacheca.value : 0
recProvince = searchList.value.find((item: ISearchList) => item.table === 'provinces')
idProvince = recProvince ? recProvince.value : 0
@@ -888,13 +899,20 @@ export default defineComponent({
obj2.idSkill = idSkill
filtersearch2.push(obj2)
}
} else if ((item.table === 'goods') && item.value === costanti.FILTER_TUTTI) {
} else if ((item.table === toolsext.TABGOODS) && item.value === costanti.FILTER_TUTTI) {
const obj2: any = {}
if (idSectorGood > 0) {
// idSectorGood
obj2['sectorGood._id'] = idSectorGood
filtersearch2.push(obj2)
}
} else if (item.table === toolsext.TABBACHECAS && item.value === costanti.FILTER_TUTTI) {
const obj2: any = {};
if (idSectorBacheca > 0) {
// idSectorBacheca
obj2['sectorBacheca._id'] = idSectorBacheca;
filtersearch2.push(obj2);
}
} else if ((item.table === 'subskills') && item.value === costanti.FILTER_TUTTI) {
const obj2: any = {}
// idSector
@@ -1313,6 +1331,14 @@ export default defineComponent({
newRecord.value.idGood = item.idGood
console.log('newRecord', newRecord)
}
} else if (col.jointable === toolsext.TABSECTORBACHECAS) {
// Sbianca la select della Categoria Bacheca
if (tools.existProp(item, 'idBacheca')) {
item.idBacheca = costanti.FILTER_NESSUNO
newRecord.value.idBacheca = item.idBacheca
console.log('newRecord', newRecord)
}
}
rowsel.value = item
idsel = item._id

View File

@@ -354,11 +354,6 @@
</div>
</q-card-section>
<q-card-actions align="center">
<q-btn
:label="$t('dialog.insert')"
color="primary"
@click="saveNewRecord"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
@@ -366,6 +361,11 @@
v-close-popup
@click="annulla"
></q-btn>
<q-btn
:label="$t('dialog.insert')"
color="primary"
@click="saveNewRecord"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
@@ -428,17 +428,17 @@
</div>
</q-card-section>
<q-card-actions align="center">
<q-btn
:label="$t('dialog.ok')"
color="primary"
@click="saverecModif"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
@click="cancelrecModif"
></q-btn>
<q-btn
:label="$t('dialog.ok')"
color="primary"
@click="saverecModif"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>

View File

@@ -18,16 +18,16 @@
v-if="editing"
class="button-group"
>
<q-btn
flat
:label="$t('dialog.cancel')"
@click="cancelUpdate"
/>
<q-btn
:label="$t('dialog.save')"
color="positive"
@click="confirmUpdate"
/>
<q-btn
:label="$t('dialog.cancel')"
color="negative"
@click="cancelUpdate"
/>
</div>
</div>
</template>

View File

@@ -1,43 +1,3 @@
// ========================================
// VARIABILI MODERNE CON GRADIENTI
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$primary-dark: #1565c0;
$secondary-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$info-color: #31ccec;
$warning-color: #f2c037;
@use 'sass:color';
$grey-text: #555;
$grey-light: #999;
$grey-dark: #333;
$border-radius: 12px;
$border-radius-sm: 8px;
$border-radius-lg: 16px;
$transition-speed: 0.3s;
$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.15);
$mobile-breakpoint: 768px;
$small-breakpoint: 600px;
// ========================================
// GRADIENTI MODERNI
// ========================================
$gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
$gradient-secondary: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
$gradient-info: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
$gradient-positive: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
$gradient-card-light: linear-gradient(135deg, #fdfbfb 0%, #ebedee 100%);
$gradient-card-white: linear-gradient(to bottom, #ffffff 0%, #f8f9fa 100%);
$gradient-hover: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
// ========================================
// PROFILE (con gradiente)
@@ -858,4 +818,77 @@ $gradient-hover: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118,
border-left: 4px solid $positive-color;
background: linear-gradient(to right, rgba(33, 186, 69, 0.08), transparent 20%);
box-shadow: 0 2px 12px rgba(33, 186, 69, 0.1);
}
.category-hierarchy {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 2px;
.hierarchy-arrow {
opacity: 0.5;
font-size: 16px;
}
@media (max-width: $mobile-breakpoint) {
gap: 0px;
}
}
.tag-chip {
height: 20px;
font-size: 0.9rem;
padding: 0 px;
border-radius: 4px;
box-shadow: none;
font-weight: 500;
// Categoria principale - più scura e intensa
&.sector {
background: linear-gradient(135deg, $primary-color, #1976d2);
color: white;
}
// Sottocategoria - stessa base ma più chiara
&.subsector {
background: linear-gradient(135deg, color.adjust($primary-color, $lightness: 10%), #42a5f5);
color: white;
opacity: 0.9; // Opzionale: leggera trasparenza
}
@media (max-width: $mobile-breakpoint) {
height: 19px;
font-size: 0.8rem;
padding: 0 4px;
}
:deep(.q-chip__content) {
padding: 0;
}
}
.categories-dialog {
.dialog-header {
padding: 16px 20px;
}
.dialog-content {
padding: 20px;
max-height: 60vh;
overflow-y: auto;
}
.categories-grid {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.category-chip {
font-size: 14px;
padding: 8px 12px;
font-weight: 500;
}
}

View File

@@ -87,6 +87,7 @@ export default defineComponent({
const showPic = ref(false)
const loading = ref(false)
const showPreferencesDialog = ref(false)
const $router = useRouter()
@@ -275,19 +276,21 @@ export default defineComponent({
}
function getRecGoodSkillByRec(rec: any) {
if (props.table === 'myskills')
if ((props.table === toolsext.TABMYSKILLS) || (props.table === toolsext.TABMYBACHECAS))
return rec.recSkill
else if (props.table === 'mygoods')
else if (props.table === toolsext.TABMYGOODS)
return rec.recGood
return null
}
function getSectorByRec(rec: any) {
if (props.table === 'myskills')
if (props.table === toolsext.TABMYSKILLS)
return rec.sector
else if (props.table === 'mygoods')
else if (props.table === toolsext.TABMYGOODS)
return rec.sectorGood
else if (props.table === toolsext.TABMYBACHECAS)
return rec.sectorBacheca
return null
}
@@ -674,10 +677,24 @@ export default defineComponent({
emit('showInMap', rec)
}
const arrSubSector = computed(() => {
return tools.getArrSubSector(props.table, myrec.value);
});
const arrSector = computed(() => {
return tools.getArrSector(props.table, myrec.value);
});
const getColorSubSector = computed(() => {
return arrSector.value && arrSector.value.length == 1 ? arrSector.value[0].color : 'primary'
})
onMounted(mounted)
return {
getColorSubSector,
arrSector,
arrSubSector,
expandDialog,
profile,
tools,
@@ -735,6 +752,7 @@ export default defineComponent({
updatePart,
numpart,
colmyUserPeople,
showPreferencesDialog,
}
}
})

View File

@@ -431,6 +431,30 @@
>
</q-item-section>
</q-item>
<!--<q-item v-if="table === shared_consts.TABLES_MYHOSPS">
<div
v-if="myrec.preferences && myrec.preferences.length > 0"
class="preferences-section q-mb-sm"
>
<div class="preferences-icons-container">
<q-avatar
v-for="(prefId, ind) of myrec.preferences"
:key="ind"
size="32px"
:style="`background-color: ${tools.getPreferenceById(prefId)?.color || 'grey'}; cursor: pointer;`"
class="preference-icon-avatar"
@click.stop="showPreferencesDialog = true"
>
<q-icon
:name="tools.getPreferenceById(prefId)?.icon || 'help'"
size="18px"
color="white"
/>
<q-tooltip>{{ tools.getPreferenceById(prefId)?.label }}</q-tooltip>
</q-avatar>
</div>
</div>
</q-item>-->
<q-item
v-if="
myrec.idStatusSkill &&
@@ -504,28 +528,49 @@
<q-item-section>
<q-item-label>
<q-chip
v-if="getSectorByRec(myrec) && getSectorByRec(myrec)[0].descr"
class="glossy"
color="blue"
text-color="white"
dense
>
<span>{{ getSectorByRec(myrec)[0].descr }}</span>
</q-chip>
<q-chip
v-if="
getRecGoodSkillByRec(myrec) &&
getRecGoodSkillByRec(myrec).length > 0 &&
getRecGoodSkillByRec(myrec)[0].descr
"
class="glossy"
dense
color="blue"
text-color="white"
>
<span>{{ getRecGoodSkillByRec(myrec)[0].descr }}</span>
</q-chip>
<div class="category-hierarchy">
<q-chip
v-for="(recSect, ind) of arrSector"
:key="'sec-' + ind"
class="tag-chip sector"
:style="{
background: `linear-gradient(135deg, ${recSect.color}, ${recSect.color})`,
}"
:color="recSect.color"
>
<q-icon
v-if="recSect.icon"
:name="recSect.icon"
size="xs"
class="q-mr-xs"
/>
{{ recSect.descr }}
</q-chip>
<q-icon
v-if="arrSubSector.length > 0"
name="chevron_right"
size="sm"
class="hierarchy-arrow"
/>
<q-chip
v-for="(rec, ind) of arrSubSector"
:key="'sub-' + ind"
class="tag-chip subsector"
:style="{
background: `linear-gradient(135deg, ${getColorSubSector}, ${getColorSubSector})`,
opacity: 0.8,
}"
:color="getColorSubSector"
>
<q-icon
v-if="rec.icon"
:name="rec.icon"
size="xs"
class="q-mr-xs"
/>
{{ rec.descr }}
</q-chip>
</div>
</q-item-label>
</q-item-section>
</q-item>
@@ -579,6 +624,7 @@
:rec="myrec"
:type="costanti.FieldType.multiselect"
:value="myrec.preferences"
size="md"
:options="
globalStore.getTableJoinByName(
toolsext.TABPREF,
@@ -589,7 +635,7 @@
"
:optval="fieldsTable.getKeyByTable(toolsext.TABPREF)"
:optlab="fieldsTable.getLabelByTable(toolsext.TABPREF)"
:opticon="fieldsTable.getIconByTable(toolsext.TABPREF)"
:dense="false"
></CMyChipList>
</q-item-label>
</q-item-section>
@@ -1041,7 +1087,9 @@
<span v-if="myrec.createdBy"
><br />{{ $t('services.createdBy') }}
<span class="text-bold"
><a :href="'my/' + myrec.createdBy">{{ myrec.createdBy }}</a></span
><a :href="'my/' + myrec.createdBy">{{
myrec.createdBy
}}</a></span
></span
>
</q-item-label>
@@ -1415,21 +1463,64 @@
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn
flat
:label="$t('dialog.sendmsg')"
color="primary"
@click="sendMsg(true)"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
></q-btn>
<q-btn
flat
:label="$t('dialog.sendmsg')"
color="primary"
@click="sendMsg(true)"
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>
<!-- Categories Dialog -->
<q-dialog v-model="showPreferencesDialog">
<q-card
class="categories-dialog"
:style="{ minWidth: $q.screen.lt.sm ? '90vw' : '400px' }"
>
<q-card-section class="dialog-header">
<div class="text-h6">Categorie</div>
</q-card-section>
<q-separator />
<q-card-section class="dialog-content">
<div class="categories-grid">
<q-chip
v-for="(rec, ind) of myrec.preferences"
:key="ind"
class="category-chip shadow-3"
:style="`background-color: ${tools.getPreferenceById(rec).color}; color: white;`"
>
<q-icon
:name="tools.getPreferenceById(rec).icon"
left
size="18px"
/>
{{ tools.getPreferenceById(rec).label }}
</q-chip>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
flat
label="Chiudi"
color="primary"
v-close-popup
/>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog
v-model="bookEventpage.show"
no-backdrop-dismiss
@@ -1504,6 +1595,12 @@
</div>
<q-card-actions align="right">
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
></q-btn>
<q-btn
v-if="bookEventpage.state === EState.Modifying"
flat
@@ -1525,13 +1622,6 @@
@click="saveBookEvent"
:disable="!(bookEventpage.state === EState.Creating || hasModifiedBooking)"
></q-btn>
<q-btn
flat
:label="$t('dialog.cancel')"
color="primary"
v-close-popup
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>

View File

@@ -1,80 +1,72 @@
// ========================================
// CMyChipList - SCSS Moderno con Gradienti
// CMyChipList - RISO Design System
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$secondary-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$info-color: #31ccec;
$warning-color: #f2c037;
.c-chiplist {
margin-bottom: $s-sm;
@use 'sass:color';
$border-radius-sm: 8px;
$border-radius: 10px;
$transition-speed: 0.3s;
$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
$mobile-breakpoint: 768px;
// ========================================
// CONTAINER
// ========================================
.q-mb-sm {
// Padding e margini ottimizzati
@media (max-width: $mobile-breakpoint) {
margin-bottom: 10px !important;
@media (max-width: $mobile) {
margin-bottom: $s-xs;
}
}
// ========================================
// LABEL/TITLE (con gradiente sottile)
// LABEL
// ========================================
.text-subtitle2 {
&.text-primary {
background: linear-gradient(135deg, $primary-color, color.adjust($primary-color, $lightness: 15%));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 600;
letter-spacing: 0.02em;
margin-bottom: 8px;
.c-chiplist__label {
font-size: 0.9125rem;
font-weight: 600;
color: $mainColor;
margin-bottom: $s-xs;
letter-spacing: 0.02em;
background: linear-gradient(135deg, $mainColor, lighten($mainColor, 12%));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
@media (max-width: $mobile-breakpoint) {
font-size: 0.875rem;
margin-bottom: 6px;
}
@media (max-width: $mobile) {
font-size: 0.85rem;
margin-bottom: 4px;
}
}
// ========================================
// CHIPS CONTAINER
// ========================================
.q-gutter-sm {
&.row.wrap {
gap: 8px;
.c-chiplist__chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
@media (max-width: $mobile-breakpoint) {
gap: 6px;
}
@media (max-width: $mobile) {
gap: 4px;
}
}
// ========================================
// SINGLE CHIP (con gradienti bellissimi!)
// SINGLE CHIP - RISO Style
// ========================================
.q-chip {
.c-chip {
position: relative;
overflow: hidden;
transition: all $transition-speed cubic-bezier(0.4, 0, 0.2, 1);
border-radius: $border-radius !important;
border-radius: 20px !important;
font-size: 0.9125rem;
font-weight: 500;
letter-spacing: 0.01em;
padding: 4px 10px !important;
height: auto !important;
min-height: 26px;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.08);
@media (max-width: $mobile) {
font-size: 0.85rem;
padding: 2px 4px !important;
min-height: 24px;
border-radius: 16px !important;
}
// Effetto luce scorrevole
// Gradiente di luce animato
&::before {
content: '';
position: absolute;
@@ -82,171 +74,255 @@ $mobile-breakpoint: 768px;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.25),
transparent
);
transition: left 0.5s ease;
}
// Shadow con gradiente
&.shadow-1 {
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
// Testo con ombra per leggibilità
&::v-deep(.q-chip__content) {
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
white-space: nowrap;
@media (max-width: $mobile) {
font-size: 0.75rem;
}
}
// Padding compatto
&.q-px-sm {
padding-left: 10px !important;
padding-right: 10px !important;
@media (max-width: $mobile-breakpoint) {
padding-left: 8px !important;
padding-right: 8px !important;
font-size: 0.8125rem !important;
// Icona
&::v-deep(.q-icon) {
font-size: 1rem;
margin-right: 4px;
transition: transform 0.25s ease;
@media (max-width: $mobile) {
font-size: 0.875rem;
margin-right: 3px;
}
}
// Hover effect
&:hover {
transform: translateY(-2px) scale(1.02);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
transform: translateY(-1px) scale(1.02);
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16), 0 2px 4px rgba(0, 0, 0, 0.12);
&::before {
left: 100%;
}
}
// Colori con gradienti
&[class*='bg-primary'],
&[class*='bg-blue'] {
background: linear-gradient(135deg, $primary-color, color.adjust($primary-color, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba($primary-color, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust($primary-color, $lightness: -5%), $primary-color) !important;
box-shadow: 0 4px 12px rgba($primary-color, 0.4);
&::v-deep(.q-icon) {
transform: scale(1.1) rotate(5deg);
}
}
&[class*='bg-secondary'],
&[class*='bg-teal'] {
background: linear-gradient(135deg, $secondary-color, color.adjust($secondary-color, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba($secondary-color, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust($secondary-color, $lightness: -5%), $secondary-color) !important;
box-shadow: 0 4px 12px rgba($secondary-color, 0.4);
}
}
&[class*='bg-positive'],
&[class*='bg-green'] {
background: linear-gradient(135deg, $positive-color, color.adjust($positive-color, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba($positive-color, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust($positive-color, $lightness: -5%), $positive-color) !important;
box-shadow: 0 4px 12px rgba($positive-color, 0.4);
}
}
&[class*='bg-negative'],
&[class*='bg-red'] {
background: linear-gradient(135deg, $negative-color, color.adjust($negative-color, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba($negative-color, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust($negative-color, $lightness: -5%), $negative-color) !important;
box-shadow: 0 4px 12px rgba($negative-color, 0.4);
}
}
&[class*='bg-warning'],
&[class*='bg-orange'],
&[class*='bg-amber'] {
background: linear-gradient(135deg, $warning-color, color.adjust($warning-color, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba($warning-color, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust($warning-color, $lightness: -5%), $warning-color) !important;
box-shadow: 0 4px 12px rgba($warning-color, 0.4);
}
}
&[class*='bg-info'],
&[class*='bg-cyan'] {
background: linear-gradient(135deg, $info-color, color.adjust($info-color, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba($info-color, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust($info-color, $lightness: -5%), $info-color) !important;
box-shadow: 0 4px 12px rgba($info-color, 0.4);
}
}
&[class*='bg-purple'] {
background: linear-gradient(135deg, #9c27b0, color.adjust(#9c27b0, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba(#9c27b0, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust(#9c27b0, $lightness: -5%), #9c27b0) !important;
box-shadow: 0 4px 12px rgba(#9c27b0, 0.4);
}
}
&[class*='bg-pink'] {
background: linear-gradient(135deg, #e91e63, color.adjust(#e91e63, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba(#e91e63, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust(#e91e63, $lightness: -5%), #e91e63) !important;
box-shadow: 0 4px 12px rgba(#e91e63, 0.4);
}
}
&[class*='bg-grey'],
&[class*='bg-gray'] {
background: linear-gradient(135deg, #757575, color.adjust(#757575, $lightness: 10%)) !important;
box-shadow: 0 2px 8px rgba(#757575, 0.3);
&:hover {
background: linear-gradient(135deg, color.adjust(#757575, $lightness: -5%), #757575) !important;
box-shadow: 0 4px 12px rgba(#757575, 0.4);
}
}
// Icon dentro il chip
.q-icon {
transition: transform $transition-speed ease;
}
&:hover .q-icon {
transform: scale(1.1) rotate(5deg);
}
// Text color bianco con ombra sottile per leggibilità
&[class*='text-white'] {
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}
}
// ========================================
// DENSE VARIANT
// ========================================
.q-chip--dense {
padding: 3px 8px !important;
font-size: 0.8125rem;
@media (max-width: $mobile-breakpoint) {
padding: 2px 6px !important;
// Dense variant
&.q-chip--dense {
padding: 3px 8px !important;
min-height: 24px;
font-size: 0.75rem;
@media (max-width: $mobile) {
padding: 2px 6px !important;
min-height: 22px;
font-size: 0.6875rem;
}
}
}
// ========================================
// ANIMATION
// SIZE VARIANTS
// ========================================
@keyframes chipAppear {
// Medium size
.c-chip--md {
font-size: 0.9375rem !important;
padding: 6px 14px !important;
min-height: 34px !important;
border-radius: 24px !important;
&::v-deep(.q-chip__content) {
font-size: 0.9375rem;
}
&::v-deep(.q-icon) {
font-size: 1.25rem !important;
margin-right: 6px;
}
@media (max-width: $mobile) {
font-size: 0.875rem !important;
padding: 5px 12px !important;
min-height: 32px !important;
border-radius: 20px !important;
&::v-deep(.q-chip__content) {
font-size: 0.875rem;
}
&::v-deep(.q-icon) {
font-size: 1.125rem !important;
margin-right: 5px;
}
}
}
// Large size
.c-chip--lg {
font-size: 1.0625rem !important;
padding: 8px 18px !important;
min-height: 42px !important;
border-radius: 28px !important;
font-weight: 600;
&::v-deep(.q-chip__content) {
font-size: 1.0625rem;
font-weight: 600;
}
&::v-deep(.q-icon) {
font-size: 1.5rem !important;
margin-right: 8px;
}
@media (max-width: $mobile) {
font-size: 1rem !important;
padding: 7px 16px !important;
min-height: 38px !important;
border-radius: 24px !important;
&::v-deep(.q-chip__content) {
font-size: 1rem;
}
&::v-deep(.q-icon) {
font-size: 1.375rem !important;
margin-right: 7px;
}
}
}
// ========================================
// GRADIENTI PER COLORI - RISO Style
// ========================================
// Blue/Primary
.c-chip.bg-blue,
.c-chip.bg-primary,
.c-chip.bg-indigo,
.c-chip.bg-light-blue {
background: linear-gradient(135deg, #1976d2, #42a5f5) !important;
&:hover {
background: linear-gradient(135deg, #1565c0, #1976d2) !important;
}
}
// Teal/Cyan
.c-chip.bg-teal,
.c-chip.bg-cyan {
background: linear-gradient(135deg, #00897b, #26a69a) !important;
&:hover {
background: linear-gradient(135deg, #00796b, #00897b) !important;
}
}
// Green
.c-chip.bg-green,
.c-chip.bg-light-green {
background: linear-gradient(135deg, #388e3c, #66bb6a) !important;
&:hover {
background: linear-gradient(135deg, #2e7d32, #388e3c) !important;
}
}
// Purple/Deep Purple
.c-chip.bg-purple,
.c-chip.bg-deep-purple {
background: linear-gradient(135deg, #7b1fa2, #9c27b0) !important;
&:hover {
background: linear-gradient(135deg, #6a1b9a, #7b1fa2) !important;
}
}
// Pink
.c-chip.bg-pink {
background: linear-gradient(135deg, #c2185b, #e91e63) !important;
&:hover {
background: linear-gradient(135deg, #ad1457, #c2185b) !important;
}
}
// Orange/Amber
.c-chip.bg-orange,
.c-chip.bg-amber,
.c-chip.bg-deep-orange {
background: linear-gradient(135deg, #f57c00, #ff9800) !important;
&:hover {
background: linear-gradient(135deg, #ef6c00, #f57c00) !important;
}
}
// Yellow/Lime
.c-chip.bg-yellow,
.c-chip.bg-lime {
background: linear-gradient(135deg, #f9a825, #fdd835) !important;
color: rgba(0, 0, 0, 0.87) !important;
&::v-deep(.q-chip__content) {
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
color: rgba(0, 0, 0, 0.87) !important;
}
&:hover {
background: linear-gradient(135deg, #f57f17, #f9a825) !important;
}
}
// Red/Negative
.c-chip.bg-red,
.c-chip.bg-negative {
background: linear-gradient(135deg, #c62828, #e53935) !important;
&:hover {
background: linear-gradient(135deg, #b71c1c, #c62828) !important;
}
}
// Brown
.c-chip.bg-brown {
background: linear-gradient(135deg, #5d4037, #6d4c41) !important;
&:hover {
background: linear-gradient(135deg, #4e342e, #5d4037) !important;
}
}
// Grey/Blue Grey
.c-chip.bg-grey,
.c-chip.bg-gray,
.c-chip.bg-blue-grey {
background: linear-gradient(135deg, #546e7a, #78909c) !important;
&:hover {
background: linear-gradient(135deg, #455a64, #546e7a) !important;
}
}
// ========================================
// ANIMAZIONE INGRESSO
// ========================================
@keyframes chipFadeIn {
from {
opacity: 0;
transform: scale(0.8) translateY(10px);
transform: scale(0.92) translateY(4px);
}
to {
opacity: 1;
@@ -254,29 +330,28 @@ $mobile-breakpoint: 768px;
}
}
.q-chip {
animation: chipAppear 0.3s ease-out;
animation-fill-mode: both;
.c-chip {
animation: chipFadeIn 0.25s ease-out backwards;
// Stagger animation per chip multipli
@for $i from 1 through 20 {
// Stagger per chip multipli
@for $i from 1 through 25 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
animation-delay: #{$i * 0.04}s;
}
}
}
// ========================================
// GLASSMORPHISM VARIANT (opzionale)
// RESPONSIVE TOUCH OPTIMIZATION
// ========================================
.q-chip.glass-effect {
background: rgba(255, 255, 255, 0.2) !important;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
&:hover {
background: rgba(255, 255, 255, 0.3) !important;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
@media (max-width: $mobile) {
.c-chip {
// Touch target più grande su mobile
min-height: 28px;
&:active {
transform: scale(0.96);
transition-duration: 0.1s;
}
}
}

View File

@@ -63,6 +63,12 @@ export default defineComponent({
required: false,
default: '',
},
size: {
type: String,
required: false,
default: 'sm',
validator: (value: string) => ['sm', 'md', 'lg'].includes(value),
},
},
components: {},
setup(props, { emit }) {
@@ -85,7 +91,7 @@ export default defineComponent({
// --- MULTISELECT: itera sulle selezioni, non sulle options ---
if (props.type === costanti.FieldType.multiselect) {
if (Array.isArray(myval.value) && myval.value.length) {
myval.value.forEach((recout, idx) => {
myval.value.forEach((recout: any, idx) => {
// valore "chiave" della selezione
const value =
props.type_out === costanti.FieldType.object
@@ -105,14 +111,14 @@ export default defineComponent({
recFromOptions || (typeof recout === 'object' ? recout : null);
const mydata = {
label: null,
label: '',
value,
valbool: true,
icon: '',
icon: baseRec?.icon || '',
// priorità: optcolor -> color su record -> fallback colore
color:
(props.optcolor && baseRec?.[props.optcolor]) ||
baseRec?.color ||
(props.optcolor && baseRec?.[props.optcolor]) ||
tools.getColorByIndexBest(idx),
};
@@ -146,17 +152,17 @@ export default defineComponent({
} else if (props.type === costanti.FieldType.select) {
// --- SELECT: itera sulle options e trova la corrispondenza ---
if (Array.isArray(props.options) && props.options.length) {
props.options.forEach((rec, index) => {
props.options.forEach((rec: any, index) => {
if (myval.value === rec?.[props.optval]) {
const mydata = {
value: myval.value,
valbool: true,
icon: '',
color:
(props.optcolor && rec?.[props.optcolor]) ||
rec?.color ||
(props.optcolor && rec?.[props.optcolor]) ||
tools.getColorByIndexBest(index),
label: null,
label: '',
};
if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon];
@@ -182,23 +188,26 @@ export default defineComponent({
} else {
// --- BITMASK (o altro tipo legacy): itera sulle options e verifica i bit attivi ---
if (Array.isArray(props.options) && props.options.length) {
props.options.forEach((rec, index) => {
props.options.forEach((rec: any, index) => {
const optVal = rec?.[props.optval];
if (optVal == null) return;
if (tools.isBitActive(myval.value, optVal)) {
const mydata = {
label: t(tools.getValueByFunzOrVal(rec, props.optlab)),
value: optVal,
valbool: true,
icon: '',
icon: tools.getValueByFunzOrVal(rec, 'icon') || '',
color:
rec.color ||
(props.optcolor && rec?.[props.optcolor]) ||
rec?.color ||
tools.getColorByIndexBest(index),
};
if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon];
if (rec[props.opticon]) {
if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon];
}
myarrvalues.value.push(mydata);
}
@@ -215,7 +224,7 @@ export default defineComponent({
label: props.rec?.[props.optlab],
value: 0,
valbool: true,
icon: '',
icon: props.rec?.icon || '',
color: tools.getColorByIndexBest(0),
};

View File

@@ -1,21 +1,18 @@
<template>
<div class="q-mb-sm">
<!-- Etichetta / Titolo -->
<div class="text-subtitle2 text-primary text-weight-medium q-mb-xs">
<div class="c-chiplist">
<div v-if="label" class="c-chiplist__label">
{{ label }}
</div>
<!-- Chips come valori -->
<div class="q-gutter-sm row wrap">
<div class="c-chiplist__chips">
<q-chip
v-for="(rec, index) in myarrvalues"
:key="index"
:dense="dense"
class="shadow-1 q-px-sm"
:color="rec.color || 'primary'"
:class="['c-chip', `c-chip--${size}`]"
:style="{ 'background-color': rec.color || 'var(--q-primary)' }"
text-color="white"
:icon="rec.icon || undefined"
style="border-radius: 10px;"
>
{{ rec.label }}
</q-chip>

View File

@@ -580,6 +580,12 @@
</div>
</q-card-section>
<q-card-actions align="center">
<q-btn
outline
:label="$t('dialog.cancel')"
icon="close"
v-close-popup
></q-btn>
<q-btn
class="centeritems q-ma-lg"
icon="fas fa-user-plus"
@@ -597,12 +603,6 @@
);
"
/>
<q-btn
outline
:label="$t('dialog.cancel')"
icon="close"
v-close-popup
></q-btn>
</q-card-actions>
</q-card>
</q-dialog>

View File

@@ -1,29 +1,3 @@
// ========================================
// CMyGroup - SCSS Moderno con Gradienti
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$primary-dark: #1565c0;
$secondary-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$info-color: #31ccec;
$warning-color: #f2c037;
@use 'sass:color';
$grey-text: #555;
$grey-light: #999;
$border-radius-sm: 8px;
$border-radius: 12px;
$transition-speed: 0.3s;
$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.15);
$mobile-breakpoint: 768px;
// Gradiente speciale per gruppi
$gradient-group-primary: linear-gradient(135deg, $secondary-color 0%, color.adjust($secondary-color, $lightness: 15%) 100%);

View File

@@ -1,23 +1,3 @@
// ========================================
// VARIABILI
// ========================================
$primary-color: #1976d2;
$positive-color: #21ba45;
$negative-color: #c10015;
$grey-color: #666;
$grey-light: #999;
$border-radius: 10px;
$border-radius-sm: 6px;
$transition-speed: 0.3s;
$shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06);
$shadow-md: 0 2px 6px rgba(0, 0, 0, 0.08);
$shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.12);
$mobile-breakpoint: 768px;
// ========================================
// WRAPPER CARD - ALTERNATING COLORS
// ========================================
@@ -269,10 +249,16 @@ $mobile-breakpoint: 768px;
.tags-row {
display: flex;
flex-direction: column;
flex-wrap: wrap;
gap: 3px;
margin-bottom: 3px;
align-items: center;
.status-row {
display: flex;
gap: $s-xs;
flex-wrap: wrap;
}
@media (max-width: $mobile-breakpoint) {
gap: 2px;
@@ -329,7 +315,8 @@ $mobile-breakpoint: 768px;
.description-text {
font-size: 0.9375rem;
color: #333;
color: #2c3e50;
font-weight: 500;
line-height: 1.4;
margin: 3px 0;
word-break: break-word;
@@ -345,54 +332,84 @@ $mobile-breakpoint: 768px;
}
}
// ========================================
// PREFERENCES ROW (dopo descrizione)
// ========================================
.preferences-row {
margin: 8px 0 6px 0;
@media (max-width: $mobile-breakpoint) {
margin: 6px 0 4px 0;
}
}
.preferences-icons-container {
display: flex;
flex-wrap: wrap;
gap: 6px;
align-items: center;
@media (max-width: $mobile-breakpoint) {
gap: 5px;
}
}
.preference-icon-avatar {
cursor: pointer;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
&:hover {
transform: translateY(-2px) scale(1.08);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.25);
}
@media (max-width: $mobile-breakpoint) {
width: 28px !important;
height: 28px !important;
.q-icon {
font-size: 16px !important;
}
}
}
.user-stats-row {
display: flex;
justify-content: space-between;
align-items: center;
margin: 3px 0;
font-size: 0.8125rem;
color: $grey-color;
align-items: flex-start;
gap: $s-sm;
flex-wrap: wrap;
@media (max-width: $mobile-breakpoint) {
font-size: 0.75rem;
margin: 2px 0;
.user-name {
flex: 1 1 auto;
min-width: 0;
color: $mainColor;
font-weight: 600;
font-size: 0.9rem;
@media (max-width: $mobile) {
font-size: 0.85rem;
}
}
}
.user-name {
font-weight: 600;
font-style: italic;
color: #333;
margin-right: 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.stats-container {
flex: 0 0 auto;
white-space: nowrap;
margin-left: auto;
font-size: 0.85rem;
@media (max-width: $mobile-breakpoint) {
margin-right: 5px;
}
}
@media (max-width: $mobile) {
font-size: 0.75rem;
.stats-container {
display: flex;
align-items: center;
gap: 5px;
flex-shrink: 0;
white-space: nowrap;
.stat-item {
margin-left: 4px;
@media (max-width: $mobile-breakpoint) {
gap: 4px;
}
}
.stat-item {
display: inline-flex;
align-items: center;
gap: 2px;
font-weight: 500;
.q-icon {
vertical-align: middle;
.q-icon {
font-size: 12px !important;
}
}
}
}
}
@@ -418,15 +435,14 @@ $mobile-breakpoint: 768px;
}
.cities-text {
font-size: 0.8125rem;
color: $grey-light;
color: rgba(44, 62, 80, 0.7); // Grigio bluastro più caldo del grigio puro
font-size: 0.85rem;
display: flex;
text-align: right;
margin-top: 2px;
overflow: hidden;
text-overflow: ellipsis;
gap: 4px;
@media (max-width: $mobile-breakpoint) {
font-size: 0.75rem;
i {
color: rgba($mainColor, 0.6); // Icona location con colore primario attenuato
}
}
@@ -526,4 +542,27 @@ $mobile-breakpoint: 768px;
gap: 0px;
}
}
.categories-dialog {
.dialog-header {
padding: 16px 20px;
}
.dialog-content {
padding: 20px;
max-height: 60vh;
overflow-y: auto;
}
.categories-grid {
display: flex;
flex-wrap: wrap;
gap: 2px;
}
.category-chip {
font-size: 1.1rem;
padding: 8px 12px;
font-weight: 500;
}
}

View File

@@ -55,18 +55,23 @@ export default defineComponent({
const $router = useRouter();
const myrec = ref(<any>null);
const showPreferencesDialog = ref(false);
const visupage = ref(false);
const disabilita = computed(() => {
return props.table === shared_consts.TABLES_MYBACHECAS;
});
const arrSubSector = computed(() => {
return tools.getArrSubSector(props.table, myrec.value)
return tools.getArrSubSector(props.table, myrec.value);
});
const arrSector = computed(() => {
return tools.getArrSector(props.table, myrec.value)
return tools.getArrSector(props.table, myrec.value);
});
const getColorSubSector = computed(() => {
return arrSector.value && arrSector.value.length == 1 ? arrSector.value[0].color : 'primary'
})
watch(
() => props.prop_myrec,
(newval, oldval) => {
@@ -132,7 +137,12 @@ export default defineComponent({
function computedWidth() {
//const width = tools.getwidth($q) - 20;
//return `${Math.min(width, 600)}px`; // Limita la larghezza massima a 600px
return '100%'; // Rimuovi la limitazione a 600px
const width = tools.getwidth($q);
// Limita la larghezza per evitare overflow
return `${Math.min(width - 40, 600)}px`;
//return '100%'; // Rimuovi la limitazione a 600px
}
function computedEventImageHeight() {
@@ -176,6 +186,8 @@ export default defineComponent({
computedEventImageHeight,
arrSubSector,
arrSector,
getColorSubSector,
showPreferencesDialog,
};
},
});

View File

@@ -121,7 +121,6 @@
/>
</q-avatar>
</q-item-section>
<q-item-section
v-else-if="!myrec.organisedBy && table !== shared_consts.TABLES_MYBACHECAS"
avatar
@@ -155,20 +154,21 @@
<q-item-label class="tags-row">
<div class="category-hierarchy">
<q-chip
v-for="(rec, ind) of arrSector"
v-for="(recSect, ind) of arrSector"
:key="'sec-' + ind"
class="tag-chip sector"
:style="{
background: `linear-gradient(135deg, ${rec.color}, ${rec.color})`,
background: `linear-gradient(135deg, ${recSect.color}, ${recSect.color})`,
}"
:color="recSect.color"
>
<q-icon
v-if="rec.icon"
:name="rec.icon"
v-if="recSect.icon"
:name="recSect.icon"
size="xs"
class="q-mr-xs"
/>
{{ rec.descr }}
{{ recSect.descr }}
</q-chip>
<q-icon
v-if="arrSubSector.length > 0"
@@ -181,9 +181,10 @@
:key="'sub-' + ind"
class="tag-chip subsector"
:style="{
background: `linear-gradient(135deg, ${rec.color}, ${rec.color})`,
background: `linear-gradient(135deg, ${getColorSubSector}, ${getColorSubSector})`,
opacity: 0.8,
}"
:color="getColorSubSector"
>
<q-icon
v-if="rec.icon"
@@ -194,23 +195,25 @@
{{ rec.descr }}
</q-chip>
</div>
<template v-for="(recstatus, index) in myrec.idStatusSkill">
<q-badge
v-if="
recstatus === shared_consts.STATUSSKILL_ONLINE ||
myrec.idStatusSkill?.length > 1
"
:key="'stat-' + index"
:color="globalStore.getColByStatusSkills(recstatus)"
class="status-badge"
>
<q-icon
:name="globalStore.getStatusSkillIconById(recstatus)"
size="14px"
/>
{{ globalStore.getStatusSkillById(recstatus) }}
</q-badge>
</template>
<div class="status-row">
<div v-for="(recstatus, index) in myrec.idStatusSkill">
<q-badge
v-if="
recstatus === shared_consts.STATUSSKILL_ONLINE ||
myrec.idStatusSkill?.length > 1
"
:key="'stat-' + index"
:color="globalStore.getColByStatusSkills(recstatus)"
class="status-badge"
>
<q-icon
:name="globalStore.getStatusSkillIconById(recstatus)"
size="14px"
/>
{{ globalStore.getStatusSkillById(recstatus) }}
</q-badge>
</div>
</div>
</q-item-label>
<!-- Descrizione -->
@@ -225,6 +228,30 @@
{{ myrec.descr }}
</q-item-label>
<!-- Preferences (solo per MYHOSPS) -->
<q-item-label
v-if="table === shared_consts.TABLES_MYHOSPS && myrec.preferences && myrec.preferences.length > 0"
class="preferences-row"
>
<div class="preferences-icons-container">
<q-avatar
v-for="(prefId, ind) of myrec.preferences"
:key="ind"
size="32px"
:style="`background-color: ${tools.getPreferenceById(prefId)?.color || 'grey'}; cursor: pointer;`"
class="preference-icon-avatar"
@click.stop="showPreferencesDialog = true"
>
<q-icon
:name="tools.getPreferenceById(prefId)?.icon || 'help'"
size="18px"
color="white"
/>
<q-tooltip>{{ tools.getPreferenceById(prefId)?.label }}</q-tooltip>
</q-avatar>
</div>
</q-item-label>
<!-- Info Utente e Stats -->
<q-item-label class="user-stats-row">
<div class="user-name">
@@ -364,6 +391,49 @@
</q-item>
<q-separator />
</div>
<!-- Categories Dialog -->
<q-dialog v-model="showPreferencesDialog">
<q-card
class="categories-dialog"
:style="{ minWidth: $q.screen.lt.sm ? '90vw' : '400px' }"
>
<q-card-section class="dialog-header">
<div class="text-h6">Categorie</div>
</q-card-section>
<q-separator />
<q-card-section class="dialog-content">
<div class="categories-grid">
<q-chip
v-for="(rec, ind) of myrec.preferences"
:key="ind"
class="category-chip shadow-3"
:style="`background-color: ${tools.getPreferenceById(rec).color}; color: white;`"
>
<q-icon
:name="tools.getPreferenceById(rec).icon"
left
size="18px"
/>
{{ tools.getPreferenceById(rec).label }}
</q-chip>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
flat
label="Chiudi"
color="primary"
v-close-popup
/>
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script lang="ts" src="./CMyRecCard.ts"></script>

View File

@@ -45,13 +45,13 @@
>
Clicca qui per cercarlo su GM
</span>
<span v-else>
Testo non trovato: '{{ mystr }}'
</span>
<span v-else> Testo non trovato: '{{ mystr }}' </span>
</q-item-section>
</q-item>
<q-item v-else>
<q-item-section class="text-grey"> Digita il testo da cercare </q-item-section>
<q-item-section class="text-grey">
Digita il testo da cercare
</q-item-section>
</q-item>
</template>
@@ -80,7 +80,9 @@
<template v-slot:option="{ itemProps, opt, selected, toggleOption }">
<q-item v-bind="itemProps">
<q-item-section>
<q-item-label>{{ opt[fieldsTable.getLabelByTable(tablesel)] }}</q-item-label>
<q-item-label>{{
opt[fieldsTable.getLabelByTable(tablesel)]
}}</q-item-label>
</q-item-section>
<q-item-section side>
<q-toggle
@@ -137,20 +139,19 @@
>
Clicca qui per cercarlo su GM
</span>
<span v-else>
Testo non trovato: '{{ mystr }}'
</span>
<span v-else> Testo non trovato: '{{ mystr }}' </span>
</q-item-section>
</q-item>
<q-item v-else>
<q-item-section class="text-grey"> Digita il testo da cercare </q-item-section>
<q-item-section class="text-grey">
Digita il testo da cercare
</q-item-section>
</q-item>
</template>
<template v-slot:option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section :class="applyLabelColorBasedOnProductStatus(scope.opt)">
<q-item-label >
<q-item-label>
{{ tools.getValueByFunzOrVal(scope.opt, optlab) }}
</q-item-label>
</q-item-section>
@@ -183,8 +184,6 @@
:option-label="optlab"
:dense="dense"
>
<!--options-selected-class="text-deep-blue"-->
<template
v-if="getIcon()"
v-slot:prepend
@@ -198,15 +197,13 @@
dense
@remove="scope.removeAtIndex(scope.index)"
v-if="checkIfShowRec(scope.opt)"
:color="$q.dark.isActive ? `black` : `white`"
:style="`background-color: ${scope.opt.color || ($q.dark.isActive ? `black` : `white`) }`"
:text-color="
scope.opt.color ? 'white' : $q.dark.isActive ? `white` : `black`
"
:icon="scope.opt.icon || undefined"
class="q-my-none q-ml-xs q-mr-none"
>
<q-avatar
color="primary"
text-color="white"
:icon="scope.opt.icon ? scope.opt.icon : ''"
size="12px"
/>
{{ tools.getValueByFunzOrVal(scope.opt, optlab) }}
</q-chip>
</div>
@@ -216,6 +213,12 @@
v-slot:option="{ itemProps, opt, selected, toggleOption }"
>
<q-item v-bind="itemProps">
<q-item-section avatar>
<q-icon
:name="opt.icon || ''"
:style="`background-color: ${opt.color || 'var(--q-primary)'}`"
/>
</q-item-section>
<q-item-section>
<q-item-label>{{ tools.getValueByFunzOrVal(opt, optlab) }}</q-item-label>
<q-item-label
@@ -270,7 +273,9 @@
<q-icon :name="scope.opt.icon ? scope.opt.icon : ''" />
</q-item-section>
<q-item-section>
<q-item-label>{{ tools.getValueByFunzOrVal(scope.opt, optlab) }}</q-item-label>
<q-item-label>{{
tools.getValueByFunzOrVal(scope.opt, optlab)
}}</q-item-label>
<q-item-label
v-if="'hint' in scope.opt"
class="hint"

View File

@@ -1,30 +1,3 @@
// ========================================
// CMyUser - SCSS Moderno con Gradienti
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$primary-dark: #1565c0;
$secondary-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$info-color: #31ccec;
$warning-color: #f2c037;
@use 'sass:color';
$grey-text: #555;
$grey-light: #999;
$border-radius-sm: 8px;
$border-radius: 12px;
$transition-speed: 0.3s;
$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
$shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
$shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.15);
$mobile-breakpoint: 768px;
// ========================================
// Q-ITEM CONTAINER (con gradiente)
// ========================================

View File

@@ -1,24 +1,3 @@
// ========================================
// VARIABILI (Sincronizzate con CSignUp)
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$primary-dark: #1565c0;
$accent-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$info-color: #31ccec;
$border-radius: 16px;
$border-radius-sm: 12px;
$border-radius-lg: 24px;
$transition-speed: 0.3s;
$shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
$shadow-md: 0 4px 16px rgba(0, 0, 0, 0.12);
$shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.16);
$mobile-breakpoint: 768px;
// ========================================
// CONTAINER PRINCIPALE

View File

@@ -1,24 +1,3 @@
// ========================================
// VARIABILI (Sincronizzate con CSignUp)
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$primary-dark: #1565c0;
$accent-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$border-radius: 16px;
$border-radius-sm: 12px;
$border-radius-lg: 24px;
$transition-speed: 0.3s;
$shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
$shadow-md: 0 4px 16px rgba(0, 0, 0, 0.12);
$shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.16);
$mobile-breakpoint: 768px;
// ========================================
// CONTAINER PRINCIPALE
// ========================================

View File

@@ -1,27 +1,3 @@
// ========================================
// VARIABILI E CONFIGURAZIONE
// ========================================
$primary-color: #1976d2;
$primary-light: #42a5f5;
$primary-dark: #1565c0;
$accent-color: #26a69a;
$positive-color: #21ba45;
$negative-color: #c10015;
$warning-color: #f2c037;
@use 'sass:color';
$border-radius: 16px;
$border-radius-sm: 12px;
$border-radius-lg: 24px;
$transition-speed: 0.3s;
$shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
$shadow-md: 0 4px 16px rgba(0, 0, 0, 0.12);
$shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.16);
$mobile-breakpoint: 768px;
$mobile-footer-height: 80px;
// ========================================
// CONTAINER PRINCIPALE