{"id":2207,"date":"2026-09-03T14:53:34","date_gmt":"2026-09-03T14:53:34","guid":{"rendered":"https:\/\/prueba.empremart.cl\/tablas\/?page_id=2207"},"modified":"2026-09-03T14:53:35","modified_gmt":"2026-09-03T14:53:35","slug":"plugin-para-wp-data-access","status":"publish","type":"page","link":"https:\/\/prueba.empremart.cl\/tablas\/plugin-para-wp-data-access\/","title":{"rendered":"Plugin para wp data access"},"content":{"rendered":"    <script>\r\n        window.WPDA_CONFIG = {\"selectUrl\":\"https:\\\/\\\/prueba.empremart.cl\\\/tablas\\\/wp-json\\\/wpda\\\/table\\\/select\",\"updateUrl\":\"https:\\\/\\\/prueba.empremart.cl\\\/tablas\\\/wp-json\\\/wpda\\\/table\\\/update\",\"nonce\":\"89e422fe2c\",\"dbs\":\"adminmanager_wp415\",\"tbl\":\"wpda_ventas_productos\"};\r\n    <\/script>\r\n\r\n    <div x-data=\"catalogoProductos()\" x-init=\"cargarProductos()\" class=\"wpda-catalogo-container\" style=\"max-width: 950px; margin: 20px auto; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\">\r\n        \r\n        <!-- Barra de B\u00fasqueda y Controles -->\r\n        <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; gap: 10px;\">\r\n            <input \r\n                type=\"text\" \r\n                x-model=\"search\" \r\n                @input.debounce.400ms=\"cargarProductos(0)\" \r\n                placeholder=\"Buscar producto...\" \r\n                style=\"flex: 1; padding: 10px; border: 1px solid #ccd0d4; border-radius: 6px; font-size: 14px;\"\r\n            \/>\r\n            <button \r\n                @click=\"cargarProductos(pageIndex)\" \r\n                style=\"padding: 10px 16px; background: #2271b1; color: #fff; border: none; border-radius: 6px; cursor: pointer; font-weight: 500;\">\r\n                Refrescar\r\n            <\/button>\r\n        <\/div>\r\n\r\n        <!-- Estado de Notificaci\u00f3n \/ Mensajes -->\r\n        <div x-show=\"mensajeExito\" style=\"background: #edf7ed; color: #1e4620; border-left: 4px solid #4caf50; padding: 12px; margin-bottom: 15px;\" x-text=\"mensajeExito\"><\/div>\r\n        <div x-show=\"error\" style=\"background: #fcf0f1; border-left: 4px solid #d63638; color: #3c434a; padding: 12px; margin-bottom: 15px;\" x-text=\"error\"><\/div>\r\n\r\n        <!-- Cargando -->\r\n        <div x-show=\"loading\" style=\"text-align: center; padding: 25px; color: #646970;\">\r\n            <span>Consultando datos...<\/span>\r\n        <\/div>\r\n\r\n        <!-- Tabla de Datos -->\r\n        <div x-show=\"!loading\" style=\"overflow-x: auto; box-shadow: 0 1px 3px rgba(0,0,0,0.1); border-radius: 6px; background: #fff;\">\r\n            <table style=\"width: 100%; border-collapse: collapse; text-align: left; font-size: 14px;\">\r\n                <thead>\r\n                    <tr style=\"background: #f6f7f7; border-bottom: 1px solid #dcdcde;\">\r\n                        <th style=\"padding: 12px 16px;\">ID<\/th>\r\n                        <th style=\"padding: 12px 16px;\">Producto<\/th>\r\n                        <th style=\"padding: 12px 16px;\">Categor\u00eda<\/th>\r\n                        <th style=\"padding: 12px 16px; text-align: right;\">Precio<\/th>\r\n                        <th style=\"padding: 12px 16px; text-align: center;\">Acciones<\/th>\r\n                    <\/tr>\r\n                <\/thead>\r\n                <tbody>\r\n                    <template x-for=\"item in productos\" :key=\"item.id_producto\">\r\n                        <tr style=\"border-bottom: 1px solid #f0f0f1;\">\r\n                            <td style=\"padding: 12px 16px;\" x-text=\"item.id_producto\"><\/td>\r\n                            <td style=\"padding: 12px 16px; font-weight: 500;\" x-text=\"item.nombre_producto\"><\/td>\r\n                            <td style=\"padding: 12px 16px;\" x-text=\"'Cat #' + item.id_categoria\"><\/td>\r\n                            <td style=\"padding: 12px 16px; text-align: right; color: #1e8cbe; font-weight: 600;\" x-text=\"'$' + Number(item.precio).toLocaleString('es-CL')\"><\/td>\r\n                            <td style=\"padding: 12px 16px; text-align: center;\">\r\n                                <button \r\n                                    @click=\"abrirModalEdicion(item)\" \r\n                                    style=\"padding: 6px 12px; background: #f0f0f1; border: 1px solid #8c8f94; border-radius: 4px; cursor: pointer; font-size: 12px;\">\r\n                                    Editar\r\n                                <\/button>\r\n                            <\/td>\r\n                        <\/tr>\r\n                    <\/template>\r\n                    <tr x-show=\"productos.length === 0\">\r\n                        <td colspan=\"5\" style=\"text-align: center; padding: 25px; color: #a7aaad;\">No se encontraron registros.<\/td>\r\n                    <\/tr>\r\n                <\/tbody>\r\n            <\/table>\r\n        <\/div>\r\n\r\n        <!-- Paginaci\u00f3n -->\r\n        <div style=\"display: flex; justify-content: space-between; align-items: center; margin-top: 15px;\">\r\n            <small style=\"color: #646970;\" x-text=\"`Mostrando ${productos.length} de ${totalRows} productos`\"><\/small>\r\n            <div style=\"display: flex; gap: 8px;\">\r\n                <button \r\n                    @click=\"cargarProductos(pageIndex - 1)\" \r\n                    :disabled=\"pageIndex === 0 || loading\" \r\n                    style=\"padding: 6px 12px; border: 1px solid #ccd0d4; border-radius: 4px; cursor: pointer; background: #f6f7f7;\">\r\n                    &laquo; Anterior\r\n                <\/button>\r\n                <span style=\"align-self: center; font-size: 13px; color: #3c434a;\" x-text=\"`P\u00e1g. ${pageIndex + 1}`\"><\/span>\r\n                <button \r\n                    @click=\"cargarProductos(pageIndex + 1)\" \r\n                    :disabled=\"(pageIndex + 1) * pageSize >= totalRows || loading\" \r\n                    style=\"padding: 6px 12px; border: 1px solid #ccd0d4; border-radius: 4px; cursor: pointer; background: #f6f7f7;\">\r\n                    Siguiente &raquo;\r\n                <\/button>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- Modal de Edici\u00f3n -->\r\n        <div \r\n            x-show=\"modalAbierto\" \r\n            style=\"position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 9999;\"\r\n            x-cloak>\r\n            \r\n            <div @click.away=\"modalAbierto = false\" style=\"background: #fff; border-radius: 8px; width: 100%; max-width: 450px; padding: 24px; box-shadow: 0 4px 20px rgba(0,0,0,0.15);\">\r\n                <h3 style=\"margin-top: 0; margin-bottom: 20px; font-size: 18px; border-bottom: 1px solid #eee; padding-bottom: 10px;\">\r\n                    Editar Producto #<span x-text=\"formEdicion.id_producto\"><\/span>\r\n                <\/h3>\r\n\r\n                <form @submit.prevent=\"guardarEdicion()\">\r\n                    <div style=\"margin-bottom: 15px;\">\r\n                        <label style=\"display: block; font-weight: 500; font-size: 13px; margin-bottom: 5px;\">Nombre del Producto<\/label>\r\n                        <input \r\n                            type=\"text\" \r\n                            x-model=\"formEdicion.nombre_producto\" \r\n                            required \r\n                            style=\"width: 100%; padding: 8px 12px; border: 1px solid #ccd0d4; border-radius: 4px; box-sizing: border-box;\"\r\n                        \/>\r\n                    <\/div>\r\n\r\n                    <div style=\"margin-bottom: 15px;\">\r\n                        <label style=\"display: block; font-weight: 500; font-size: 13px; margin-bottom: 5px;\">ID Categor\u00eda<\/label>\r\n                        <input \r\n                            type=\"number\" \r\n                            x-model.number=\"formEdicion.id_categoria\" \r\n                            required \r\n                            style=\"width: 100%; padding: 8px 12px; border: 1px solid #ccd0d4; border-radius: 4px; box-sizing: border-box;\"\r\n                        \/>\r\n                    <\/div>\r\n\r\n                    <div style=\"margin-bottom: 20px;\">\r\n                        <label style=\"display: block; font-weight: 500; font-size: 13px; margin-bottom: 5px;\">Precio ($)<\/label>\r\n                        <input \r\n                            type=\"number\" \r\n                            x-model.number=\"formEdicion.precio\" \r\n                            required \r\n                            style=\"width: 100%; padding: 8px 12px; border: 1px solid #ccd0d4; border-radius: 4px; box-sizing: border-box;\"\r\n                        \/>\r\n                    <\/div>\r\n\r\n                    <div style=\"display: flex; justify-content: flex-end; gap: 10px;\">\r\n                        <button \r\n                            type=\"button\" \r\n                            @click=\"modalAbierto = false\" \r\n                            style=\"padding: 8px 16px; border: 1px solid #ccd0d4; border-radius: 4px; background: #fff; cursor: pointer;\">\r\n                            Cancelar\r\n                        <\/button>\r\n                        <button \r\n                            type=\"submit\" \r\n                            :disabled=\"guardando\" \r\n                            style=\"padding: 8px 16px; border: none; border-radius: 4px; background: #2271b1; color: #fff; cursor: pointer; font-weight: 500;\">\r\n                            <span x-text=\"guardando ? 'Guardando...' : 'Guardar Cambios'\"><\/span>\r\n                        <\/button>\r\n                    <\/div>\r\n                <\/form>\r\n            <\/div>\r\n        <\/div>\r\n\r\n    <\/div>\r\n\r\n    <!-- Componente Reactivo Alpine.js -->\r\n    <script>\r\n    function catalogoProductos() {\r\n        return {\r\n            productos: [],\r\n            loading: false,\r\n            guardando: false,\r\n            error: null,\r\n            mensajeExito: null,\r\n            search: '',\r\n            pageIndex: 0,\r\n            pageSize: 5,\r\n            totalRows: 0,\r\n            modalAbierto: false,\r\n            formEdicion: {\r\n                id_producto: null,\r\n                nombre_producto: '',\r\n                id_categoria: 1,\r\n                precio: 0\r\n            },\r\n\r\n            async cargarProductos(page = 0) {\r\n                this.pageIndex = Math.max(0, page);\r\n                this.loading = true;\r\n                this.error = null;\r\n\r\n                const config = window.WPDA_CONFIG;\r\n                try {\r\n                    const response = await fetch(config.selectUrl, {\r\n                        method: 'POST',\r\n                        headers: {\r\n                            'Content-Type': 'application\/json',\r\n                            'X-WP-Nonce': config.nonce\r\n                        },\r\n                        body: JSON.stringify({\r\n                            dbs: config.dbs,\r\n                            tbl: config.tbl,\r\n                            page_index: this.pageIndex,\r\n                            page_size: this.pageSize,\r\n                            search: this.search\r\n                        })\r\n                    });\r\n\r\n                    if (!response.ok) throw new Error(`Error ${response.status}: ${response.statusText}`);\r\n\r\n                    const res = await response.json();\r\n                    if (res.code === 'ok' || Array.isArray(res.data)) {\r\n                        this.productos = res.data || [];\r\n                        this.totalRows = (res.meta && res.meta.rowCount !== undefined) \r\n                            ? parseInt(res.meta.rowCount, 10) \r\n                            : this.productos.length;\r\n                    } else {\r\n                        throw new Error(res.message || 'Error al obtener los datos.');\r\n                    }\r\n                } catch (err) {\r\n                    this.error = err.message;\r\n                    this.productos = [];\r\n                } finally {\r\n                    this.loading = false;\r\n                }\r\n            },\r\n\r\n            abrirModalEdicion(item) {\r\n                this.formEdicion = {\r\n                    id_producto: item.id_producto,\r\n                    nombre_producto: item.nombre_producto,\r\n                    id_categoria: Number(item.id_categoria),\r\n                    precio: Number(item.precio)\r\n                };\r\n                this.modalAbierto = true;\r\n                this.error = null;\r\n                this.mensajeExito = null;\r\n            },\r\n\r\n            async guardarEdicion() {\r\n                this.guardando = true;\r\n                this.error = null;\r\n                this.mensajeExito = null;\r\n\r\n                const config = window.WPDA_CONFIG;\r\n\r\n                try {\r\n                    const response = await fetch(config.updateUrl, {\r\n                        method: 'POST',\r\n                        headers: {\r\n                            'Content-Type': 'application\/json',\r\n                            'X-WP-Nonce': config.nonce\r\n                        },\r\n                        body: JSON.stringify({\r\n                            dbs: config.dbs,\r\n                            tbl: config.tbl,\r\n                            key: {\r\n                                id_producto: this.formEdicion.id_producto\r\n                            },\r\n                            val: {\r\n                                nombre_producto: this.formEdicion.nombre_producto,\r\n                                id_categoria: this.formEdicion.id_categoria,\r\n                                precio: this.formEdicion.precio\r\n                            }\r\n                        })\r\n                    });\r\n\r\n                    if (!response.ok) throw new Error(`Error ${response.status}: Fallo al actualizar el registro.`);\r\n\r\n                    const res = await response.json();\r\n\r\n                    if (res.code === 'ok') {\r\n                        this.modalAbierto = false;\r\n                        this.mensajeExito = `Producto #${this.formEdicion.id_producto} actualizado exitosamente.`;\r\n                        await this.cargarProductos(this.pageIndex);\r\n                        setTimeout(() => this.mensajeExito = null, 4000);\r\n                    } else {\r\n                        throw new Error(res.message || 'El motor rechaz\u00f3 la actualizaci\u00f3n.');\r\n                    }\r\n                } catch (err) {\r\n                    this.error = err.message;\r\n                } finally {\r\n                    this.guardando = false;\r\n                }\r\n            }\r\n        };\r\n    }\r\n    <\/script>\r\n    \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-2207","page","type-page","status-publish","hentry"],"acf":[],"ams_acf":[],"mb":[],"mfb_acf":[],"ase":null,"mfb_rest_fields":["title","ams_acf","ase"],"_links":{"self":[{"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/pages\/2207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/comments?post=2207"}],"version-history":[{"count":1,"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/pages\/2207\/revisions"}],"predecessor-version":[{"id":2208,"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/pages\/2207\/revisions\/2208"}],"wp:attachment":[{"href":"https:\/\/prueba.empremart.cl\/tablas\/wp-json\/wp\/v2\/media?parent=2207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}