import { PropType, computed, defineComponent, onMounted, ref, watch } from "vue"; import draggable from 'vuedraggable' import { tools } from '@tools' import { useGlobalStore } from '@src/store/globalStore' import { CMyValueDb } from '@src/components/CMyValueDb' import { CSchedaProdotto } from '@src/components/CSchedaProdotto' import { CSearchProduct } from '@src/components/CSearchProduct' import { CMyDialog } from '@src/components/CMyDialog' import { costanti } from '@costanti' import { IAuthor, ICatProd } from "app/src/model"; import type { IMyScheda, IOptCatalogo, IProduct } from '@src/model'; import { shared_consts } from "app/src/common/shared_vuejs"; import { useProducts } from "app/src/store/Products"; import { CViewTable } from "../CViewTable"; import { CLabel } from "../CLabel"; import { useI18n } from "vue-i18n"; export default defineComponent({ name: "CProductTable", emits: ["update:lista_prodotti", "update:optcatalogo", "rigenera"], components: { draggable, CSearchProduct, CMyDialog, CMyValueDb, CViewTable, CLabel, CSchedaProdotto, }, props: { lista_prodotti: { type: Array, required: true, }, optcatalogo: { type: Object as PropType, required: false, default: null, }, scheda: { type: Object as PropType, required: false, default: () => ({ }), }, }, setup(props, { emit }) { // Copia locale della lista_prodotti per manipolazione interna const internalProducts = ref([...props.lista_prodotti || []]); const { t } = useI18n() const globalStore = useGlobalStore() const products = useProducts() const showProd = ref(false) const selProd = ref(null) const cmd = ref(shared_consts.SCHEDA_PRODOTTO.CMD_NONE) const showQtaDisponibile = ref(false) const loading = ref(true) const visufromgm = ref(false) const updatefromgm = ref(false) const field_updated_fromGM = ref('') const modifOn = ref(false) const sortAttribute = ref('') const sortDirection = ref(1) const optionscatalogo = ref({ maxlength: 0 }) function handleUpdate(newList) { internalProducts.value = newList emit('update:lista_prodotti', internalProducts.value) } const editOn = computed({ get(): boolean { return globalStore.editOn ? globalStore.editOn : false }, set(value: boolean) { return tools.updateEditOn(value) } }) async function mounted() { console.log('mounted CProductTable') loading.value = true optionscatalogo.value = { maxlength: props.scheda?.testo_bottom?.maxlength } const savedColumns = tools.getCookie("selColCat_2"); if (savedColumns) { selectedColumns.value = savedColumns; } loading.value = false } // Aggiorna la copia locale quando il prop cambia watch( () => props.lista_prodotti, (newVal) => { internalProducts.value = [...newVal]; } ), { deep: true }; // Colonne della tabella const allColumns = [ { name: "pos", label: "Ind", field: "pos", align: "left", style: "width: 50px" }, { name: "drag", label: "Ord", field: "", align: "left", style: "width: 50px", edit: true, noexp: true }, { name: "validato", label: "Val", field: "validato", align: "left", style: "" }, { name: "image", label: "Foto", field: "image", align: "center", noexp: true }, { name: "name", label: "Titolo del Libro", field: "name", align: "left" }, { name: "authors", label: "Autore", field: "authors", align: "left" }, { name: "isbn", label: "ISBN", field: "isbn", align: "left" }, { name: "trafiletto", label: "Sinossi", field: "trafiletto", align: "left" }, { name: "catprods", label: "Argomento", field: "catprods", align: "left" }, { name: "edizione", label: "Edizione", field: "edizione", align: "left" }, { name: "casaeditrice", label: "Casa Editrice", field: "casaeditrice", align: "left" }, { name: "idCollana", label: "Collana", field: "idCollana", align: "left" }, { name: "stato", label: "Stato", field: "stato", align: "left" }, { name: "tipologia", label: "Tipologia", field: "tipologia", align: "left" }, { name: "tipoformato", label: "Formato", field: "tipoformato", align: "left" }, { name: "pagine", label: "Pag.", field: "pagine", align: "right" }, { name: "prezzo", label: "€", field: "prezzo", align: "right" }, { name: "prezzo_sconto", label: "€ (sconto)", field: "prezzo_sconto", align: "right" }, { name: "date_pub", label: "Pubblicato", field: "date_pub", align: "left" }, //{ name: "ranking", label: "Class.", field: "ranking", align: "right" }, //{ name: "rank3M", label: "Class. 3M", field: "rank3M", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, //{ name: "rank6M", label: "Class. 6M", field: "rank6M", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, //{ name: "rank1Y", label: "Class. 1Y", field: "rank1Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "totVen", label: "Vend", field: "totVen", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "vLast6M", label: "Ven 6M", field: "vLast6M", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "fatLast6M", label: "Fat 6M", field: "fatLast6M", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "fatLast1Y", label: "Fat 1A", field: "fatLast1Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "fatLast2Y", label: "Fat 2A", field: "fatLast2Y", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "totFat", label: "Fat 5A", field: "totFat", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "ult_ord", label: "Ult. Ordine", field: "ult_ord", align: "left", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "quantity", label: "Magazz.", field: "quantity", align: "right", visu: costanti.VISUCAMPI.PER_EDITORE }, { name: "actions", label: "Azioni", field: "", align: "center", visu: costanti.VISUCAMPI.PER_EDITORE, noexp: true }, ]; function getFieldValue(element: any, field: any): any { if (!element) return '' try { switch (field.field) { case 'image': return element.productInfo?.imagefile ? tools.getFullFileNameByImageFile('productInfos', element.productInfo?.imagefile) : element.productInfo?.image_link; case 'name': return element.productInfo?.name; case 'authors': return formatAuthors(element.productInfo?.authors); case 'validato': return element.validaprod?.esito === costanti.VALIDATO.SI ? 'SI' : (element.validaprod?.esito === costanti.VALIDATO.TO_RESOLV ? 'ERR' : 'NO'); case 'isbn': return element.isbn; case 'trafiletto': return element.productInfo?.descr_trafiletto_catalogo?.length > 100 ? 'SI' : 'NO'; case 'catprods': return tools.formatCatProds(element.productInfo?.catprods); case 'edizione': return element.arrvariazioni?.[0]?.edizione; case 'casaeditrice': return products.getCasaEditriceByIdPublisher(element.productInfo?.idPublisher); case 'idCollana': return tools.formatCollane(element.productInfo?.idCollana); case 'stato': return products.getDescrStatiProdottoByIdStatoProdotto(element.productInfo?.idStatoProdotto || ''); case 'tipologia': return products.getDescrByIdTipologia(element.arrvariazioni?.[0]?.idTipologia || ''); case 'tipoformato': return products.getDescrByIdTipoFormato(element.arrvariazioni?.[0]?.idTipoFormato || ''); case 'date_pub': return tools.getstrDate(element.productInfo?.date_pub); case 'prezzo': return element.price ? '€ ' + element.price.toFixed(2) : ''; case 'prezzo_sconto': return element.sale_price ? '€ ' + element.sale_price.toFixed(2) : ''; case 'rank3M': return element.productInfo?.rank3M; case 'rank6M': return element.productInfo?.rank6M; case 'rank1Y': return element.productInfo?.rank1Y; case 'pagine': return element.arrvariazioni?.[0]?.pagine; case 'totVen': return element.productInfo?.totVen; case 'totFat': return element.productInfo?.totFat; case 'fatLast6M': return element.productInfo?.fatLast6M; case 'fatLast1Y': return element.productInfo?.fatLast1Y; case 'fatLast2Y': return element.productInfo?.fatLast2Y; case 'ult_ord': return tools.getstrDate(element.productInfo?.dataUltimoOrdine); case 'quantity': return element.arrvariazioni?.[0]?.quantita; default: return null; } } catch (e) { console.error('Errore getFieldValue:', e, element, field); return null; } } function getFieldClass(element: any, field: any): string { if (!element) return '' switch (field.field) { case 'trafiletto': return element.productInfo?.descr_trafiletto_catalogo?.length > 100 ? 'text-green' : 'text-red'; case 'stato': if (products.isProssimaUscita(element.productInfo)) { return 'bg-purple-3'; } if (products.isPrevendita(element.productInfo)) { return 'bg-blue-3'; } if (products.isNonVendibile(element.productInfo)) { return 'bg-grey'; } return ''; case 'validato': if (element.validaprod?.esito === costanti.VALIDATO.SI) { return 'bg-green'; } else if (element.validaprod?.esito === costanti.VALIDATO.TO_RESOLV) { return 'bg-red'; } else { return 'bg-grey'; } case 'quantity': if (products.isPubblicato(element.productInfo)) { if (products.isQtaLimitata(element)) { return 'bg-yellow'; } if (products.isInEsaurendo(element)) { return 'bg-orange'; } if (products.isEsaurito(element)) { return 'text-white bg-red-10'; } } return ''; case 'rank3M': case 'rank6M': case 'rank1Y': case 'pagine': case 'totVen': case 'totFat': case 'fatLast6M': case 'fatLast1Y': case 'fatLast2Y': default: return ''; } } function getFieldStyle(element: any, field: any): Record { if (!element) return {} switch (field.field) { case 'prezzo': case 'prezzo_sconto': return { width: '55px', textAlign: 'right' }; case 'validato': return { cursor: 'pointer', textAlign: 'center', color: 'white', } case 'image': return { width: '50px', height: '50px' }; case 'pagine': case 'totVen': case 'totFat': case 'fatLast6M': case 'fatLast1Y': case 'fatLast2Y': case 'quantity': return { textAlign: 'right' }; case 'trafiletto': return { textAlign: 'center' }; default: return {}; } } let cookieValue: [] | null = null; try { cookieValue = tools.getCookie("selColCat_2"); // Se il cookie esiste e contiene una stringa JSON valida cookieValue = cookieValue ? cookieValue : []; } catch (error) { console.error("Errore durante la lettura del cookie 'selColCat'", error); cookieValue = []; // In caso di errore, inizializza come array vuoto } const selectedColumns = ref(cookieValue.length > 0 ? cookieValue : ["pos", "drag", "validato", "image", "name", "authors", "isbn", "catprods", "stato", "date_pub", "pagine", "trafiletto", "fatLast1Y", "quantity", "actions"]); // 3. Funzione per verificare se una colonna è visibile (isColumnVisible) const isColumnVisible = (column, real?: boolean) => { if (column === 'actions' && !real) { return false } if (internalProducts.value?.length > 1000) { if (column === 'image') { return false } } const ok = allColumns.some((col) => col.name === column) && (!props.optcatalogo.showListaArgomenti || (props.optcatalogo.showListaArgomenti && !column.edit)) return selectedColumns.value.includes(column) && ok; } const getColumnLabelByName = (name: string): string => { const column = allColumns.find((col) => col.name === name); return column ? column.label : ''; } // Funzione per eliminare un prodotto const removeProduct = (product) => { internalProducts.value = internalProducts.value.filter((p: any) => p._id !== product._id); emit("update:lista_prodotti", internalProducts.value); // Notifica il parent del cambiamento } // 8. Salvataggio delle colonne selezionate in un cookie const saveSelectedColumns = () => { tools.setCookie("selColCat_2", JSON.stringify(selectedColumns.value)); }; // 9. Watcher per salvare automaticamente le preferenze quando cambiano watch(() => selectedColumns.value, () => { saveSelectedColumns(); }); // Funzione chiamata alla fine del drag-and-drop const onDragEnd = () => { // console.log("Nuovo ordine:", internalProducts.value); emit("update:lista_prodotti", internalProducts.value); // Notifica il parent del cambiamento } function formatAuthors(authors: IAuthor[] | undefined | null): string { if (!authors || !Array.isArray(authors)) { return ""; // Restituisci una stringa vuota se authors non è un array valido } // Estrai il nome e il cognome di ogni autore e uniscili con ', ' return authors .map((author) => `${author.name ?? ""} ${author.surname ?? ""}`.trim()) .filter((name) => name.length > 0) // Filtra eventuali nomi vuoti .join(", "); } function showProduct(element: any) { selProd.value = element showProd.value = true } function modifyProduct(element: any) { if (element) { selProd.value = element cmd.value = shared_consts.SCHEDA_PRODOTTO.CMD_MODIFICA modifOn.value = true } } function updateProduct(element: any) { selProd.value = element // Aggiorna l'elemento nella lista interna internalProducts.value = internalProducts.value.map((prod: any) => { if (prod._id === selProd.value._id) { return selProd.value; } return prod; }); emit("update:lista_prodotti", internalProducts.value); // Notifica il parent del cambiamento } async function updateproductmodif(element: any) { console.log('PRODUCT TABLE: updateproductmodif') try { if (element?._id) { selProd.value = await products.getProductById(element?._id) } else { selProd.value = await products.getProductById(selProd.value?._id) } // update record inside internalProducts internalProducts.value = internalProducts.value.map((prod: any) => { if (prod._id === selProd.value._id) { return selProd.value; } return prod; }); } catch (e) { console.error('err', e) } } async function refreshFieldFromGM(field: string) { if (selProd.value) { loading.value = true updatefromgm.value = true field_updated_fromGM.value = '' field_updated_fromGM.value = await globalStore.getGM_FieldOf_T_Web_Articoli(selProd.value.productInfo.sku!, field, shared_consts.CmdQueryMs.GET) loading.value = false } } const sortTable = (sortAttributeToSort: string) => { if (!props.optcatalogo.showListaArgomenti) return false if (sortAttributeToSort) { if (sortAttribute.value === sortAttributeToSort) { sortDirection.value = -sortDirection.value } else { sortAttribute.value = sortAttributeToSort sortDirection.value = 1 } internalProducts.value = internalProducts.value.sort((a: any, b: any) => { const aVal = getFieldValue(a, { field: sortAttributeToSort }); const bVal = getFieldValue(b, { field: sortAttributeToSort }); if (aVal instanceof Date && bVal instanceof Date) { return sortDirection.value === 1 ? aVal.getTime() - bVal.getTime() : bVal.getTime() - aVal.getTime(); } if (typeof aVal === 'number' && typeof bVal === 'number') { return sortDirection.value === 1 ? aVal - bVal : bVal - aVal; } if (typeof aVal === 'string' && typeof bVal === 'string') { return sortDirection.value === 1 ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal); } return sortDirection.value === 1 ? String(aVal).localeCompare(String(bVal)) : String(bVal).localeCompare(String(aVal)); }) } } function rigenera() { emit('rigenera') } function getFieldClick(element: any, field: any): (() => void) | null { switch (field.field) { case 'validato': return () => modifyProduct(element) case 'image': return () => showProduct(element); case 'stato': return () => { // esempio: mostra dettagli dello stato console.log('Stato prodotto:', element.productInfo?.idStatoProdotto); }; case 'quantity': return () => { // esempio: mostra log disponibilità console.log('Quantità disponibile:', element.arrvariazioni?.[0]?.quantita); }; default: return null; } } function exportToCSV() { const csvContent = [ selectedColumns.value .filter((col) => !allColumns.find((c) => c.name === col)?.noexp) .map((col) => getColumnLabelByName(col)) .join('|'), ...internalProducts.value.map((product: any) => { return selectedColumns.value .filter((col) => !allColumns.find((c) => c.name === col)?.noexp) .map((col: string) => { const field = { field: col }; return field.field === 'pos' ? internalProducts.value.indexOf(product) + 1 : getFieldValue(product, field); }).join('|'); }), ].join('\r\n'); const filename = 'prodotti_' + new Date().toISOString().slice(0, 10) + '.csv'; const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', filename); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } onMounted(mounted) return { allColumns, selectedColumns, isColumnVisible, internalProducts, formatAuthors, removeProduct, modifyProduct, tools, globalStore, costanti, onDragEnd, showProduct, showProd, selProd, cmd, shared_consts, updateProduct, field_updated_fromGM, refreshFieldFromGM, updatefromgm, visufromgm, loading, showQtaDisponibile, modifOn, updateproductmodif, optionscatalogo, t, products, sortTable, sortAttribute, sortDirection, getFieldValue, getFieldClass, getFieldStyle, getFieldClick, handleUpdate, exportToCSV, } } })