web-paging/views/index.ejs

154 lines
8.1 KiB
Plaintext

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/tuta-amb/fontawesome-pro@latest/web/css/all.min.css">
<title>Paging Console</title>
<style type="text/tailwindcss">
@layer components {
.btn {
@apply inline-flex items-center justify-center font-bold text-center whitespace-nowrap select-none border border-transparent py-3 px-6 rounded-xl text-lg transition-all duration-200 ease-in-out focus:outline-none focus:ring-4 focus:ring-offset-2 shadow-md hover:shadow-lg transform hover:-translate-y-0.5 active:translate-y-0 active:shadow-sm;
}
.btn-primary {
@apply text-white bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 focus:ring-blue-500/50 border-blue-700;
}
.btn-secondary {
@apply text-white bg-gradient-to-r from-gray-600 to-gray-700 hover:from-gray-700 hover:to-gray-800 focus:ring-gray-500/50 border-gray-700;
}
.btn-success {
@apply text-white bg-gradient-to-r from-green-600 to-green-700 hover:from-green-700 hover:to-green-800 focus:ring-green-500/50 border-green-700;
}
.btn-danger {
@apply text-white bg-gradient-to-r from-red-600 to-red-700 hover:from-red-700 hover:to-red-800 focus:ring-red-500/50 border-red-700;
}
.btn-warning {
@apply text-gray-900 bg-gradient-to-r from-yellow-400 to-yellow-500 hover:from-yellow-500 hover:to-yellow-600 focus:ring-yellow-400/50 border-yellow-500;
}
.btn-info {
@apply text-white bg-gradient-to-r from-cyan-500 to-cyan-600 hover:from-cyan-600 hover:to-cyan-700 focus:ring-cyan-400/50 border-cyan-600;
}
.btn-light {
@apply text-gray-800 bg-gradient-to-r from-gray-100 to-gray-200 hover:from-gray-200 hover:to-gray-300 focus:ring-gray-200/50 border-gray-300;
}
.btn-dark {
@apply text-white bg-gradient-to-r from-gray-800 to-gray-900 hover:from-gray-900 hover:to-black focus:ring-gray-800/50 border-gray-900;
}
.btn-tall {
@apply h-[160px] text-2xl;
}
.btn-short {
@apply h-[80px] text-xl;
}
.glass-panel {
@apply bg-white/80 backdrop-blur-md border border-white/20 shadow-xl rounded-2xl;
}
}
body {
background-color: #0f172a;
background-image: radial-gradient(at 0% 0%, hsla(253,16%,7%,1) 0, transparent 50%), radial-gradient(at 50% 0%, hsla(225,39%,30%,1) 0, transparent 50%), radial-gradient(at 100% 0%, hsla(339,49%,30%,1) 0, transparent 50%);
background-attachment: fixed;
}
</style>
</head>
<body class="text-gray-100 antialiased min-h-screen flex flex-col">
<nav class="w-full bg-gray-900/50 backdrop-blur-md border-b border-white/10 px-6 py-4 flex justify-between items-center sticky top-0 z-50 shadow-sm">
<div class="flex items-center gap-3">
<img src="/assets/img/logo.png" alt="Logo" class="h-10 w-auto">
<h1 class="text-xl font-bold text-white tracking-wide">Paging Console</h1>
</div>
<div class="flex items-center gap-4">
<div class="relative group">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fa-regular fa-phone text-gray-400 group-focus-within:text-blue-400 transition-colors"></i>
</div>
<select class="appearance-none bg-gray-800/90 hover:bg-gray-700 border border-transparent hover:border-blue-500/50 text-gray-200 py-2 pl-10 pr-8 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all cursor-pointer font-medium text-sm" id="phoneSelect">
<% Object.entries(phones).forEach(([name, number])=> { %>
<option value="<%= number %>">
<%= name %>
</option>
<% }); %>
</select>
<div class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none">
<i class="fa-solid fa-chevron-down text-xs text-gray-400"></i>
</div>
</div>
</div>
</nav>
<%
// determine columns and chunk rows
const cols = Object.keys(buttons);
const numCols = Math.max(1, cols.length);
%>
<main class="flex-grow flex justify-center items-start p-6 md:p-12">
<div class="w-full max-w-7xl">
<div class="grid gap-8" style="grid-template-columns: repeat(<%= numCols %>, minmax(0, 1fr));">
<% cols.forEach(col => { %>
<div class="flex flex-col gap-4">
<div class="pb-2 border-b border-white/20 mb-2">
<h3 class="text-2xl font-bold text-white drop-shadow-md flex items-center gap-2">
<%= col %>
</h3>
</div>
<% buttons[col].forEach((cell) => {
const ctx = cell.context || {};
%>
<button
class="btn <%= cell.btnClass || 'btn-secondary' %> w-full <%= cell.doubleHeight ? 'btn-tall' : 'btn-short' %> group relative overflow-hidden"
name="<%= cell.name || '' %>"
onclick="triggerAnnouncement(this)"
<% if (ctx.context) { %> data-context="<%= ctx.context %>" <% } %>
<% if (ctx.timeout) { %> data-timeout="<%= ctx.timeout %>" <% } %>
<% if (ctx.cid) { %> data-cid="<%= ctx.cid %>" <% } %>
<% if (ctx.dial) { %> data-dial="<%= ctx.dial %>" <% } %>
>
<div class="absolute inset-0 bg-white/10 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
<div class="relative z-10 flex flex-col items-center justify-center gap-2">
<% if (cell.faIcon) { %>
<i class="<%= cell.faIcon %> text-3xl mb-1 opacity-90 group-hover:scale-110 transition-transform duration-300" <% if (cell.faStyle) { %> style="<%= cell.faStyle %>" <% } %>></i>
<span class="tracking-wide"><%= cell.text || '' %></span>
<% } else { %>
<span class="tracking-wide"><%= cell.text || '' %></span>
<% } %>
</div>
</button>
<% }); %>
</div>
<% }); %>
</div>
</div>
</main>
<script>
function triggerAnnouncement(button) {
const ann = button.getAttribute('name');
const phoneSelect = document.getElementById('phoneSelect');
const phone = phoneSelect.value;
console.log(ann);
// send the button's context attrs if you want them server-side
const payload = {
pageType: ann,
phone: phone,
context: {
context: button.dataset.context,
timeout: button.dataset.timeout,
cid: button.dataset.cid,
dial: button.dataset.dial
}
};
fetch('/trig', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
}
</script>
</body>
</html>