fix: replace alert() with slide-in toast notification in dashboard
This commit is contained in:
parent
1b0b602aa4
commit
94c6b7f42d
@ -214,10 +214,31 @@
|
|||||||
|
|
||||||
@keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.5; } }
|
@keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.5; } }
|
||||||
.animate-pulse { animation: pulse 2s infinite; }
|
.animate-pulse { animation: pulse 2s infinite; }
|
||||||
|
|
||||||
|
.toast {
|
||||||
|
position: fixed;
|
||||||
|
top: 1.5rem;
|
||||||
|
right: 1.5rem;
|
||||||
|
z-index: 9999;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--green);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
max-width: 420px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
||||||
|
transform: translateX(120%);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
.toast.show { transform: translateX(0); }
|
||||||
|
.toast.error { border-color: var(--red); }
|
||||||
|
.toast-title { font-weight: 600; font-size: 0.9rem; margin-bottom: 0.25rem; }
|
||||||
|
.toast-body { font-size: 0.8rem; color: var(--text-dim); }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<div id="toast" class="toast"><div class="toast-title"></div><div class="toast-body"></div></div>
|
||||||
|
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>TIP — Transceiver Intelligence Platform</h1>
|
<h1>TIP — Transceiver Intelligence Platform</h1>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
@ -360,6 +381,17 @@ async function api(path) {
|
|||||||
|
|
||||||
function el(id) { return document.getElementById(id); }
|
function el(id) { return document.getElementById(id); }
|
||||||
|
|
||||||
|
function showToast(title, body, isError) {
|
||||||
|
var t = el('toast');
|
||||||
|
t.querySelector('.toast-title').textContent = title;
|
||||||
|
t.querySelector('.toast-body').textContent = body;
|
||||||
|
t.className = 'toast' + (isError ? ' error' : '');
|
||||||
|
void t.offsetWidth;
|
||||||
|
t.classList.add('show');
|
||||||
|
clearTimeout(showToast._timer);
|
||||||
|
showToast._timer = setTimeout(function() { t.classList.remove('show'); }, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
function buildDOM(parent, html) {
|
function buildDOM(parent, html) {
|
||||||
// Using textContent where possible, innerHTML only with escaped data
|
// Using textContent where possible, innerHTML only with escaped data
|
||||||
parent.textContent = '';
|
parent.textContent = '';
|
||||||
@ -534,9 +566,13 @@ function generateBlog(topic, speed) {
|
|||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
}).then(function(r) { return r.json(); }).then(function(data) {
|
}).then(function(r) { return r.json(); }).then(function(data) {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
alert('Draft generated: "' + data.draft.title + '" (' + data.draft.word_count + ' words)');
|
showToast('Draft generated', data.draft.title + ' — ' + data.draft.word_count + ' words');
|
||||||
|
} else {
|
||||||
|
showToast('Generation failed', data.error || 'Unknown error', true);
|
||||||
}
|
}
|
||||||
loadBlogDrafts();
|
loadBlogDrafts();
|
||||||
|
}).catch(function(err) {
|
||||||
|
showToast('Network error', err.message, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user