docsys/templates/base.html

206 lines
9.9 KiB
HTML

{{define "base"}}
<!DOCTYPE html>
<html lang="en" class="h-full">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Title}} - DocSys</title>
<!-- Sora Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Sora:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Tailwind CSS (CDN) -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
fontFamily: {
'sora': ['Sora', 'system-ui', 'sans-serif'],
},
colors: {
'brand': {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
}
}
}
}
}
</script>
<!-- htmx -->
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<!-- PDF.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.mjs" type="module"></script>
<style>
* { font-family: 'Sora', system-ui, sans-serif; }
/* Smooth transitions */
.transition-theme {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
/* Custom scrollbar */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
.dark ::-webkit-scrollbar-thumb { background: #475569; }
/* Drag and drop zone */
.dropzone {
border: 2px dashed #cbd5e1;
transition: all 0.3s ease;
}
.dropzone.dragover {
border-color: #0ea5e9;
background: rgba(14, 165, 233, 0.05);
}
.dark .dropzone { border-color: #475569; }
.dark .dropzone.dragover { background: rgba(14, 165, 233, 0.1); }
/* Card hover effects */
.card-hover {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card-hover:hover {
transform: translateY(-2px);
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.1);
}
.dark .card-hover:hover {
box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.4);
}
/* Loading indicator */
.htmx-request .htmx-indicator { display: inline-block; }
.htmx-indicator { display: none; }
/* Fade in animation */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in {
animation: fadeIn 0.3s ease forwards;
}
/* PDF container */
.pdf-container {
background: #525659;
border-radius: 8px;
overflow: hidden;
}
</style>
</head>
<body class="h-full bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-theme">
<div class="min-h-full">
<!-- Navigation -->
<nav class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700 transition-theme">
<div class="max-w-[1800px] mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<a href="/" class="flex items-center space-x-3">
<span class="text-2xl">🗂️</span>
<span class="text-xl font-semibold bg-gradient-to-r from-brand-600 to-brand-400 bg-clip-text text-transparent">DocSys</span>
</a>
<div class="hidden sm:ml-10 sm:flex sm:space-x-1">
<a href="/" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">Dashboard</a>
<a href="/browse" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">Browse</a>
<a href="/search" class="px-4 py-2 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all">Search</a>
</div>
</div>
<div class="flex items-center space-x-4">
<!-- Search bar -->
<div class="hidden md:block relative">
<input type="search"
placeholder="Quick search..."
class="w-64 pl-10 pr-4 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 border-0 text-sm focus:ring-2 focus:ring-brand-500 transition-all"
hx-post="/api/search"
hx-trigger="keyup changed delay:300ms"
hx-target="#search-results-dropdown"
name="q">
<svg class="absolute left-3 top-2.5 h-4 w-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<div id="search-results-dropdown" class="absolute top-full left-0 right-0 mt-2 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 max-h-96 overflow-auto z-50 hidden"></div>
</div>
<!-- Dark mode toggle -->
<button onclick="toggleDarkMode()" class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-all" title="Toggle dark mode">
<svg class="h-5 w-5 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd"></path>
</svg>
<svg class="h-5 w-5 dark:hidden" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
</svg>
</button>
</div>
</div>
</div>
<!-- Mobile nav -->
<div class="sm:hidden border-t border-gray-200 dark:border-gray-700">
<div class="flex space-x-1 p-2">
<a href="/" class="flex-1 text-center px-3 py-2 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Dashboard</a>
<a href="/browse" class="flex-1 text-center px-3 py-2 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Browse</a>
<a href="/search" class="flex-1 text-center px-3 py-2 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Search</a>
</div>
</div>
</nav>
<!-- Main content -->
<main class="max-w-[1800px] mx-auto px-4 sm:px-6 lg:px-8 py-8">
{{template "content" .}}
</main>
</div>
<script>
// Dark mode
function toggleDarkMode() {
document.documentElement.classList.toggle('dark');
localStorage.setItem('darkMode', document.documentElement.classList.contains('dark'));
}
// Check saved preference
if (localStorage.getItem('darkMode') === 'true' ||
(!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
// Search dropdown
document.addEventListener('htmx:afterSwap', function(e) {
if (e.detail.target.id === 'search-results-dropdown') {
const dropdown = document.getElementById('search-results-dropdown');
if (dropdown.innerHTML.trim()) {
dropdown.classList.remove('hidden');
} else {
dropdown.classList.add('hidden');
}
}
});
// Close dropdown on click outside
document.addEventListener('click', function(e) {
const dropdown = document.getElementById('search-results-dropdown');
if (dropdown && !e.target.closest('.relative')) {
dropdown.classList.add('hidden');
}
});
</script>
</body>
</html>
{{end}}