Files
sistema-abogadas-litoral/resources/views/cliente/dashboard.blade.php
T
2026-06-24 16:19:32 -03:00

795 lines
40 KiB
PHP

<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dashboard Cliente</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
<style>
.profesional-card-img {
width: 100%;
height: 260px;
object-fit: cover;
object-position: center;
}
.assistant-toggle {
width: 56px;
height: 56px;
border-radius: 50%;
position: fixed;
left: 1.2rem;
bottom: 4.8rem;
z-index: 1050;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2);
}
.assistant-panel {
position: fixed;
left: 1.2rem;
bottom: 8.8rem;
width: min(360px, calc(100vw - 2.4rem));
max-height: 70vh;
z-index: 1050;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 14px;
overflow: hidden;
display: none;
background: #fff;
}
.assistant-panel.open {
display: block;
}
.assistant-tip {
position: fixed;
left: 1.2rem;
bottom: 9.8rem;
z-index: 1050;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 12px;
padding: 0.65rem 0.8rem;
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.16);
font-size: 0.9rem;
max-width: min(280px, calc(100vw - 2.4rem));
}
.assistant-tip.hidden {
display: none;
}
.assistant-messages {
height: 300px;
overflow-y: auto;
background: #fffdf8;
padding: 0.9rem;
}
.assistant-msg {
padding: 0.55rem 0.7rem;
border-radius: 10px;
margin-bottom: 0.6rem;
max-width: 90%;
line-height: 1.35;
font-size: 0.92rem;
}
.assistant-msg.bot {
background: #f3f4f6;
margin-right: auto;
}
.assistant-msg.user {
background: #ffdeaf;
margin-left: auto;
}
.assistant-chips {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
padding: 0 0.2rem 0.4rem;
}
.assistant-chip {
font-size: 0.82rem;
border-radius: 999px;
white-space: nowrap;
}
.carousel-cards .carousel-control-prev,
.carousel-cards .carousel-control-next {
width: 2.5rem;
background: rgba(0, 0, 0, 0.15);
border-radius: 6px;
opacity: 1;
}
.carousel-cards .carousel-inner {
padding: 0 2.8rem;
}
</style>
</head>
<body id="top" class="d-flex flex-column min-vh-100 bg-light">
<header class="app-navbar">
<nav class="navbar navbar-expand-lg">
<div class="container">
<a class="navbar-brand d-flex align-items-center" href="/cliente/dashboard">
<div class="d-flex align-items-center justify-content-center" style="width: 130px; height: 52px;">
<img src="{{ asset('images/logo.png') }}" alt="Logo" class="img-fluid" style="max-height: 70px; width: auto; object-fit: contain;">
</div>
<span class="app-navbar-greeting ms-2">¡Hola, {{ explode(' ', trim((string) session('cliente_nombre', 'Cliente')))[0] }}!</span>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#menuPrincipal" aria-controls="menuPrincipal" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="menuPrincipal">
<ul class="navbar-nav mx-auto mb-2 mb-lg-0">
<li class="nav-item"><a class="btn app-navbar-link" href="#servicios">Servicios</a></li>
<li class="nav-item"><a class="btn app-navbar-link" href="#quienes-somos">Quienes Somos</a></li>
<li class="nav-item"><a class="btn app-navbar-link" href="#equipo">Equipo</a></li>
<li class="nav-item"><a class="btn app-navbar-link" href="#ubicacion">Ubicacion</a></li>
<li class="nav-item"><a class="btn app-navbar-link" href="#formulario">Pedir Turno</a></li>
<li class="nav-item"><a class="btn app-navbar-link" href="/cliente/mis-turnos">Mis Turnos</a></li>
<li class="nav-item"><a class="btn app-navbar-link" href="/cliente/ayuda" title="Ayuda para clientes" aria-label="Ayuda para clientes">¿Necesitas Ayuda?</a></li>
</ul>
<a class="btn app-navbar-link" href="/logout">Cerrar Sesion</a>
</div>
</div>
</nav>
</header>
<main class="container py-5 flex-grow-1 text-center d-flex flex-column align-items-center">
<section id="servicios" class="mb-5 w-100">
<h2 class="h4">Servicios</h2>
@if(collect($servicios)->isEmpty())
<p class="text-muted mt-2">No hay servicios disponibles.</p>
@else
<div id="carouselServicios" class="carousel slide carousel-cards mt-2" data-bs-theme="dark">
<div class="carousel-inner">
@foreach(collect($servicios)->chunk(3) as $chunk)
<div class="carousel-item {{ $loop->first ? 'active' : '' }}">
<div class="row justify-content-center g-4">
@foreach($chunk as $servicio)
@php
$foto = $servicio->foto ?? null;
$fotoSrc = $foto ? asset($foto->ruta) : null;
@endphp
<div class="col-12 col-sm-6 col-md-4">
<div class="card h-100 mx-auto" style="max-width: 18rem;">
@if($fotoSrc)
<img src="{{ $fotoSrc }}" class="card-img-top servicio-card-img" alt="{{ $servicio->titulo }}">
@endif
<div class="card-body">
<h5 class="card-title">{{ $servicio->titulo }}</h5>
<p class="card-text text-muted small">{{ $servicio->descripcion }}</p>
</div>
</div>
</div>
@endforeach
</div>
</div>
@endforeach
</div>
@if(collect($servicios)->count() > 3)
<button class="carousel-control-prev" type="button" data-bs-target="#carouselServicios" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Anterior</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselServicios" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Siguiente</span>
</button>
@endif
</div>
@endif
</section>
<hr class="my-4 w-50 mx-auto border-2 border-dark opacity-100">
<section id="quienes-somos" class="mb-5 w-100">
<h2 class="h4">Quienes Somos</h2>
<p class="text-muted mb-0">
{!! nl2br(e($quienesSomos ?? 'Aun no hay contenido cargado para Quienes Somos.')) !!}
</p>
</section>
<hr class="my-4 w-50 mx-auto border-2 border-dark opacity-100">
<section id="equipo" class="mb-5 w-100">
<h2 class="h4">Equipo</h2>
@if(collect($profesionales)->isEmpty())
<p class="text-muted mt-2">No hay profesionales registrados.</p>
@else
<div id="carouselEquipo" class="carousel slide carousel-cards mt-2" data-bs-theme="dark">
<div class="carousel-inner">
@foreach(collect($profesionales)->chunk(3) as $chunk)
<div class="carousel-item {{ $loop->first ? 'active' : '' }}">
<div class="row justify-content-center g-4">
@foreach($chunk as $profesional)
@php
$persona = $profesional->persona;
$foto = $persona->Foto ?? null;
$fotoSrc = $foto ? asset($foto->ruta) : asset('images/avatar_default.png');
$profesionesTexto = $profesional->profesiones
->pluck('titulo')
->push($profesional->profesion?->titulo)
->filter()
->unique()
->implode(' | ');
@endphp
<div class="col-12 col-sm-6 col-md-4">
<div class="card h-100 mx-auto" style="max-width: 18rem;">
<img src="{{ $fotoSrc }}" class="card-img-top profesional-card-img" alt="{{ $persona->nombre }} {{ $persona->apellido }}">
<div class="card-body">
<h5 class="card-title">{{ $persona->nombre }} {{ $persona->apellido }}</h5>
<p class="card-text text-muted small">{{ $profesionesTexto }}</p>
</div>
</div>
</div>
@endforeach
</div>
</div>
@endforeach
</div>
@if(collect($profesionales)->count() > 3)
<button class="carousel-control-prev" type="button" data-bs-target="#carouselEquipo" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Anterior</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselEquipo" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Siguiente</span>
</button>
@endif
</div>
@endif
</section>
<hr class="my-4 w-50 mx-auto border-2 border-dark opacity-100">
<section id="ubicacion" class="mb-5 w-100">
<h2 class="h4">Ubicacion</h2>
<p class="text-muted mb-3">Pasteur 141</p>
<div class="ratio ratio-16x9 mx-auto" style="max-width: 900px;" data-map-widget>
<iframe
data-map-embed
data-map-src="https://maps.google.com/maps?q=Pasteur%20141&t=&z=15&ie=UTF8&iwloc=&output=embed"
style="border: 0;"
allowfullscreen
loading="lazy"
referrerpolicy="no-referrer-when-downgrade"
title="Mapa de ubicacion - Pasteur 141"></iframe>
<div class="d-none border rounded bg-light p-3 text-center d-flex align-items-center justify-content-center" data-map-fallback>
<div>
<p class="mb-2 fw-semibold">No se pudo cargar el mapa sin conexión.</p>
<p class="mb-2">Dirección: Dr. Luis Pasteur 141, Paraná, Entre Ríos, Argentina.</p>
<a href="https://www.google.com/maps/place/Dr.+Luis+Pasteur+141,+Paran%C3%A1,+Entre+R%C3%ADos,+Argentina" target="_blank" rel="noopener noreferrer">Abrir en Google Maps</a>
</div>
</div>
</div>
</section>
<hr class="my-4 w-50 mx-auto border-2 border-dark opacity-100">
<section id="formulario" class="w-100">
<h2 class="h4">Formulario de Consulta</h2>
<div class="card shadow-sm mx-auto text-start" style="max-width: 920px;">
<div class="card-body p-4 p-md-5">
@if(session('form_success'))
<div class="alert alert-success" role="alert">
{{ session('form_success') }}
</div>
@endif
@if(session('form_error'))
<div class="alert alert-danger" role="alert">
{{ session('form_error') }}
</div>
@endif
@if($errors->any())
<div class="alert alert-danger" role="alert">
<ul class="mb-0 ps-3">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="/cliente/formulario" class="row g-3">
@csrf
<div class="col-12 col-md-6">
<label for="nombre" class="form-label">Nombre</label>
<input type="text" id="nombre" class="form-control" value="{{ $nombreClienteForm }}" readonly>
</div>
<div class="col-12 col-md-6">
<label for="apellido" class="form-label">Apellido</label>
<input type="text" id="apellido" class="form-control" value="{{ $apellidoClienteForm }}" readonly>
</div>
<div class="col-12 col-md-6">
<label for="correo" class="form-label">Correo</label>
<input type="email" id="correo" class="form-control" value="{{ $correoClienteForm }}" readonly>
</div>
<div class="col-12 col-md-6">
<label for="celular" class="form-label">Celular</label>
<input type="text" id="celular" class="form-control" value="{{ $celularClienteForm }}" readonly>
</div>
<div class="col-12 col-md-6">
<label for="profesion_id" class="form-label">Profesion</label>
<select id="profesion_id" name="profesion_id" class="form-select" required>
<option value="">Seleccionar profesion</option>
@foreach($profesiones as $profesion)
<option value="{{ $profesion->id }}" @selected(old('profesion_id') == $profesion->id)>
{{ $profesion->titulo }}
</option>
@endforeach
</select>
</div>
<div class="col-12 col-md-6">
<label for="servicio_id" class="form-label">Servicio</label>
<select id="servicio_id" name="servicio_id" class="form-select" required>
<option value="" data-default-text="Seleccionar servicio">Primero elegi una profesion</option>
@foreach($servicios as $servicio)
<option
value="{{ $servicio->id }}"
data-profesion-ids="{{ $servicio->profesion_id }}"
@selected(old('servicio_id') == $servicio->id)
>
{{ $servicio->titulo }}
</option>
@endforeach
</select>
<div class="form-text">Solo se muestran servicios de la profesion seleccionada.</div>
</div>
<div class="col-12 col-md-6">
<label for="profesional_id" class="form-label">Profesional</label>
<select id="profesional_id" name="profesional_id" class="form-select" required>
<option value="" data-default-text="Seleccionar profesional">Primero elegi una profesion</option>
<option value="INDISTINTO" data-indistinto="1" @selected(old('profesional_id') === 'INDISTINTO')>INDISTINTO</option>
@foreach($profesionales as $profesional)
@php
$profesionesIds = $profesional->profesiones
->pluck('id')
->push((int) $profesional->profesion_id)
->unique()
->implode(',');
@endphp
<option
value="{{ $profesional->id }}"
data-profesion-ids="{{ $profesionesIds }}"
@selected(old('profesional_id') == $profesional->id)
>
{{ $profesional->persona->nombre }} {{ $profesional->persona->apellido }}
</option>
@endforeach
</select>
<div class="form-text">Solo se muestran profesionales de la profesion seleccionada o la opcion INDISTINTO.</div>
</div>
<input type="hidden" name="modalidad_id" value="1">
<div class="col-12 col-md-8">
<label class="form-label d-block">Dias de preferencia</label>
@php
$diasDisponibles = ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Indistinto'];
$diasSeleccionados = old('dias_preferencia', []);
@endphp
<div class="d-flex flex-wrap gap-3" id="dias-preferencia-container">
@foreach($diasDisponibles as $dia)
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="dia_{{ strtolower($dia) }}"
name="dias_preferencia[]"
value="{{ $dia }}"
@checked(in_array($dia, $diasSeleccionados, true))
>
<label class="form-check-label" for="dia_{{ strtolower($dia) }}">{{ $dia }}</label>
</div>
@endforeach
</div>
<div class="form-text">Si elegis Indistinto, no podes combinarlo con otros dias.</div>
</div>
<div class="col-12 col-md-4">
<label for="horario_preferencia" class="form-label">Horario de preferencia</label>
<select id="horario_preferencia" name="horario_preferencia" class="form-select" required>
<option value="">Seleccionar horario</option>
<option value="AM" @selected(old('horario_preferencia') == 'AM')>AM</option>
<option value="PM" @selected(old('horario_preferencia') == 'PM')>PM</option>
<option value="INDISTINTO" @selected(old('horario_preferencia') == 'INDISTINTO')>INDISTINTO</option>
</select>
</div>
<div class="col-12">
<label for="descripcion" class="form-label">Descripcion</label>
<textarea id="descripcion" placeholder="Describa brevemente el motivo de su consulta" name="descripcion" class="form-control" rows="4" maxlength="3000" required>{{ old('descripcion') }}</textarea>
</div>
<div style="position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden;" aria-hidden="true">
<label for="website">No completar este campo</label>
<input type="text" id="website" name="website" value="{{ old('website') }}" tabindex="-1" autocomplete="off">
</div>
<div class="col-12 d-grid d-md-flex justify-content-md-end">
<button type="button" class="btn btn-primary px-4" data-bs-toggle="modal" data-bs-target="#confirmarEnvioModal">Enviar</button>
</div>
</form>
<!-- Modal de confirmación de envío -->
<div class="modal fade" id="confirmarEnvioModal" tabindex="-1" aria-labelledby="confirmarEnvioModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmarEnvioModalLabel">Confirmar envío</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body">
¿Deseás enviar el formulario?<br>
<span class="text-muted">Si se confirma tu turno, se te enviará un correo electronico con los detalles del mismo</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary" id="btnConfirmarEnvioFormCliente">Confirmar envío</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</section>
</main>
<footer class="app-footer mt-auto py-4">
<div class="container">
<div class="row g-4 align-items-start text-center">
<div class="col-12 col-md-4">
<div class="d-inline-flex align-items-center justify-content-center" style="width: 120px; height: 52px;">
<img src="{{ asset('images/logo.png') }}" alt="Logo" class="img-fluid" style="max-height: 70px; width: auto; object-fit: contain;">
</div>
</div>
<div class="col-12 col-md-4 text-center">
<h3 class="h6 mb-2">Redes Sociales</h3>
<p class="mb-2"><a href="https://www.instagram.com/abogadasdellitoral?utm_source=ig_web_button_share_sheet&igsh=ZDNlZDc0MzIxNw==" target="_blank" rel="noopener noreferrer">Instagram</a></p>
<p class="small mb-0">Desarrollado por Luciano Belini</p>
</div>
<div class="col-12 col-md-4">
<h3 class="h6 mb-2">Ubicacion</h3>
<p class="mb-0"> <a href="https://www.google.com/maps/place/Dr.+Luis+Pasteur+141,+Paran%C3%A1,+Entre+R%C3%ADos,+Argentina" target="_blank" rel="noopener noreferrer">Dr. Luis Pasteur 141, Paraná, Entre Ríos, Argentina</a></p>
</div>
</div>
</div>
</footer>
<a href="#top" class="btn btn-primary rounded-circle position-fixed bottom-0 end-0 m-4 d-flex align-items-center justify-content-center" style="width: 44px; height: 44px;" aria-label="Volver arriba" title="Volver arriba">
</a>
<button id="assistant-toggle" type="button" class="btn btn-warning assistant-toggle" aria-label="Abrir {{ $nombreAsistente }}" title="{{ $nombreAsistente }}">
🤖
</button>
<div id="assistant-tip" class="assistant-tip" role="status" aria-live="polite">
{{ $mensajeBurbujaAsistente }}
</div>
<section id="assistant-panel" class="assistant-panel shadow" aria-label="{{ $nombreAsistente }}">
<div class="bg-warning-subtle border-bottom px-3 py-2 d-flex justify-content-between align-items-center">
<strong>{{ $nombreAsistente }}</strong>
<button id="assistant-close" type="button" class="btn btn-sm btn-outline-secondary">Cerrar</button>
</div>
<div id="assistant-messages" class="assistant-messages">
<div class="assistant-msg bot">{{ $mensajeInicioPanelAsistente }}</div>
@if(!empty($chipsAsistente))
<div id="assistant-chips" class="assistant-chips">
@foreach($chipsAsistente as $chip)
<button type="button" class="btn btn-sm btn-outline-warning assistant-chip">{{ $chip }}</button>
@endforeach
</div>
@endif
</div>
<form id="assistant-form" class="p-2 border-top bg-white">
<div class="input-group">
<input id="assistant-input" type="text" class="form-control" maxlength="500" placeholder="Escribí tu consulta..." required>
<button class="btn btn-primary" type="submit">Enviar</button>
</div>
</form>
</section>
<script>
(function () {
const profesionSelect = document.getElementById('profesion_id');
const servicioSelect = document.getElementById('servicio_id');
const profesionalSelect = document.getElementById('profesional_id');
const diaIndistinto = document.getElementById('dia_indistinto');
const diasContainer = document.getElementById('dias-preferencia-container');
const normalizarTexto = (texto) => {
return (texto || '')
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.toLowerCase()
.trim();
};
const inicializarSelectBuscable = (select) => {
if (!select || select.dataset.buscableInicializado === '1') {
return { refresh: () => {} };
}
select.dataset.buscableInicializado = '1';
select.classList.add('d-none');
const wrapper = document.createElement('div');
wrapper.className = 'position-relative';
const trigger = document.createElement('button');
trigger.type = 'button';
trigger.className = 'form-select text-start';
trigger.setAttribute('aria-haspopup', 'listbox');
trigger.setAttribute('aria-expanded', 'false');
const dropdown = document.createElement('div');
dropdown.className = 'position-absolute w-100 bg-white border rounded shadow-sm mt-1 p-2';
dropdown.style.zIndex = '1080';
dropdown.style.display = 'none';
dropdown.style.maxHeight = '280px';
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.className = 'form-control form-control-sm mb-2';
searchInput.placeholder = 'Buscar...';
const list = document.createElement('div');
list.className = 'd-flex flex-column gap-1 overflow-auto';
list.style.maxHeight = '210px';
dropdown.appendChild(searchInput);
dropdown.appendChild(list);
wrapper.appendChild(trigger);
wrapper.appendChild(dropdown);
select.insertAdjacentElement('afterend', wrapper);
const obtenerLabelSeleccionado = () => {
const selected = select.options[select.selectedIndex];
if (!selected) {
return 'Seleccionar opcion';
}
return selected.textContent.trim();
};
const renderOpciones = () => {
const termino = normalizarTexto(searchInput.value);
const opcionesVisibles = Array.from(select.options).filter((option) => !option.hidden && !option.disabled);
list.innerHTML = '';
opcionesVisibles
.filter((option) => {
if (!termino) {
return true;
}
return normalizarTexto(option.textContent).includes(termino);
})
.forEach((option) => {
const item = document.createElement('button');
item.type = 'button';
item.className = 'btn btn-sm btn-light text-start';
item.textContent = option.textContent.trim();
item.dataset.value = option.value;
if (option.value === select.value) {
item.classList.add('active');
}
item.addEventListener('click', () => {
select.value = option.value;
select.dispatchEvent(new Event('change', { bubbles: true }));
dropdown.style.display = 'none';
trigger.setAttribute('aria-expanded', 'false');
});
list.appendChild(item);
});
if (!list.children.length) {
const vacio = document.createElement('div');
vacio.className = 'small text-muted px-1 py-1';
vacio.textContent = 'Sin resultados';
list.appendChild(vacio);
}
};
const refresh = () => {
trigger.textContent = obtenerLabelSeleccionado();
trigger.disabled = select.disabled;
if (select.disabled) {
dropdown.style.display = 'none';
trigger.setAttribute('aria-expanded', 'false');
}
renderOpciones();
};
trigger.addEventListener('click', () => {
if (trigger.disabled) {
return;
}
const abierto = dropdown.style.display === 'block';
dropdown.style.display = abierto ? 'none' : 'block';
trigger.setAttribute('aria-expanded', abierto ? 'false' : 'true');
if (!abierto) {
searchInput.focus();
searchInput.select();
}
});
searchInput.addEventListener('input', renderOpciones);
select.addEventListener('change', refresh);
document.addEventListener('click', (event) => {
if (!wrapper.contains(event.target)) {
dropdown.style.display = 'none';
trigger.setAttribute('aria-expanded', 'false');
}
});
refresh();
return { refresh };
};
if (profesionSelect && servicioSelect && profesionalSelect) {
const servicioOptions = Array.from(servicioSelect.querySelectorAll('option[value]'));
const profesionalOptions = Array.from(profesionalSelect.querySelectorAll('option[value]'));
const buscadorProfesion = inicializarSelectBuscable(profesionSelect);
const buscadorServicio = inicializarSelectBuscable(servicioSelect);
const buscadorProfesional = inicializarSelectBuscable(profesionalSelect);
const aplicarFiltro = (select, options, profesionId) => {
const selectedOption = select.options[select.selectedIndex];
const placeholderOption = select.querySelector('option[value=""]');
options.forEach((option) => {
const esIndistinto = option.dataset.indistinto === '1';
const profesionesDelProfesional = (option.dataset.profesionIds || '')
.split(',')
.map((id) => id.trim())
.filter((id) => id !== '');
const coincide = Boolean(profesionId) && (esIndistinto || profesionesDelProfesional.includes(profesionId));
option.hidden = !coincide;
option.disabled = !coincide;
});
if (placeholderOption) {
const defaultText = placeholderOption.dataset.defaultText || 'Seleccionar opcion';
placeholderOption.textContent = profesionId ? defaultText : 'Primero elegi una profesion';
}
select.disabled = !profesionId;
if (selectedOption && selectedOption.value && (selectedOption.disabled || selectedOption.hidden)) {
select.value = '';
}
};
const filtrarPorProfesion = () => {
const profesionId = profesionSelect.value;
aplicarFiltro(servicioSelect, servicioOptions, profesionId);
aplicarFiltro(profesionalSelect, profesionalOptions, profesionId);
buscadorProfesion.refresh();
buscadorServicio.refresh();
buscadorProfesional.refresh();
};
filtrarPorProfesion();
profesionSelect.addEventListener('change', filtrarPorProfesion);
}
if (diaIndistinto && diasContainer) {
const checkboxes = Array.from(diasContainer.querySelectorAll('input[type="checkbox"]'));
const otrosDias = checkboxes.filter((checkbox) => checkbox !== diaIndistinto);
const syncDias = () => {
if (diaIndistinto.checked) {
otrosDias.forEach((checkbox) => {
checkbox.checked = false;
checkbox.disabled = true;
});
return;
}
otrosDias.forEach((checkbox) => {
checkbox.disabled = false;
});
const algunOtroDiaSeleccionado = otrosDias.some((checkbox) => checkbox.checked);
diaIndistinto.disabled = algunOtroDiaSeleccionado;
};
checkboxes.forEach((checkbox) => checkbox.addEventListener('change', syncDias));
syncDias();
}
const assistantToggle = document.getElementById('assistant-toggle');
const assistantPanel = document.getElementById('assistant-panel');
const assistantClose = document.getElementById('assistant-close');
const assistantForm = document.getElementById('assistant-form');
const assistantInput = document.getElementById('assistant-input');
const assistantMessages = document.getElementById('assistant-messages');
const assistantTip = document.getElementById('assistant-tip');
const appendAssistantMessage = (text, type) => {
const msg = document.createElement('div');
msg.className = `assistant-msg ${type}`;
msg.textContent = text;
assistantMessages.appendChild(msg);
assistantMessages.scrollTop = assistantMessages.scrollHeight;
};
assistantToggle?.addEventListener('click', () => {
assistantPanel?.classList.add('open');
assistantTip?.classList.add('hidden');
assistantInput?.focus();
});
assistantClose?.addEventListener('click', () => {
assistantPanel?.classList.remove('open');
});
document.querySelectorAll('.assistant-chip').forEach((chip) => {
chip.addEventListener('click', () => {
const texto = chip.textContent.trim();
if (!texto) return;
assistantInput.value = texto;
assistantForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
});
});
assistantForm?.addEventListener('submit', async (e) => {
e.preventDefault();
const mensaje = assistantInput.value.trim();
if (!mensaje) {
return;
}
appendAssistantMessage(mensaje, 'user');
assistantInput.value = '';
try {
const res = await fetch('/asistente/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json',
},
body: JSON.stringify({ mensaje }),
});
if (!res.ok) {
throw new Error('No se pudo obtener respuesta.');
}
const data = await res.json();
appendAssistantMessage(data.respuesta || 'No pude responder en este momento.', 'bot');
} catch (error) {
appendAssistantMessage('Estoy con inconvenientes técnicos. Probá nuevamente en unos segundos.', 'bot');
}
});
})();
</script>
@include('partials.reportar-falla-boton')
</body>
</html>