Actualizar asignados.html
This commit is contained in:
296
asignados.html
296
asignados.html
@@ -40,7 +40,7 @@
|
||||
</head>
|
||||
<body class="text-slate-800 font-sans antialiased h-screen flex flex-col overflow-hidden relative">
|
||||
|
||||
<header class="bg-white px-5 pt-8 pb-4 shadow-sm z-20 shrink-0 border-b border-slate-100 flex justify-between items-center">
|
||||
<header class="bg-white px-5 pt-8 pb-4 shadow-sm z-20 shrink-0 border-b border-slate-100 flex justify-between items-center relative">
|
||||
<div>
|
||||
<p class="text-[10px] font-black text-primary-dynamic uppercase tracking-widest mb-0.5">Por Agendar</p>
|
||||
<h1 class="text-2xl font-black tracking-tight text-slate-800 leading-none">Sin Cita</h1>
|
||||
@@ -53,10 +53,29 @@
|
||||
<main class="flex-1 overflow-y-auto no-scrollbar p-5 relative z-10" id="mainArea">
|
||||
<div id="loader" class="text-center py-10 opacity-50">
|
||||
<i data-lucide="loader-2" class="w-8 h-8 animate-spin mx-auto text-primary-dynamic mb-2"></i>
|
||||
<p class="text-xs font-bold uppercase tracking-widest">Buscando pendientes...</p>
|
||||
<p class="text-xs font-bold uppercase tracking-widest mt-2 text-slate-400">Sincronizando...</p>
|
||||
</div>
|
||||
|
||||
<div id="servicesList" class="space-y-4 pb-24 hidden fade-in">
|
||||
<div id="contentWrapper" class="hidden pb-24 fade-in">
|
||||
|
||||
<div id="requestsSection" class="mb-6 hidden">
|
||||
<h2 class="text-xs font-black text-slate-400 uppercase tracking-widest mb-3 flex items-center gap-2">
|
||||
<span class="relative flex h-2.5 w-2.5">
|
||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
|
||||
<span class="relative inline-flex rounded-full h-2.5 w-2.5 bg-blue-500"></span>
|
||||
</span>
|
||||
Citas Solicitadas
|
||||
</h2>
|
||||
<div id="requestsList" class="space-y-4">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="noDateSection">
|
||||
<h2 class="text-xs font-black text-slate-400 uppercase tracking-widest mb-3">Pendientes de Fecha</h2>
|
||||
<div id="servicesList" class="space-y-4">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -85,7 +104,7 @@
|
||||
<span id="detRef" class="text-[10px] font-black text-slate-400 uppercase tracking-widest"></span>
|
||||
<h3 class="font-black text-xl text-slate-800 uppercase leading-none" id="detName"></h3>
|
||||
</div>
|
||||
<button onclick="closeModal()" class="w-8 h-8 bg-slate-100 rounded-full flex items-center justify-center text-slate-500 hover:text-red-500"><i data-lucide="x" class="w-4 h-4"></i></button>
|
||||
<button onclick="closeModal('actionModal', 'modalContent')" class="w-8 h-8 bg-slate-100 rounded-full flex items-center justify-center text-slate-500 hover:text-red-500"><i data-lucide="x" class="w-4 h-4"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="overflow-y-auto no-scrollbar flex-1 pb-4">
|
||||
@@ -111,7 +130,6 @@
|
||||
<hr class="border-slate-100 mb-6">
|
||||
|
||||
<div class="bg-white border border-slate-200 rounded-[1.5rem] p-5 shadow-sm space-y-5">
|
||||
|
||||
<div>
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<p class="text-[10px] font-black text-primary-dynamic uppercase tracking-widest flex items-center gap-1.5"><i data-lucide="clock" class="w-4 h-4"></i> Duración Estimada</p>
|
||||
@@ -133,21 +151,17 @@
|
||||
|
||||
<div>
|
||||
<p class="text-[10px] font-black text-primary-dynamic uppercase tracking-widest mb-2 flex items-center gap-1.5"><i data-lucide="calendar" class="w-4 h-4"></i> Seleccionar Día</p>
|
||||
<div id="dayCarousel" class="flex overflow-x-auto gap-2 pb-2 no-scrollbar">
|
||||
</div>
|
||||
<div id="dayCarousel" class="flex overflow-x-auto gap-2 pb-2 no-scrollbar"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-[10px] font-black text-primary-dynamic uppercase tracking-widest mb-2 flex items-center gap-1.5"><i data-lucide="watch" class="w-4 h-4"></i> Huecos Disponibles</p>
|
||||
<div id="timeGrid" class="grid grid-cols-4 gap-2">
|
||||
</div>
|
||||
<div id="timeGrid" class="grid grid-cols-4 gap-2"></div>
|
||||
<p id="noSlotsMsg" class="hidden text-xs text-rose-500 font-bold bg-rose-50 p-3 rounded-xl border border-rose-100 text-center mt-2">
|
||||
No hay huecos libres para esta duración.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="pt-4 shrink-0 bg-white border-t border-slate-100">
|
||||
@@ -155,7 +169,53 @@
|
||||
<i data-lucide="calendar-check" class="w-5 h-5"></i> Confirmar Cita
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="approveModal" class="fixed inset-0 bg-slate-900/60 z-[110] hidden flex-col justify-end transition-opacity duration-300 opacity-0">
|
||||
<div id="approveModalContent" class="bg-white rounded-t-[2rem] p-6 pb-12 transform translate-y-full transition-transform duration-300 shadow-2xl">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<span id="appRef" class="text-[10px] font-black text-slate-400 uppercase tracking-widest"></span>
|
||||
<h3 class="font-black text-xl text-slate-800 uppercase leading-none" id="appName"></h3>
|
||||
</div>
|
||||
<button onclick="closeModal('approveModal', 'approveModalContent')" class="w-8 h-8 bg-slate-100 rounded-full flex items-center justify-center text-slate-500 hover:text-red-500"><i data-lucide="x" class="w-4 h-4"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="bg-blue-50 border border-blue-100 p-5 rounded-2xl mb-6 shadow-inner text-center">
|
||||
<p class="text-[10px] font-black text-blue-600 uppercase tracking-widest mb-1">Fecha Solicitada por el Cliente</p>
|
||||
<h4 class="text-2xl font-black text-slate-800" id="appDate">--/--/----</h4>
|
||||
<p class="text-sm font-bold text-slate-600 mt-1" id="appTime">--:--</p>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="appId">
|
||||
|
||||
<div class="mb-8">
|
||||
<p class="text-[10px] font-black text-slate-500 uppercase tracking-widest mb-2 ml-1">¿Cuánto tiempo vas a tardar?</p>
|
||||
<div class="relative">
|
||||
<select id="appDurationInput" class="w-full bg-slate-50 border border-slate-200 p-4 rounded-xl text-sm font-black text-slate-700 outline-none focus:ring-2 focus:ring-blue-500 appearance-none pr-10">
|
||||
<option value="15">15 Minutos (Muy rápido)</option>
|
||||
<option value="30">30 Minutos</option>
|
||||
<option value="45">45 Minutos</option>
|
||||
<option value="60" selected>1 Hora (Estándar)</option>
|
||||
<option value="90">1 Hora y Media</option>
|
||||
<option value="120">2 Horas</option>
|
||||
<option value="180">3 Horas</option>
|
||||
<option value="240">4 Horas (Media jornada)</option>
|
||||
</select>
|
||||
<i data-lucide="chevron-down" class="w-5 h-5 absolute right-4 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<button onclick="rejectRequest()" id="btnReject" class="bg-white border-2 border-rose-200 text-rose-600 font-black py-4 rounded-xl hover:bg-rose-50 flex items-center justify-center gap-2 transition-all text-xs uppercase tracking-widest">
|
||||
<i data-lucide="x" class="w-4 h-4"></i> Rechazar
|
||||
</button>
|
||||
<button onclick="approveRequest()" id="btnApprove" class="bg-blue-600 text-white font-black py-4 rounded-xl shadow-lg shadow-blue-500/30 hover:bg-blue-700 flex items-center justify-center gap-2 transition-all text-xs uppercase tracking-widest">
|
||||
<i data-lucide="check" class="w-4 h-4"></i> Aceptar
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-center text-[9px] font-bold text-slate-400 mt-4">Al aceptar, se enviará un WhatsApp al cliente confirmando la cita automáticamente.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -170,7 +230,8 @@
|
||||
: 'https://integrarepara-api.integrarepara.es';
|
||||
|
||||
let localServices = []; // Solo los "Sin Cita"
|
||||
let globalAllServices = []; // TODOS los servicios para calcular solapamientos
|
||||
let globalAllServices = []; // TODOS para solapamientos
|
||||
let pendingRequests = []; // Solicitudes del portal
|
||||
let systemStatuses = [];
|
||||
let bizHours = { m_start: '09:00', m_end: '14:00', a_start: '16:00', a_end: '19:00' };
|
||||
|
||||
@@ -188,11 +249,8 @@
|
||||
const data = await res.json();
|
||||
|
||||
if(data.ok && data.config && data.config.portal_settings) {
|
||||
// Extraemos horario comercial
|
||||
const ps = data.config.portal_settings;
|
||||
if(ps.m_start) bizHours = { m_start: ps.m_start, m_end: ps.m_end, a_start: ps.a_start, a_end: ps.a_end };
|
||||
|
||||
// Extraemos colores
|
||||
if(ps.app_settings) {
|
||||
theme = ps.app_settings;
|
||||
localStorage.setItem('app_theme', JSON.stringify(theme));
|
||||
@@ -207,7 +265,7 @@
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
if (!localStorage.getItem("token") || localStorage.getItem("role") !== 'operario') {
|
||||
if (!localStorage.getItem("token") || (localStorage.getItem("role") !== 'operario' && localStorage.getItem("role") !== 'operario_cerrado')) {
|
||||
window.location.href = "index.html"; return;
|
||||
}
|
||||
await applyTheme();
|
||||
@@ -225,23 +283,32 @@
|
||||
}
|
||||
|
||||
async function refreshData() {
|
||||
document.getElementById('servicesList').classList.add('hidden');
|
||||
document.getElementById('contentWrapper').classList.add('hidden');
|
||||
document.getElementById('loader').classList.remove('hidden');
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/services/active`, {
|
||||
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
|
||||
});
|
||||
const data = await res.json();
|
||||
const headers = { "Authorization": `Bearer ${localStorage.getItem("token")}` };
|
||||
|
||||
if (data.ok) {
|
||||
globalAllServices = data.services; // Guardamos TODOS para chequear la agenda real
|
||||
// 1. Cargar servicios activos del operario
|
||||
const resActivos = await fetch(`${API_URL}/services/active`, { headers });
|
||||
const dataActivos = await resActivos.json();
|
||||
|
||||
// Filtramos los SIN CITA
|
||||
localServices = data.services.filter(s => {
|
||||
// 2. Cargar peticiones de cita pendientes de este operario
|
||||
const resReqs = await fetch(`${API_URL}/agenda/requests`, { headers });
|
||||
const dataReqs = await resReqs.json();
|
||||
|
||||
if (dataActivos.ok && dataReqs.ok) {
|
||||
globalAllServices = dataActivos.services;
|
||||
pendingRequests = dataReqs.requests;
|
||||
|
||||
// Filtrar la lista normal de "Sin Cita"
|
||||
localServices = globalAllServices.filter(s => {
|
||||
if (s.provider === 'SYSTEM_BLOCK') return false;
|
||||
const raw = s.raw_data || {};
|
||||
// Si ya tiene fecha o si tiene una solicitud pendiente, no lo mostramos en el listado base
|
||||
if (raw.scheduled_date && raw.scheduled_date.trim() !== "") return false;
|
||||
if (raw.appointment_status === 'pending') return false;
|
||||
|
||||
if (raw.status_operativo) {
|
||||
const st = systemStatuses.find(x => String(x.id) === String(raw.status_operativo));
|
||||
if (st && st.is_final) return false;
|
||||
@@ -249,22 +316,151 @@
|
||||
return true;
|
||||
});
|
||||
|
||||
renderRequests();
|
||||
renderServices();
|
||||
}
|
||||
} catch (e) {
|
||||
alert("Error de conexión");
|
||||
} finally {
|
||||
document.getElementById('loader').classList.add('hidden');
|
||||
document.getElementById('servicesList').classList.remove('hidden');
|
||||
document.getElementById('contentWrapper').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// RENDERIZADO DE SOLICITUDES PENDIENTES
|
||||
// ==========================================
|
||||
function renderRequests() {
|
||||
const reqSection = document.getElementById('requestsSection');
|
||||
const reqList = document.getElementById('requestsList');
|
||||
reqList.innerHTML = '';
|
||||
|
||||
if (pendingRequests.length === 0) {
|
||||
reqSection.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
reqSection.classList.remove('hidden');
|
||||
|
||||
pendingRequests.forEach(req => {
|
||||
const raw = req.raw_data || {};
|
||||
const name = raw["Nombre Cliente"] || raw["CLIENTE"] || "Cliente";
|
||||
const rDate = formatDate(raw.requested_date);
|
||||
const rTime = addOneHour(raw.requested_time); // Calculamos el tramo para mostrarlo
|
||||
|
||||
reqList.innerHTML += `
|
||||
<div class="bg-blue-50 border border-blue-200 p-4 rounded-3xl flex justify-between items-center shadow-sm relative overflow-hidden">
|
||||
<div class="absolute right-0 top-0 w-16 h-16 bg-blue-100 rounded-bl-full opacity-50 z-0"></div>
|
||||
<div class="relative z-10 flex-1">
|
||||
<p class="text-[9px] font-black text-blue-500 uppercase tracking-widest mb-0.5">Cita Solicitada</p>
|
||||
<h3 class="font-black text-slate-800 text-sm leading-tight truncate">${name}</h3>
|
||||
<p class="text-[10px] font-bold text-slate-600 mt-1">${rDate} | ${raw.requested_time} - ${rTime}</p>
|
||||
</div>
|
||||
<button onclick="openApproveModal(${req.id})" class="bg-blue-600 text-white w-10 h-10 rounded-full flex items-center justify-center shadow-lg active:scale-95 transition-transform shrink-0 ml-3 relative z-10">
|
||||
<i data-lucide="chevron-right" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
function openApproveModal(id) {
|
||||
const req = pendingRequests.find(r => r.id === id);
|
||||
if(!req) return;
|
||||
const raw = req.raw_data || {};
|
||||
|
||||
document.getElementById('appId').value = id;
|
||||
document.getElementById('appRef').innerText = `Exp. #${req.service_ref || "S/R"}`;
|
||||
document.getElementById('appName').innerText = raw["Nombre Cliente"] || "Cliente";
|
||||
|
||||
document.getElementById('appDate').innerText = formatDate(raw.requested_date);
|
||||
document.getElementById('appTime').innerText = `Llegada aprox: ${raw.requested_time} - ${addOneHour(raw.requested_time)}`;
|
||||
|
||||
// Reseteamos el selector de duración a 1 hora por defecto
|
||||
document.getElementById('appDurationInput').value = "60";
|
||||
|
||||
const modal = document.getElementById('approveModal');
|
||||
const content = document.getElementById('approveModalContent');
|
||||
modal.classList.remove('hidden');
|
||||
void modal.offsetWidth;
|
||||
modal.classList.remove('opacity-0');
|
||||
content.classList.remove('translate-y-full');
|
||||
}
|
||||
|
||||
async function approveRequest() {
|
||||
const id = document.getElementById('appId').value;
|
||||
const duration = document.getElementById('appDurationInput').value;
|
||||
|
||||
const btn = document.getElementById('btnApprove');
|
||||
const originalContent = btn.innerHTML;
|
||||
btn.innerHTML = `<i data-lucide="loader-2" class="w-4 h-4 animate-spin"></i>`;
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/agenda/requests/${id}/approve`, {
|
||||
method: 'POST',
|
||||
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` },
|
||||
body: JSON.stringify({ duration: duration })
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
showToast("Cita Aceptada");
|
||||
closeModal('approveModal', 'approveModalContent');
|
||||
refreshData();
|
||||
} else {
|
||||
alert("Error al confirmar.");
|
||||
}
|
||||
} catch (e) {
|
||||
alert("Error de conexión");
|
||||
} finally {
|
||||
btn.innerHTML = originalContent;
|
||||
btn.disabled = false;
|
||||
lucide.createIcons();
|
||||
}
|
||||
}
|
||||
|
||||
async function rejectRequest() {
|
||||
if(!confirm("¿Seguro que quieres rechazar este horario? El cliente recibirá un mensaje para elegir otro.")) return;
|
||||
|
||||
const id = document.getElementById('appId').value;
|
||||
const btn = document.getElementById('btnReject');
|
||||
const originalContent = btn.innerHTML;
|
||||
btn.innerHTML = `<i data-lucide="loader-2" class="w-4 h-4 animate-spin"></i>`;
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/agenda/requests/${id}/reject`, {
|
||||
method: 'POST',
|
||||
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${localStorage.getItem("token")}` }
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
showToast("Cita Rechazada");
|
||||
closeModal('approveModal', 'approveModalContent');
|
||||
refreshData();
|
||||
} else {
|
||||
alert("Error al rechazar.");
|
||||
}
|
||||
} catch (e) {
|
||||
alert("Error de conexión");
|
||||
} finally {
|
||||
btn.innerHTML = originalContent;
|
||||
btn.disabled = false;
|
||||
lucide.createIcons();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// RENDERIZADO DE LISTADO NORMAL (SIN CITA)
|
||||
// ==========================================
|
||||
function renderServices() {
|
||||
const container = document.getElementById('servicesList');
|
||||
const noDateSec = document.getElementById('noDateSection');
|
||||
|
||||
if (localServices.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="text-center py-12 bg-white rounded-3xl border border-slate-100 shadow-sm mt-4">
|
||||
<div class="text-center py-12 bg-white rounded-3xl border border-slate-100 shadow-sm mt-2">
|
||||
<div class="w-16 h-16 bg-emerald-50 text-emerald-500 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<i data-lucide="check-check" class="w-8 h-8"></i>
|
||||
</div>
|
||||
@@ -272,9 +468,19 @@
|
||||
<p class="text-xs text-slate-400 font-medium mt-1">No tienes avisos pendientes de agendar.</p>
|
||||
</div>`;
|
||||
lucide.createIcons();
|
||||
|
||||
// Si tampoco hay peticiones, ocultamos el título "Pendientes de fecha"
|
||||
if (pendingRequests.length === 0) {
|
||||
noDateSec.querySelector('h2').classList.add('hidden');
|
||||
} else {
|
||||
noDateSec.classList.add('hidden');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
noDateSec.classList.remove('hidden');
|
||||
noDateSec.querySelector('h2').classList.remove('hidden');
|
||||
|
||||
container.innerHTML = localServices.map(s => {
|
||||
const raw = s.raw_data || {};
|
||||
const name = raw["Nombre Cliente"] || raw["CLIENTE"] || "Asegurado";
|
||||
@@ -328,6 +534,26 @@
|
||||
return `${h}:${min}`;
|
||||
}
|
||||
|
||||
function addOneHour(timeStr) {
|
||||
if(!timeStr) return "";
|
||||
let [h, m] = timeStr.split(':').map(Number);
|
||||
let totalMins = h * 60 + m + 60;
|
||||
let newH = Math.floor(totalMins / 60);
|
||||
let newM = totalMins % 60;
|
||||
return `${String(newH).padStart(2,'0')}:${String(newM).padStart(2,'0')}`;
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return "";
|
||||
try {
|
||||
const parts = dateStr.split('-');
|
||||
if(parts.length !== 3) return dateStr;
|
||||
const d = new Date(parts[0], parts[1]-1, parts[2]);
|
||||
const opciones = { weekday: 'long', day: 'numeric', month: 'short' };
|
||||
return d.toLocaleDateString('es-ES', opciones);
|
||||
} catch(e) { return dateStr; }
|
||||
}
|
||||
|
||||
function buildDayCarousel() {
|
||||
const container = document.getElementById('dayCarousel');
|
||||
container.innerHTML = "";
|
||||
@@ -419,8 +645,8 @@
|
||||
let startMins = timeToMins(startStr);
|
||||
let endMins = timeToMins(endStr);
|
||||
|
||||
// Saltos de 15 minutos
|
||||
for (let m = startMins; m + duration <= endMins; m += 15) {
|
||||
// Saltos de 30 minutos (igual que en buscar.html)
|
||||
for (let m = startMins; m + duration <= endMins; m += 30) {
|
||||
if (!isOverlapping(m, m + duration, occupied)) {
|
||||
const timeStr = minsToTime(m);
|
||||
const isSelected = timeStr === pickerSelectedTime;
|
||||
@@ -447,7 +673,7 @@
|
||||
grid.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// Si la hora que estaba seleccionada ya no sale (porque ampliaron la duración), la borramos
|
||||
// Si la hora que estaba seleccionada ya no sale, la borramos
|
||||
if (pickerSelectedTime && !grid.innerHTML.includes(`'${pickerSelectedTime}'`)) {
|
||||
pickerSelectedTime = "";
|
||||
}
|
||||
@@ -456,7 +682,7 @@
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// APERTURA DE MODAL Y GUARDADO
|
||||
// APERTURA DE MODAL Y GUARDADO (MANUAL)
|
||||
// ==========================================
|
||||
function openActionModal(id) {
|
||||
const s = localServices.find(x => x.id === id);
|
||||
@@ -487,9 +713,9 @@
|
||||
content.classList.remove('translate-y-full');
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
const modal = document.getElementById('actionModal');
|
||||
const content = document.getElementById('modalContent');
|
||||
function closeModal(modalId, contentId) {
|
||||
const modal = document.getElementById(modalId);
|
||||
const content = document.getElementById(contentId);
|
||||
|
||||
modal.classList.add('opacity-0');
|
||||
content.classList.add('translate-y-full');
|
||||
@@ -537,7 +763,7 @@
|
||||
|
||||
if (res.ok) {
|
||||
showToast("Cita Agendada en Calendario");
|
||||
closeModal();
|
||||
closeModal('actionModal', 'modalContent');
|
||||
refreshData();
|
||||
} else {
|
||||
alert("Error al guardar la cita.");
|
||||
|
||||
Reference in New Issue
Block a user