diff --git a/ci4/app/Entities/Mensajeria/ConversacionEntity.php b/ci4/app/Entities/Mensajeria/ConversacionEntity.php
new file mode 100644
index 00000000..4ee45b16
--- /dev/null
+++ b/ci4/app/Entities/Mensajeria/ConversacionEntity.php
@@ -0,0 +1,28 @@
+ null,
+ 'pedido_libro_id' => null,
+ 'pedido_maquetacion_id' => null,
+ 'factura_id' => null,
+ 'departamento' => null,
+ 'asunto' => null,
+ 'created_at' => null,
+ 'updated_at' => null,
+ 'deleted_at' => null,
+ ];
+
+ protected $casts = [
+ "pedido_libro_id" => "?int",
+ "pedido_maquetacion_id" => "?int",
+ "factura_id" => "?int"
+ ];
+
+
+}
diff --git a/ci4/app/Entities/Mensajeria/ParticipanteEntity.php b/ci4/app/Entities/Mensajeria/ParticipanteEntity.php
new file mode 100644
index 00000000..6a38ebab
--- /dev/null
+++ b/ci4/app/Entities/Mensajeria/ParticipanteEntity.php
@@ -0,0 +1,26 @@
+ null,
+ 'conversacion_id' => null,
+ 'usuario_id' => null,
+ 'cliente_id' => null,
+ 'email' => null,
+ 'last_read' => null,
+ 'created_at' => null,
+ 'updated_at' => null,
+ 'deleted_at' => null,
+ ];
+
+ protected $casts = [
+ "conversacion_id" => "?int",
+ "usuario_id" => "?int",
+ "cliente_id" => "?int"
+ ];
+}
diff --git a/ci4/app/Models/Mensajeria/ConversacionModel.php b/ci4/app/Models/Mensajeria/ConversacionModel.php
new file mode 100644
index 00000000..32aff33d
--- /dev/null
+++ b/ci4/app/Models/Mensajeria/ConversacionModel.php
@@ -0,0 +1,138 @@
+db
+ ->table('pedido_libros')
+ ->where('id', $this->pedido_libro_id)
+ ->get()
+ ->getFirstRow();
+ }
+
+ public function pedidoMaquetacion()
+ {
+ return $this->db
+ ->table('pedido_maquetaciones')
+ ->where('id', $this->pedido_maquetacion_id)
+ ->get()
+ ->getFirstRow();
+ }
+
+ public function factura()
+ {
+ return $this->db
+ ->table('facturas')
+ ->where('id', $this->factura_id)
+ ->get()
+ ->getFirstRow();
+ }
+
+ /**
+ * Devuelve si la conversacion tiene algún cliente
+ */
+ public function isClient()
+ {
+ $isCliente = false;
+ $participantes = $this->participantes(); // Asegúrate de implementar este método
+ foreach ($participantes as $p) {
+ if (($p->user && $p->user->customer_id) || $p->customer_id) {
+ $isCliente = true;
+ break;
+ }
+ }
+
+ return $isCliente;
+ }
+
+ /**
+ * Comprueba si la conversacion del mensaje tiene el cliente
+ */
+ public function haveCliente($userCustomer)
+ {
+ $customer_id = $userCustomer->customer_id;
+ $participants = $this->participantes(); // Asegúrate de implementar este método
+
+ foreach ($participants as $p) {
+ if ($p->customer_id && $p->customer_id === $customer_id) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public function getParticipanteDesdeCliente($cliente_id)
+ {
+ return $this->db->table('chat_participantes')
+ ->where('cliente_id', $cliente_id)
+ ->where('conversacion_id', $this->id)
+ ->get()
+ ->getFirstRow();
+ }
+
+ public function marcarLeidoCliente($cliente_id)
+ {
+ try {
+ $participante = $this->getParticipanteDesdeCliente($cliente_id);
+ if ($participante) {
+ $this->db->table('chat_participantes')
+ ->where('id', $participante->id)
+ ->update(['last_read' => date('Y-m-d H:i:s')]);
+ }
+ } catch (\Exception $e) {
+ // do nothing
+ }
+ }
+
+ public function marcarNoLeido($usuario_id)
+ {
+ try {
+ $participante = $this->getParticipanteDesdeUsuario($usuario_id); // Asegúrate de implementar este método
+ if ($participante) {
+ $this->db->table('chat_participantes')
+ ->where('id', $participante->id)
+ ->update(['last_read' => null]);
+ }
+ } catch (\Exception $e) {
+ // do nothing
+ }
+ }
+
+ protected function participantes()
+ {
+ return $this->db
+ ->table('chat_participantes')
+ ->where('conversacion_id', $this->id)
+ ->get()
+ ->getResult();
+ }
+
+ protected function getParticipanteDesdeUsuario($usuario_id)
+ {
+ return $this->db->table('chat_participantes')
+ ->where('usuario_id', $usuario_id)
+ ->where('conversacion_id', $this->id)
+ ->get()
+ ->getFirstRow();
+ }
+}
diff --git a/ci4/app/Models/Mensajeria/ParticipanteModel.php b/ci4/app/Models/Mensajeria/ParticipanteModel.php
new file mode 100644
index 00000000..f20c177e
--- /dev/null
+++ b/ci4/app/Models/Mensajeria/ParticipanteModel.php
@@ -0,0 +1,30 @@
+find($this->attributes['customer_id']);
+ }
+}
diff --git a/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/_mensajeria.php b/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/_mensajeria.php
new file mode 100644
index 00000000..86abbe58
--- /dev/null
+++ b/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/_mensajeria.php
@@ -0,0 +1,498 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
How can we help? We're here for you! 😄
+
+
+
+ 10:00 AM
+
+
+
+
+

