migrated to react

This commit is contained in:
2026-03-27 22:15:50 +01:00
parent 11ac1e008f
commit 176f821598
24 changed files with 2281 additions and 888 deletions

View File

@@ -1,132 +1,9 @@
---
import AdminLayout from '../../layouts/AdminLayout.astro';
import Settings from '../../components/react/admin/Settings';
---
<AdminLayout title="Site Settings">
<p slot="header-subtitle" class="mt-2 text-sm md:text-base" style="color: var(--text) !important;">Configure how your blog looks and feels globally.</p>
<form id="settings-form" class="space-y-8">
<div id="alert" class="hidden p-4 rounded-lg mb-6"></div>
<section class="space-y-6">
<h2 class="text-xl font-bold text-lavender border-l-4 border-lavender pl-4">General Identity</h2>
<div class="grid md:grid-cols-2 gap-6">
<div>
<label for="title" class="block text-sm font-medium text-subtext1 mb-2">Blog Title (Nav)</label>
<input type="text" id="title" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
</div>
<div>
<label for="subtitle" class="block text-sm font-medium text-subtext1 mb-2">Nav Subtitle</label>
<input type="text" id="subtitle" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
</div>
<div>
<label for="welcome_title" class="block text-sm font-medium text-subtext1 mb-2">Welcome Title (Frontpage)</label>
<input type="text" id="welcome_title" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
</div>
<div>
<label for="welcome_subtitle" class="block text-sm font-medium text-subtext1 mb-2">Welcome Subtitle</label>
<input type="text" id="welcome_subtitle" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
</div>
</div>
<div>
<label for="favicon" class="block text-sm font-medium text-subtext1 mb-2">Favicon URL</label>
<input type="text" id="favicon" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
<p class="text-[10px] text-subtext0 mt-1">URL to the icon shown in browser tabs.</p>
</div>
</section>
<section class="space-y-6">
<h2 class="text-xl font-bold text-blue border-l-4 border-blue pl-4">Appearance</h2>
<div>
<label for="theme" class="block text-sm font-medium text-subtext1 mb-2">Color Theme (Catppuccin)</label>
<select id="theme" class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors">
<option value="mocha">Mocha (Dark, High Contrast)</option>
<option value="macchiato">Macchiato (Dark, Medium Contrast)</option>
<option value="frappe">Frappe (Dark, Low Contrast)</option>
<option value="latte">Latte (Light Mode)</option>
<option value="scaled-and-icy">Scaled and Icy (Vibrant Light)</option>
</select>
<p class="text-[10px] text-subtext0 mt-1">Select a predefined Catppuccin color palette.</p>
</div>
<div>
<label for="custom_css" class="block text-sm font-medium text-subtext1 mb-2">Custom CSS</label>
<textarea id="custom_css" rows="4" class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors font-mono text-xs" placeholder="body { ... }"></textarea>
<p class="text-[10px] text-subtext0 mt-1">Inject custom CSS styles globally.</p>
</div>
</section>
<section class="space-y-6">
<h2 class="text-xl font-bold text-teal border-l-4 border-teal pl-4">Footer</h2>
<div>
<label for="footer" class="block text-sm font-medium text-subtext1 mb-2">Footer Text</label>
<input type="text" id="footer" required class="w-full bg-crust border border-surface1 rounded-lg px-4 py-3 text-text focus:outline-none focus:border-mauve transition-colors" />
</div>
</section>
<button type="submit" class="w-full md:w-auto bg-mauve text-crust font-bold py-4 px-12 rounded-lg hover:bg-pink transition-all transform hover:scale-[1.02] active:scale-[0.98]">
Save Site Configuration
</button>
</form>
<script>
import { showAlert } from '../../components/ui/Alert';
document.addEventListener('admin-auth-ready', (e: any) => {
const token = e.detail.token;
loadSettings();
async function loadSettings() {
try {
const res = await fetch('/api/config');
if (res.ok) {
const data = await res.json();
(document.getElementById('title') as HTMLInputElement).value = data.title || '';
(document.getElementById('subtitle') as HTMLInputElement).value = data.subtitle || '';
(document.getElementById('welcome_title') as HTMLInputElement).value = data.welcome_title || '';
(document.getElementById('welcome_subtitle') as HTMLInputElement).value = data.welcome_subtitle || '';
(document.getElementById('footer') as HTMLInputElement).value = data.footer || '';
(document.getElementById('favicon') as HTMLInputElement).value = data.favicon || '';
(document.getElementById('theme') as HTMLSelectElement).value = data.theme || 'mocha';
(document.getElementById('custom_css') as HTMLTextAreaElement).value = data.custom_css || '';
}
} catch (err) {
showAlert('Failed to load settings from server.', 'error');
}
}
document.getElementById('settings-form')?.addEventListener('submit', async (ev) => {
ev.preventDefault();
const payload = {
title: (document.getElementById('title') as HTMLInputElement).value,
subtitle: (document.getElementById('subtitle') as HTMLInputElement).value,
welcome_title: (document.getElementById('welcome_title') as HTMLInputElement).value,
welcome_subtitle: (document.getElementById('welcome_subtitle') as HTMLInputElement).value,
footer: (document.getElementById('footer') as HTMLInputElement).value,
favicon: (document.getElementById('favicon') as HTMLInputElement).value,
theme: (document.getElementById('theme') as HTMLSelectElement).value,
custom_css: (document.getElementById('custom_css') as HTMLTextAreaElement).value,
};
try {
const res = await fetch('/api/config', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(payload)
});
if (res.ok) {
showAlert('Settings saved successfully! Refresh to see changes.', 'success');
} else {
const err = await res.json();
showAlert(`Error: ${err.error}`, 'error');
}
} catch (err) {
showAlert('Failed to save settings. Please check your connection.', 'error');
}
});
});
</script>
<Settings client:load />
</AdminLayout>