UNPKG

gentelella

Version:

Gentelella v4 — free admin template. 60 pages, 20 chart variants, fully interactive inbox & kanban, live theme generator, component playground, PWA-ready. Vite 8, vanilla JS, no Bootstrap, no jQuery.

143 lines (128 loc) 6.96 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Notifications | Gentelella 2026 v4</title> <link rel="icon" href="../images/favicon.svg" type="image/svg+xml"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <script type="module" src="/src/main-v4.js"></script> </head> <body data-shell="admin" data-page="notifications" data-breadcrumb="Home > Notifications"> <main class="main"> <div class="page-wrapper"> <div class="page-header"> <div class="page-header-row"> <div> <div class="page-pretitle">Activity</div> <h1 class="page-title">Notifications</h1> </div> <div class="page-actions"> <button class="btn btn-outline" id="mark-all-read">Mark all read</button> <button class="btn btn-outline"> <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="3"/><path d="M8 1v3M8 12v3M1 8h3M12 8h3"/></svg> Settings </button> </div> </div> </div> <div class="card"> <div class="card-header" style="border-bottom:1px solid var(--border-color-light)"> <div class="chart-tabs notif-tabs" id="notif-tabs"> <button class="chart-tab active" data-filter="all">All</button> <button class="chart-tab" data-filter="unread">Unread <span class="notif-tab-count" id="count-unread">0</span></button> <button class="chart-tab" data-filter="mentions">Mentions</button> <button class="chart-tab" data-filter="reviews">Reviews</button> </div> </div> <div class="card-body" style="padding:0"> <div class="notifications-list" id="notif-list"> <!-- rendered by inline script --> </div> <div class="notifications-empty" id="notif-empty" hidden> <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 3a6 6 0 00-6 6c0 6-3 7-3 7h18s-3-1-3-7a6 6 0 00-6-6z"/></svg> <div class="empty-title">All caught up</div> <div class="empty-desc">No notifications match this filter.</div> </div> </div> </div> </div> </main> <script type="module"> const notifications = [ { id:1, kind:'info', cat:'all', from:'Stripe', text:'Payment of $499.00 received from Acme Corp', time:'2 min ago', unread:true }, { id:2, kind:'task', cat:'reviews', from:'GitHub', text:'PR #248 ready for review on the analytics-pipeline repo', time:'14 min ago', unread:true }, { id:3, kind:'alert', cat:'all', from:'Linear', text:'GEN-128 marked as urgent — needs attention before EOD', time:'1 hour ago', unread:true }, { id:4, kind:'mention', cat:'mentions', from:'Sarah K.', text:'Mentioned you in a comment on "Q2 Marketing Campaign"', time:'2 hours ago', unread:true }, { id:5, kind:'info', cat:'all', from:'Vercel', text:'Deployment succeeded — gentelella-v4.vercel.app live in 28s', time:'3 hours ago', unread:false }, { id:6, kind:'task', cat:'reviews', from:'GitHub', text:'PR #246 was merged into main by Michael R.', time:'5 hours ago', unread:false }, { id:7, kind:'mention', cat:'mentions', from:'Notion', text:'You were mentioned in "Q2 OKRs" by Emily Wang', time:'Yesterday', unread:false }, { id:8, kind:'info', cat:'all', from:'Stripe', text:'Subscription renewed — Pro plan $29 billed for May 2026', time:'Yesterday', unread:false }, { id:9, kind:'alert', cat:'all', from:'System', text:'Scheduled maintenance window: April 30 02:00–04:00 UTC', time:'2 days ago', unread:false }, { id:10, kind:'task', cat:'reviews', from:'Linear', text:'GEN-129 assigned to you — fix table sort indicators', time:'2 days ago', unread:false }, { id:11, kind:'mention', cat:'mentions', from:'Diego R.', text:'Replied to your comment on "Customer feedback summary"', time:'3 days ago', unread:false }, { id:12, kind:'info', cat:'all', from:'Notion', text:'Page "API integration guide" was edited by Tom Hardy', time:'4 days ago', unread:false } ]; const ICON = { info: '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="6"/><path d="M8 5v3M8 11h.01"/></svg>', task: '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 8l3 3 7-7"/></svg>', alert: '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 1l7 13H1L8 1z"/><path d="M8 6v4"/><circle cx="8" cy="12" r="0.5"/></svg>', mention: '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="3"/><path d="M11 8v1a2 2 0 004 0V8a7 7 0 10-2.7 5.5"/></svg>' }; let filter = 'all'; function visible() { if (filter === 'all') return notifications; if (filter === 'unread') return notifications.filter((n) => n.unread); return notifications.filter((n) => n.cat === filter); } function render() { const list = document.getElementById('notif-list'); const empty = document.getElementById('notif-empty'); const items = visible(); if (!items.length) { list.innerHTML = ''; empty.hidden = false; } else { empty.hidden = true; list.innerHTML = items.map((n) => ` <button type="button" class="notification-row${n.unread ? ' unread' : ''}" data-id="${n.id}"> <span class="notif-icon notif-${n.kind}" aria-hidden="true">${ICON[n.kind] || ICON.info}</span> <span class="notif-body"> <span class="notif-from">${n.from}</span> <span class="notif-text">${n.text}</span> </span> <span class="notif-time">${n.time}</span> </button> `).join(''); } // Update unread counter const unread = notifications.filter((n) => n.unread).length; const badge = document.getElementById('count-unread'); badge.textContent = unread; badge.style.display = unread ? '' : 'none'; } document.getElementById('notif-tabs').addEventListener('click', (e) => { const btn = e.target.closest('.chart-tab'); if (!btn) return; filter = btn.dataset.filter; render(); }); document.getElementById('notif-list').addEventListener('click', (e) => { const row = e.target.closest('.notification-row'); if (!row) return; const id = parseInt(row.dataset.id, 10); const n = notifications.find((x) => x.id === id); if (n) n.unread = false; render(); }); document.getElementById('mark-all-read').addEventListener('click', (e) => { e.stopPropagation(); notifications.forEach((n) => { n.unread = false; }); render(); }); render(); </script> </body> </html>