Spaces:
Running
Running
| {% extends "base.html" %} | |
| {% block content %} | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6"> | |
| <div class="mb-8"> | |
| <h1 class="font-display text-4xl sm:text-5xl font-bold tracking-tight mb-2"> | |
| <span class="bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent"> | |
| Upload Notes | |
| </span> | |
| </h1> | |
| <p class="font-mono text-sm text-gray-400">Share your knowledge with the community</p> | |
| </div> | |
| <form method="POST" enctype="multipart/form-data" class="space-y-6"> | |
| <div class="glass p-8 rounded-2xl space-y-6"> | |
| <!-- Title --> | |
| <div> | |
| <label class="block font-mono text-sm text-gray-400 mb-2">Title *</label> | |
| <input type="text" name="title" required | |
| class="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition"> | |
| </div> | |
| <!-- Description --> | |
| <div> | |
| <label class="block font-mono text-sm text-gray-400 mb-2">Description</label> | |
| <textarea name="description" rows="3" | |
| class="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition"></textarea> | |
| </div> | |
| <!-- Subject --> | |
| <div> | |
| <label class="block font-mono text-sm text-gray-400 mb-2">Subject *</label> | |
| <select name="subject" required | |
| class="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition"> | |
| <option value="">-- Select Subject --</option> | |
| {% for subject in subjects %} | |
| <option value="{{ subject.id }}">{{ subject.name }}</option> | |
| {% endfor %} | |
| </select> | |
| </div> | |
| <!-- Type --> | |
| <div> | |
| <label class="block font-mono text-sm text-gray-400 mb-2">Type *</label> | |
| <select name="note_type" id="note_type" onchange="toggleInputType()" required | |
| class="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition"> | |
| <option value="">-- Select Type --</option> | |
| <option value="file">File</option> | |
| <option value="link">Link</option> | |
| </select> | |
| </div> | |
| <!-- File Input --> | |
| <div id="file_input" style="display: none;"> | |
| <label class="block font-mono text-sm text-gray-400 mb-2">Files (Multiple allowed)</label> | |
| <div id="file_dropzone" class="w-full border-2 border-dashed border-white/20 bg-white/5 rounded-xl px-4 py-8 text-center transition cursor-pointer hover:border-blue-500/60 hover:bg-blue-500/5"> | |
| <p class="font-mono text-sm text-gray-300">Drop files here or click to browse</p> | |
| <p id="selected_file_count" class="font-mono text-xs text-gray-500 mt-2">No files selected</p> | |
| <input id="files" type="file" name="files" multiple | |
| class="hidden w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:bg-blue-500/20 file:text-blue-400 file:font-mono file:text-sm hover:file:bg-blue-500/30"> | |
| </div> | |
| </div> | |
| <!-- Link Input --> | |
| <div id="link_input" style="display: none;"> | |
| <label class="block font-mono text-sm text-gray-400 mb-2">Links (one per line)</label> | |
| <p class="font-mono text-xs text-gray-500 mb-2">YouTube videos, playlists, docs, and normal URLs are supported.</p> | |
| <textarea name="links" rows="5" | |
| class="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 font-mono focus:outline-none focus:border-blue-500 transition"></textarea> | |
| </div> | |
| </div> | |
| <div class="flex flex-col sm:flex-row gap-4 justify-center"> | |
| <button type="submit" class="btn-magnetic glass px-8 py-4 rounded-xl font-mono font-semibold border-2 border-blue-500/50 hover:border-blue-400 animate-glow"> | |
| Upload | |
| </button> | |
| <a href="{{ url_for('notes.list') }}" class="btn-magnetic glass px-8 py-4 rounded-xl font-mono font-semibold hover:bg-white/5"> | |
| Cancel | |
| </a> | |
| </div> | |
| </form> | |
| </div> | |
| <script> | |
| const noteTypeInput = document.getElementById('note_type'); | |
| const fileInput = document.getElementById('file_input'); | |
| const linkInput = document.getElementById('link_input'); | |
| const dropzone = document.getElementById('file_dropzone'); | |
| const filesField = document.getElementById('files'); | |
| const fileCount = document.getElementById('selected_file_count'); | |
| const linksField = document.querySelector('textarea[name="links"]'); | |
| function updateSelectedFileText(files) { | |
| if (!files || files.length === 0) { | |
| fileCount.textContent = 'No files selected'; | |
| return; | |
| } | |
| fileCount.textContent = files.length === 1 | |
| ? `Selected: ${files[0].name}` | |
| : `${files.length} files selected`; | |
| } | |
| function toggleInputType() { | |
| const type = noteTypeInput.value; | |
| if (type === 'file') { | |
| fileInput.style.display = 'block'; | |
| linkInput.style.display = 'none'; | |
| } else if (type === 'link') { | |
| fileInput.style.display = 'none'; | |
| linkInput.style.display = 'block'; | |
| } else { | |
| fileInput.style.display = 'none'; | |
| linkInput.style.display = 'none'; | |
| } | |
| } | |
| dropzone.addEventListener('click', () => filesField.click()); | |
| filesField.addEventListener('change', () => { | |
| updateSelectedFileText(filesField.files); | |
| }); | |
| ['dragenter', 'dragover'].forEach((eventName) => { | |
| dropzone.addEventListener(eventName, (event) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| dropzone.classList.add('border-blue-500', 'bg-blue-500/10'); | |
| }); | |
| }); | |
| ['dragleave', 'drop'].forEach((eventName) => { | |
| dropzone.addEventListener(eventName, (event) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| dropzone.classList.remove('border-blue-500', 'bg-blue-500/10'); | |
| }); | |
| }); | |
| dropzone.addEventListener('drop', (event) => { | |
| if (!event.dataTransfer || !event.dataTransfer.files.length) { | |
| return; | |
| } | |
| try { | |
| filesField.files = event.dataTransfer.files; | |
| } catch (error) { | |
| const dt = new DataTransfer(); | |
| Array.from(event.dataTransfer.files).forEach((file) => dt.items.add(file)); | |
| filesField.files = dt.files; | |
| } | |
| updateSelectedFileText(filesField.files); | |
| }); | |
| toggleInputType(); | |
| linksField.addEventListener('focus', () => { | |
| if (!noteTypeInput.value) { | |
| noteTypeInput.value = 'link'; | |
| toggleInputType(); | |
| } | |
| }); | |
| </script> | |
| {% endblock %} | |