feat: renderizar adjuntos multimedia en el chat (imagen, video, audio, archivo)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 12:31:00 -06:00
parent ab967e8ba4
commit 7c95937b94
+28 -11
View File
@@ -107,33 +107,50 @@ document.getElementById('chat-form').addEventListener('submit', function(e) {
const data = new FormData(form); const data = new FormData(form);
axios.post('{{ route("chat.send") }}', data, { axios.post('{{ route("chat.send") }}', data, {
headers: { headers: { 'X-Socket-ID': window.Echo.socketId() }
'X-Socket-ID': window.Echo.socketId() }).then(response => {
} appendMessage(response.data, true);
})
.then(response => {
appendMessage({
body: response.data.body,
created_at: response.data.created_at,
}, true);
scrollBottom(); scrollBottom();
form.reset(); form.reset();
document.getElementById('attachment-preview').textContent = ''; document.getElementById('attachment-preview').textContent = '';
}); });
}); });
function buildAttachmentHtml(msg, isMine) {
if (!msg.attachment) return '';
const url = '/storage/' + msg.attachment;
const linkClass = isMine ? 'text-white' : 'text-dark';
switch (msg.attachment_type) {
case 'image':
return `<img src="${url}" class="img-fluid rounded mt-1" style="max-width:240px; cursor:pointer"
onclick="window.open('${url}','_blank')">`;
case 'video':
return `<video controls class="mt-1 rounded" style="max-width:240px">
<source src="${url}">Tu navegador no soporta video.
</video>`;
case 'audio':
return `<audio controls class="mt-1" style="max-width:240px">
<source src="${url}">Tu navegador no soporta audio.
</audio>`;
default:
return `<a href="${url}" target="_blank" class="btn btn-sm ${isMine ? 'btn-light' : 'btn-secondary'} mt-1">
<i class="fas fa-file mr-1"></i>Ver archivo
</a>`;
}
}
function appendMessage(msg, isMine) { function appendMessage(msg, isMine) {
const div = document.createElement('div'); const div = document.createElement('div');
div.className = `d-flex mb-2 ${isMine ? 'justify-content-end' : 'justify-content-start'}`; div.className = `d-flex mb-2 ${isMine ? 'justify-content-end' : 'justify-content-start'}`;
// formatear hora const time = typeof msg.created_at === 'string' && msg.created_at.length > 5
const time = msg.created_at.length > 5
? new Date(msg.created_at).toLocaleTimeString('es-MX', {hour:'2-digit', minute:'2-digit'}) ? new Date(msg.created_at).toLocaleTimeString('es-MX', {hour:'2-digit', minute:'2-digit'})
: msg.created_at; : msg.created_at;
div.innerHTML = ` div.innerHTML = `
<div class="px-3 py-2 rounded ${isMine ? 'bg-primary text-white' : 'bg-light'}" style="max-width:65%"> <div class="px-3 py-2 rounded ${isMine ? 'bg-primary text-white' : 'bg-light'}" style="max-width:65%">
${msg.body ? `<div>${msg.body}</div>` : ''} ${msg.body ? `<div>${msg.body}</div>` : ''}
${buildAttachmentHtml(msg, isMine)}
<div class="text-right mt-1" style="font-size:0.7rem; opacity:0.7">${time}</div> <div class="text-right mt-1" style="font-size:0.7rem; opacity:0.7">${time}</div>
</div>`; </div>`;
chatMessages.appendChild(div); chatMessages.appendChild(div);