Document page: two-row layout - details|summary+notes top, OCR|PDF bottom
This commit is contained in:
parent
6adfefff7a
commit
1b49dac87f
|
|
@ -49,135 +49,122 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 1: Details (left) | Summary + Notes (right) — equal height -->
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<!-- Left Column: Details -->
|
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden flex flex-col">
|
||||||
<div class="space-y-6">
|
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700">
|
||||||
<!-- Metadata Card -->
|
<h2 class="font-semibold text-gray-900 dark:text-white">Details</h2>
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
</div>
|
||||||
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700">
|
<div class="p-6 flex-1">
|
||||||
<h2 class="font-semibold text-gray-900 dark:text-white">Details</h2>
|
<div class="grid grid-cols-2 gap-x-8 gap-y-4">
|
||||||
</div>
|
<dl class="space-y-4">
|
||||||
<div class="p-6">
|
<div>
|
||||||
<div class="grid grid-cols-2 gap-x-8 gap-y-4">
|
<dt class="text-sm text-gray-500 dark:text-gray-400">Category</dt>
|
||||||
<!-- Left column -->
|
<dd class="mt-1">
|
||||||
<dl class="space-y-4">
|
<select onchange="inlineUpdateCategory(this.value)"
|
||||||
<div>
|
class="font-medium text-gray-900 dark:text-white bg-gray-100 dark:bg-gray-700 rounded-lg px-2 py-1 border-0 cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 text-sm">
|
||||||
<dt class="text-sm text-gray-500 dark:text-gray-400">Category</dt>
|
{{range .Categories}}
|
||||||
<dd class="mt-1">
|
<option value="{{.}}" {{if eq . $.Document.Category}}selected{{end}}>{{categoryIcon .}} {{title .}}</option>
|
||||||
<select onchange="inlineUpdateCategory(this.value)"
|
{{end}}
|
||||||
class="font-medium text-gray-900 dark:text-white bg-gray-100 dark:bg-gray-700 rounded-lg px-2 py-1 border-0 cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 text-sm">
|
</select>
|
||||||
{{range .Categories}}
|
</dd>
|
||||||
<option value="{{.}}" {{if eq . $.Document.Category}}selected{{end}}>{{categoryIcon .}} {{title .}}</option>
|
</div>
|
||||||
{{end}}
|
{{if .Document.Vendor}}
|
||||||
</select>
|
<div>
|
||||||
</dd>
|
<dt class="text-sm text-gray-500 dark:text-gray-400">Vendor</dt>
|
||||||
</div>
|
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{.Document.Vendor}}</dd>
|
||||||
{{if .Document.Vendor}}
|
</div>
|
||||||
<div>
|
{{end}}
|
||||||
<dt class="text-sm text-gray-500 dark:text-gray-400">Vendor</dt>
|
{{if .Document.Amount}}
|
||||||
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{.Document.Vendor}}</dd>
|
<div>
|
||||||
</div>
|
<dt class="text-sm text-gray-500 dark:text-gray-400">Amount</dt>
|
||||||
{{end}}
|
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{.Document.Amount}}</dd>
|
||||||
{{if .Document.Amount}}
|
</div>
|
||||||
<div>
|
{{end}}
|
||||||
<dt class="text-sm text-gray-500 dark:text-gray-400">Amount</dt>
|
</dl>
|
||||||
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{.Document.Amount}}</dd>
|
<dl class="space-y-4">
|
||||||
</div>
|
{{if .Document.Date}}
|
||||||
{{end}}
|
<div>
|
||||||
</dl>
|
<dt class="text-sm text-gray-500 dark:text-gray-400">Date</dt>
|
||||||
<!-- Right column -->
|
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{formatDate .Document.Date}}</dd>
|
||||||
<dl class="space-y-4">
|
</div>
|
||||||
{{if .Document.Date}}
|
{{end}}
|
||||||
<div>
|
{{if .Document.ProcessedAt}}
|
||||||
<dt class="text-sm text-gray-500 dark:text-gray-400">Date</dt>
|
<div>
|
||||||
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{formatDate .Document.Date}}</dd>
|
<dt class="text-sm text-gray-500 dark:text-gray-400">Processed</dt>
|
||||||
</div>
|
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{formatDateTime .Document.ProcessedAt}}</dd>
|
||||||
{{end}}
|
</div>
|
||||||
{{if .Document.ProcessedAt}}
|
{{end}}
|
||||||
<div>
|
{{if .Document.OriginalFile}}
|
||||||
<dt class="text-sm text-gray-500 dark:text-gray-400">Processed</dt>
|
<div>
|
||||||
<dd class="mt-1 font-medium text-gray-900 dark:text-white">{{formatDateTime .Document.ProcessedAt}}</dd>
|
<dt class="text-sm text-gray-500 dark:text-gray-400">Original File</dt>
|
||||||
</div>
|
<dd class="mt-1 font-medium text-gray-900 dark:text-white truncate">{{.Document.OriginalFile}}</dd>
|
||||||
{{end}}
|
</div>
|
||||||
{{if .Document.OriginalFile}}
|
{{end}}
|
||||||
<div>
|
</dl>
|
||||||
<dt class="text-sm text-gray-500 dark:text-gray-400">Original File</dt>
|
|
||||||
<dd class="mt-1 font-medium text-gray-900 dark:text-white truncate">{{.Document.OriginalFile}}</dd>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Summary -->
|
|
||||||
{{if .Document.Summary}}
|
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
|
||||||
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700">
|
|
||||||
<h2 class="font-semibold text-gray-900 dark:text-white">Summary</h2>
|
|
||||||
</div>
|
|
||||||
<div class="p-6">
|
|
||||||
<p class="text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{.Document.Summary}}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
<!-- Notes -->
|
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
|
||||||
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700">
|
|
||||||
<h2 class="font-semibold text-gray-900 dark:text-white">Notes</h2>
|
|
||||||
</div>
|
|
||||||
<div class="p-6">
|
|
||||||
{{if .Document.Notes}}
|
|
||||||
<p class="text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{.Document.Notes}}</p>
|
|
||||||
{{else}}
|
|
||||||
<p class="text-gray-400 dark:text-gray-500 italic">No notes yet. Click Edit to add notes.</p>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Full Text -->
|
|
||||||
{{if .Document.FullText}}
|
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
|
||||||
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between">
|
|
||||||
<h2 class="font-semibold text-gray-900 dark:text-white">OCR Text</h2>
|
|
||||||
<button onclick="copyText()" class="text-sm text-brand-600 dark:text-brand-400 hover:underline">Copy</button>
|
|
||||||
</div>
|
|
||||||
<div class="p-6 max-h-96 overflow-auto">
|
|
||||||
<div id="ocr-text" class="text-sm text-gray-700 dark:text-gray-300 prose dark:prose-invert max-w-none">{{.Document.FullText | safe}}</div>
|
|
||||||
<script>
|
|
||||||
// Simple markdown rendering
|
|
||||||
(function() {
|
|
||||||
const el = document.getElementById('ocr-text');
|
|
||||||
let md = el.textContent;
|
|
||||||
// Headers
|
|
||||||
md = md.replace(/^### (.+)$/gm, '<h4 class="font-semibold mt-4 mb-2">$1</h4>');
|
|
||||||
md = md.replace(/^## (.+)$/gm, '<h3 class="font-semibold text-lg mt-4 mb-2">$1</h3>');
|
|
||||||
// Bold
|
|
||||||
md = md.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
|
||||||
// Tables (simple)
|
|
||||||
md = md.replace(/\|(.+)\|/g, function(match) {
|
|
||||||
const cells = match.split('|').filter(c => c.trim());
|
|
||||||
return '<tr>' + cells.map(c => '<td class="border px-2 py-1">' + c.trim() + '</td>').join('') + '</tr>';
|
|
||||||
});
|
|
||||||
md = md.replace(/(<tr>.*<\/tr>\n?)+/g, '<table class="border-collapse border my-2">$&</table>');
|
|
||||||
// Bullets
|
|
||||||
md = md.replace(/^- (.+)$/gm, '<li>$1</li>');
|
|
||||||
md = md.replace(/(<li>.*<\/li>\n?)+/g, '<ul class="list-disc ml-4 my-2">$&</ul>');
|
|
||||||
// Line breaks
|
|
||||||
md = md.replace(/\n/g, '<br>');
|
|
||||||
el.innerHTML = md;
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right Column: PDF Viewer -->
|
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden flex flex-col">
|
||||||
|
{{if .Document.Summary}}
|
||||||
|
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700">
|
||||||
|
<h2 class="font-semibold text-gray-900 dark:text-white">Summary</h2>
|
||||||
|
</div>
|
||||||
|
<div class="p-6 border-b border-gray-100 dark:border-gray-700">
|
||||||
|
<p class="text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{.Document.Summary}}</p>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700">
|
||||||
|
<h2 class="font-semibold text-gray-900 dark:text-white">Notes</h2>
|
||||||
|
</div>
|
||||||
|
<div class="p-6 flex-1">
|
||||||
|
{{if .Document.Notes}}
|
||||||
|
<p class="text-gray-700 dark:text-gray-300 whitespace-pre-wrap">{{.Document.Notes}}</p>
|
||||||
|
{{else}}
|
||||||
|
<p class="text-gray-400 dark:text-gray-500 italic">No notes yet. Click Edit to add notes.</p>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 2: OCR Text (left) | PDF Viewer (right) -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
|
{{if .Document.FullText}}
|
||||||
|
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
||||||
|
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between">
|
||||||
|
<h2 class="font-semibold text-gray-900 dark:text-white">OCR Text</h2>
|
||||||
|
<button onclick="copyText()" class="text-sm text-brand-600 dark:text-brand-400 hover:underline">Copy</button>
|
||||||
|
</div>
|
||||||
|
<div class="p-6 max-h-[700px] overflow-auto">
|
||||||
|
<div id="ocr-text" class="text-sm text-gray-700 dark:text-gray-300 prose dark:prose-invert max-w-none">{{.Document.FullText | safe}}</div>
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
const el = document.getElementById('ocr-text');
|
||||||
|
let md = el.textContent;
|
||||||
|
md = md.replace(/^### (.+)$/gm, '<h4 class="font-semibold mt-4 mb-2">$1</h4>');
|
||||||
|
md = md.replace(/^## (.+)$/gm, '<h3 class="font-semibold text-lg mt-4 mb-2">$1</h3>');
|
||||||
|
md = md.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
||||||
|
md = md.replace(/\|(.+)\|/g, function(match) {
|
||||||
|
const cells = match.split('|').filter(c => c.trim());
|
||||||
|
return '<tr>' + cells.map(c => '<td class="border px-2 py-1">' + c.trim() + '</td>').join('') + '</tr>';
|
||||||
|
});
|
||||||
|
md = md.replace(/(<tr>.*<\/tr>\n?)+/g, '<table class="border-collapse border my-2">$&</table>');
|
||||||
|
md = md.replace(/^- (.+)$/gm, '<li>$1</li>');
|
||||||
|
md = md.replace(/(<li>.*<\/li>\n?)+/g, '<ul class="list-disc ml-4 my-2">$&</ul>');
|
||||||
|
md = md.replace(/\n/g, '<br>');
|
||||||
|
el.innerHTML = md;
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div></div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{{if .Document.PDFPath}}
|
{{if .Document.PDFPath}}
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden sticky top-6">
|
<div class="bg-white dark:bg-gray-800 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden">
|
||||||
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between">
|
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between">
|
||||||
<h2 class="font-semibold text-gray-900 dark:text-white">Document Preview</h2>
|
<h2 class="font-semibold text-gray-900 dark:text-white">Document Preview</h2>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue