diff --git a/ci4/app/Controllers/Clientes/ClientePrecios.php b/ci4/app/Controllers/Clientes/ClientePrecios.php index 2a73ba78..bc258921 100755 --- a/ci4/app/Controllers/Clientes/ClientePrecios.php +++ b/ci4/app/Controllers/Clientes/ClientePrecios.php @@ -108,16 +108,18 @@ class ClientePrecios extends \App\Controllers\BaseResourceController $dir3 = $reqData['order']['2']['dir'] ?? $dir; $dir4= $reqData['order']['3']['dir'] ?? $dir; $dir5= $reqData['order']['4']['dir'] ?? $dir; + + $searchValues = get_filter_datatables_columns($reqData); $cliente_id = $reqData['cliente_id'] ?? 0; - $resourceData = $this->model->getResource($cliente_id) + $resourceData = $this->model->getResource($searchValues, $cliente_id) ->orderBy($order, $dir)->orderBy($order2, $dir2)->orderBy($order3, $dir3)->orderBy($order4, $dir4)->orderBy($order5, $dir5) ->limit($length, $start)->get()->getResultObject(); return $this->respond(Collection::datatable( $resourceData, - $this->model->getResource($cliente_id)->countAllResults(), - $this->model->getResource($cliente_id)->countAllResults() + $this->model->getResource($searchValues, $cliente_id)->countAllResults(), + $this->model->getResource($searchValues, $cliente_id)->countAllResults() )); } else { return $this->failUnauthorized('Invalid request', 403); diff --git a/ci4/app/Models/Clientes/ClientePreciosModel.php b/ci4/app/Models/Clientes/ClientePreciosModel.php index a52893c8..3bfbdb1d 100755 --- a/ci4/app/Models/Clientes/ClientePreciosModel.php +++ b/ci4/app/Models/Clientes/ClientePreciosModel.php @@ -256,7 +256,7 @@ class ClientePreciosModel extends \App\Models\BaseModel * * @return \CodeIgniter\Database\BaseBuilder */ - public function getResource($cliente_id = -1) + public function getResource($search = [], $cliente_id = -1) { $builder = $this->db ->table($this->table . " t1") @@ -271,9 +271,20 @@ class ClientePreciosModel extends \App\Models\BaseModel $builder->where('t1.is_deleted', 0); $builder->where('t1.cliente_id', $cliente_id); - - return $builder; + if (empty($search)) + return $builder; + else { + $builder->groupStart(); + foreach ($search as $col_search) { + if ($col_search[0] > 2) + $builder->like(self::SORTABLE[$col_search[0]], $col_search[2]); + else + $builder->where(self::SORTABLE[$col_search[0]], $col_search[2]); + } + $builder->groupEnd(); + return $builder; + } } diff --git a/ci4/app/Views/themes/vuexy/form/clientes/cliente/_clienteFormItems.php b/ci4/app/Views/themes/vuexy/form/clientes/cliente/_clienteFormItems.php index f66999c1..dc3e7967 100644 --- a/ci4/app/Views/themes/vuexy/form/clientes/cliente/_clienteFormItems.php +++ b/ci4/app/Views/themes/vuexy/form/clientes/cliente/_clienteFormItems.php @@ -591,10 +591,10 @@ - - - plantilla_id - + + + plantilla_id + @@ -924,7 +924,7 @@ $(document).on('click', '.btn-remove', function(e) { `; }; - +/* const tipo_linea = [ {label:'', value:'interior'}, {label:'', value: 'cubierta'}, @@ -1045,7 +1045,7 @@ $(document).on('click', '.btn-remove', function(e) { } }) }) - +*/ /* var theTablePrecios = $('#tableOfPrecios').DataTable( { diff --git a/ci4/app/Views/themes/vuexy/form/clientes/cliente/viewClienteForm.php b/ci4/app/Views/themes/vuexy/form/clientes/cliente/viewClienteForm.php index 9c3eb039..a149252e 100644 --- a/ci4/app/Views/themes/vuexy/form/clientes/cliente/viewClienteForm.php +++ b/ci4/app/Views/themes/vuexy/form/clientes/cliente/viewClienteForm.php @@ -43,5 +43,8 @@ section("additionalExternalJs") ?> + + + endSection() ?> \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/table.js b/httpdocs/assets/js/safekat/components/table.js new file mode 100644 index 00000000..83ea0bee --- /dev/null +++ b/httpdocs/assets/js/safekat/components/table.js @@ -0,0 +1,175 @@ +let Table = function ( + domItem, + alias, + url, + columns, + data, + language = "es-ES") { + + this.domItem = domItem; + this.alias = alias; + this.url = url; + this.columns = columns; + this.data = data; + this.language = language; + + this.table = null; + this.actions = []; // Declaración inicial de actions como propiedad + this.deleteModal = null; + + const self = this; + + this.init = function ({ + dom = '<"mt-4"><"float-end"B><"float-start"l><"mt-4 mb-3"p>', + actions = ['view', 'edit', 'delete', 'cancel'], + order = [[0, 'asc']], + deleteModal = null, + buttonsExport = true, + buttonNewWithEditor = false, + editor = null, + booleanColumns = [], + } = {}) { + + this.actions = actions; // Guardar actions como propiedad de la instancia + this.deleteModal = deleteModal; + + const lastColNr = this.domItem.find("tr:first th").length - 1; + + let columnDefs = []; + if (actions.length > 0) { + columnDefs = [ + { + orderable: false, + searchable: false, + targets: [lastColNr] + } + ]; + columns.push( + { + 'data': self.actionBtns.bind(self), // Vincular correctamente el contexto + 'className': 'row-edit dt-center', + } + ); + } + + let buttons = []; + if (buttonsExport) { + buttons = [ + { + extend: 'colvis', + columns: ':not(.noVis)', + + }, + 'copy', 'csv', 'excel', 'print', { + extend: 'pdfHtml5', + orientation: 'landscape', + pageSize: 'A4' + } + ]; + } + if (buttonNewWithEditor) { + buttons.push( + { + className: 'btn btn-primary me-sm-3 me-1', + extend: "createInline", + editor: editor, + formOptions: { + submitTrigger: -1, + submitHtml: '' + } + } + ); + } + + // Inicialización de DataTable + this.table = this.domItem.DataTable({ + processing: true, + serverSide: true, + autoWidth: true, + responsive: true, + scrollX: true, + stateSave: false, + lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500], + order: order, + orderCellsTop: true, + fixedHeader: true, + dom: dom, + ajax: $.fn.dataTable.pipeline({ + url: this.url, + method: 'POST', + headers: { 'X-Requested-With': 'XMLHttpRequest' }, + data: function (d) { + $.each(self.data, function (key, val) { + d[val.name] = val.value; + }); + }, + async: true, + }), + buttons: buttons, + columns: this.columns, + language: { + url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/" + this.language + ".json" + }, + columnDefs: columnDefs, + }); + + if (Array.isArray(booleanColumns) && booleanColumns.length > 0) { + this.table.on('draw.dt', function () { + for (let coln of booleanColumns) { + self.table.column(coln, { page: 'current' }).nodes().each(function (cell) { + cell.innerHTML = cell.innerHTML == '1' ? '' : ''; + }); + } + }); + } + }; + + this.setData = function (data) { + this.data = data; + } + + this.setPageLength = function (length) { + this.table.page.len(length).draw(); + } + + this.setEditCallback = function (callback) { + this.domItem.on('click', '.btn-edit-' + this.alias, function () { + let id = $(this).data('id'); + callback(id); + }); + } + + this.setDeleteCallback = function (callback) { + this.domItem.on('click', '.btn-delete-' + this.alias, function () { + let id = $(this).data('id'); + callback(id); + }); + } + + this.setViewCallback = function (callback) { + this.domItem.on('click', '.btn-view-' + this.alias, function () { + let id = $(this).data('id'); + callback(id); + }); + } + + this.actionBtns = function (data) { + let btns = ``; + if (this.actions.includes('view')) { + btns += ``; + } + if (this.actions.includes('edit')) { + btns += ``; + } + if (this.actions.includes('delete')) { + btns += ``; + } + if (this.actions.includes('cancel')) { + btns += ``; + } + return btns; + }; + +} + +export default Table; diff --git a/httpdocs/assets/js/safekat/components/tableEditor.js b/httpdocs/assets/js/safekat/components/tableEditor.js new file mode 100644 index 00000000..89b12369 --- /dev/null +++ b/httpdocs/assets/js/safekat/components/tableEditor.js @@ -0,0 +1,32 @@ +let TableEditor = function ( + table, + url, + headers, + idSrc, + fields) { + + + this.table = table; + this.url = url; + this.headers = headers; + this.idSrc = idSrc; + this.fields = fields; + + this.editor = null; + + this.init = function () { + + this.editor = new $.fn.dataTable.Editor( { + ajax: { + url: url, + headers: headers, + }, + table : table, + idSrc: idSrc, + fields: fields + }); + }; +} + +export default TableEditor; + diff --git a/httpdocs/assets/js/safekat/pages/cliente/cliente.js b/httpdocs/assets/js/safekat/pages/cliente/cliente.js index 0bd83277..0ef85e60 100644 --- a/httpdocs/assets/js/safekat/pages/cliente/cliente.js +++ b/httpdocs/assets/js/safekat/pages/cliente/cliente.js @@ -57,6 +57,8 @@ class Cliente { document.addEventListener('DOMContentLoaded', function () { const locale = document.querySelector('meta[name="locale"]').getAttribute('content'); + + new Ajax('/translate/getTranslation', { locale: locale, translationFile: ['ClienteContactos', 'ClientePrecios'] }, {}, function(translations) { diff --git a/httpdocs/assets/js/safekat/pages/cliente/tarifasCliente.js b/httpdocs/assets/js/safekat/pages/cliente/tarifasCliente.js index 55d61ad0..5e6ad756 100644 --- a/httpdocs/assets/js/safekat/pages/cliente/tarifasCliente.js +++ b/httpdocs/assets/js/safekat/pages/cliente/tarifasCliente.js @@ -1,6 +1,8 @@ import Table from '../../components/table.js'; +import TableEditor from '../../components/tableEditor.js'; import { getToken } from '../../common/common.js'; + class tarifasClienteView { constructor(domItem) { @@ -12,12 +14,148 @@ class tarifasClienteView { this.clienteId = window.location.href.split("/").pop(); this.actions = ['edit', 'delete']; + + this.headerSearcher(); + + this.tableTarifas = null; + this.editorTarifas = null; } init() { const self = this; + const tipo_linea = [ + { label: window.language.ClientePrecios.interior, value: 'interior' }, + { label: window.language.ClientePrecios.cubierta, value: 'cubierta' }, + { label: window.language.ClientePrecios.sobrecubierta, value: 'sobrecubierta' } + ]; + + const tipo_maquina = [ + { label: window.language.ClientePrecios.toner, value: 'toner' }, + { label: window.language.ClientePrecios.inkjet, value: 'inkjet' }, + ]; + + const tipo_impresion = [ + { label: window.language.ClientePrecios.negro, value: 'negro' }, + { label: window.language.ClientePrecios.negrohq, value: 'negrohq' }, + { label: window.language.ClientePrecios.color, value: 'color' }, + { label: window.language.ClientePrecios.colorhq, value: 'colorhq' }, + ]; + + const editorFields = [{ + name: "tipo", + type: "select", + options: tipo_linea + }, { + name: "tipo_maquina", + type: "select", + options: tipo_maquina + }, { + name: "tipo_impresion", + type: "select", + options: tipo_impresion + }, { + name: "tiempo_min" + }, { + name: "tiempo_max" + }, { + name: "precio_hora" + }, { + name: "margen" + }, { + name: "user_updated_id", + type: 'hidden', + + }, { + name: "updated_at", + type: 'hidden', + + }, { + "name": "plantilla_id", + "type": "hidden" + }, { + "name": "cliente_id", + "type": "hidden" + }, { + "name": "deleted_at", + "type": "hidden" + }, { + "name": "is_deleted", + "type": "hidden" + }, + ]; + this.editorTarifas = new TableEditor( + $('#tableOfPrecios'), + '/clienteprecios/datatable_editor', + { [this.csrf_token]: this.csrf_hash }, + editorFields); + + this.editorTarifas.init(); + + this.editorTarifas.editor.on('preSubmit', function (e, d, type) { + if (type === 'create') { + d.data[0]['cliente_id'] = this.clienteId; + } + else if (type === 'edit') { + for (v in d.data) { + d.data[v]['cliente_id'] = this.clienteId; + } + } + }); + + this.editorTarifas.editor.on('submitSuccess', function (e, json, data, action) { + + this.tableTarifas.table.clearPipeline(); + this.tableTarifas.table.draw(); + }); + + this.editorTarifas.editor.on('postEdit', function (e, json, data, action) { + /*const domain = window.location.origin + fetch(domain + "/clientes/clienteprecios/update/" + id, { + method: "POST", + body: JSON.stringify({ + : v + }), + headers: { + "Content-type": "application/json; charset=UTF-8" + } + })*/ + }) + + this.editorTarifas.editor.on('postCreate', function (e, json, data, action) { + const domain = window.location.origin + /*fetch(domain + "/clientes/clienteprecios/update/" + id, { + method: "POST", + body: JSON.stringify({ + : v + }), + headers: { + "Content-type": "application/json; charset=UTF-8" + } + })*/ + }) + this.#initTable(); + + this.tableTarifas.table.on( 'click', 'tbody span.edit', function (e) { + self.editorTarifas.editor.inline( + self.tableTarifas.table.cells(this.parentNode.parentNode, '*').nodes(), + { + cancelHtml: '', + cancelTrigger: 'span.cancel', + submitHtml: '', + submitTrigger: 'span.edit', + submit: 'allIfChanged' + } + ); + } ); + } + + + #initTable() { + + const self = this; + const columns = [ { 'data': 'tipo', @@ -58,9 +196,14 @@ class tarifasClienteView { { 'data': 'margen' }, { 'data': 'user_updated' }, { 'data': 'updated_at' }, - { 'data': 'plantilla_id' }, + { + 'data': 'plantilla_id', + 'searchable': false, + 'visible': false, + }, ]; + this.tableTarifas = new Table( $('#tableOfPrecios'), 'tarifasCliente', @@ -72,20 +215,116 @@ class tarifasClienteView { ] ); + this.tableTarifas.init({ actions: ['edit', 'delete'], - buttonsNewEditor: true, - + buttonNewWithEditor: true, + buttonsExport: true, + editor: this.editorTarifas.editor, }); - $('button[data-bs-target="#tarifascliente"]').on('shown.bs.tab', function(event) { + + this.tableTarifas.table.on('init.dt', function () { + self.tableTarifas.table.page.len(50).draw(); + }); + + $('button[data-bs-target="#tarifascliente"]').on('shown.bs.tab', function (event) { setTimeout(() => { self.tableTarifas.table.columns.adjust().draw(); - }, 100); // Usamos setTimeout para asegurar que se dibuje después del renderizado + }, 1000); // Usamos setTimeout para asegurar que se dibuje después del renderizado }); + } + headerSearcher() { + const self = this; + + $('#tableOfPrecios thead tr').clone(false).appendTo('#tableOfPrecios thead'); + $('#tableOfPrecios thead tr:eq(1) th').each(function (i) { + + if (!$(this).hasClass("noFilter")) { + + if (i == 0) { + + // Agregar un selector en la segunda columna + $(this).html(''); + + // Agregar opciones al selector + var selector = $('select', this); + selector.append(''); // Opción vacía + selector.append(''); + selector.append(''); + selector.append(''); + + selector.on('change', function () { + var val = $.fn.dataTable.util.escapeRegex( + $(this).val() + ); + self.tableTarifas.table.column(i).search(val).draw(); + }); + + } + + else if (i == 1) { + // Agregar un selector en la tercera columna + $(this).html(''); + + // Agregar opciones al selector + var selector = $('select', this); + selector.append(''); // Opción vacía + selector.append(''); + selector.append(''); + + selector.on('change', function () { + var val = $.fn.dataTable.util.escapeRegex( + $(this).val() + ); + self.tableTarifas.table.column(i).search(val).draw(); + }); + } + + else if (i == 2) { + // Agregar un selector en la cuarta columna + $(this).html(''); + + // Agregar opciones al selector + var selector = $('select', this); + selector.append(''); // Opción vacía + selector.append(''); + selector.append(''); + selector.append(''); + selector.append(''); + + selector.on('change', function () { + var val = $.fn.dataTable.util.escapeRegex( + $(this).val() + ); + self.tableTarifas.table.column(i).search(val).draw(); + }); + } + else { + $(this).html(''); + + $('input', this).on('change clear', function () { + if (self.tableTarifas.table.column(i).search() !== this.value) { + self.tableTarifas.table + .column(i) + .search(this.value) + .draw(); + } + }); + } + } + else { + $(this).html(''); + } + }); + + + } } + + export default tarifasClienteView; \ No newline at end of file