AITools prime cose

This commit is contained in:
Surya Paolo
2024-01-30 14:00:48 +01:00
parent 8a5a2bd79a
commit 74d1bf356f
97 changed files with 3832 additions and 223 deletions

View File

@@ -146,6 +146,8 @@ export const shared_consts = {
PROFILETUTORIAL: 280,
VISUVIDEOPROMOANDPDF: 290,
ECOMMERCE: 300,
CATALOGO: 310,
TOOLSAI: 320,
},
QUERYTYPE_MYGROUP: 1,
@@ -342,6 +344,7 @@ export const shared_consts = {
CAT_NO_SPAZI: 5,
CAT_GOODS_TXT: 10,
PRODUCTS: 20,
INVENTARIO: 30,
},
BotType: [
@@ -1677,6 +1680,10 @@ export const shared_consts = {
value: 300,
label: 'E-COMMERCE',
},
{
value: 310,
label: 'CATALOGO',
},
],

View File

@@ -0,0 +1,78 @@
.colmodif {
cursor: pointer;
}
.coldate {
max-width: 250px;
min-width: 200px;
}
.tdclass, .trclass{
min-height: 20px !important;
margin-top: 5px;
}
.q-table td {
padding-left: 1px;
padding-right: 2px;
padding-top: 0;
padding-bottom: 0;
&__title {
font-size: 1rem;
}
}
.q-table {
&__col {
font-size: 1rem;
color: gray;
}
}
.newrec_fields{
display: flex;
padding: 2px;
margin: 2px;
align-items: center;
justify-content: center;
}
.riduci_pad {
min-height: 30px;
padding: 4px 8px !important;
}
.q-table__top{
padding-top: 0 !important;
}
.barselection {
padding: 0;
flex-wrap: nowrap;
display: flex;
align-items: center;
justify-content: space-between;
}
.myitem {
padding: 0px 0px 0px 0px !important;
}
.myitem-0 {
flex-grow: 0;
padding-left: 2px;
}
.myitem-1 {
flex-grow: 0;
}
.myitem-2 {
flex-grow: 0;
}
.myitem-3 {
flex-grow: 1;
}

View File

@@ -0,0 +1,46 @@
import { defineComponent, ref, onMounted, computed } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { tools } from '../../store/Modules/tools'
import { shared_consts } from '@/common/shared_vuejs'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { costanti } from '@costanti'
import { useRouter } from 'vue-router'
export default defineComponent({
name: 'CAITools',
props: {
},
components: {
},
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const isfinishLoading = computed(() => globalStore.finishLoading)
const $router = useRouter()
const querySel = ref('')
function mount() {
// Mount
}
onMounted(mount)
return {
t,
querySel,
$q,
globalStore,
}
}
})

View File

@@ -0,0 +1,20 @@
<template>
<div>
<q-select
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
outlined
v-model="querySel"
:options="globalStore.getQueryAI()"
:label="t('ai.selectquery') + `:`"
emit-value
map-options
>
</q-select>
</div>
</template>
<script lang="ts" src="./CAITools.ts">
</script>
<style lang="scss">
@import './CAITools.scss';
</style>

View File

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

View File

View File

@@ -0,0 +1,8 @@
import { defineComponent } from 'vue'
import { Catalogo } from '@src/views/ecommerce'
export default defineComponent({
name: 'CCatalogo',
components: { Catalogo },
})

View File

@@ -0,0 +1,14 @@
<template>
<div>
<Catalogo>
</Catalogo>
</div>
</template>
<script lang="ts" src="./CCatalogo.ts">
</script>
<style lang="scss" scoped>
@import './CCatalogo.scss';
</style>

View File

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

View File

