- catalogo avanti, parte 1

This commit is contained in:
Surya Paolo
2024-05-04 14:49:09 +02:00
parent a7604a63ad
commit 399599d450
11 changed files with 2242 additions and 72 deletions

View File

@@ -2087,4 +2087,77 @@ export const shared_consts = {
TYPEHOSP_SCAMBIOCASA: 1,
TYPEHOSP_OSPITALITA: 2,
PRODUCTTYPE: {
BENE: 1,
SERVIZIO: 2,
OSPITALITA: 4,
PRODOTTO: 10,
LIBRO: 20,
EBOOK: 21,
AUDIOLIBRO: 22,
VIDEO: 23,
CARTE: 25,
},
VERSIONE: {
NUOVO: 1,
USATO: 2,
DOWNLOAD: 3,
DVD: 4,
EPUB: 5,
MOBI: 6,
PDF: 7,
STREAMING: 8,
},
VERSIONI_PRODOTTO: [
{
label: '[Nessuno]',
value: 0,
color: '',
},
{
label: 'Nuovo',
value: 1,
color: 'primary',
},
{
label: 'Usato',
value: 2,
color: 'warning',
},
{
label: 'Download',
value: 3,
color: 'success',
},
{
label: 'DVD',
value: 4,
color: 'secondary',
},
{
label: 'EPUB',
value: 5,
color: 'orange',
},
{
label: 'MOBI',
value: 6,
color: 'indigo',
},
{
label: 'PDF',
value: 7,
color: 'purple',
},
{
label: 'Streaming',
value: 8,
color: 'red',
},
],
}

View File

@@ -0,0 +1,208 @@
.card .product-image {
height: 300px;
}
.text-title {
font-size: 0.9rem;
}
.centeritems {
place-content: center;
}
.prod_price {
font-size: 1.25rem;
@media (max-width: 718px) {
font-size: 1.15rem;
}
}
.prod_sale_price {
font-size: 1.25rem;
@media (max-width: 718px) {
font-size: 1.15rem;
}
}
.prod_off_price {
font-size: 1rem;
@media (max-width: 718px) {
font-size: 0.85rem;
}
color: gray;
text-decoration: line-through;
padding-left: 5px;
}
.prod_disp {
font-size: 1.2rem;
@media (max-width: 718px) {
font-size: 1rem;
}
}
.prod_preorder {
font-size: 1.2rem;
@media (max-width: 718px) {
font-size: 1rem;
}
}
.prod_qtywarn {
padding-left: 10px;
font-size: 1rem;
color: grey;
}
.totali {
font-weight: bold;
font-size: 1.2rem;
}
.prod_sconti {
font-size: 1.1rem;
color: blue;
}
.product_code {
font-size: 0.75rem;
color: gray;
}
.label-qta {
font-size: 1.15rem;
font-weight: bold;
}
.countdown_scadenza {
font-size: 1.15rem;
font-weight: bold;
}
.subtit_prod {
font-style: italic;
}
.icone_prod {
font-size: 1.25rem;
@media (max-width: 718px) {
font-size: 1.15rem;
}
}
.thumbnail {
max-width: 100%;
max-height: 100%;
}
.fullscreen-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
display: flex;
align-items: center;
justify-content: center;
}
.fullscreen-image {
max-width: 100%;
max-height: 100%;
}
.titolo_prod {
cursor: pointer;
}
.image-section {
justify-content: center;
}
.card_titolo_prod {
text-align: center;
padding: 4px 4px 4px 4px;
height: 70px;
}
.image-container {
width: 300px;
height: 300px;
position: relative;
overflow: hidden;
@media (max-width: 718px) {
width: 200px;
height: 200px;
}
}
.img-pic {
width: 100%;
height: 100%;
object-fit: cover;
}
.q-card__section--vert {
padding: 4px;
}
.book-details {
margin: 20px;
}
.book-card {
max-width: 300px;
background-color: #f8f8f8;
}
.book-card-section {
display: flex;
}
.book-image {
flex: 1;
}
.book-image q-img {
max-width: 100%;
}
.book-info {
flex: 2;
padding: 20px;
}
.book-title {
font-family: 'Poppins,sans-serif';
font-size: 1rem;
line-height: 20px;
font-weight: 400;
color: #333;
display: block;
text-align: center;
}
.book-author {
color: #263238;
display: block;
font-family: Poppins, sans-serif;
font-size: 0.85em;
font-weight: 400;
line-height: 18px;
text-align: center;
}
.book-description {
font-size: 0.85rem;
color: #777;
}

