115 lines
5.7 KiB
PHP
115 lines
5.7 KiB
PHP
|
|
<?php
|
||
|
|
$pageTitle = 'Media';
|
||
|
|
$items = $items ?? [];
|
||
|
|
$folders = $folders ?? [];
|
||
|
|
$activeFolder = (int)($active_folder ?? 0);
|
||
|
|
$error = (string)($error ?? '');
|
||
|
|
$success = (string)($success ?? '');
|
||
|
|
ob_start();
|
||
|
|
?>
|
||
|
|
<section class="admin-card">
|
||
|
|
<div class="badge">Media</div>
|
||
|
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:16px; margin-top:16px;">
|
||
|
|
<div>
|
||
|
|
<h1 style="font-size:28px; margin:0;">Media Library</h1>
|
||
|
|
<p style="color: var(--muted); margin-top:6px;">Upload and reuse images across pages, posts, and newsletters.</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<?php if ($error !== ''): ?>
|
||
|
|
<div style="margin-top:12px; color:#f3b0b0; font-size:13px;"><?= htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?></div>
|
||
|
|
<?php elseif ($success !== ''): ?>
|
||
|
|
<div style="margin-top:12px; color:var(--accent-2); font-size:13px;">Upload complete.</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<div style="margin-top:18px; display:grid; gap:12px;">
|
||
|
|
<div style="display:flex; gap:10px; flex-wrap:wrap;">
|
||
|
|
<a href="/admin/media" class="btn outline small" style="<?= $activeFolder === 0 ? 'border-color: var(--accent); color: var(--text);' : '' ?>">All</a>
|
||
|
|
<?php foreach ($folders as $folder): ?>
|
||
|
|
<a href="/admin/media?folder=<?= (int)$folder['id'] ?>" class="btn outline small" style="<?= $activeFolder === (int)$folder['id'] ? 'border-color: var(--accent); color: var(--text);' : '' ?>">
|
||
|
|
<?= htmlspecialchars((string)$folder['name'], ENT_QUOTES, 'UTF-8') ?>
|
||
|
|
</a>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form method="post" action="/admin/media/folders" style="display:flex; gap:10px; flex-wrap:wrap;">
|
||
|
|
<input class="input" name="name" placeholder="New folder name" style="max-width:280px;">
|
||
|
|
<button type="submit" class="btn outline small">Create Folder</button>
|
||
|
|
</form>
|
||
|
|
|
||
|
|
<form method="post" action="/admin/media/upload" enctype="multipart/form-data" id="mediaUploadForm">
|
||
|
|
<input type="hidden" name="folder_id" value="<?= $activeFolder > 0 ? $activeFolder : 0 ?>">
|
||
|
|
<label for="mediaFileInput" id="mediaDropzone" style="display:flex; flex-direction:column; gap:8px; align-items:center; justify-content:center; padding:24px; border-radius:16px; border:1px dashed rgba(255,255,255,0.2); background: rgba(0,0,0,0.2); cursor:pointer;">
|
||
|
|
<div style="font-size:12px; text-transform:uppercase; letter-spacing:0.2em; color:var(--muted);">Drag & Drop</div>
|
||
|
|
<div style="font-size:14px; color:var(--text);">or click to upload</div>
|
||
|
|
<div id="mediaFileName" style="font-size:12px; color:var(--muted);">No file selected</div>
|
||
|
|
</label>
|
||
|
|
<input class="input" type="file" id="mediaFileInput" name="media_file" accept="image/*" style="display:none;">
|
||
|
|
<div style="margin-top:10px; display:flex; justify-content:flex-end;">
|
||
|
|
<button type="submit" class="btn small">Upload</button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div style="margin-top:18px; display:grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap:12px;">
|
||
|
|
<?php if (!$items): ?>
|
||
|
|
<div style="color: var(--muted); font-size:13px;">No media uploaded yet.</div>
|
||
|
|
<?php else: ?>
|
||
|
|
<?php foreach ($items as $item): ?>
|
||
|
|
<div style="border-radius:16px; border:1px solid var(--stroke); background: rgba(14,14,16,0.9); padding:10px;">
|
||
|
|
<div style="aspect-ratio: 1 / 1; border-radius:12px; overflow:hidden; background:#0b0c10; display:flex; align-items:center; justify-content:center;">
|
||
|
|
<?php if (str_starts_with((string)($item['file_type'] ?? ''), 'image/')): ?>
|
||
|
|
<img src="<?= htmlspecialchars((string)$item['file_url'], ENT_QUOTES, 'UTF-8') ?>" alt="" style="width:100%; height:100%; object-fit:cover;">
|
||
|
|
<?php else: ?>
|
||
|
|
<div style="color:var(--muted); font-size:12px;">File</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
</div>
|
||
|
|
<div style="margin-top:8px; font-size:12px; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
|
||
|
|
<?= htmlspecialchars((string)($item['file_name'] ?? ''), ENT_QUOTES, 'UTF-8') ?>
|
||
|
|
</div>
|
||
|
|
<input class="input" readonly value="<?= htmlspecialchars((string)($item['file_url'] ?? ''), ENT_QUOTES, 'UTF-8') ?>" style="margin-top:6px; font-size:11px;">
|
||
|
|
<form method="post" action="/admin/media/delete" onsubmit="return confirm('Delete this file?');" style="margin-top:8px;">
|
||
|
|
<input type="hidden" name="id" value="<?= (int)($item['id'] ?? 0) ?>">
|
||
|
|
<button type="submit" class="btn outline small">Delete</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
<?php endif; ?>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
<script>
|
||
|
|
(function () {
|
||
|
|
const dropzone = document.getElementById('mediaDropzone');
|
||
|
|
const fileInput = document.getElementById('mediaFileInput');
|
||
|
|
const fileName = document.getElementById('mediaFileName');
|
||
|
|
if (!dropzone || !fileInput || !fileName) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
dropzone.addEventListener('dragover', (event) => {
|
||
|
|
event.preventDefault();
|
||
|
|
dropzone.style.borderColor = 'var(--accent)';
|
||
|
|
});
|
||
|
|
|
||
|
|
dropzone.addEventListener('dragleave', () => {
|
||
|
|
dropzone.style.borderColor = 'rgba(255,255,255,0.2)';
|
||
|
|
});
|
||
|
|
|
||
|
|
dropzone.addEventListener('drop', (event) => {
|
||
|
|
event.preventDefault();
|
||
|
|
dropzone.style.borderColor = 'rgba(255,255,255,0.2)';
|
||
|
|
if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length) {
|
||
|
|
fileInput.files = event.dataTransfer.files;
|
||
|
|
fileName.textContent = event.dataTransfer.files[0].name;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
fileInput.addEventListener('change', () => {
|
||
|
|
fileName.textContent = fileInput.files.length ? fileInput.files[0].name : 'No file selected';
|
||
|
|
});
|
||
|
|
})();
|
||
|
|
</script>
|
||
|
|
<?php
|
||
|
|
$content = ob_get_clean();
|
||
|
|
require __DIR__ . '/../../../admin/views/layout.php';
|