Selector de teléfonos en asignados y calendario, priorizando móviles sobre fijos
This commit is contained in:
@@ -120,6 +120,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="detId">
|
<input type="hidden" id="detId">
|
||||||
<input type="hidden" id="detPhoneRaw">
|
<input type="hidden" id="detPhoneRaw">
|
||||||
|
<div id="phoneSelectorRow" class="hidden flex items-center gap-2 mb-3 overflow-x-auto no-scrollbar"></div>
|
||||||
<div class="grid grid-cols-2 gap-3 mb-6">
|
<div class="grid grid-cols-2 gap-3 mb-6">
|
||||||
<button onclick="callClient()" class="bg-blue-50 border border-blue-100 text-blue-600 font-black py-3 rounded-2xl flex items-center justify-center gap-2 active:scale-95 transition-transform shadow-sm">
|
<button onclick="callClient()" class="bg-blue-50 border border-blue-100 text-blue-600 font-black py-3 rounded-2xl flex items-center justify-center gap-2 active:scale-95 transition-transform shadow-sm">
|
||||||
<i data-lucide="phone" class="w-5 h-5"></i>
|
<i data-lucide="phone" class="w-5 h-5"></i>
|
||||||
@@ -675,9 +676,16 @@ function renderServices(servicesToRender = localServices) {
|
|||||||
document.getElementById('detName').innerText = raw["Nombre Cliente"] || "Asegurado";
|
document.getElementById('detName').innerText = raw["Nombre Cliente"] || "Asegurado";
|
||||||
document.getElementById('detAddress').innerText = `${raw["Dirección"] || ""}, ${raw["Población"] || ""}`;
|
document.getElementById('detAddress').innerText = `${raw["Dirección"] || ""}, ${raw["Población"] || ""}`;
|
||||||
|
|
||||||
|
// 📞 Usamos los teléfonos ya extraídos y priorizados (móvil primero) por la API.
|
||||||
|
// Si por caché no vinieran, caemos al match simple de siempre.
|
||||||
const rawPhone = raw["Teléfono"] || raw["TELEFONOS"] || raw["TELEFONO"] || "";
|
const rawPhone = raw["Teléfono"] || raw["TELEFONOS"] || raw["TELEFONO"] || "";
|
||||||
const matchPhone = String(rawPhone).match(/[6789]\d{8}/);
|
const matchPhone = String(rawPhone).match(/[6789]\d{8}/);
|
||||||
document.getElementById('detPhoneRaw').value = matchPhone ? matchPhone[0] : "";
|
const fallbackPhone = matchPhone ? matchPhone[0] : "";
|
||||||
|
const detailPhones = Array.isArray(s.phones) && s.phones.length > 0
|
||||||
|
? s.phones
|
||||||
|
: (fallbackPhone ? [{ number: fallbackPhone, isMobile: /^[67]/.test(fallbackPhone), horario: '', contacto: '' }] : []);
|
||||||
|
document.getElementById('detPhoneRaw').value = detailPhones[0]?.number || "";
|
||||||
|
renderPhoneSelector(detailPhones);
|
||||||
document.getElementById('durationInput').value = "60";
|
document.getElementById('durationInput').value = "60";
|
||||||
pickerSelectedDate = "";
|
pickerSelectedDate = "";
|
||||||
pickerSelectedTime = "";
|
pickerSelectedTime = "";
|
||||||
@@ -870,6 +878,29 @@ function renderServices(servicesToRender = localServices) {
|
|||||||
if (phone) window.open(`https://wa.me/34${phone}`, '_blank');
|
if (phone) window.open(`https://wa.me/34${phone}`, '_blank');
|
||||||
else alert("No hay un teléfono válido guardado.");
|
else alert("No hay un teléfono válido guardado.");
|
||||||
}
|
}
|
||||||
|
// 📞 Cuando el servicio trae más de un teléfono (típico de HomeServe), pintamos un
|
||||||
|
// selector de chips para que el operario elija cuál usar antes de Llamar/WhatsApp.
|
||||||
|
// Con un solo teléfono no mostramos nada (para no añadir ruido visual de más).
|
||||||
|
function renderPhoneSelector(phones) {
|
||||||
|
const row = document.getElementById('phoneSelectorRow');
|
||||||
|
if (!row) return;
|
||||||
|
if (!phones || phones.length <= 1) { row.innerHTML = ''; row.classList.add('hidden'); return; }
|
||||||
|
const active = document.getElementById('detPhoneRaw').value;
|
||||||
|
row.innerHTML = phones.map(p => {
|
||||||
|
const isActive = p.number === active;
|
||||||
|
return `
|
||||||
|
<button type="button" onclick="selectPhone('${p.number}')" class="shrink-0 flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-[10px] font-black uppercase tracking-widest ${isActive ? 'bg-primary-dynamic text-white border-primary-dynamic' : 'bg-white text-slate-500 border-slate-200'}">
|
||||||
|
<i data-lucide="${p.isMobile ? 'smartphone' : 'phone'}" class="w-3 h-3"></i> ${p.number}
|
||||||
|
</button>`;
|
||||||
|
}).join('');
|
||||||
|
row.classList.remove('hidden');
|
||||||
|
lucide.createIcons();
|
||||||
|
}
|
||||||
|
function selectPhone(number) {
|
||||||
|
document.getElementById('detPhoneRaw').value = number;
|
||||||
|
const s = localServices.find(x => String(x.id) === String(document.getElementById('detId').value));
|
||||||
|
renderPhoneSelector(Array.isArray(s?.phones) && s.phones.length > 0 ? s.phones : [{number, isMobile:/^[67]/.test(number)}]);
|
||||||
|
}
|
||||||
async function saveAppointment() {
|
async function saveAppointment() {
|
||||||
const id = document.getElementById('detId').value;
|
const id = document.getElementById('detId').value;
|
||||||
const duration = document.getElementById('durationInput').value;
|
const duration = document.getElementById('durationInput').value;
|
||||||
@@ -981,7 +1012,9 @@ function renderServices(servicesToRender = localServices) {
|
|||||||
id: s.id, type: 'sin_cita', address,
|
id: s.id, type: 'sin_cita', address,
|
||||||
name: raw["Nombre Cliente"] || raw["CLIENTE"] || "Asegurado",
|
name: raw["Nombre Cliente"] || raw["CLIENTE"] || "Asegurado",
|
||||||
company: raw["Compañía"] || raw["Procedencia"] || "Particular",
|
company: raw["Compañía"] || raw["Procedencia"] || "Particular",
|
||||||
phone: extractPhone(raw), isUrgent: !!s.is_urgent
|
// 📞 Preferimos el teléfono ya priorizado (móvil primero) que manda la API;
|
||||||
|
// si no vino (caché vieja), caemos al match simple de siempre.
|
||||||
|
phone: (Array.isArray(s.phones) && s.phones[0]?.number) || extractPhone(raw), isUrgent: !!s.is_urgent
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
pendingRequests.forEach(req => {
|
pendingRequests.forEach(req => {
|
||||||
@@ -1124,6 +1157,7 @@ function renderServices(servicesToRender = localServices) {
|
|||||||
<div class="flex flex-col gap-1.5 shrink-0">
|
<div class="flex flex-col gap-1.5 shrink-0">
|
||||||
${dirUrl ? `<a href="${dirUrl}" target="_blank" onclick="event.stopPropagation()" class="w-8 h-8 bg-blue-50 border border-blue-100 text-blue-600 rounded-lg flex items-center justify-center"><i data-lucide="navigation" class="w-4 h-4"></i></a>` : ''}
|
${dirUrl ? `<a href="${dirUrl}" target="_blank" onclick="event.stopPropagation()" class="w-8 h-8 bg-blue-50 border border-blue-100 text-blue-600 rounded-lg flex items-center justify-center"><i data-lucide="navigation" class="w-4 h-4"></i></a>` : ''}
|
||||||
${r.phone ? `<a href="tel:+34${r.phone}" onclick="event.stopPropagation()" class="w-8 h-8 bg-slate-50 border border-slate-200 text-slate-600 rounded-lg flex items-center justify-center"><i data-lucide="phone" class="w-4 h-4"></i></a>` : ''}
|
${r.phone ? `<a href="tel:+34${r.phone}" onclick="event.stopPropagation()" class="w-8 h-8 bg-slate-50 border border-slate-200 text-slate-600 rounded-lg flex items-center justify-center"><i data-lucide="phone" class="w-4 h-4"></i></a>` : ''}
|
||||||
|
${r.phone ? `<a href="https://wa.me/34${r.phone}" target="_blank" onclick="event.stopPropagation()" class="w-8 h-8 bg-emerald-50 border border-emerald-100 text-emerald-600 rounded-lg flex items-center justify-center"><i data-lucide="message-circle" class="w-4 h-4"></i></a>` : ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -171,6 +171,8 @@
|
|||||||
<i data-lucide="external-link" class="w-4 h-4"></i> Copiar y Abrir Portal
|
<i data-lucide="external-link" class="w-4 h-4"></i> Copiar y Abrir Portal
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div id="phoneSelectorRow" class="hidden flex items-center gap-2 mb-3 overflow-x-auto no-scrollbar"></div>
|
||||||
|
|
||||||
<button onclick="callClient()" class="w-full bg-primary-dynamic text-white font-black py-4 rounded-2xl shadow-xl flex items-center justify-center gap-3 uppercase text-sm tracking-widest active:scale-95 transition-all">
|
<button onclick="callClient()" class="w-full bg-primary-dynamic text-white font-black py-4 rounded-2xl shadow-xl flex items-center justify-center gap-3 uppercase text-sm tracking-widest active:scale-95 transition-all">
|
||||||
<i data-lucide="phone" class="w-5 h-5 fill-current"></i> Llamar al Cliente
|
<i data-lucide="phone" class="w-5 h-5 fill-current"></i> Llamar al Cliente
|
||||||
</button>
|
</button>
|
||||||
@@ -1010,9 +1012,16 @@
|
|||||||
const fullAddress = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
|
const fullAddress = `${raw["Dirección"] || ""}, ${raw["Código Postal"] || ""} ${raw["Población"] || ""}`;
|
||||||
document.getElementById('detAddress').innerText = fullAddress;
|
document.getElementById('detAddress').innerText = fullAddress;
|
||||||
|
|
||||||
|
// 📞 Usamos los teléfonos ya extraídos y priorizados (móvil primero) por la API.
|
||||||
|
// Si por caché no vinieran, caemos al match simple de siempre.
|
||||||
const rawPhone = raw["Teléfono"] || raw["TELEFONOS"] || raw["TELEFONO"] || "";
|
const rawPhone = raw["Teléfono"] || raw["TELEFONOS"] || raw["TELEFONO"] || "";
|
||||||
const matchPhone = String(rawPhone).match(/[6789]\d{8}/);
|
const matchPhone = String(rawPhone).match(/[6789]\d{8}/);
|
||||||
document.getElementById('detPhoneRaw').value = matchPhone ? matchPhone[0] : "";
|
const fallbackPhone = matchPhone ? matchPhone[0] : "";
|
||||||
|
const detailPhones = Array.isArray(s.phones) && s.phones.length > 0
|
||||||
|
? s.phones
|
||||||
|
: (fallbackPhone ? [{ number: fallbackPhone, isMobile: /^[67]/.test(fallbackPhone), horario: '', contacto: '' }] : []);
|
||||||
|
document.getElementById('detPhoneRaw').value = detailPhones[0]?.number || "";
|
||||||
|
renderPhoneSelector(detailPhones);
|
||||||
|
|
||||||
const banner = document.getElementById('urgentBanner');
|
const banner = document.getElementById('urgentBanner');
|
||||||
if (s.is_urgent) banner.classList.remove('hidden');
|
if (s.is_urgent) banner.classList.remove('hidden');
|
||||||
@@ -1394,6 +1403,30 @@
|
|||||||
} else { alert("Sin teléfono"); }
|
} else { alert("Sin teléfono"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 📞 Cuando el servicio trae más de un teléfono (típico de HomeServe), pintamos un
|
||||||
|
// selector de chips para que el operario elija cuál usar antes de Llamar/WhatsApp.
|
||||||
|
// Con un solo teléfono no mostramos nada (para no añadir ruido visual de más).
|
||||||
|
function renderPhoneSelector(phones) {
|
||||||
|
const row = document.getElementById('phoneSelectorRow');
|
||||||
|
if (!row) return;
|
||||||
|
if (!phones || phones.length <= 1) { row.innerHTML = ''; row.classList.add('hidden'); return; }
|
||||||
|
const active = document.getElementById('detPhoneRaw').value;
|
||||||
|
row.innerHTML = phones.map(p => {
|
||||||
|
const isActive = p.number === active;
|
||||||
|
return `
|
||||||
|
<button type="button" onclick="selectPhone('${p.number}')" class="shrink-0 flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-[10px] font-black uppercase tracking-widest ${isActive ? 'bg-primary-dynamic text-white border-primary-dynamic' : 'bg-white text-slate-500 border-slate-200'}">
|
||||||
|
<i data-lucide="${p.isMobile ? 'smartphone' : 'phone'}" class="w-3 h-3"></i> ${p.number}
|
||||||
|
</button>`;
|
||||||
|
}).join('');
|
||||||
|
row.classList.remove('hidden');
|
||||||
|
lucide.createIcons();
|
||||||
|
}
|
||||||
|
function selectPhone(number) {
|
||||||
|
document.getElementById('detPhoneRaw').value = number;
|
||||||
|
const s = localServices.find(x => String(x.id) === String(document.getElementById('detId').value));
|
||||||
|
renderPhoneSelector(Array.isArray(s?.phones) && s.phones.length > 0 ? s.phones : [{number, isMobile:/^[67]/.test(number)}]);
|
||||||
|
}
|
||||||
|
|
||||||
async function copyAndOpenPortal() {
|
async function copyAndOpenPortal() {
|
||||||
const btn = document.getElementById('btnPortal');
|
const btn = document.getElementById('btnPortal');
|
||||||
const originalHtml = btn.innerHTML;
|
const originalHtml = btn.innerHTML;
|
||||||
|
|||||||
Reference in New Issue
Block a user