+
+
+
+
+ -
+
+
+
+

+
+
+
+
+
Hey John, I am looking for the best admin template.
+
Could you please help me to find it out? 🤔
+
+
+
It should be Bootstrap 5 compatible.
+
+
+ 10:02 AM
+
+
+
+
+ -
+
+
+
+
Vuexy has all the components you'll ever need in a app.
+
+
+
+ 10:03 AM
+
+
+
+
+

+
+
+
+
+ -
+
+
+
+

+
+
+
+
+
Looks clean and fresh UI. 😃
+
+
+
It's perfect for my next project.
+
+
+
How can I purchase it?
+
+
+ 10:05 AM
+
+
+
+
+ -
+
+
+
+
Thanks, you can purchase it.
+
+
+
+ 10:06 AM
+
+
+
+
+

+
+
+
+
+ -
+
+
+
+

+
+
+
+
+
I will purchase it for sure. 👍
+
+
+
+ 10:08 AM
+
+
+
+
+ -
+
+
+
+
Great, Feel free to get in touch.
+
+
+
+ 10:10 AM
+
+
+
+
+

+
+
+
+
+ -
+
+
+
+

+
+
+
+
+
Do you have design files for Vuexy?
+
+
+ 10:15 AM
+
+
+
+
+ -
+
+
+
+
+ Yes that's correct documentation file, Design files are included with
+ the template.
+
+
+
+
+ 10:15 AM
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+= $this->section("additionalInlineJs") ?>
+
+/**
+ * App Chat
+ */
+
+// Seleccionar elementos del DOM
+const chatContactsBody = document.querySelector('.app-chat-contacts .sidebar-body'),
+ chatContactListItems = [].slice.call(
+ document.querySelectorAll('.chat-contact-list-item:not(.chat-contact-list-item-title)')
+ ),
+ chatHistoryBody = document.querySelector('.chat-history-body'),
+ chatSidebarLeftUserAbout = document.querySelector('.chat-sidebar-left-user-about'),
+ messageInput = document.querySelector('.message-input'),
+ searchInput = document.querySelector('.chat-search-input'),
+ sendMsgBtn = document.querySelector('.send-msg-btn'); // Seleccionar el botón de envío de mensaje
+
+// Inicializar PerfectScrollbar
+if (chatContactsBody) {
+ new PerfectScrollbar(chatContactsBody, {
+ wheelPropagation: false,
+ suppressScrollX: true
+ });
+}
+
+if (chatHistoryBody) {
+ new PerfectScrollbar(chatHistoryBody, {
+ wheelPropagation: false,
+ suppressScrollX: true
+ });
+}
+
+// Función para desplazar el scroll al final
+function scrollToBottom() {
+ if (chatHistoryBody) {
+ chatHistoryBody.scrollTo(0, chatHistoryBody.scrollHeight);
+ }
+}
+scrollToBottom();
+
+// Seleccionar chat o contacto
+chatContactListItems.forEach(chatContactListItem => {
+ chatContactListItem.addEventListener('click', e => {
+ chatContactListItems.forEach(item => {
+ item.classList.remove('active');
+ });
+ e.currentTarget.classList.add('active');
+ });
+});
+
+// Filtrar chats
+if (searchInput) {
+ searchInput.addEventListener('keyup', e => {
+ const searchValue = e.currentTarget.value.toLowerCase(),
+ chatListItem0 = document.querySelector('.chat-list-item-0'),
+ contactListItem0 = document.querySelector('.contact-list-item-0'),
+ searchChatListItems = [].slice.call(
+ document.querySelectorAll('#chat-list li:not(.chat-contact-list-item-title)')
+ ),
+ searchContactListItems = [].slice.call(
+ document.querySelectorAll('#contact-list li:not(.chat-contact-list-item-title)')
+ );
+
+ // Buscar en chats
+ const chatListItemsCount = searchChatContacts(searchChatListItems, searchValue);
+ // Mostrar u ocultar mensaje de "No se encontraron resultados" en chats
+ if (chatListItem0) {
+ chatListItem0.classList.toggle('d-none', chatListItemsCount !== 0);
+ }
+
+ // Buscar en contactos
+ const contactListItemsCount = searchChatContacts(searchContactListItems, searchValue);
+ // Mostrar u ocultar mensaje de "No se encontraron resultados" en contactos
+ if (contactListItem0) {
+ contactListItem0.classList.toggle('d-none', contactListItemsCount !== 0);
+ }
+ });
+}
+
+// Función para buscar en chats y contactos
+function searchChatContacts(searchListItems, searchValue) {
+ let searchListItemsCount = 0;
+ searchListItems.forEach(searchListItem => {
+ const searchListItemText = searchListItem.textContent.toLowerCase();
+ const matchesSearch = searchListItemText.indexOf(searchValue) !== -1;
+
+ searchListItem.classList.toggle('d-flex', matchesSearch);
+ searchListItem.classList.toggle('d-none', !matchesSearch);
+
+ if (matchesSearch) {
+ searchListItemsCount++;
+ }
+ });
+
+ return searchListItemsCount;
+}
+
+// Enviar mensaje
+if (sendMsgBtn) {
+ sendMsgBtn.addEventListener('click', e => {
+ e.preventDefault();
+ if (messageInput.value) {
+ const renderMsg = document.createElement('div');
+ renderMsg.className = 'chat-message-text mt-2';
+ renderMsg.innerHTML = `${messageInput.value}
`;
+ const lastChatMessageWrapper = document.querySelector('li:last-child .chat-message-wrapper');
+ if (lastChatMessageWrapper) {
+ lastChatMessageWrapper.appendChild(renderMsg);
+ }
+ messageInput.value = '';
+ scrollToBottom();
+ }
+ });
+}
+
+
+
+
+
+
+
+= $this->endSection() ?>
+
+
diff --git a/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/viewCosidotapablandaForm.php b/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/viewCosidotapablandaForm.php
index c0596ac0..5d3c296c 100644
--- a/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/viewCosidotapablandaForm.php
+++ b/ci4/app/Views/themes/vuexy/form/presupuestos/cosidotapablanda/viewCosidotapablandaForm.php
@@ -35,7 +35,8 @@
= view("themes/vuexy/form/presupuestos/cosidotapablanda/_datosEnvios") ?>
= view("themes/vuexy/form/presupuestos/cosidotapablanda/_comentariosItems") ?>
= view("themes/vuexy/form/presupuestos/cosidotapablanda/_resumenPresupuestoItems") ?>
- = view("themes/vuexy/form/presupuestos/cosidotapablanda/_tiradasAlternativasItems") ?>
+ = view("themes/vuexy/form/presupuestos/cosidotapablanda/_tiradasAlternativasItems") ?>
+ = view("themes/vuexy/form/presupuestos/cosidotapablanda/_mensajeria") ?>
@@ -367,6 +368,7 @@ $('#bc-save').on( "click", function() {
= $this->section('css') ?>
">
+
= $this->endSection() ?>
@@ -390,5 +392,6 @@ $('#bc-save').on( "click", function() {
+
= $this->endSection() ?>