fix: admin login, clean URLs, blog links

- Fix admin login: ID mismatch (loginUser->loginUsername, loginPass->loginPassword)
- Fix auth URL: /api/auth -> /api/auth/login
- Fix init() structure: broken if/else for checkAuth
- Remove onclick from login button (JS handles via addEventListener)
- Clean URLs: /blog/post/slug instead of post.html?slug=slug
- Updated blog.js, post.js, main.js with clean URL links
- post.js supports both /blog/post/slug and ?slug=x formats
- nginx configured for /blog/post/* rewrite
This commit is contained in:
jae 2026-03-31 22:55:45 +00:00
parent 252c7b95b3
commit 2ca01d2b3a
5 changed files with 32 additions and 14 deletions

View file

@ -26,7 +26,7 @@
<label class="login-label">PASSPHRASE</label>
<input type="password" id="loginPassword" class="login-input" placeholder="Enter password..." autocomplete="current-password">
</div>
<button id="loginBtn" class="login-btn" onclick="AdminApp.login()">▶ AUTHENTICATE</button>
<button id="loginBtn" class="login-btn">▶ AUTHENTICATE</button>
<div id="loginError" class="login-error"></div>
</div>
<div class="login-footer">SECURE CHANNEL // AES-256 ENCRYPTED</div>

View file

@ -25,11 +25,22 @@ const AdminApp = {
/* ───────────────────────── AUTH ───────────────────────── */
init() {
// Login form
// Login form - support both <form> submit and button click
const loginForm = document.getElementById('loginForm');
if (loginForm) {
loginForm.addEventListener('submit', (e) => this.login(e));
}
const loginBtn = document.getElementById('loginBtn');
if (loginBtn && !loginForm) {
loginBtn.addEventListener('click', (e) => this.login(e));
}
// Also handle Enter key in password field
const loginPass = document.getElementById('loginPassword');
if (loginPass) {
loginPass.addEventListener('keydown', (e) => {
if (e.key === 'Enter') this.login(e);
});
}
// Check auth state
if (this.checkAuth()) {
@ -111,14 +122,14 @@ const AdminApp = {
},
async login(e) {
e.preventDefault();
const user = document.getElementById('loginUser').value.trim();
const pass = document.getElementById('loginPass').value;
if (e && e.preventDefault) e.preventDefault();
const user = document.getElementById('loginUsername').value.trim();
const pass = document.getElementById('loginPassword').value;
const errEl = document.getElementById('loginError');
errEl.textContent = '';
if (errEl) errEl.textContent = '';
try {
const res = await fetch(this.API + '/auth', {
const res = await fetch(this.API + '/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: user, password: pass })

View file

@ -57,7 +57,7 @@
// ─── Render Post Card ───
function renderPostCard(post) {
return `
<article class="post-card" onclick="window.location='post.html?slug=${post.slug}'" data-tags="${(post.tags || []).join(',')}">
<article class="post-card" onclick="window.location='/blog/post/${post.slug}'" data-tags="${(post.tags || []).join(',')}">
<div class="post-card-content">
<div class="post-card-meta">
<span class="post-date">${post.date}</span>

View file

@ -800,7 +800,7 @@
<p class="blog-excerpt">${post.excerpt || (post.content || '').substring(0, 120) + '...'}</p>
<div class="blog-footer">
<span class="blog-read-time"> ${Math.max(1, Math.ceil((post.word_count || 300) / 250))} MIN READ</span>
<a href="post.html?slug=${post.slug}" class="blog-link">READ </a>
<a href="/blog/post/${post.slug}" class="blog-link">READ </a>
</div>
</article>
`).join('');

View file

@ -227,7 +227,7 @@
if (idx > 0) {
const prev = sorted[idx - 1];
navHtml += `<a href="post.html?slug=${prev.slug}" class="post-nav-link nav-newer">
navHtml += `<a href="/blog/post/${prev.slug}" class="post-nav-link nav-newer">
<span class="nav-dir"> NEWER</span>
<span class="nav-post-title">${prev.title}</span>
</a>`;
@ -235,13 +235,13 @@
if (idx < sorted.length - 1) {
const next = sorted[idx + 1];
navHtml += `<a href="post.html?slug=${next.slug}" class="post-nav-link nav-older">
navHtml += `<a href="/blog/post/${next.slug}" class="post-nav-link nav-older">
<span class="nav-dir">OLDER </span>
<span class="nav-post-title">${next.title}</span>
</a>`;
}
navHtml += `<a href="blog.html" class="post-nav-link nav-all">
navHtml += `<a href="/blog" class="post-nav-link nav-all">
<span class="nav-dir"> ALL TRANSMISSIONS</span>
</a>`;
@ -250,8 +250,15 @@
// ─── Load Post ───
async function loadPost() {
// Support both /blog/post/slug and ?slug=x formats
let slug = null;
const pathMatch = window.location.pathname.match(/\/blog\/post\/([^\/]+)/);
if (pathMatch) {
slug = decodeURIComponent(pathMatch[1]);
} else {
const params = new URLSearchParams(window.location.search);
const slug = params.get('slug');
slug = params.get('slug');
}
if (!slug) {
document.getElementById('postContent').innerHTML =