232 lines
5.4 KiB
PHP
232 lines
5.4 KiB
PHP
@extends('layouts.landing')
|
|
|
|
@section('title',"Chat")
|
|
|
|
@section('content')
|
|
|
|
<div class="container-fluid">
|
|
<div class="card shadow mb-4">
|
|
|
|
<div class="card-header py-3">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
Mensajes
|
|
</h6>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
{{-- CONTENEDOR CHAT --}}
|
|
<div id="chat-app"
|
|
data-conversation-id="{{ $conversation->id }}">
|
|
|
|
<div id="messages"
|
|
style="height:70vh;overflow-y:auto;padding:10px;background:#f5f5f5;border-radius:10px;">
|
|
|
|
@foreach($conversation->messages->sortBy('created_at') as $message)
|
|
|
|
<div class="message {{ $message->user_id == auth()->id() ? 'mine' : 'theirs' }}">
|
|
<div class="bubble">
|
|
<strong>{{ $message->user->name }}</strong><br>
|
|
{{ $message->message }}
|
|
</div>
|
|
</div>
|
|
|
|
@endforeach
|
|
|
|
</div>
|
|
|
|
<div id="typingIndicator"
|
|
style="font-size:12px;color:#888;padding:8px 5px;height:20px;">
|
|
</div>
|
|
|
|
{{-- INPUT --}}
|
|
<div style="margin-top:10px;display:flex;gap:10px;">
|
|
<input id="messageInput"
|
|
class="form-control"
|
|
placeholder="Escribe mensaje...">
|
|
|
|
<button onclick="sendMessage()"
|
|
class="btn btn-primary">
|
|
Enviar
|
|
</button>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@endsection
|
|
|
|
|
|
@push('scripts')
|
|
|
|
<script>
|
|
window.USER_ID = {{ auth()->id() }};
|
|
</script>
|
|
|
|
<script>
|
|
let conversationId;
|
|
let typingTimeout;
|
|
let typingActive = false;
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
const chatApp = document.getElementById('chat-app');
|
|
const messagesDiv = document.getElementById('messages');
|
|
const input = document.getElementById('messageInput');
|
|
|
|
if (!chatApp || !messagesDiv) {
|
|
console.error('Chat DOM no encontrado');
|
|
return;
|
|
}
|
|
|
|
conversationId = chatApp.dataset.conversationId;
|
|
|
|
console.log('Chat conectado a:', conversationId);
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| ESCUCHAR "USUARIO ESCRIBIENDO"
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
window.Echo.private(`chat.${conversationId}`)
|
|
.listen('.UserTyping', (e) => {
|
|
|
|
if (e.user.id == window.USER_ID) return;
|
|
|
|
document.getElementById('typingIndicator').innerText =
|
|
e.user.name + ' está escribiendo...';
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| ESCUCHAR "USUARIO DEJÓ DE ESCRIBIR"
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
window.Echo.private(`chat.${conversationId}`)
|
|
.listen('.UserStoppedTyping', (e) => {
|
|
|
|
if (e.user.id == window.USER_ID) return;
|
|
|
|
document.getElementById('typingIndicator').innerText = '';
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| ESCUCHAR MENSAJES
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
window.Echo.private(`chat.${conversationId}`)
|
|
.listen('.ChatMessageSent', (e) => {
|
|
|
|
if (e.message.user_id == window.USER_ID) return;
|
|
|
|
appendMessage(e.message);
|
|
|
|
document.getElementById('typingIndicator').innerText = '';
|
|
});
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| DETECTAR ESCRITURA
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
input.addEventListener('input', () => {
|
|
|
|
if (!typingActive) {
|
|
|
|
typingActive = true;
|
|
|
|
axios.post('/chat/typing', {
|
|
conversation_id: conversationId
|
|
});
|
|
|
|
}
|
|
|
|
clearTimeout(typingTimeout);
|
|
|
|
typingTimeout = setTimeout(() => {
|
|
|
|
typingActive = false;
|
|
|
|
axios.post('/chat/stop-typing', {
|
|
conversation_id: conversationId
|
|
});
|
|
|
|
}, 700);
|
|
|
|
});
|
|
|
|
scrollChat();
|
|
});
|
|
|
|
|
|
function sendMessage() {
|
|
|
|
let input = document.getElementById('messageInput');
|
|
|
|
if (!input.value.trim()) return;
|
|
|
|
typingActive = false;
|
|
|
|
axios.post('/chat/stop-typing', {
|
|
conversation_id: conversationId
|
|
});
|
|
|
|
axios.post('/chat/send', {
|
|
conversation_id: conversationId,
|
|
message: input.value
|
|
})
|
|
.then(response => {
|
|
|
|
appendMessage(response.data.message);
|
|
|
|
document.getElementById('typingIndicator').innerText = '';
|
|
|
|
});
|
|
|
|
input.value = '';
|
|
}
|
|
|
|
|
|
function appendMessage(message) {
|
|
|
|
const messagesDiv = document.getElementById('messages');
|
|
|
|
let mine = message.user_id == window.USER_ID;
|
|
|
|
let div = document.createElement('div');
|
|
|
|
div.className = 'message ' + (mine ? 'mine' : 'theirs');
|
|
|
|
div.innerHTML = `
|
|
<div class="bubble">
|
|
<strong>${message.user.name}</strong><br>
|
|
${message.message}
|
|
</div>
|
|
`;
|
|
|
|
messagesDiv.appendChild(div);
|
|
|
|
scrollChat();
|
|
}
|
|
|
|
|
|
function scrollChat() {
|
|
|
|
const container = document.getElementById('messages');
|
|
|
|
container.scrollTop = container.scrollHeight;
|
|
|
|
}
|
|
</script>
|
|
|
|
@endpush
|