View File

@@ -0,0 +1,478 @@
import { defineComponent, ref, toRef, computed, PropType, watch, onMounted, reactive, onBeforeUnmount } from 'vue'
import { useI18n } from '@src/boot/i18n'
import { useUserStore } from '@store/UserStore'
import { useGlobalStore } from '@store/globalStore'
import { useQuasar } from 'quasar'
import { CTitleBanner } from '../CTitleBanner'
import { CCardState } from '../CCardState'
import { CCopyBtn } from '../CCopyBtn'
import { CMyValueDb } from '../CMyValueDb'
import { func_tools, toolsext } from '@store/Modules/toolsext'
import { IBaseOrder, IGasordine, IOrder, IOrderCart, IProduct } from '@src/model'
import { tools } from '@store/Modules/tools'
import { useProducts } from '@store/Products'
import { shared_consts } from '@src/common/shared_vuejs'
import { useRouter } from 'vue-router'
import { costanti } from '@costanti'
import VuePdfApp from 'vue3-pdf-app'
// import this to use default icons for buttons
import 'vue3-pdf-app/dist/icons/main.css'
export default defineComponent({
name: 'CCatalogoCard',
props: {
product: {
type: Object as PropType<IProduct | null>,
required: false,
default: null,
},
id: {
type: String,
required: false,
default: '',
},
cosa: {
type: Number,
required: false,
default: 0,
},
complete: {
type: Boolean,
required: false,
default: false,
},
},
components: { CTitleBanner, CCardState, CCopyBtn, CMyValueDb, VuePdfApp },
setup(props, { emit }) {
const $q = useQuasar()
const { t } = useI18n()
const userStore = useUserStore()
const globalStore = useGlobalStore()
const products = useProducts()
const listord = ref(<IOrderCart[]>[])
const sumval = ref(0)
const editOn = ref(false)
const site = ref(globalStore.site)
const $router = useRouter()
const fullscreenImage = ref(<any>null)
const apriSchedaPDF = ref(false)
let myorder = reactive(<IOrder>{
idapp: process.env.APP_ID,
quantity: 0,
quantitypreordered: 0,
idStorehouse: '',
idGasordine: '',
storehouse: {},
gasordine: { active: false },
})
const storeSelected = ref('')
const arrordersCart = ref(<IOrderCart[]>[])
const timerInterval = ref(<any>null)
const timerLabelScadenza = ref('')
const labelDataRitiro = ref('')
const labelDataArrivoMerce = ref('')
const openlistorders = ref(false)
const endload = ref(false)
const myproduct = ref(<IProduct>{})
const isFullScreen = ref(false)
const imageSrc = ref('URL_DEL_TUO_FILE_IMMAGINE')
const startX = ref(0)
const startY = ref(0)
const scale = ref(1)
watch(() => editOn.value, (to: any, from: any) => {
if (!editOn.value)
ricarica()
})
/*const myproduct = computed((): IProduct => {
console.log('getproduct computed')
const ris = products.getProduct(props.code)
console.log(' received', ris)
return ris
})*/
function iconWhishlist(order: IProduct) {
if (true) {
return 'far fa-heart'
} else {
return 'fas fa-heart'
}
}
async function addtoCart(add: boolean) {
if (!userStore.isLogged) {
tools.showNeutralNotif($q, t('ecomm.area_personale'))
globalStore.rightDrawerOpen = true
return false
}
const ris = await products.addtoCartBase({ $q, t, id: myproduct.value._id, order: myorder, addqty: add })
updateproduct()
if (ris && ris.myord) {
}
}
function getnumstore() {
if (myproduct.value) {
if (myproduct.value.storehouses)
return myproduct.value.storehouses.length
else
return 0
}
return 0
}
function getSingleStorehouse() {
try {
const mystore = myproduct.value.storehouses[0]
if (mystore)
return mystore.name + ' (' + mystore.city + ')'
else
return ''
} catch (e) {
return ''
}
}
function getSingleGasordine(gasordine: IGasordine) {
try {
const mygas = gasordine
if (mygas)
/*return mygas.name + ' (' + mygas.city + ') ' + t('gas.dataora_chiusura_ordini') + ': ' + tools.getstrDateShort(mygas.dataora_chiusura_ordini)
+ ' ' + t('gas.data_arrivo_merce') + ': ' + tools.getstrDateShort(mygas.data_arrivo_merce)
+ ' ' + t('gas.dataora_ritiro') + ': ' + tools.getstrDateShort(mygas.dataora_ritiro)*/
return mygas.name
else
return ''
} catch (e) {
return ''
}
}
function initproduct() {
myorder.quantity = 0
myorder.quantitypreordered = 0
myorder.idStorehouse = ''
myorder.idGasordine = ''
}
function updateproduct() {
myproduct.value = products.getProductById(props.id)
// products.updateQuantityAvailable(myproduct.value._id)
}
async function ricarica() {
endload.value = false
const prod = await products.loadProductById(myproduct.value._id)
if (prod) {
myproduct.value = prod
}
load()
endload.value = true
}
function updateproductmodif() {
try {
myproduct.value = products.getProductById(props.id)
updateLabel()
} catch (e) {
console.error('err', e)
}
}
function getStorehouses() {
if (!myproduct.value)
return []
const myarr: any = []
let ind = 1
myproduct.value.storehouses.forEach((store) => {
myarr.push(
{
id: ind,
label: store.name + ' (' + store.city + ')',
value: store._id
})
ind++
})
// console.log('arraystore', myarr)
return myarr
}
function checkifCartDisable() {
// return !myorder.idStorehouse
return isOrdineChiuso()
}
function getQtyWarn() {
if (myorder.quantity > 0) {
return t('ecomm.di_cui_x_in_carrello', { qty: myorder.quantity })
}
return ''
}
function getQtyWarnPreOrdered() {
if (myorder.quantitypreordered > 0) {
return t('ecomm.di_cui_x_in_carrello', { qty: myorder.quantitypreordered })
}
return ''
}
watch(() => props.id, (newval, oldval) => {
// console.log('change code')
load()
})
watch(() => storeSelected.value, (newval, oldval) => {
myorder.idStorehouse = newval
})
function updateLabel() {
let dataArrivoMerce = ''
let dataRitiro = ''
try {
if (myproduct.value && myproduct.value.gasordine) {
if (myproduct.value.gasordine.data_arrivo_merce)
dataArrivoMerce = tools.getstrDateShort(myproduct.value.gasordine.data_arrivo_merce)
if (myproduct.value.gasordine.dataora_ritiro)
dataRitiro = tools.getstrDateTime(myproduct.value.gasordine.dataora_ritiro)
} else {
dataArrivoMerce = ''
dataRitiro = ''
}
} catch (e) {
}
if (labelDataArrivoMerce.value !== dataArrivoMerce)
labelDataArrivoMerce.value = dataArrivoMerce
if (labelDataRitiro.value !== dataRitiro)
labelDataRitiro.value = dataRitiro
updateTimerLabel()
}
function mounted() {
load()
// Start the timer when the component is mounted
startTimer();
}
function beforeDestroy() {
// Clear the interval when the component is destroyed to prevent memory leaks
clearInterval(timerInterval.value);
}
function updateTimerLabel() {
if (myproduct.value && myproduct.value.gasordine && myproduct.value.gasordine._id && myproduct.value.gasordine.dataora_chiusura_ordini)
timerLabelScadenza.value = tools.getCountDown(myproduct.value.gasordine.dataora_chiusura_ordini)
else
timerLabelScadenza.value = ''
}
function isOrdineChiuso() {
return myproduct.value.gasordine && myproduct.value.gasordine.dataora_chiusura_ordini &&
tools.getCountDown(myproduct.value.gasordine.dataora_chiusura_ordini) === ''
}
function startTimer() {
// Update the timer label every second
timerInterval.value = setInterval(() => updateTimerLabel(), 60000);
}
function load() {
initproduct()
updateproduct()
labelDataArrivoMerce.value = ''
labelDataRitiro.value = ''
// console.log('Load', myproduct.value.name)
arrordersCart.value = products.getOrdersCartInAttesaByIdProduct(myproduct.value._id)
if (!!myproduct.value) {
if (myproduct.value.storehouses && myproduct.value.storehouses.length === 1) {
// Se solo 1 presente, metto fisso l'unico negozio !
myorder.idStorehouse = myproduct.value.storehouses[0]._id
}
if (myproduct.value.gasordine) {
myorder.idGasordine = myproduct.value.gasordine._id
}
const ord = products.getOrderProductInCart(myproduct.value._id)
if (ord) {
myorder.quantity = ord.quantity
myorder.quantitypreordered = ord.quantitypreordered
// Seleziona il Negozio che avevo già scelto nell'ordine !
if (ord.idStorehouse)
storeSelected.value = ord.idStorehouse
}
}
updateLabel()
// console.log('°°° ENDLOAD °°°')
endload.value = true
}
function getclimgproduct() {
return 'myimgproduct centermydiv'
}
function visuListDisponibili() {
openlistorders.value = true
sumval.value = products.getSumQtyOrderProductInOrdersCart(myproduct.value._id)
listord.value = arrordersCart.value.filter((orderscart: IOrderCart) => orderscart.items!.reduce((accumulator, item) => {
return accumulator + item.order.quantity
}, 0))
}
function visuListBookable() {
openlistorders.value = true
sumval.value = products.getSumQtyPreOrderInOrdersCart(myproduct.value._id)
listord.value = arrordersCart.value.filter((orderscart: IOrderCart) => orderscart.items!.reduce((accumulator, item) => {
return accumulator + item.order.quantitypreordered
}, 0))
}
function isOrdGas(): boolean {
return (myproduct.value && !!myproduct.value.idGasordine && myproduct.value.gasordine! && myproduct.value.gasordine.active)
}
function getpercqtaraggiunta(): number {
if (myproduct.value)
return tools.calcperc((myproduct.value.bookableGASBloccatiQty + myproduct.value.QuantitaPrenotateInAttesa!) * myproduct.value.productInfo.weight!, myproduct.value.qtyToReachForGas * myproduct.value.productInfo.weight!) / 100
else
return 0
}
function toggleFullScreen() {
isFullScreen.value = !isFullScreen.value;
scale.value = 1;
}
function onTouchStart(e: any) {
startX.value = e.touches[0].pageX;
startY.value = e.touches[0].pageY;
}
function onTouchMove(e: any) {
const deltaX = e.touches[0].pageX - startX.value;
const deltaY = e.touches[0].pageY - startY.value;
// Calcola la distanza percorsa
const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2);
// Imposta il fattore di scala in base alla distanza percorsa
scale.value = Math.min(Math.max(1, scale.value + distance / 100), 3);
// Salva le nuove coordinate di partenza
startX.value = e.touches[0].pageX;
startY.value = e.touches[0].pageY;
// Applica la trasformazione
if (fullscreenImage.value)
fullscreenImage.value.style.transform = `scale(${scale.value})`;
}
function onTouchEnd() {
// Ripristina la trasformazione quando l'utente solleva il dito
if (fullscreenImage.value)
fullscreenImage.value.fullscreenImage.style.transform = 'scale(1)';
}
function naviga(path: string) {
$router.push(path)
}
onMounted(mounted)
onBeforeUnmount(beforeDestroy)
return {
visuListDisponibili,
visuListBookable,
addtoCart,
iconWhishlist,
getclimgproduct,
getnumstore,
getSingleStorehouse,
getSingleGasordine,
getStorehouses,
checkifCartDisable,
myproduct,
myorder,
tools,
t,
storeSelected,
getQtyWarn,
openlistorders,
func_tools,
toolsext,
products,
arrordersCart,
endload,
shared_consts,
site,
getQtyWarnPreOrdered,
listord,
sumval,
timerLabelScadenza,
labelDataRitiro,
labelDataArrivoMerce,
getpercqtaraggiunta,
isOrdGas,
isFullScreen,
toggleFullScreen,
onTouchStart,
onTouchMove,
onTouchEnd,
naviga,
globalStore,
editOn,
costanti,
updateproduct,
updateproductmodif,
isOrdineChiuso,
ricarica,
apriSchedaPDF,
}
}
})

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -3,39 +3,45 @@ import { IUserFields, IUserShort } from './UserStore'
export interface IProductInfo {
_id?: any
code?: string,
id_wp?: string,
name?: string,
description?: string,
department?: string,
idCatProds?: string[],
idSubCatProds?: string[],
catprods?: ICatProd[],
subcatprods?: ISubCatProd[],
color?: string,
size?: string,
weight?: number,
weight_lordo?: number,
unit: number,
unit_lordo?: number,
sfuso?: boolean,
stars?: number,
date?: Date,
icon?: string,
code?: string
id_wp?: string
name?: string
description?: string
department?: string
idCatProds?: string[]
idSubCatProds?: string[]
catprods?: ICatProd[]
subcatprods?: ISubCatProd[]
color?: string
size?: string
weight?: number
weight_lordo?: number
unit: number
unit_lordo?: number
sfuso?: boolean
stars?: number
date?: Date
icon?: string
img?: string
img2?: string
img3?: string
img4?: string
image_link?: string
ingredienti?: string,
link_scheda?: string,
valori_nutrizionali?: string,
author?: string,
collezione?: string,
publisher?: string,
numpages?: number,
ingredienti?: string
link_scheda?: string
valori_nutrizionali?: string
authors?: string[]
collezione?: string
publisher?: string
date_publishing?: Date
numpages?: number
productType?: number
}
export interface IProduct {
_id?: any
active?: boolean
isbn?: string
idProductInfo?: string,
productInfo: IProductInfo,
idProducer?: string,
@@ -56,6 +62,7 @@ export interface IProduct {
QuantitaOrdinateInAttesa?: number,
QuantitaPrenotateInAttesa?: number,
note?: string
versione?: number
stockQty: number, // UPDATING
status?: string,

View File

@@ -401,6 +401,8 @@ export default defineComponent({
if (cmd === shared_consts.Cmd.PRODUCTS_V2) {
skipfirstrow.value = false
} else if (cmd === shared_consts.Cmd.MACRO_CATALOGO_JSON) {
skipfirstrow.value = false
}
for (const rec of myarr) {

View File

@@ -2077,6 +2077,7 @@ export const colTableProductInfos = [
AddCol({ name: 'valori_nutrizionali', label_trans: 'products.valori_nutrizionali', fieldtype: costanti.FieldType.html }),
AddCol({ name: 'author', label_trans: 'products.author', fieldtype: costanti.FieldType.string }),
AddCol({ name: 'collezione', label_trans: 'products.collezione', fieldtype: costanti.FieldType.string }),
AddCol({ name: 'date_publishing', label_trans: 'products.date_publishing', fieldtype: costanti.FieldType.onlydate }),
AddCol({ name: 'publisher', label_trans: 'products.publisher', fieldtype: costanti.FieldType.string }),
AddCol({ name: 'numpages', label_trans: 'products.numpages', fieldtype: costanti.FieldType.number }),
AddCol({ name: 'note', label_trans: 'products.note', fieldtype: costanti.FieldType.html }),
@@ -2096,6 +2097,7 @@ export const colTableOrdersCart = [
export const colTableProducts = [
AddCol({ name: 'active', label_trans: 'products.active', fieldtype: costanti.FieldType.boolean }),
AddCol({ name: 'isbn', label_trans: 'products.isbn' }),
AddCol({
name: 'idProductInfo',
label_trans: 'products.productInfo',
@@ -2182,6 +2184,12 @@ export const colTableProducts = [
label_trans: 'ecomm.note',
fieldtype: costanti.FieldType.html
}),
AddCol({
name: 'versione',
label_trans: 'products.versione',
fieldtype: costanti.FieldType.select,
jointable: 'versions',
}),
AddCol({
name: 'maxbookableGASQty',
label_trans: 'ecomm.maxbookableGASQty',

View File

@@ -1896,6 +1896,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
else if (table === toolsext.TABCALDATE) myarr = this.getArrDateEvent()
else if (table === toolsext.TABCALALLDATE) myarr = this.getArrAllDateEvent()
else if (table === toolsext.TABTYPEHOSP) myarr = shared_consts.TypeHosps
else if (table === 'versions') myarr = shared_consts.VERSIONI_PRODOTTO
else if (table === toolsext.TABPEOPLE) myarr = shared_consts.People
else if (table === toolsext.TABTYPEACCOM) myarr = shared_consts.TypeAccom
else if (table === toolsext.TABLOCACCOM) myarr = shared_consts.LocationAccom

View File

@@ -11,12 +11,13 @@ import { costanti } from '@costanti'
import { shared_consts } from '@/common/shared_vuejs'
import { CProductCard } from '@src/components/CProductCard'
import { CCatalogoCard } from '@src/components/CCatalogoCard'
import { CSelectUserActive } from '@src/components/CSelectUserActive'
import { IProduct } from '@src/model'
export default defineComponent({
name: 'Catalogo',
components: { CProductCard, CSelectUserActive },
components: { CCatalogoCard, CProductCard, CSelectUserActive },
props: {},
setup() {
const userStore = useUserStore()
@@ -28,18 +29,38 @@ export default defineComponent({
const search = ref('')
const filter = ref(<any>{
author: '',
publisher: '',
type: '',
ageGroup: ''
})
const cosa = ref(0)
const cat = ref('')
const idGasSel = ref('')
const loadpage = ref(false)
const refreshpage = ref(false)
const show_hide = ref(false)
const arrProducts = ref<any>([])
const numRecLoaded = ref(0)
// Create a ref for the component to fix
const componentToFixRef = ref(<any>null);
const isFixed = ref(false);
const arrLoaded = computed(() => {
if (arrProducts.value && numRecLoaded.value)
return arrProducts.value.slice(0, numRecLoaded.value)
else {
return []
}
})
// Register the scroll event on component mount
const handleScroll = () => {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
@@ -54,6 +75,11 @@ export default defineComponent({
watch(() => cat.value, (newval, oldval) => {
calcArrProducts()
})
watch(() => idGasSel.value, (newval, oldval) => {
calcArrProducts()
})
watch(() => search.value, (newval, oldval) => {
calcArrProducts()
if (tools.scrollTop() > 300) {
@@ -69,30 +95,44 @@ export default defineComponent({
})
function calcArrProducts() {
// console.log('calcArrProducts')
refreshpage.value = true
let arrprod = productStore.getProducts(cosa.value)
let catstr = cat.value;
let gasselstr = ''
if (cosa.value === shared_consts.PROD.GAS) {
gasselstr = idGasSel.value
}
let lowerSearchText = search.value.toLowerCase().trim();
if ((!lowerSearchText || (lowerSearchText && lowerSearchText.length < 2)) && !catstr) {
if ((!lowerSearchText || (lowerSearchText && lowerSearchText.length < 2)) && !catstr && (!gasselstr && (cosa.value !== shared_consts.PROD.GAS))) {
} else {
arrprod = arrprod.filter((product: IProduct) => {
let lowerName = product.productInfo.name!.toLowerCase();
let hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
if (product && product.productInfo) {
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');
let productgassel = true
if (gasselstr || (cosa.value === shared_consts.PROD.GAS)) {
productgassel = (product.idGasordine === gasselstr)
}
// Check if any word in lowerName starts with lowerSearchText
let anyWordStartsWithSearch = lowerName.split(/\s+/).some(word => nameMatch.test(word));
// Use a regular expression to match whole words
let codeMatch = new RegExp(`\\b${lowerSearchText}\\b`, 'i');
let nameMatch = new RegExp(`\\b${lowerSearchText}`, 'i');
return (codeMatch.test(product.productInfo.code!) || anyWordStartsWithSearch) && hasCategoria;
// 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 && productgassel;
}
});
}
arrProducts.value = arrprod
loaddata()
refreshpage.value = false
}
@@ -115,12 +155,21 @@ export default defineComponent({
async function mounted() {
loadpage.value = false
await productStore.loadProducts()
cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.TUTTI, true)
cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.GAS, true)
if (cosa.value === shared_consts.PROD.TUTTI)
cosa.value = shared_consts.PROD.GAS
// Inizializza
loadpage.value = true
window.addEventListener('scroll', handleScroll);
calcArrProducts()
loaddata()
}
function loaddata() {
numRecLoaded.value = 20
}
// Remove the event listener on component destroy
@@ -138,6 +187,26 @@ export default defineComponent({
return riscat
}
function onLoadScroll(index: number, done: any) {
if (index >= 1) {
if (numRecLoaded.value < arrProducts.value.length) {
const step = 10
let mynrec = numRecLoaded.value + step
if (mynrec > arrProducts.value.length)
mynrec = arrProducts.value.length
numRecLoaded.value = mynrec
}
done()
} else {
done(true)
}
}
onMounted(mounted)
return {
@@ -150,6 +219,7 @@ export default defineComponent({
shared_consts,
getCatProds,
cat,
idGasSel,
productStore,
t,
loadpage,
@@ -157,6 +227,11 @@ export default defineComponent({
componentToFixRef,
isFixed,
arrProducts,
show_hide,
onLoadScroll,
numRecLoaded,
arrLoaded,
filter,
}
}
})

View File

@@ -4,9 +4,9 @@
<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 v-if="true">
<!--<CSelectUserActive></CSelectUserActive>-->
<div class="text-center text-h7 text-blue">Filtra Prodotti per:</div>
<div class="text-center">
<q-btn-toggle
v-model="cosa"
@@ -16,9 +16,8 @@
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' },
{ value: shared_consts.PROD.BOTTEGA, slot: 'bottega' },
]"
>
<template v-slot:tutti>
@@ -34,6 +33,12 @@
<div class="row items-center no-wrap">
<div class="text-center">
{{ t('gas.ordina_sul_gas') }}
<!--<br />
{{
t('gas.x_prodotti_gas', {
qta: productStore.getNumQtaGas(),
})
}}-->
</div>
<q-icon right name="fas fa-user-friends" />
</div>
@@ -43,13 +48,19 @@
<div class="row items-center no-wrap">
<div class="text-center">
{{ t('gas.bottega') }}
<!--<br />
{{
t('gas.x_prodotti_bottega', {
qta: productStore.getNumQtaBottega(),
})
}}-->
</div>
<q-icon right name="fas fa-store" />
</div>
</template>
</q-btn-toggle>
</div>
</div>-->
</div>
<div class="container">
<q-slide-transition>
@@ -80,37 +91,204 @@
</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"
<div v-if="cosa === shared_consts.PROD.GAS">
<div v-if="!idGasSel">
<div class="text-center text-h6 text-red">Ordini Attivi:</div>
</div>
<div class="row q-gutter-xs justify-center q-mx-auto">
<div
v-for="(recgas, index) in productStore.getGasordinesActives()"
:key="index"
>
</q-btn>
<q-btn
push
dense
:size="tools.isMobile() ? '0.9rem' : '1.05rem'"
:color="idGasSel === recgas._id ? 'primary' : undefined"
:text-color="idGasSel === recgas._id ? 'white' : 'black'"
:label="recgas.name"
@click="idGasSel = recgas._id"
>
</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" v-if="tools.isManager()">
<q-toggle
v-model="show_hide"
push
label="Mostra Nascosti"
rounded
glossy
toggle-color="primary"
></q-toggle>
</div>
<div class="row justify-around">
<q-infinite-scroll
v-if="arrLoaded && arrLoaded.length > 0"
ref="myinfscroll"
:initial-index="0"
@load="onLoadScroll"
:offset="2000"
debounce="200"
class="q-pa-xs row items-start"
>
<div
class="q-pa-xs"
v-for="(product, index) in arrLoaded"
:key="index"
>
<CCatalogoCard
v-if="
product.active ||
(show_hide &&
productInfo.productType ===
shared_consts.PRODUCTTYPE.PRODUCT)
"
:id="product._id"
:complete="false"
:cosa="cosa"
/>
<CProductCard
v-else-if="product.active || show_hide"
:id="product._id"
:complete="false"
:cosa="cosa"
/>
</div>
<template v-slot:loading>
<div class="text-center">
<q-spinner-dots color="primary" size="40px" />
</div>
</template>
</q-infinite-scroll>
</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 v-else>
<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" v-if="tools.isManager()">
<q-toggle
v-model="show_hide"
push
label="Mostra Nascosti"
rounded
glossy
toggle-color="primary"
></q-toggle>
</div>
<q-toolbar>
<q-input
v-model="search"
debounce="300"
placeholder="Cerca libri..."
dense
/>
<q-select
v-model="filter.author"
:options="authors"
label="Autore"
placeholder="Tutti"
dense
/>
<q-select
v-model="filter.publisher"
:options="publishers"
label="Editore"
placeholder="Tutti"
dense
/>
<q-select
v-model="filter.type"
:options="types"
label="Tipo"
placeholder="Tutti"
dense
/>
<q-select
v-model="filter.ageGroup"
:options="ageGroups"
label="Fascia d'età"
placeholder="Tutte"
dense
/>
</q-toolbar>
<div class="row justify-around">
<q-infinite-scroll
v-if="arrLoaded && arrLoaded.length > 0"
ref="myinfscroll"
:initial-index="0"
@load="onLoadScroll"
:offset="2000"
debounce="200"
class="q-pa-xs row items-start"
>
<div
class="q-pa-xs"
v-for="(product, index) in arrLoaded"
:key="index"
>
<CCatalogoCard
v-if="
product.active ||
(show_hide &&
productInfo.productType ===
shared_consts.PRODUCTTYPE.PRODUCT)
"
:id="product._id"
:complete="false"
:cosa="cosa"
/>
<CProductCard
v-else-if="product.active || show_hide"
:id="product._id"
:complete="false"
:cosa="cosa"
/>
</div>
<template v-slot:loading>
<div class="text-center">
<q-spinner-dots color="primary" size="40px" />
</div>
</template>
</q-infinite-scroll>
</div>
</div>
</div>
@@ -122,5 +300,5 @@
</script>
<style lang="scss" scoped>
@import './catalogo';
@import './catalogo.scss';
</style>