@@ -14,6 +14,8 @@ import { shared_consts } from '@/common/shared_vuejs'
import { LandingFooter } from '@/components/LandingFooter'
import { CMyActivities } from '@/components/CMyActivities'
import { CECommerce } from '@/components/CECommerce'
import { CAITools } from '@/components/CAITools'
import { CCatalogo } from '@/components/CCatalogo'
import { COpenStreetMap } from '@src/components/COpenStreetMap'
import { CCardCarousel } from '@src/components/CCardCarousel'
import { CMyPage } from '@src/components/CMyPage'
@@ -54,7 +56,7 @@ export default defineComponent({
CPresentazione, CMyActivities,
CMyProfileTutorial, CSendRISTo,
CTitleBanner, CShareSocial, CCheckAppRunning, CRegistration,
CVisuVideoPromoAndPDF, CECommerce,
CVisuVideoPromoAndPDF, CECommerce, CCatalogo, CAITools,
},
emits: ['selElemClick'],
props: {

View File

@@ -531,7 +531,15 @@
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.ECOMMERCE">
<div v-if="editOn" class="elemEdit">PRODOTTI ECOMMERCE:</div>
<CECommerce> </CECommerce>
<CECommerce></CECommerce>
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.CATALOGO">
<div v-if="editOn" class="elemEdit">PRODOTTI CATALOGO:</div>
<CCatalogo> </CCatalogo>
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.TOOLSAI">
<div v-if="editOn" class="elemEdit">STRUMENTI AI:</div>
<CAITools></CAITools>
</div>
<div v-else-if="myel.type === shared_consts.ELEMTYPE.NOTIFATTOP">
<div v-if="editOn" class="elemEdit">Notifiche in Cima</div>

View File

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

View File

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

View File

@@ -1,9 +1,9 @@
const msg_website_it = {
ws: {
sitename: 'Più che Buono',
siteshortname: 'Più che Buono',
description: '',
keywords: '',
sitename: 'Riso',
siteshortname: 'RISO',
description: 'Siamo la Rete Italiana di Scambio Orizzontale, abbiamo creato questa piattaforma per metterla al servizio di chi vuole riscoprire il valore della condivisione e della cooperazione. Valori semplici e profondi che ci aiutano a ritrovare il Senso della Vita, perduto in questa società consumista, e riporti quei Sani Pricìpi Naturali ed Umani di Fratellanza che intere popolazioni antiche conoscevano bene.',
keywords: 'riso, piattaforma di scambio, rete italiana scambio orizzontale, riso app, riso piattaforma, scambio e baratto, momenta RIS',
},
hours: {
descr: 'Descrizione',
@@ -16,7 +16,6 @@ const msg_website_it = {
pages: {
home: 'Home',
profile: 'Profilo',
install_site: 'Installa Sito',
profile2: 'ProfiloU',
mypage2: 'mypage2',
myservice2: 'myservice2',
@@ -31,18 +30,9 @@ const msg_website_it = {
producer: 'Produttore',
orderinfo: 'Ordini Effettuati',
products: 'Prodotti',
cash: 'Cassa',
productInfos: 'Info Prodotti',
listinoprodotti: 'Listino Prodotti',
productslist: 'Lista Prodotti',
collabora: 'Collabora',
categories: 'Categorie',
storehouses: 'Magazzino',
providers: 'Fornitori',
catprods: 'Categorie',
subcatprods: 'Sotto-Categorie',
gasordine: 'Gas Ordine',
scontisticas: 'Scontistica',
departments: 'Uffici',
orders: 'Ordini Ricevuti',
orders2: 'Ordini Ricevuti',
@@ -131,10 +121,9 @@ const msg_website_it = {
only_residenti: 'Solo Residenti',
only_consiglio: 'Solo Consiglieri',
color: 'Colore',
gasordini: 'Gas Ordini',
},
msg: {
myAppName: 'Più che Buono',
myAppName: 'Riso',
myAppDescription: 'Il primo Vero Social Libero, Equo e Solidale, dove Vive Consapevolezza e Aiuto Comunitario. Gratuito',
underconstruction: 'App in costruzione...',
myDescriz: '',

View File

@@ -7,6 +7,30 @@ import {
import { func } from '@store/Modules/fieldsTable'
// const SHOW_PROJINTHEMENU = false
//
// let arrlistafavourite = []
// let arrlistaprojtutti = []
// let arrlistaprojmiei = []
// if (SHOW_PROJINTHEMENU) {
// arrlistaprojtutti = Projects.getters.listaprojects(RouteNames.projectsall)
// arrlistaprojmiei = Projects.getters.listaprojects(RouteNames.myprojects)
// arrlistafavourite = Projects.getters.listaprojects(RouteNames.favouriteprojects)
// }
// PROGETTI -> FAVORITI :
// if (arrlistafavourite.length > 0) {
// arrMenu.push({
// icon: 'favorite_border',
// nametranslate: 'pages.' + RouteNames.favouriteprojects,
// urlroute: RouteNames.favouriteprojects,
// level_parent: 0.0,
// level_child: 0.5,
// routes2: arrlistafavourite,
// idelem: ''
// })
// }
const firstPage = {
active: true,
order: 5,
@@ -33,57 +57,56 @@ function getDynamicPages(site: ISites): IListRoutes[] {
inmenu: true,
infooter: true,
},
/*{
active: true,
order: 20,
path: '/events',
materialIcon: 'fas fa-bullhorn',
name: 'mypages.events',
component: () => import('@/root/eventi/eventi.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},*/
{
active: site.confpages && site.confpages.showProfile,
order: 120,
path: '/myprofile',
materialIcon: 'fas fa-user',
name: 'pages.profile',
component: () => import('@/views/user/myprofile/myprofile.vue'),
active: true,
order: 400,
path: '/test',
materialIcon: 'fas fa-test',
name: 'mypages.test',
component: () => import('@/views/testServer/testServer.vue'),
inmenu: false,
infooter: false,
},
{
active: true,
order: 12,
path: '/goods',
materialIcon: 'fas fa-tshirt',
name: 'mypages.goods',
component: () => import('@/root/goods/goods.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true,
order: 120,
path: '/install_site',
materialIcon: 'fas fa-user',
name: 'pages.install_site',
component: () => import('@/views/admin/install_site/install_site.vue'),
order: 15,
path: '/services',
materialIcon: 'fas fa-house-user',
name: 'mypages.services',
component: () => import('@/root/services/services.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true,
order: 15,
path: '/provapao',
materialIcon: 'fas fa-house-user',
name: 'mypages.provapao',
component: () => import('@/root/provapao/provapao.vue'),
meta: { requiresAuth: true },
inmenu: false,
infooter: false,
},
{
active: site.confpages && site.confpages.showProfile,
order: 120,
path: '/editprofile',
materialIcon: 'fas fa-user',
name: 'pages.profile3',
component: () => import('@/views/user/editprofile/editprofile.vue'),
meta: { requiresAuth: true },
inmenu: false,
infooter: false,
},
{
active: site.confpages && site.confpages.showiscrittiMenu,
order: 130,
path: '/friends',
materialIcon: 'fas fa-user-friends',
name: 'mypages.iscritti',
component: () => import('@/views/user/myfriends/myfriends.vue'),
active: true,
order: 15,
path: '/hosps',
materialIcon: 'fas fa-bed',
name: 'mypages.hosp',
component: () => import('@/root/hosp/hosp.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
@@ -98,8 +121,50 @@ function getDynamicPages(site: ISites): IListRoutes[] {
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
onlyAdmin: true,
onlyManager: true,
},
{
active: true,
order: 20,
path: '/events',
materialIcon: 'fas fa-bullhorn',
name: 'mypages.events',
component: () => import('@/root/eventi/eventi.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true,
order: 120,
path: '/myprofile',
materialIcon: 'fas fa-user',
name: 'pages.profile',
component: () => import('@/views/user/myprofile/myprofile.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: true,
order: 120,
path: '/editprofile',
materialIcon: 'fas fa-user',
name: 'pages.profile3',
component: () => import('@/views/user/editprofile/editprofile.vue'),
meta: { requiresAuth: true },
inmenu: false,
infooter: false,
},
{
active: true,
order: 130,
path: '/friends',
materialIcon: 'fas fa-user-friends',
name: 'mypages.iscritti',
component: () => import('@/views/user/myfriends/myfriends.vue'),
meta: { requiresAuth: true },
inmenu: true,
infooter: true,
},
{
active: site.confpages && site.confpages.enableGroups,
@@ -111,8 +176,6 @@ function getDynamicPages(site: ISites): IListRoutes[] {
meta: { requiresAuth: true },
inmenu: true,
infooter: false,
onlyAdmin: true,
onlyManager: true,
},
{
active: true,

View File

@@ -1,7 +1,7 @@
import { IAction } from '@src/model/Projects'
import { IFriends, IGroupShort, IMyGroup, IPaymentType } from '@src/model/UserStore'
import {
IDepartment, IProducer, IShareWithUs, IStorehouse, IProductInfo, IProvider, IScontistica, ICategory, IGasordine, ICatProd, ISubCatProd
IDepartment, IQueryAI, IProducer, IShareWithUs, IStorehouse, IProductInfo, IProvider, IScontistica, ICategory, IGasordine, ICatProd, ISubCatProd, ICatAI
} from '@src/model/Products'
import { IUserFields, IUserProfile } from '@src/model/UserStore'
@@ -240,6 +240,7 @@ export interface IConfPages {
showConnected: boolean
bookingEvents: boolean
enableEcommerce: boolean
enableAI: boolean
enableGroups: boolean
enableCircuits: boolean
enableProj: boolean
@@ -475,6 +476,8 @@ export interface IGlobalState {
sectors: ISector[],
sectorgoods: ISectorGood[],
catgrps: ICatGrp[],
catAI: ICatAI[],
queryAIList: IQueryAI[],
provinces: IProvince[],
datastat?: INotData
site: ISites,

View File

@@ -139,6 +139,22 @@ export interface ICatProd {
color?: string,
}
export interface ICatAI {
_id?: any
name: string,
img?: string,
icon?: string,
color?: string,
}
export interface IQueryAI {
_id?: any
name: string,
img?: string,
icon?: string,
color?: string,
}
export interface ISubCatProd {
_id?: any
idCatProd: string

View File

View File

@@ -0,0 +1,24 @@
import { defineComponent } from 'vue'
import { CImgText } from '../../../components/CImgText/index'
import { CCard } from '@/components/CCard'
import { CMyPage } from '@/components/CMyPage'
import { CTitleBanner } from '@/components/CTitleBanner'
import { CGridTableRec } from '@/components/CGridTableRec'
import { colTableCatAI } from '@src/store/Modules/fieldsTable'
import MixinMetaTags from '@/mixins/mixin-metatags'
export default defineComponent({
name: 'CatAIPage',
components: { CImgText, CCard, CMyPage, CTitleBanner, CGridTableRec },
setup() {
const { setmeta } = MixinMetaTags()
return {
colTableCatAI,
setmeta,
}
}
})

View File

@@ -0,0 +1,31 @@
<template>
<CMyPage title="Categorie AI" imgbackground="images/produttori.jpg" sizes="max-height: 120px">
<span>{{
setmeta({
title: 'Categorie AI',
description: '',
keywords: '',
})
}}
</span>
<div class="q-ma-sm q-gutter-sm q-pa-xs">
<CTitleBanner title="Categorie AI"></CTitleBanner>
<CGridTableRec
prop_mytable="catais"
prop_mytitle="Categorie AI"
:prop_mycolumns="colTableCatAI"
prop_colkey="name"
nodataLabel="Nessuna Categoria AI"
noresultLabel="Il filtro selezionato non ha trovato nessun risultato">
</CGridTableRec>
</div>
</CMyPage>
</template>
<script lang="ts" src="./catAI.ts">
</script>
<style lang="scss" scoped>
@import 'catAI.scss';
</style>

View File

@@ -563,6 +563,16 @@
:type="costanti.FieldType.boolean"
>
</CMyFieldDb>
<CMyFieldDb
table="sites"
:title="$t('confpages.enableAI')"
:id="mysite._id"
:rec="mysite"
mykey="confpages"
mysubkey="enableAI"
:type="costanti.FieldType.boolean"
>
</CMyFieldDb>
<CMyFieldDb
table="sites"
:title="$t('confpages.enableGroups')"

View File

@@ -46,6 +46,10 @@ export default defineComponent({
label: 'Importa Prodotti',
value: shared_consts.Cmd.PRODUCTS
},
{
label: 'Importa Inventario',
value: shared_consts.Cmd.INVENTARIO
},
{
label: 'Importa Province',
value: shared_consts.Cmd.PROVINCE
@@ -368,6 +372,13 @@ export default defineComponent({
let ind = 1
let primo = true
let arrCols: any = []
if (skipfirstrow.value) {
arrCols = myarr[0].split(',');
}
console.log('arrCols', arrCols)
for (const rec of myarr) {
if (skipfirstrow.value) {
@@ -418,8 +429,8 @@ export default defineComponent({
strris += addfield(col, 'price_acquistato', rec, { isnumero: true }); col++;
strris += addfield(col, 'minBuyQty', rec, { isnumero: true }); col++;
strris += addfield(col, 'minStepQty', rec, { isnumero: true }); col++;
strris += addfield(col, 'cat_name', rec,{}); col++;
strris += addfield(col, 'subcat_name', rec,{}); col++;
strris += addfield(col, 'cat_name', rec, {}); col++;
strris += addfield(col, 'subcat_name', rec, {}); col++;
strris += addfield(col, 'producer_name', rec, {}); col++;
strris += addfield(col, 'provider_name', rec, {}); col++;
strris += addfield(col, 'magazzino_name', rec, {}); col++;
@@ -431,6 +442,18 @@ export default defineComponent({
strris += addfield(col, 'note', rec, {}); col++;
strris += '} '
} else if (cmd === shared_consts.Cmd.INVENTARIO) {
if (!primo) {
strris += ', '
}
strris += '{ '
let col = 0;
strris += addfield(col, 'idapp', rec, { strinput: tools.appid(), primo: true });
for (const mycol of arrCols) {
strris += addfield(col, mycol, rec, {}); col++;
}
} else if (cmd === shared_consts.Cmd.CITIES_SERVER) {
strris += '{ \n'
strris += ' _id :' + ind + ',\n'
@@ -487,6 +510,11 @@ export default defineComponent({
userStore.importToServerCmd($q, t, cosafare.value, { arrdata: risultato.value, options })
}
function eseguiCmdInventario() {
let options = { aggiornaStockQty: checkAggiornaQta.value }
userStore.importToServerCmd($q, t, cosafare.value, { arrdata: risultato.value, options })
}
function createProvLink() {
let str = ''
@@ -531,6 +559,7 @@ export default defineComponent({
skipfirstrow,
eseguiCmdProduct,
checkAggiornaQta,
eseguiCmdInventario,
}
}
})

View File

@@ -17,7 +17,8 @@
<br>
<q-btn v-if="cosafare !== shared_consts.Cmd.PRODUCTS" label="Esegui" @click="eseguiCmd"></q-btn>
<q-btn v-else label="Importa Prodotti" @click="eseguiCmdProduct"></q-btn>
<q-btn v-else-if="cosafare === shared_consts.Cmd.PRODUCTS" label="Importa Prodotti" @click="eseguiCmdProduct"></q-btn>
<q-btn v-else-if="cosafare === shared_consts.Cmd.INVENTARIO" label="Importa Inventario" @click="eseguiCmdInventario"></q-btn>
<br>
<q-btn label="Genera HTML Province Territoriali" @click="createProvLink"></q-btn>

View File

View File

@@ -0,0 +1,24 @@
import { defineComponent } from 'vue'
import { CImgText } from '../../../components/CImgText/index'
import { CCard } from '@/components/CCard'
import { CMyPage } from '@/components/CMyPage'
import { CTitleBanner } from '@/components/CTitleBanner'
import { CGridTableRec } from '@/components/CGridTableRec'
import { colTableCatAI } from '@src/store/Modules/fieldsTable'
import MixinMetaTags from '@/mixins/mixin-metatags'
export default defineComponent({
name: 'CatAIPage',
components: { CImgText, CCard, CMyPage, CTitleBanner, CGridTableRec },
setup() {
const { setmeta } = MixinMetaTags()
return {
colTableCatAI,
setmeta,
}
}
})

View File

@@ -0,0 +1,31 @@
<template>
<CMyPage title="Query AI" imgbackground="images/queryai.jpg" sizes="max-height: 120px">
<span>{{
setmeta({
title: 'Query AI',
description: '',
keywords: '',
})
}}
</span>
<div class="q-ma-sm q-gutter-sm q-pa-xs">
<CTitleBanner title="Query AI"></CTitleBanner>
<CGridTableRec
prop_mytable="queryais"
prop_mytitle="Query AI"
:prop_mycolumns="colTableCatAI"
prop_colkey="name"
nodataLabel="Nessuna Query AI"
noresultLabel="Il filtro selezionato non ha trovato nessun risultato">
</CGridTableRec>
</div>
</CMyPage>
</template>
<script lang="ts" src="./queryAI.ts">
</script>
<style lang="scss" scoped>
@import 'queryAI.scss';
</style>

View File

@@ -9,4 +9,5 @@ export const RouteNames = {
listprojects: 'listproj',
livelli: 'livelli',
ecommerce: 'ecommerce',
toolsAI: 'strumentiAI',
}

90
src/router/routesAI.ts Normal file
View File

@@ -0,0 +1,90 @@
import { IListRoutes, ISites } from '@src/model'
function getRoutesAI(site: ISites) {
const routes_ai: IListRoutes[] = [
{
active: true,
order: 30,
path: '/ai',
materialIcon: 'fas fa-book',
name: 'pages.aitools',
component: () => import('@/views/toolsAI/main/main.vue'),
inmenu: true,
submenu: true,
level_parent: 0,
level_child: 0.5,
},
]
const routes_admin_ai: IListRoutes[] = [
{
active: true,
order: 32,
path: '/admin/ai/catAI',
materialIcon: 'fas fa-file-alt',
name: 'pages.catAI',
component: () => import('@/rootgen/admin/catAI/catAI.vue'),
inmenu: true,
submenu: true,
level_parent: 0,
level_child: 0.5,
onlyManager: true,
onlyEditor: true
},
{
active: true,
order: 32,
path: '/admin/ai/queryAI',
materialIcon: 'fas fa-file-alt',
name: 'pages.queryAI',
component: () => import('@/rootgen/admin/queryAI/queryAI.vue'),
inmenu: true,
submenu: true,
level_parent: 0,
level_child: 0.5,
onlyManager: true,
onlyEditor: true
},
]
const menuAI = [
{
active: site.confpages && site.confpages.enableAI,
path: '/ai',
order: 1402,
faIcon: 'fas fa-lemon',
materialIcon: 'fas fa-lemon',
name: 'pages.toolsAI',
routes2: routes_ai,
inmenu: true,
onlyif_logged: true,
// onlySocioResidente: true,
solotitle: true,
infooter: true
},
...routes_ai,
{
active: site.confpages && site.confpages.enableAI,
path: '/admin/ai',
order: 1420,
materialIcon: 'next_week',
name: 'pages.admin_ai',
routes2: routes_admin_ai,
inmenu: true,
solotitle: true,
onlyAdmin: true,
onlyManager: true,
onlyDepartment: true
},
...routes_admin_ai,
]
return menuAI
}
export const routesAI = {
routesAI: getRoutesAI,
}

View File

@@ -15,6 +15,18 @@ function getRoutesEcomm(site: ISites) {
level_parent: 0,
level_child: 0.5,
},
{
active: true,
order: 30,
path: '/catalogo',
materialIcon: 'fas fa-lemon',
name: 'pages.catalogo',
component: () => import('@/views/ecommerce/catalogo/catalogo.vue'),
inmenu: true,
submenu: true,
level_parent: 0,
level_child: 0.5,
},
{
active: true,
order: 30,
@@ -226,85 +238,6 @@ function getRoutesEcomm(site: ISites) {
]
const routes_admin_ecommerce_menu: IListRoutes[] = [
{
active: true,
order: 30,
path: '/admin/ecommerce/products',
name: 'pages.products',
component: () => import('@/rootgen/admin/products/products.vue'),
inmenu: false,
infooter: false,
},
{
active: true,
order: 30,
path: '/admin/ecommerce/productInfos',
name: 'pages.productInfos',
component: () => import('@src/rootgen/admin/productInfos/productInfos.vue'),
inmenu: false,
infooter: false,
},
{
active: true,
order: 31,
path: '/admin/ecommerce/producers',
name: 'pages.producer',
component: () => import('@/rootgen/admin/producer/producer.vue'),
inmenu: false,
infooter: false,
},
{
active: true,
order: 32,
path: '/admin/ecommerce/storehouses',
name: 'pages.storehouses',
component: () => import('@/rootgen/admin/storehouses/storehouses.vue'),
infooter: false,
},
{
active: true,
order: 32,
path: '/admin/ecommerce/providers',
name: 'pages.providers',
component: () => import('@/rootgen/admin/providers/providers.vue'),
infooter: false,
},
{
active: true,
order: 32,
path: '/admin/ecommerce/scontistica',
name: 'pages.scontisticas',
component: () => import('@/rootgen/admin/scontistica/scontistica.vue'),
infooter: false,
},
{
active: true,
order: 32,
path: '/admin/ecommerce/departments',
name: 'pages.departments',
component: () => import('@/rootgen/admin/departments/departments.vue'),
infooter: false,
},
{
active: true,
order: 35,
path: '/admin/ecommerce/orders',
name: 'pages.orders2',
component: () => import('@/rootgen/admin/orders/orders.vue'),
infooter: false,
},
{
active: true,
order: 36,
path: '/admin/ecommerce/categories',
name: 'pages.categories',
component: () => import('@/rootgen/admin/categories/categories.vue'),
infooter: false,
},
]
const menuEcomm = [
{
active: site.confpages && site.confpages.enableEcommerce,

View File

@@ -1571,6 +1571,7 @@ const msg_it = {
enableEcommerce: 'ECommerce',
enableGroups: 'Gruppi',
enableCircuits: 'Circuiti',
enableAI: 'AI Tools',
enableProj: 'Mostra Project',
enableTodos: 'Mostra Todos',
enableRegByBot: 'Registratione By Bot',
@@ -1764,6 +1765,9 @@ const msg_it = {
confirmed: 'Confermato',
causale: 'Causale',
},
ai: {
selectquery: 'Scegli',
},
},
};

View File

@@ -428,6 +428,31 @@ export const colTableCatProd = [
AddCol(DeleteRec),
AddCol(DuplicateRec),
]
export const colTableCatAI = [
AddCol({ name: 'name', label_trans: 'categories.name' }),
AddCol({ name: 'img', label_trans: 'categories.img' }),
AddCol({ name: 'icon', label_trans: 'categories.icon' }),
AddCol({ name: 'color', label_trans: 'categories.color' }),
AddCol(DeleteRec),
AddCol(DuplicateRec),
]
export const colTableQueryAI = [
AddCol({ name: 'descr', label_trans: 'categories.name' }),
AddCol({
name: 'catAI',
label_trans: 'products.category',
fieldtype: costanti.FieldType.select,
jointable: 'catais',
}),
AddCol({ name: 'query', label_trans: 'ai.query' }),
AddCol({ name: 'ask', label_trans: 'ai.ask' }),
AddCol({ name: 'output_type', label_trans: 'ai.output_type' }),
AddCol(DeleteRec),
AddCol(DuplicateRec),
]
export const colTableSubCatProd = [
AddCol({ name: 'name', label_trans: 'categories.name' }),
AddCol({
@@ -3751,6 +3776,20 @@ export const fieldsTable = {
colkey: '_id',
collabel: 'name',
},
{
value: 'catais',
label: 'Categorie AI',
columns: colTableCatAI,
colkey: '_id',
collabel: 'name',
},
{
value: 'queryais',
label: 'Query AI',
columns: colTableQueryAI,
colkey: '_id',
collabel: 'descr',
},
{
value: 'gasordines',
label: 'Gas Ordini',

View File

@@ -36,6 +36,7 @@ import { useNotifStore } from '@store/NotifStore'
import { useCircuitStore } from '@store/CircuitStore'
import { routesAdmin } from '@src/router/routesAdmin'
import { routesECommerce } from '@src/router/routesECommerce'
import { routesAI } from '@src/router/routesAI'
import LandingFooter from '@src/components/LandingFooter/LandingFooter'
import { useProducts } from '@store/Products'
@@ -144,6 +145,8 @@ export const useGlobalStore = defineStore('GlobalStore', {
sectors: [],
sectorgoods: [],
catgrps: [],
catAI: [],
queryAIList: [],
site: {
confsite: {
options: 0
@@ -170,6 +173,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
showConnected: false,
bookingEvents: false,
enableEcommerce: false,
enableAI: false,
enableGroups: false,
enableCircuits: false,
enableProj: false,
@@ -328,6 +332,8 @@ export const useGlobalStore = defineStore('GlobalStore', {
else if (table === 'categorys') ris = state.categories
else if (table === 'catprods') ris = Products.catprods
else if (table === 'catprods_gas') ris = Products.catprods_gas
else if (table === 'catais') ris = state.catAI
else if (table === 'queryais') ris = state.queryAIList
else if (table === 'sharewithus') ris = state.sharewithus
else if (table === 'paymenttypes') ris = state.paymenttypes
else if (table === 'circuits') ris = circuitStore.listcircuits
@@ -527,6 +533,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
const adminRoutes = routesAdmin.routesAd(this.site);
const ecommRoutes = routesECommerce.routesEcomm(this.site);
const AIRoutes = routesAI.routesAI(this.site);
const last = {
active: true,
@@ -555,7 +562,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
if (!toolsext.sito_online(false)) {
static_data.routes = [sito_offline, last]
} else {
static_data.routes = [...baseroutes, ...ecommRoutes, ...adminRoutes, ...arrpagesroute, last]
static_data.routes = [...baseroutes, ...ecommRoutes, ...adminRoutes, ...arrpagesroute, ...AIRoutes, last]
}
/*for (const menu of static_data.routes) {
@@ -1572,6 +1579,9 @@ export const useGlobalStore = defineStore('GlobalStore', {
this.sectorgoods = (res.data.sectorgoods) ? [...res.data.sectorgoods] : []
this.provinces = (res.data.provinces) ? [...res.data.provinces] : []
this.catgrps = (res.data.catgrps) ? [...res.data.catgrps] : []
this.catAI = (res.data.catAI) ? [...res.data.catAI] : []
if (res.data.queryAIList)
this.queryAIList = res.data.queryAIList
this.site = (res.data.site) ? res.data.site : {}
this.mygroups = (res.data.mygroups) ? [...res.data.mygroups] : []
this.adtypes = (res.data.adtypes) ? [...res.data.adtypes] : []
@@ -1785,6 +1795,26 @@ export const useGlobalStore = defineStore('GlobalStore', {
},
async getQueryAI() {
const userStore = useUserStore()
const paramquery = {
locale: tools.getLocale(),
username: userStore.my.username
}
return Api.SendReq('/aitools/getlist', 'POST', paramquery)
.then((res) => {
// console.log('queryAIList', res)
this.queryAIList = res.data.queryAIList
return this.queryAIList
}).catch((error) => {
return {}
})
},
getItemDate(num: number, day: number, numdays: number, mystr: string) {
let mydate = tools.addDays(tools.getDateNow(), day)
let mydateend = tools.addDays(mydate, numdays)

View File

@@ -0,0 +1,25 @@
$heightBtn: 100%;
.card .product-image {
height: 300px;
}
.container{
margin-top: 4px;
margin-bottom: 4px;
}
.prod_trov{
font-style: italic;
color: blue;
}
.fixed-group {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #ffffff; /* Customize the background color as needed */
z-index: 1000; /* Adjust the z-index to ensure it's above other elements */
transition: all 1s ease;
}

View File

@@ -0,0 +1,163 @@
import { defineComponent, onMounted, ref, watch, computed, onBeforeUnmount } from 'vue'
import { tools } from '@store/Modules/tools'
import { useUserStore } from '@store/UserStore'
import { useRouter } from 'vue-router'
import { useGlobalStore } from '@store/globalStore'
import { useProducts } from '@store/Products'
import { useI18n } from '@/boot/i18n'
import { toolsext } from '@store/Modules/toolsext'
import { useQuasar } from 'quasar'
import { costanti } from '@costanti'
import { shared_consts } from '@/common/shared_vuejs'
import { CProductCard } from '@src/components/CProductCard'
import { CSelectUserActive } from '@src/components/CSelectUserActive'
import { IProduct } from '@src/model'
export default defineComponent({
name: 'Catalogo',
components: { CProductCard, CSelectUserActive },
props: {},
setup() {
const userStore = useUserStore()
const globalStore = useGlobalStore()
const productStore = useProducts()
const router = useRouter()
const $q = useQuasar()
const { t } = useI18n()
const search = ref('')
const cosa = ref(0)
const cat = ref('')
const loadpage = ref(false)
const refreshpage = ref(false)
const arrProducts = ref<any>([])
// Create a ref for the component to fix
const componentToFixRef = ref(<any>null);
const isFixed = ref(false);
// Register the scroll event on component mount
const handleScroll = () => {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
// Set a threshold value based on how much scroll is needed to fix the components
const threshold = 300;
// Update the isFixed ref based on the scroll position
isFixed.value = scrollTop > threshold;
};
watch(() => cat.value, (newval, oldval) => {
calcArrProducts()
})
watch(() => search.value, (newval, oldval) => {
calcArrProducts()
if (tools.scrollTop() > 300) {
tools.scrollToTopValue(300)
}
})
watch(() => cosa.value, (newval, oldval) => {
tools.setCookie(tools.COOK_COSA_PRODOTTI, cosa.value.toString())
if (cosa.value !== shared_consts.PROD.TUTTI)
cat.value = ''
calcArrProducts()
})
function calcArrProducts() {
refreshpage.value = true
let arrprod = productStore.getProducts(cosa.value)
let catstr = cat.value;
let lowerSearchText = search.value.toLowerCase().trim();
if ((!lowerSearchText || (lowerSearchText && lowerSearchText.length < 2)) && !catstr) {
} else {
arrprod = arrprod.filter((product: IProduct) => {
let lowerName = product.productInfo.name!.toLowerCase();
let hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
// Use a regular expression to match whole words
let codeMatch = new RegExp(`\\b${lowerSearchText}\\b`, 'i');
let nameMatch = new RegExp(`\\b${lowerSearchText}`, 'i');
// Check if any word in lowerName starts with lowerSearchText
let anyWordStartsWithSearch = lowerName.split(/\s+/).some(word => nameMatch.test(word));
return (codeMatch.test(product.productInfo.code!) || anyWordStartsWithSearch) && hasCategoria;
});
}
arrProducts.value = arrprod
refreshpage.value = false
}
/*function getProducts() {
let arrprod = productStore.getProducts(cosa.value)
if (!search.value) {
return arrprod
}
let lowerSearchText = search.value.toLowerCase();
let catstr = cat.value;
return arrprod.filter((product: IProduct) => {
let lowerName = product.productInfo.name!.toLowerCase();
const hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
return (product.productInfo.code!.includes(search.value) || lowerName.includes(lowerSearchText)) && hasCategoria
});
}*/
async function mounted() {
loadpage.value = false
await productStore.loadProducts()
cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.TUTTI, true)
// Inizializza
loadpage.value = true
window.addEventListener('scroll', handleScroll);
calcArrProducts()
}
// Remove the event listener on component destroy
onBeforeUnmount(() => {
window.removeEventListener('scroll', handleScroll);
});
function getCatProds() {
let arrcat = productStore.getCatProds(cosa.value)
let riscat: any = [{ label: 'Tutti', value: '', icon: undefined, color: undefined }]
for (const rec of arrcat) {
riscat.push({ label: rec.name, value: rec._id, icon: rec.icon, color: rec.color })
}
return riscat
}
onMounted(mounted)
return {
userStore,
costanti,
tools,
toolsext,
search,
cosa,
shared_consts,
getCatProds,
cat,
productStore,
t,
loadpage,
refreshpage,
componentToFixRef,
isFixed,
arrProducts,
}
}
})

View File

@@ -0,0 +1,126 @@
<template>
<q-page>
<div class="text-center">
<q-spinner v-if="!loadpage" color="primary" size="3em" :thickness="2" />
</div>
<div v-if="loadpage" class="panel">
<!--<div>
<CSelectUserActive></CSelectUserActive>
<div class="text-center text-h7 text-blue">Filtra per:</div>
<div class="text-center">
<q-btn-toggle
v-model="cosa"
push
:size="tools.isMobile() ? '0.75rem' : '1rem'"
rounded
glossy
toggle-color="primary"
:options="[
{ value: shared_consts.PROD.TUTTI, slot: 'tutti' },
{ value: shared_consts.PROD.BOTTEGA, slot: 'bottega' },
{ value: shared_consts.PROD.GAS, slot: 'gas' },
]"
>
<template v-slot:tutti>
<div class="row items-center no-wrap">
<div class="text-center">
{{ t('ecomm.tutti') }}
</div>
<q-icon right name="fas fa-check-square" />
</div>
</template>
<template v-slot:gas>
<div class="row items-center no-wrap">
<div class="text-center">
{{ t('gas.ordina_sul_gas') }}
</div>
<q-icon right name="fas fa-user-friends" />
</div>
</template>
<template v-slot:bottega>
<div class="row items-center no-wrap">
<div class="text-center">
{{ t('gas.bottega') }}
</div>
<q-icon right name="fas fa-store" />
</div>
</template>
</q-btn-toggle>
</div>
</div>-->
<div class="container">
<q-slide-transition>
<div
v-show="isFixed || tools.scrollTop() < 300"
:class="
'column text-center q-mx-auto q-py-sm q-mb-sm ' +
(isFixed ? 'fixed-group ' : '')
"
style="width: 350px; max-width: 100%"
>
<div>
<q-input
ref="componentToFixRef"
filled
stack-label
rounded
:dense="tools.isMobile() ? true : false"
:label="t('ecomm.code_o_text_search')"
v-model="search"
debounce="300"
class="q-ml-md"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</div>
</div>
</q-slide-transition>
<div class="row q-gutter-xs justify-center q-mx-auto">
<div v-for="(reccat, index) in getCatProds()" :key="index">
<q-btn
:push="cat === reccat.value"
dense
:size="tools.isMobile() ? '0.70rem' : '1rem'"
:icon="reccat.icon ? reccat.icon : undefined"
:color="cat === reccat.value ? 'primary' : undefined"
:text-color="cat === reccat.value ? 'white' : 'black'"
rounded
:label="reccat.label"
@click="cat = reccat.value"
>
</q-btn>
</div>
</div>
<div class="text-center q-py-sm prod_trov">
<span v-show="productStore.getNumProdTot() !== arrProducts.length">{{
t('ecomm.prodotti_trovati', {
qta: arrProducts.length,
qtatot: productStore.getNumProdTot(),
})
}}</span>
</div>
<div class="row justify-around">
<div
class="q-pa-xs row items-start"
v-for="(product, index) in arrProducts"
:key="index"
>
<CProductCard :id="product._id" :complete="false" :cosa="cosa" />
</div>
</div>
</div>
</div>
</q-page>
</template>
<script lang="ts" src="./catalogo.ts">
</script>
<style lang="scss" scoped>
@import './catalogo';
</style>

View File

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

View File

@@ -1 +1,2 @@
export * from './productsList'
export * from './catalogo'

View File

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

View File

@@ -0,0 +1,25 @@
$heightBtn: 100%;
.card .product-image {
height: 300px;
}
.container{
margin-top: 4px;
margin-bottom: 4px;
}
.prod_trov{
font-style: italic;
color: blue;
}
.fixed-group {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #ffffff; /* Customize the background color as needed */
z-index: 1000; /* Adjust the z-index to ensure it's above other elements */
transition: all 1s ease;
}

162
src/views/toolsAI/main/main.ts Executable file
View File

@@ -0,0 +1,162 @@
import { defineComponent, onMounted, ref, watch, computed, onBeforeUnmount } from 'vue'
import { tools } from '@store/Modules/tools'
import { useUserStore } from '@store/UserStore'
import { useRouter } from 'vue-router'
import { useGlobalStore } from '@store/globalStore'
import { useProducts } from '@store/Products'
import { useI18n } from '@/boot/i18n'
import { toolsext } from '@store/Modules/toolsext'
import { useQuasar } from 'quasar'
import { costanti } from '@costanti'
import { shared_consts } from '@/common/shared_vuejs'
import { CAITools } from '@src/components/CAITools'
import { IProduct } from '@src/model'
export default defineComponent({
name: 'ToolsAIMain',
components: { CAITools },
props: {},
setup() {
const userStore = useUserStore()
const globalStore = useGlobalStore()
const productStore = useProducts()
const router = useRouter()
const $q = useQuasar()
const { t } = useI18n()
const search = ref('')
const cosa = ref(0)
const cat = ref('')
const loadpage = ref(false)
const refreshpage = ref(false)
const arrProducts = ref<any>([])
// Create a ref for the component to fix
const componentToFixRef = ref(<any>null);
const isFixed = ref(false);
// Register the scroll event on component mount
const handleScroll = () => {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
// Set a threshold value based on how much scroll is needed to fix the components
const threshold = 300;
// Update the isFixed ref based on the scroll position
isFixed.value = scrollTop > threshold;
};
watch(() => cat.value, (newval, oldval) => {
calcArrProducts()
})
watch(() => search.value, (newval, oldval) => {
calcArrProducts()
if (tools.scrollTop() > 300) {
tools.scrollToTopValue(300)
}
})
watch(() => cosa.value, (newval, oldval) => {
tools.setCookie(tools.COOK_COSA_PRODOTTI, cosa.value.toString())
if (cosa.value !== shared_consts.PROD.TUTTI)
cat.value = ''
calcArrProducts()
})
function calcArrProducts() {
refreshpage.value = true
let arrprod = productStore.getProducts(cosa.value)
let catstr = cat.value;
let lowerSearchText = search.value.toLowerCase().trim();
if ((!lowerSearchText || (lowerSearchText && lowerSearchText.length < 2)) && !catstr) {
} else {
arrprod = arrprod.filter((product: IProduct) => {
let lowerName = product.productInfo.name!.toLowerCase();
let hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
// Use a regular expression to match whole words
let codeMatch = new RegExp(`\\b${lowerSearchText}\\b`, 'i');
let nameMatch = new RegExp(`\\b${lowerSearchText}`, 'i');
// Check if any word in lowerName starts with lowerSearchText
let anyWordStartsWithSearch = lowerName.split(/\s+/).some(word => nameMatch.test(word));
return (codeMatch.test(product.productInfo.code!) || anyWordStartsWithSearch) && hasCategoria;
});
}
arrProducts.value = arrprod
refreshpage.value = false
}
/*function getProducts() {
let arrprod = productStore.getProducts(cosa.value)
if (!search.value) {
return arrprod
}
let lowerSearchText = search.value.toLowerCase();
let catstr = cat.value;
return arrprod.filter((product: IProduct) => {
let lowerName = product.productInfo.name!.toLowerCase();
const hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
return (product.productInfo.code!.includes(search.value) || lowerName.includes(lowerSearchText)) && hasCategoria
});
}*/
async function mounted() {
loadpage.value = false
await productStore.loadProducts()
cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.TUTTI, true)
// Inizializza
loadpage.value = true
window.addEventListener('scroll', handleScroll);
calcArrProducts()
}
// Remove the event listener on component destroy
onBeforeUnmount(() => {
window.removeEventListener('scroll', handleScroll);
});
function getCatProds() {
let arrcat = productStore.getCatProds(cosa.value)
let riscat: any = [{ label: 'Tutti', value: '', icon: undefined, color: undefined }]
for (const rec of arrcat) {
riscat.push({ label: rec.name, value: rec._id, icon: rec.icon, color: rec.color })
}
return riscat
}
onMounted(mounted)
return {
userStore,
costanti,
tools,
toolsext,
search,
cosa,
shared_consts,
getCatProds,
cat,
productStore,
t,
loadpage,
refreshpage,
componentToFixRef,
isFixed,
arrProducts,
}
}
})

17
src/views/toolsAI/main/main.vue Executable file
View File

@@ -0,0 +1,17 @@
<template>
<q-page>
<div class="text-center">
<q-spinner v-if="!loadpage" color="primary" size="3em" :thickness="2" />
</div>
<div v-if="loadpage" class="panel">
<CAITools></CAITools>
</div>
</q-page>
</template>
<script lang="ts" src="./main.ts">
</script>
<style lang="scss" scoped>
@import './main.scss';
</style>