- Add /admin route with password-protected visual page builder
- Page Builder: manage hero images, standalone albums, subpages, and sections
- Album Picker: browse all shared Immich albums with search and filtering
- Settings Editor: theme, grid, footer, legal, SEO configuration
- YAML service with atomic writes and automatic backups (content/.backups/)
- HMAC-signed admin sessions (24h expiry, HttpOnly cookies)
- API endpoints: /api/admin/{auth,gallery,settings,albums,reload}
- Enable with ADMIN_PASSWORD env var; disabled by default
- invalidateConfigCache() export for hot-reload after saves
55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import AdminLogin from './components/AdminLogin';
|
|
import AdminDashboard from './components/AdminDashboard';
|
|
import './admin.css';
|
|
|
|
export default function AdminPage() {
|
|
const [authenticated, setAuthenticated] = useState<boolean | null>(null);
|
|
const [enabled, setEnabled] = useState(true);
|
|
|
|
useEffect(() => {
|
|
checkAuth();
|
|
}, []);
|
|
|
|
async function checkAuth() {
|
|
try {
|
|
const res = await fetch('/api/admin/auth');
|
|
const data = await res.json();
|
|
setAuthenticated(data.authenticated);
|
|
setEnabled(data.enabled);
|
|
} catch {
|
|
setAuthenticated(false);
|
|
}
|
|
}
|
|
|
|
if (authenticated === null) {
|
|
return (
|
|
<div className="admin-loading">
|
|
<div className="admin-spinner" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!enabled) {
|
|
return (
|
|
<div className="admin-disabled">
|
|
<div className="admin-disabled-card">
|
|
<h1>Admin Panel</h1>
|
|
<p>
|
|
The admin panel is not enabled. Set <code>ADMIN_PASSWORD</code> in your environment
|
|
variables to activate it.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!authenticated) {
|
|
return <AdminLogin onSuccess={() => setAuthenticated(true)} />;
|
|
}
|
|
|
|
return <AdminDashboard onLogout={() => setAuthenticated(false)} />;
|
|
}
|