| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>ScribbleSync - Digital Notepad</title> |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://unpkg.com/feather-icons"></script> |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
| <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script> |
| <style> |
| .note-card { |
| transition: all 0.3s ease; |
| } |
| .note-card:hover { |
| transform: translateY(-5px); |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
| } |
| #vanta-bg { |
| position: fixed; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| z-index: -1; |
| opacity: 0.1; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50"> |
| <div id="vanta-bg"></div> |
| |
| |
| <nav class="bg-white shadow-sm fixed w-full z-10"> |
| <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"> |
| <div class="flex-shrink-0 flex items-center"> |
| <i data-feather="edit-3" class="text-indigo-600 h-6 w-6"></i> |
| <span class="ml-2 text-xl font-bold text-indigo-600">ScribbleSync</span> |
| </div> |
| <div class="hidden sm:ml-6 sm:flex sm:space-x-8"> |
| <a href="index.html" class="border-indigo-500 text-gray-900 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"> |
| Notes |
| </a> |
| <a href="history.html" class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"> |
| History |
| </a> |
| </div> |
| </div> |
| <div class="hidden sm:ml-6 sm:flex sm:items-center"> |
| <button id="new-note-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md text-sm font-medium flex items-center"> |
| <i data-feather="plus" class="mr-1 h-4 w-4"></i> New Note |
| </button> |
| </div> |
| <div class="-mr-2 flex items-center sm:hidden"> |
| <button type="button" id="mobile-menu-button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"> |
| <i data-feather="menu"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="mobile-menu" class="sm:hidden hidden"> |
| <div class="pt-2 pb-3 space-y-1"> |
| <a href="index.html" class="bg-indigo-50 border-indigo-500 text-indigo-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium"> |
| Notes |
| </a> |
| <a href="history.html" class="border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700 block pl-3 pr-4 py-2 border-l-4 text-base font-medium"> |
| History |
| </a> |
| <button id="mobile-new-note-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md text-sm font-medium flex items-center ml-3 mt-2 mb-2"> |
| <i data-feather="plus" class="mr-1 h-4 w-4"></i> New Note |
| </button> |
| </div> |
| </div> |
| </nav> |
|
|
| |
| <main class="pt-20 pb-10 px-4 sm:px-6 lg:px-8"> |
| <div class="max-w-7xl mx-auto"> |
| <div class="mb-8"> |
| <h1 class="text-3xl font-bold text-gray-900">Your Notes</h1> |
| <p class="mt-2 text-sm text-gray-500">Create, edit and organize your thoughts</p> |
| </div> |
|
|
| |
| <div id="notes-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> |
| |
| </div> |
|
|
| |
| <div id="empty-state" class="text-center py-16 hidden"> |
| <i data-feather="edit" class="mx-auto h-12 w-12 text-gray-400"></i> |
| <h3 class="mt-2 text-lg font-medium text-gray-900">No notes</h3> |
| <p class="mt-1 text-sm text-gray-500">Get started by creating a new note.</p> |
| <div class="mt-6"> |
| <button id="empty-new-note-btn" class="inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> |
| <i data-feather="plus" class="-ml-1 mr-2 h-5 w-5"></i> New Note |
| </button> |
| </div> |
| </div> |
| </div> |
| </main> |
|
|
| |
| <div id="note-modal" class="fixed z-50 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true"> |
| <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> |
| <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div> |
| <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span> |
| <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"> |
| <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> |
| <div class="sm:flex sm:items-start"> |
| <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full"> |
| <h3 class="text-lg leading-6 font-medium text-gray-900 mb-4" id="modal-title"> |
| <span id="modal-title-text">New Note</span> |
| </h3> |
| <div class="mt-2"> |
| <input type="text" id="note-title" class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md mb-4 p-2" placeholder="Note title"> |
| <textarea id="note-content" class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md p-2 h-64" placeholder="Write your note here..."></textarea> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> |
| <button type="button" id="save-note-btn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"> |
| Save |
| </button> |
| <button type="button" id="cancel-note-btn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> |
| Cancel |
| </button> |
| <button type="button" id="delete-note-btn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-red-600 text-white font-medium hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm hidden"> |
| Delete |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| VANTA.NET({ |
| el: "#vanta-bg", |
| color: 0x6366f1, |
| backgroundColor: 0xf9fafb, |
| points: 10, |
| maxDistance: 20, |
| spacing: 15 |
| }); |
| |
| |
| document.addEventListener('DOMContentLoaded', function() { |
| feather.replace(); |
| |
| |
| const mobileMenuButton = document.getElementById('mobile-menu-button'); |
| const mobileMenu = document.getElementById('mobile-menu'); |
| |
| mobileMenuButton.addEventListener('click', function() { |
| if (mobileMenu.classList.contains('hidden')) { |
| mobileMenu.classList.remove('hidden'); |
| } else { |
| mobileMenu.classList.add('hidden'); |
| } |
| }); |
| |
| |
| let notes = JSON.parse(localStorage.getItem('notes')) || []; |
| let currentNoteId = null; |
| |
| |
| const notesContainer = document.getElementById('notes-container'); |
| const emptyState = document.getElementById('empty-state'); |
| const noteModal = document.getElementById('note-modal'); |
| const noteTitle = document.getElementById('note-title'); |
| const noteContent = document.getElementById('note-content'); |
| const saveNoteBtn = document.getElementById('save-note-btn'); |
| const cancelNoteBtn = document.getElementById('cancel-note-btn'); |
| const deleteNoteBtn = document.getElementById('delete-note-btn'); |
| const modalTitle = document.getElementById('modal-title-text'); |
| |
| |
| const newNoteBtn = document.getElementById('new-note-btn'); |
| const mobileNewNoteBtn = document.getElementById('mobile-new-note-btn'); |
| const emptyNewNoteBtn = document.getElementById('empty-new-note-btn'); |
| |
| |
| [newNoteBtn, mobileNewNoteBtn, emptyNewNoteBtn].forEach(btn => { |
| btn.addEventListener('click', () => { |
| openNewNoteModal(); |
| }); |
| }); |
| |
| |
| cancelNoteBtn.addEventListener('click', closeNoteModal); |
| |
| |
| saveNoteBtn.addEventListener('click', saveNote); |
| |
| |
| deleteNoteBtn.addEventListener('click', deleteNote); |
| |
| |
| renderNotes(); |
| |
| |
| function openNewNoteModal() { |
| currentNoteId = null; |
| noteTitle.value = ''; |
| noteContent.value = ''; |
| modalTitle.textContent = 'New Note'; |
| deleteNoteBtn.classList.add('hidden'); |
| noteModal.classList.remove('hidden'); |
| noteTitle.focus(); |
| } |
| |
| function openEditNoteModal(id) { |
| const note = notes.find(note => note.id === id); |
| if (note) { |
| currentNoteId = id; |
| noteTitle.value = note.title; |
| noteContent.value = note.content; |
| modalTitle.textContent = 'Edit Note'; |
| deleteNoteBtn.classList.remove('hidden'); |
| noteModal.classList.remove('hidden'); |
| noteTitle.focus(); |
| } |
| } |
| |
| function closeNoteModal() { |
| noteModal.classList.add('hidden'); |
| } |
| |
| function saveNote() { |
| const title = noteTitle.value.trim(); |
| const content = noteContent.value.trim(); |
| |
| if (!title) { |
| alert('Please enter a title for your note'); |
| return; |
| } |
| |
| const now = new Date(); |
| const timestamp = now.toISOString(); |
| |
| if (currentNoteId) { |
| |
| const noteIndex = notes.findIndex(note => note.id === currentNoteId); |
| if (noteIndex !== -1) { |
| notes[noteIndex] = { |
| ...notes[noteIndex], |
| title, |
| content, |
| updatedAt: timestamp |
| }; |
| } |
| } else { |
| |
| const newNote = { |
| id: Date.now().toString(), |
| title, |
| content, |
| createdAt: timestamp, |
| updatedAt: timestamp |
| }; |
| notes.unshift(newNote); |
| } |
| |
| saveToLocalStorage(); |
| renderNotes(); |
| closeNoteModal(); |
| } |
| function deleteNote() { |
| if (confirm('Are you sure you want to delete this note?')) { |
| const noteIndex = notes.findIndex(note => note.id === currentNoteId); |
| if (noteIndex !== -1) { |
| const deletedNote = notes[noteIndex]; |
| |
| |
| const trash = JSON.parse(localStorage.getItem('trash')) || []; |
| trash.push({ |
| ...deletedNote, |
| deletedAt: new Date().toISOString() |
| }); |
| localStorage.setItem('trash', JSON.stringify(trash)); |
| |
| |
| notes.splice(noteIndex, 1); |
| saveToLocalStorage(); |
| renderNotes(); |
| closeNoteModal(); |
| } |
| } |
| } |
| function saveToLocalStorage() { |
| localStorage.setItem('notes', JSON.stringify(notes)); |
| } |
| |
| function renderNotes() { |
| notesContainer.innerHTML = ''; |
| |
| if (notes.length === 0) { |
| emptyState.classList.remove('hidden'); |
| return; |
| } |
| |
| emptyState.classList.add('hidden'); |
| |
| notes.forEach(note => { |
| const noteDate = new Date(note.updatedAt); |
| const formattedDate = noteDate.toLocaleDateString('en-US', { |
| year: 'numeric', |
| month: 'short', |
| day: 'numeric', |
| hour: '2-digit', |
| minute: '2-digit' |
| }); |
| |
| const truncatedContent = note.content.length > 150 |
| ? note.content.substring(0, 150) + '...' |
| : note.content; |
| |
| const noteCard = document.createElement('div'); |
| noteCard.className = 'bg-white overflow-hidden shadow rounded-lg note-card cursor-pointer'; |
| noteCard.innerHTML = ` |
| <div class="px-4 py-5 sm:p-6" onclick="openEditNoteModal('${note.id}')"> |
| <div class="flex items-center justify-between"> |
| <h3 class="text-lg leading-6 font-medium text-gray-900">${note.title}</h3> |
| <span class="text-xs text-gray-500">${formattedDate}</span> |
| </div> |
| <div class="mt-2 text-sm text-gray-600"> |
| <p>${truncatedContent}</p> |
| </div> |
| </div> |
| `; |
| |
| notesContainer.appendChild(noteCard); |
| }); |
| |
| feather.replace(); |
| } |
| |
| |
| window.openEditNoteModal = openEditNoteModal; |
| }); |
| </script> |
| </body> |
| </html> |
|
|