Abhi13-coder/noteblocks-modular-note-magic
0
1document.addEventListener('DOMContentLoaded', () => {2 // Sample notes data3 let notes = JSON.parse(localStorage.getItem('notes')) || [];4 let currentNoteId = null;5 6 // DOM elements7 const notesGrid = document.getElementById('notes-grid');8 const newNoteBtn = document.getElementById('new-note-btn');9 const editorModal = document.getElementById('editor-modal');10 const noteTitle = document.getElementById('note-title');11 const editorContent = document.getElementById('editor-content');12 const saveNoteBtn = document.getElementById('save-note');13 const closeEditorBtn = document.getElementById('close-editor');14 const toolbarButtons = document.querySelectorAll('#editor-toolbar button');15 16 // Render all notes17 function renderNotes() {18 notesGrid.innerHTML = '';19 notes.forEach(note => {20 const preview = note.blocks.find(block => block.type === 'paragraph')?.content || 'No content';21 22 const noteElement = document.createElement('div');23 noteElement.className = 'bg-white dark:bg-secondary-700 rounded-lg shadow-md overflow-hidden hover:shadow-lg transition cursor-pointer';24 noteElement.innerHTML = `25 <div class="p-4">26 <h3 class="font-bold text-lg mb-2 text-secondary-900 dark:text-white">${note.title || 'Untitled Note'}</h3>27 <p class="text-secondary-600 dark:text-secondary-300 line-clamp-3">${preview}</p>28 </div>29 <div class="px-4 py-2 bg-secondary-50 dark:bg-secondary-800 text-secondary-500 dark:text-secondary-400 text-sm flex justify-between items-center">30 <span>${new Date(note.updatedAt).toLocaleDateString()}</span>31 <button class="text-red-500 hover:text-red-700 delete-note" data-id="${note.id}">32 <i data-feather="trash-2"></i>33 </button>34 </div>35 `;36 37 noteElement.addEventListener('click', () => openEditor(note.id));38 notesGrid.appendChild(noteElement);39 });40 41 // Add event listeners to delete buttons42 document.querySelectorAll('.delete-note').forEach(btn => {43 btn.addEventListener('click', (e) => {44 e.stopPropagation();45 deleteNote(btn.dataset.id);46 });47 });48 49 feather.replace();50 }51 52 // Create a new note53 function createNewNote() {54 const newNote = {55 id: Date.now().toString(),56 title: '',57 blocks: [{ type: 'paragraph', content: '' }],58 createdAt: new Date(),59 updatedAt: new Date()60 };61 62 notes.unshift(newNote);63 saveNotes();64 openEditor(newNote.id);65 }66 67 // Open editor with note content68 function openEditor(noteId) {69 const note = notes.find(n => n.id === noteId);70 if (!note) return;71 72 currentNoteId = noteId;73 noteTitle.value = note.title;74 editorContent.innerHTML = '';75 76 note.blocks.forEach(block => {77 const blockElement = createBlockElement(block);78 editorContent.appendChild(blockElement);79 });80 81 editorModal.classList.remove('hidden');82 document.body.style.overflow = 'hidden';83 }84 85 // Close editor86 function closeEditor() {87 editorModal.classList.add('hidden');88 document.body.style.overflow = '';89 currentNoteId = null;90 }91 92 // Save note93 function saveNote() {94 if (!currentNoteId) return;95 96 const noteIndex = notes.findIndex(n => n.id === currentNoteId);97 if (noteIndex === -1) return;98 99 const title = noteTitle.value.trim();100 const blocks = [];101 102 // Get all blocks from editor103 editorContent.querySelectorAll('[data-block]').forEach(blockEl => {104 const type = blockEl.dataset.block;105 let content = '';106 107 if (type === 'image') {108 content = blockEl.querySelector('img')?.src || '';109 } else {110 content = blockEl.textContent;111 }112 113 blocks.push({ type, content });114 });115 116 notes[noteIndex] = {117 ...notes[noteIndex],118 title,119 blocks,120 updatedAt: new Date()121 };122 123 saveNotes();124 renderNotes();125 }126 127 // Delete note128 function deleteNote(noteId) {129 if (confirm('Are you sure you want to delete this note?')) {130 notes = notes.filter(note => note.id !== noteId);131 saveNotes();132 renderNotes();133 }134 }135 136 // Save notes to localStorage137 function saveNotes() {138 localStorage.setItem('notes', JSON.stringify(notes));139 }140 141 // Create a block element142 function createBlockElement(block) {143 const blockElement = document.createElement('div');144 blockElement.dataset.block = block.type;145 blockElement.className = `block-${block.type} mb-4`;146 blockElement.contentEditable = true;147 148 switch (block.type) {149 case 'heading':150 blockElement.innerHTML = `<h2>${block.content || 'Heading'}</h2>`;151 break;152 case 'list':153 blockElement.innerHTML = `<ul><li>${block.content || 'List item'}</li></ul>`;154 break;155 case 'image':156 blockElement.innerHTML = `<img src="${block.content || 'https://via.placeholder.com/600x400'}" alt="Image" class="rounded-lg w-full">`;157 break;158 case 'quote':159 blockElement.innerHTML = `<blockquote>${block.content || 'Quote'}</blockquote>`;160 break;161 case 'code':162 blockElement.innerHTML = `<pre><code>${block.content || 'Code'}</code></pre>`;163 break;164 default: // paragraph165 blockElement.textContent = block.content || '';166 }167 168 return blockElement;169 }170 171 // Add block to editor172 function addBlock(type) {173 const block = { type, content: '' };174 const blockElement = createBlockElement(block);175 176 // Add to end of content177 editorContent.appendChild(blockElement);178 179 // Focus the new block180 blockElement.focus();181 }182 183 // Event listeners184 newNoteBtn.addEventListener('click', createNewNote);185 saveNoteBtn.addEventListener('click', saveNote);186 closeEditorBtn.addEventListener('click', closeEditor);187 188 toolbarButtons.forEach(btn => {189 btn.addEventListener('click', () => addBlock(btn.dataset.type));190 });191 192 // Close modal when clicking outside193 editorModal.addEventListener('click', (e) => {194 if (e.target === editorModal) {195 closeEditor();196 }197 });198 199 // Initialize200 renderNotes();201});