Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>{{ app_name }} - {% block title %}{% endblock %}</title> | |
| <!-- Tailwind CSS --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <!-- Custom CSS --> | |
| <style> | |
| /* Dark mode styles */ | |
| @media (prefers-color-scheme: dark) { | |
| body { | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| } | |
| } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #f1f1f1; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #888; | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #555; | |
| } | |
| /* Dark mode scrollbar */ | |
| @media (prefers-color-scheme: dark) { | |
| ::-webkit-scrollbar-track { | |
| background: #2d2d2d; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #666; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #888; | |
| } | |
| } | |
| /* Toast notifications */ | |
| .toast { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| padding: 12px 24px; | |
| border-radius: 4px; | |
| color: white; | |
| font-weight: 500; | |
| z-index: 1000; | |
| animation: slideIn 0.3s ease-out; | |
| } | |
| .toast.success { | |
| background-color: #10B981; | |
| } | |
| .toast.error { | |
| background-color: #EF4444; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| transform: translateX(100%); | |
| opacity: 0; | |
| } | |
| to { | |
| transform: translateX(0); | |
| opacity: 1; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-gray-900 min-h-screen"> | |
| <!-- Navigation --> | |
| <nav class="bg-white dark:bg-gray-800 shadow-sm"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex justify-between h-16"> | |
| <div class="flex"> | |
| <!-- Logo --> | |
| <div class="flex-shrink-0 flex items-center"> | |
| <a href="/" class="text-xl font-bold text-blue-600 dark:text-blue-400"> | |
| {{ app_name }} | |
| </a> | |
| </div> | |
| <!-- Navigation Links --> | |
| <div class="hidden sm:ml-6 sm:flex sm:space-x-8"> | |
| <a href="/" class="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-900 dark:text-white"> | |
| Home | |
| </a> | |
| <a href="/tools" class="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white"> | |
| Tools | |
| </a> | |
| <a href="/credits" class="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white"> | |
| Credits | |
| </a> | |
| </div> | |
| </div> | |
| <!-- User Menu --> | |
| <div class="flex items-center"> | |
| <div class="flex items-center space-x-4"> | |
| {% if user %} | |
| <span class="text-sm text-gray-700 dark:text-gray-300"> | |
| Credits: <span id="user-credits">{{ user_credits }}</span> | |
| </span> | |
| <div class="relative"> | |
| <button id="user-menu-button" class="flex items-center text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white"> | |
| <span class="mr-2">{{ user.username }}</span> | |
| <svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/> | |
| </svg> | |
| </button> | |
| <div id="user-dropdown" class="hidden absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 z-10"> | |
| <a href="/profile" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Profile</a> | |
| <a href="/credits" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Add Credits</a> | |
| <a href="/logout" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Logout</a> | |
| </div> | |
| </div> | |
| {% else %} | |
| <a href="/login" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700"> | |
| Login | |
| </a> | |
| <a href="/register" class="inline-flex items-center px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 bg-white dark:bg-gray-800 border border-blue-600 dark:border-blue-400 rounded-md shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700"> | |
| Register | |
| </a> | |
| {% endif %} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Main Content --> | |
| <div class="flex"> | |
| <!-- Sidebar --> | |
| <div class="w-64 bg-white dark:bg-gray-800 shadow-sm h-screen fixed"> | |
| <div class="p-4"> | |
| <h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Tools</h2> | |
| <nav class="space-y-1"> | |
| {% for tool in tools %} | |
| <a href="/tools/{{ tool.id }}" class="flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg"> | |
| <span class="mr-3">{{ tool.icon }}</span> | |
| {{ tool.name }} | |
| </a> | |
| {% endfor %} | |
| </nav> | |
| </div> | |
| </div> | |
| <!-- Page Content --> | |
| <div class="flex-1 ml-64"> | |
| {% block content %}{% endblock %} | |
| </div> | |
| </div> | |
| <!-- Toast Container --> | |
| <div id="toast-container"></div> | |
| <!-- Common JavaScript --> | |
| <script> | |
| // Show toast notification | |
| function showToast(message, type = 'success') { | |
| const container = document.getElementById('toast-container'); | |
| const toast = document.createElement('div'); | |
| toast.className = `toast ${type}`; | |
| toast.textContent = message; | |
| container.appendChild(toast); | |
| setTimeout(() => { | |
| toast.remove(); | |
| }, 3000); | |
| } | |
| // User menu toggle | |
| const userMenuButton = document.getElementById('user-menu-button'); | |
| const userDropdown = document.getElementById('user-dropdown'); | |
| if (userMenuButton && userDropdown) { | |
| userMenuButton.addEventListener('click', function() { | |
| userDropdown.classList.toggle('hidden'); | |
| }); | |
| // Close the dropdown when clicking outside | |
| document.addEventListener('click', function(event) { | |
| if (!userMenuButton.contains(event.target) && !userDropdown.contains(event.target)) { | |
| userDropdown.classList.add('hidden'); | |
| } | |
| }); | |
| } | |
| // Dark mode toggle | |
| if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { | |
| document.documentElement.classList.add('dark'); | |
| } else { | |
| document.documentElement.classList.remove('dark'); | |
| } | |
| </script> | |
| {% block scripts %}{% endblock %} | |
| </body> | |
| </html> |