145 lines
5.4 KiB
PHP
145 lines
5.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/library.php';
|
|
|
|
function admin_render_header(string $title, string $activePage = 'dashboard'): void {
|
|
library_bootstrap();
|
|
// Get flashes and clear them
|
|
$flashes = [];
|
|
if (isset($_SESSION['library_flash'])) {
|
|
$flashes = $_SESSION['library_flash'];
|
|
unset($_SESSION['library_flash']);
|
|
}
|
|
?>
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title><?= h($title) ?> · Admin Studio</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
<style>
|
|
.admin-sidebar {
|
|
width: 260px;
|
|
height: 100vh;
|
|
position: sticky;
|
|
top: 0;
|
|
background: #fff;
|
|
border-right: 1px solid #dee2e6;
|
|
padding: 20px;
|
|
}
|
|
.nav-link {
|
|
color: #333;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
.nav-link:hover {
|
|
background-color: #f8f9fa;
|
|
}
|
|
.nav-link.active {
|
|
background-color: #e9ecef;
|
|
color: #0d6efd !important;
|
|
font-weight: 500;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-light">
|
|
<div class="d-flex">
|
|
<aside class="admin-sidebar d-flex flex-column">
|
|
<h4 class="mb-4 text-primary fw-bold"><i class="bi bi-grid-fill me-2"></i>Admin Panel</h4>
|
|
<nav class="nav flex-column flex-grow-1">
|
|
<a class="nav-link rounded <?= $activePage === 'dashboard' ? 'active' : '' ?>" href="/admin.php">
|
|
<i class="bi bi-speedometer2 me-2"></i> Dashboard
|
|
</a>
|
|
<a class="nav-link rounded <?= $activePage === 'documents' ? 'active' : '' ?>" href="/admin_documents.php">
|
|
<i class="bi bi-folder2-open me-2"></i> Material Entry
|
|
</a>
|
|
<div class="my-2 border-top"></div>
|
|
<a class="nav-link rounded <?= $activePage === 'categories' ? 'active' : '' ?>" href="/admin_categories.php">
|
|
<i class="bi bi-tags me-2"></i> Categories
|
|
</a>
|
|
<a class="nav-link rounded <?= $activePage === 'subcategories' ? 'active' : '' ?>" href="/admin_subcategories.php">
|
|
<i class="bi bi-diagram-3 me-2"></i> Subcategories
|
|
</a>
|
|
<a class="nav-link rounded <?= $activePage === 'types' ? 'active' : '' ?>" href="/admin_types.php">
|
|
<i class="bi bi-file-earmark-text me-2"></i> Types
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="mt-auto pt-3 border-top">
|
|
<a class="nav-link text-secondary rounded" href="/index.php">
|
|
<i class="bi bi-box-arrow-right me-2"></i> Return to Site
|
|
</a>
|
|
</div>
|
|
</aside>
|
|
<main class="flex-grow-1 p-4" style="min-width: 0;">
|
|
<header class="mb-4 border-bottom pb-2">
|
|
<h2 class="h3"><?= h($title) ?></h2>
|
|
</header>
|
|
|
|
<?php foreach ($flashes as $flash): ?>
|
|
<div class="alert alert-<?= $flash['type'] === 'error' ? 'danger' : 'success' ?> alert-dismissible fade show shadow-sm" role="alert">
|
|
<?= h($flash['message']) ?>
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php
|
|
}
|
|
|
|
function admin_render_footer(): void {
|
|
?>
|
|
</main>
|
|
</div>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
// Shared Admin JS - Translation Helper
|
|
async function translateText(sourceId, targetId, targetLang) {
|
|
const source = document.getElementById(sourceId);
|
|
const target = document.getElementById(targetId);
|
|
const text = source.value.trim();
|
|
|
|
if (!text) {
|
|
alert('Please enter text to translate.');
|
|
return;
|
|
}
|
|
|
|
const originalPlaceholder = target.placeholder;
|
|
target.placeholder = 'Translating...';
|
|
const originalOpacity = target.style.opacity;
|
|
target.style.opacity = '0.7';
|
|
|
|
try {
|
|
// Simple mock translation for demo purposes or real API if configured
|
|
// In a real scenario, this would call /api/translate.php
|
|
// For now, let's assume /api/translate.php exists (it does)
|
|
|
|
const response = await fetch('/api/translate.php', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ text: text, target_lang: targetLang })
|
|
});
|
|
|
|
if (!response.ok) throw new Error('Translation failed');
|
|
|
|
const data = await response.json();
|
|
if (data.translation) {
|
|
target.value = data.translation;
|
|
} else if (data.error) {
|
|
alert('Translation error: ' + data.error);
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
alert('Translation failed. Please try again.');
|
|
} finally {
|
|
target.placeholder = originalPlaceholder;
|
|
target.style.opacity = originalOpacity;
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
}
|
|
?>
|