163 lines
8.2 KiB
PHP
163 lines
8.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/includes/layout.php';
|
|
|
|
library_bootstrap();
|
|
|
|
$documentId = isset($_GET['id']) ? (int) $_GET['id'] : 0;
|
|
$context = ($_GET['context'] ?? '') === 'admin' ? 'admin' : 'public';
|
|
$publicOnly = $context !== 'admin';
|
|
$document = $documentId > 0 ? library_fetch_document($documentId, $publicOnly) : null;
|
|
|
|
if (!$document) {
|
|
http_response_code(404);
|
|
library_render_header('Document not found', 'The requested library document could not be found.', $context === 'admin' ? 'admin' : 'catalog');
|
|
?>
|
|
<section class="panel empty-panel text-center py-5">
|
|
<div class="empty-icon mb-3">?</div>
|
|
<h1 class="h4">Document not found</h1>
|
|
<p class="text-secondary mb-4">This item is unavailable or private.</p>
|
|
<a class="btn btn-dark" href="<?= $context === 'admin' ? '/admin.php' : '/index.php' ?>">Go back</a>
|
|
</section>
|
|
<?php
|
|
library_render_footer();
|
|
exit;
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'generate_summary') {
|
|
$result = library_generate_summary((int) $document['id']);
|
|
library_set_flash($result['success'] ? 'success' : 'warning', $result['message']);
|
|
header('Location: /document.php?id=' . (int) $document['id'] . ($context === 'admin' ? '&context=admin' : '') . '#summary-card');
|
|
exit;
|
|
}
|
|
|
|
if ($context !== 'admin') {
|
|
library_increment_views((int) $document['id']);
|
|
$document = library_fetch_document((int) $document['id'], true) ?: $document;
|
|
}
|
|
|
|
library_render_header(
|
|
(string) ($document['title_en'] ?: $document['title_ar'] ?: 'Document detail'),
|
|
'Read a library document online, review metadata, and generate a bilingual AI summary from saved excerpts.',
|
|
$context === 'admin' ? 'admin' : 'catalog'
|
|
);
|
|
?>
|
|
<section class="mb-4">
|
|
<a class="back-link" href="<?= $context === 'admin' ? '/admin.php' : '/index.php' ?>">← Back to <?= $context === 'admin' ? 'Admin Studio' : 'catalog' ?></a>
|
|
</section>
|
|
|
|
<section class="row g-4 align-items-start">
|
|
<div class="col-xl-8">
|
|
<div class="panel mb-4">
|
|
<div class="d-flex flex-wrap justify-content-between gap-3 mb-3">
|
|
<div>
|
|
<?php if (!empty($document['title_en'])): ?>
|
|
<h1 class="display-6 mb-1"><?= h((string) $document['title_en']) ?></h1>
|
|
<?php endif; ?>
|
|
<?php if (!empty($document['title_ar'])): ?>
|
|
<div class="lead text-secondary" dir="rtl"><?= h((string) $document['title_ar']) ?></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="d-flex flex-wrap gap-2 align-content-start">
|
|
<span class="badge text-bg-light"><?= h(library_language_label((string) $document['document_language'])) ?></span>
|
|
<span class="badge text-bg-light"><?= h(library_visibility_label((string) $document['visibility'])) ?></span>
|
|
<span class="badge text-bg-light"><?= h(library_document_type_label((string) $document['document_type'])) ?></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-3 small text-secondary border-top pt-3">
|
|
<div class="col-md-4"><strong class="text-dark d-block mb-1">Author</strong><?= h((string) ($document['author_name'] ?: 'Unknown author')) ?></div>
|
|
<div class="col-md-4"><strong class="text-dark d-block mb-1">Views</strong><?= h((string) $document['view_count']) ?></div>
|
|
<div class="col-md-4"><strong class="text-dark d-block mb-1">File</strong><?= h((string) ($document['file_name'] ?: 'Unavailable')) ?></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel reader-panel">
|
|
<div class="d-flex justify-content-between align-items-center gap-3 mb-3">
|
|
<div>
|
|
<div class="section-kicker">Online reader</div>
|
|
<h2 class="h4 mb-0">Read in the browser</h2>
|
|
</div>
|
|
<?php if (!empty($document['file_path'])): ?>
|
|
<a class="btn btn-outline-secondary btn-sm" href="<?= h(library_file_url((string) $document['file_path'])) ?>" target="_blank" rel="noopener">Open file</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($document['visibility'] === 'private' && $context !== 'admin'): ?>
|
|
<div class="reader-lock">
|
|
<h3 class="h5 mb-2">Private item</h3>
|
|
<p class="text-secondary mb-0">This title is marked as login-required by the admin, so it stays hidden from the public reading experience.</p>
|
|
</div>
|
|
<?php elseif (library_can_preview($document)): ?>
|
|
<div class="reader-frame-wrap">
|
|
<iframe class="reader-frame" src="<?= h(library_file_url((string) $document['file_path'])) ?>#toolbar=1&navpanes=0&view=FitH" title="Reader for <?= h((string) ($document['title_en'] ?: $document['title_ar'] ?: 'document')) ?>"></iframe>
|
|
</div>
|
|
<?php elseif (!empty($document['file_path'])): ?>
|
|
<div class="reader-lock">
|
|
<h3 class="h5 mb-2">Document stored</h3>
|
|
<p class="text-secondary mb-3">This file type is stored successfully, but inline reading is optimized for PDF in this first slice.</p>
|
|
<a class="btn btn-dark" href="<?= h(library_file_url((string) $document['file_path'])) ?>" target="_blank" rel="noopener">Download / open file</a>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="reader-lock">
|
|
<h3 class="h5 mb-2">No file attached</h3>
|
|
<p class="text-secondary mb-0">Upload a file from the Admin Studio to enable reading.</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-4">
|
|
<div class="panel mb-4" id="summary-card">
|
|
<div class="d-flex justify-content-between align-items-start gap-3 mb-3">
|
|
<div>
|
|
<div class="section-kicker">AI summary</div>
|
|
<h2 class="h4 mb-0">Bilingual quick summary</h2>
|
|
</div>
|
|
<form method="post" action="/document.php?id=<?= h((string) $document['id']) ?><?= $context === 'admin' ? '&context=admin' : '' ?>#summary-card">
|
|
<input type="hidden" name="action" value="generate_summary">
|
|
<button class="btn btn-dark btn-sm" type="submit"><?= !empty($document['summary_text']) ? 'Regenerate' : 'Generate' ?></button>
|
|
</form>
|
|
</div>
|
|
|
|
<?php if (!empty($document['summary_text'])): ?>
|
|
<div class="summary-box"><?= nl2br(h((string) $document['summary_text'])) ?></div>
|
|
<?php else: ?>
|
|
<div class="summary-box summary-box-muted">No AI summary yet. Use the button above after adding a strong Arabic or English excerpt in the admin upload form.</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="panel mb-4">
|
|
<div class="section-kicker">Metadata</div>
|
|
<h2 class="h5 mb-3">Catalog notes</h2>
|
|
<dl class="row small gy-2 mb-0">
|
|
<dt class="col-4">Published</dt>
|
|
<dd class="col-8 mb-0"><?= h(date('M d, Y', strtotime((string) $document['created_at']))) ?></dd>
|
|
<dt class="col-4">Tags</dt>
|
|
<dd class="col-8 mb-0"><?= h((string) ($document['tags'] ?: '—')) ?></dd>
|
|
<dt class="col-4">Size</dt>
|
|
<dd class="col-8 mb-0"><?= h((string) ($document['file_size_kb'] ?: 0)) ?> KB</dd>
|
|
</dl>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<div class="section-kicker">Descriptions</div>
|
|
<h2 class="h5 mb-3">Source text used by AI</h2>
|
|
<div class="description-stack">
|
|
<div>
|
|
<div class="small text-uppercase text-secondary mb-2">English</div>
|
|
<p class="mb-0 text-secondary"><?= h((string) ($document['description_en'] ?: 'No English excerpt yet.')) ?></p>
|
|
</div>
|
|
<div>
|
|
<div class="small text-uppercase text-secondary mb-2">العربية</div>
|
|
<p class="mb-0 text-secondary" dir="rtl"><?= h((string) ($document['description_ar'] ?: 'لا يوجد مقتطف عربي حتى الآن.')) ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<?php
|
|
library_render_footer();
|