167 lines
8.7 KiB
Plaintext
167 lines
8.7 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">
|
|
<button onclick="stopPage()" class="bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg shadow-sm transition-colors duration-150 ease-in-out flex items-center gap-2">
|
|
<i class="fa-solid fa-stop"></i>
|
|
<span>Stop Page</span>
|
|
</button>
|
|
<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)
|
|
});
|
|
}
|
|
|
|
function stopPage() {
|
|
const phoneSelect = document.getElementById('phoneSelect');
|
|
const phone = phoneSelect.value;
|
|
fetch('/stop', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
</html> |