feat(notifs): centro de notificaciones con contador interactivo de mensajes pendientes y alertas de servicio en app movil
This commit is contained in:
parent
b92a7ba6c3
commit
20b48cfd5a
@ -1302,4 +1302,174 @@ h1, h2, h3, h4, .brand-title {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
/* NOTIFICATION CENTER & UNREAD COUNTER BADGE */
|
||||
.notification-wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-notif-bell {
|
||||
position: relative;
|
||||
background: rgba(15, 23, 42, 0.85);
|
||||
border: 1px solid var(--border-glass);
|
||||
color: #cbd5e1;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-notif-bell:hover {
|
||||
background: rgba(30, 41, 59, 0.9);
|
||||
color: #fff;
|
||||
border-color: var(--accent-cyan);
|
||||
box-shadow: 0 0 12px var(--accent-cyan-glow);
|
||||
}
|
||||
|
||||
.notif-badge {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: -6px;
|
||||
background: #ef4444;
|
||||
color: #fff;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 800;
|
||||
min-width: 19px;
|
||||
height: 19px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
box-shadow: 0 0 10px rgba(239, 68, 68, 0.8);
|
||||
border: 2px solid #080c14;
|
||||
animation: notifPulse 2.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes notifPulse {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.15); box-shadow: 0 0 14px rgba(239, 68, 68, 1); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.notif-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% + 12px);
|
||||
right: 0;
|
||||
width: 360px;
|
||||
max-width: 90vw;
|
||||
background: #0f172a;
|
||||
border: 1px solid var(--border-glass);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.85);
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.notif-dropdown.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.notif-header {
|
||||
padding: 0.85rem 1.15rem;
|
||||
background: rgba(15, 23, 42, 0.95);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.notif-header strong {
|
||||
color: #fff;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.notif-header-badge {
|
||||
background: rgba(239, 68, 68, 0.2);
|
||||
color: #f87171;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
padding: 2px 7px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.btn-mark-all-read {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #38bdf8;
|
||||
font-size: 0.78rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-mark-all-read:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.notif-list {
|
||||
max-height: 380px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.notif-item {
|
||||
padding: 0.9rem 1.15rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
gap: 0.85rem;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.notif-item:hover {
|
||||
background: rgba(30, 41, 59, 0.5);
|
||||
}
|
||||
|
||||
.notif-item.unread {
|
||||
background: rgba(6, 182, 212, 0.07);
|
||||
border-left: 3px solid var(--accent-cyan);
|
||||
}
|
||||
|
||||
.notif-item-icon {
|
||||
font-size: 1.35rem;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.notif-item-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.notif-item-title {
|
||||
font-size: 0.88rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.notif-item-desc {
|
||||
font-size: 0.8rem;
|
||||
color: #94a3b8;
|
||||
line-height: 1.35;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.notif-item-time {
|
||||
font-size: 0.72rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.notif-footer {
|
||||
padding: 0.75rem;
|
||||
background: rgba(11, 17, 32, 0.95);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -69,6 +69,38 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Centro de Notificaciones & Contador de Mensajes Pendientes -->
|
||||
<div class="notification-wrapper" id="notif-wrapper">
|
||||
<button type="button" class="btn-notif-bell" id="btn-toggle-notifs" title="Notificaciones y Mensajes Pendientes">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
|
||||
</svg>
|
||||
<span class="notif-badge" id="notif-unread-count">3</span>
|
||||
</button>
|
||||
|
||||
<!-- Dropdown de Notificaciones -->
|
||||
<div class="notif-dropdown" id="notif-dropdown-panel">
|
||||
<div class="notif-header">
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
<strong>🔔 Notificaciones</strong>
|
||||
<span class="notif-header-badge" id="notif-header-unread">3 nuevas</span>
|
||||
</div>
|
||||
<button type="button" class="btn-mark-all-read" id="btn-mark-all-read">Marcar leídas</button>
|
||||
</div>
|
||||
|
||||
<div class="notif-list" id="notif-items-list">
|
||||
<!-- Renderizado dinámicamente por app.js -->
|
||||
</div>
|
||||
|
||||
<div class="notif-footer">
|
||||
<a href="https://wa.me/573167455877" target="_blank" id="notif-wa-link" style="color: var(--accent-cyan); text-decoration: none; font-size: 0.8rem; display: flex; align-items: center; justify-content: center; gap: 0.35rem;">
|
||||
<span>💬 Contactar a Central de Soporte WhatsApp</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="/PacifictransGo.apk" class="btn-apk-header" id="btn-download-header">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M17.523 15.3414c-.5511 0-.9993-.4486-.9993-1.0001s.4482-1.0001.9993-1.0001c.552 0 1.0001.4486 1.0001 1.0001s-.4481 1.0001-1.0001 1.0001m-11.046 0c-.5511 0-.9993-.4486-.9993-1.0001s.4482-1.0001.9993-1.0001c.552 0 1.0001.4486 1.0001 1.0001s-.4481 1.0001-1.0001 1.0001m11.4045-6.02l1.997-3.4589c.1408-.2439.0573-.5552-.1866-.696-.2438-.1408-.5551-.0573-.696.1866l-2.0238 3.5054c-1.5037-.6873-3.1979-1.0772-4.9691-1.0772s-3.4654.3899-4.9691 1.0772l-2.0238-3.5054c-.1409-.2439-.4522-.3274-.696-.1866-.2439.1408-.3274.4521-.1866.696l1.997 3.4589c-3.7997 2.0623-6.375 5.9863-6.446 10.5369h24.646c-.071-4.5506-2.6463-8.4746-6.446-10.5369"/>
|
||||
|
||||
@ -28,6 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
initPWA();
|
||||
initTabs();
|
||||
initAuthSystem();
|
||||
initNotificationsSystem();
|
||||
initPassengerCalculator();
|
||||
initFreightCalculator();
|
||||
initLeafletRadarMap();
|
||||
@ -1040,3 +1041,118 @@ function initFreightCalculator() {
|
||||
if (declaredValueInput) declaredValueInput.addEventListener('input', window.recalculateFreight);
|
||||
window.recalculateFreight();
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
9. CENTRO DE NOTIFICACIONES & CONTADOR DE MENSAJES PENDIENTES
|
||||
========================================================================== */
|
||||
function initNotificationsSystem() {
|
||||
const btnBell = document.getElementById('btn-toggle-notifs');
|
||||
const dropdown = document.getElementById('notif-dropdown-panel');
|
||||
const badge = document.getElementById('notif-unread-count');
|
||||
const headerUnread = document.getElementById('notif-header-unread');
|
||||
const listEl = document.getElementById('notif-items-list');
|
||||
const btnMarkAll = document.getElementById('btn-mark-all-read');
|
||||
const waLink = document.getElementById('notif-wa-link');
|
||||
|
||||
const defaultNotifs = [
|
||||
{
|
||||
id: '1',
|
||||
icon: '🚗',
|
||||
title: '¡Cupo 4/4 Completado!',
|
||||
desc: 'Tu viaje Cali ➔ Buenaventura tiene conductor asignado (Mario Fernando G.). Recogida escalonada y ruta Waze TSP activa.',
|
||||
time: 'Hace 5 min',
|
||||
unread: true
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
icon: '📦',
|
||||
title: 'Encomienda en Ruta 40',
|
||||
desc: 'Guía #PT-8921 despachada desde Cali con destino a Buenaventura. Seguimiento satelital en vivo.',
|
||||
time: 'Hace 25 min',
|
||||
unread: true
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
icon: '🛡️',
|
||||
title: 'Identidad Verificada 2FA',
|
||||
desc: 'Tu cuenta ha sido validada con WhatsApp OTP. Viajes y envíos 100% seguros y respaldados.',
|
||||
time: 'Hace 1 hora',
|
||||
unread: true
|
||||
}
|
||||
];
|
||||
|
||||
let stored = localStorage.getItem('pt_notifications');
|
||||
let notifications = stored ? JSON.parse(stored) : defaultNotifs;
|
||||
|
||||
function saveAndRender() {
|
||||
localStorage.setItem('pt_notifications', JSON.stringify(notifications));
|
||||
const unreadCount = notifications.filter(n => n.unread).length;
|
||||
|
||||
if (badge) {
|
||||
badge.textContent = unreadCount;
|
||||
badge.style.display = unreadCount > 0 ? 'flex' : 'none';
|
||||
}
|
||||
|
||||
if (headerUnread) {
|
||||
headerUnread.textContent = `${unreadCount} nuevas`;
|
||||
headerUnread.style.display = unreadCount > 0 ? 'inline-block' : 'none';
|
||||
}
|
||||
|
||||
if (listEl) {
|
||||
if (notifications.length === 0) {
|
||||
listEl.innerHTML = '<div style="padding: 1.5rem; text-align: center; color: #64748b; font-size: 0.88rem;">No tienes notificaciones pendientes.</div>';
|
||||
} else {
|
||||
listEl.innerHTML = notifications.map(n => `
|
||||
<div class="notif-item ${n.unread ? 'unread' : ''}" data-id="${n.id}">
|
||||
<div class="notif-item-icon">${n.icon}</div>
|
||||
<div class="notif-item-content">
|
||||
<div class="notif-item-title">${n.title}</div>
|
||||
<div class="notif-item-desc">${n.desc}</div>
|
||||
<div class="notif-item-time">${n.time}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
listEl.querySelectorAll('.notif-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const id = item.getAttribute('data-id');
|
||||
const target = notifications.find(n => n.id === id);
|
||||
if (target) {
|
||||
target.unread = false;
|
||||
saveAndRender();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (btnBell && dropdown) {
|
||||
btnBell.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
dropdown.classList.toggle('active');
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!dropdown.contains(e.target) && !btnBell.contains(e.target)) {
|
||||
dropdown.classList.remove('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (btnMarkAll) {
|
||||
btnMarkAll.addEventListener('click', () => {
|
||||
notifications.forEach(n => { n.unread = false; });
|
||||
saveAndRender();
|
||||
});
|
||||
}
|
||||
|
||||
// Sincronizar enlace de WhatsApp con el número configurado dinámicamente
|
||||
if (waLink && currentTariffs.numeroAtencionWhatsApp) {
|
||||
const clean = currentTariffs.numeroAtencionWhatsApp.replace(/\D/g, '');
|
||||
waLink.href = `https://wa.me/${clean}?text=Hola%20Central%20de%20Despacho%20Pacifictrans%20Go`;
|
||||
}
|
||||
|
||||
saveAndRender();
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user