lwmecham commited on
Commit
bcc275b
·
verified ·
1 Parent(s): 18d9c6f

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +1237 -219
  2. prompts.txt +6 -0
index.html CHANGED
@@ -6,9 +6,32 @@
6
  <title>MySecureNotes | Personal Information Hub</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
 
 
 
9
  <style>
10
  .sidebar {
11
  transition: all 0.3s ease;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  }
13
  .note-content {
14
  min-height: 70vh;
@@ -36,6 +59,153 @@
36
  border-color: #4299e1;
37
  background-color: #ebf8ff;
38
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  </style>
40
  </head>
41
  <body class="bg-gray-100 font-sans">
@@ -100,32 +270,43 @@
100
  </div>
101
  </div>
102
 
103
- <button id="newNoteBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md mb-6 flex items-center justify-center space-x-2">
104
- <i class="fas fa-plus"></i>
105
- <span>New Note</span>
106
- </button>
107
-
108
- <div class="mb-4">
109
- <div class="flex items-center justify-between text-gray-400 mb-2">
110
- <span class="text-sm font-medium">MY NOTES</span>
111
- <i class="fas fa-chevron-down text-xs"></i>
112
- </div>
113
- <ul id="notesList" class="space-y-1">
114
- <!-- Notes will be populated here -->
115
- </ul>
116
  </div>
117
 
118
- <div class="mb-4">
119
- <div class="flex items-center justify-between text-gray-400 mb-2">
120
- <span class="text-sm font-medium">DOCUMENTS</span>
121
- <i class="fas fa-chevron-down text-xs"></i>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  </div>
123
- <ul id="documentsList" class="space-y-1">
124
- <!-- Documents will be populated here -->
125
- </ul>
126
  </div>
127
 
128
- <div class="mt-8 pt-4 border-t border-gray-700">
129
  <button id="logoutBtn" class="flex items-center space-x-2 text-gray-400 hover:text-white w-full">
130
  <i class="fas fa-sign-out-alt"></i>
131
  <span>Logout</span>
@@ -168,7 +349,7 @@
168
  <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Profile</a>
169
  <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Settings</a>
170
  <div class="border-t border-gray-200"></div>
171
- <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Logout</a>
172
  </div>
173
  </div>
174
  </div>
@@ -220,12 +401,45 @@
220
  <div id="documentsView" class="hidden">
221
  <div class="flex justify-between items-center mb-6">
222
  <h2 class="text-xl font-semibold text-gray-800">My Documents</h2>
223
- <div class="file-upload">
224
- <button class="bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 flex items-center space-x-2">
225
- <i class="fas fa-upload"></i>
226
- <span>Upload Document</span>
227
- </button>
228
- <input type="file" id="fileInput" class="hidden" multiple>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  </div>
230
  </div>
231
 
@@ -235,19 +449,11 @@
235
  <p class="text-gray-500 mt-1">or click to browse files</p>
236
  </div>
237
 
238
- <div class="bg-white rounded-lg shadow-sm overflow-hidden">
239
- <div class="grid grid-cols-12 gap-4 border-b border-gray-200 px-4 py-3 font-medium text-gray-700">
240
- <div class="col-span-6">Name</div>
241
- <div class="col-span-2">Type</div>
242
- <div class="col-span-2">Size</div>
243
- <div class="col-span-2">Date</div>
244
- </div>
245
- <div id="documentsGrid" class="divide-y divide-gray-200">
246
- <!-- Documents will be listed here -->
247
- <div class="text-center py-8 text-gray-500">
248
- <i class="fas fa-folder-open text-3xl mb-2"></i>
249
- <p>No documents uploaded yet</p>
250
- </div>
251
  </div>
252
  </div>
253
  </div>
@@ -256,17 +462,65 @@
256
  </div>
257
 
258
  <script>
 
 
 
259
  // Sample data for demonstration
260
- const sampleNotes = [
261
- { id: 1, title: 'Personal Goals', content: '1. Learn a new language\n2. Read 20 books this year\n3. Exercise 3 times a week', lastUpdated: '2023-06-15T10:30:00' },
262
- { id: 2, title: 'Project Ideas', content: '1. Personal finance tracker\n2. Recipe organizer app\n3. Travel journal website', lastUpdated: '2023-06-10T14:45:00' },
263
- { id: 3, title: 'Shopping List', content: '- Milk\n- Eggs\n- Bread\n- Fruits\n- Vegetables', lastUpdated: '2023-06-05T09:15:00' }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  ];
265
 
 
266
  const sampleDocuments = [
267
- { id: 1, name: 'Resume.pdf', type: 'PDF', size: '2.4 MB', date: '2023-05-20' },
268
- { id: 2, name: 'Contract.docx', type: 'Word', size: '1.1 MB', date: '2023-04-15' },
269
- { id: 3, name: 'Budget.xlsx', type: 'Excel', size: '3.2 MB', date: '2023-03-10' }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  ];
271
 
272
  // DOM Elements
@@ -280,6 +534,7 @@
280
  const notesList = document.getElementById('notesList');
281
  const documentsList = document.getElementById('documentsList');
282
  const newNoteBtn = document.getElementById('newNoteBtn');
 
283
  const emptyNewNoteBtn = document.getElementById('emptyNewNoteBtn');
284
  const emptyState = document.getElementById('emptyState');
285
  const noteEditor = document.getElementById('noteEditor');
@@ -299,13 +554,26 @@
299
  const searchBtn = document.getElementById('searchBtn');
300
  const searchBox = document.getElementById('searchBox');
301
  const lastSaved = document.getElementById('lastSaved');
 
 
 
 
 
 
302
 
303
  // Current state
304
  let currentNote = null;
 
305
  let currentView = 'notes'; // 'notes' or 'documents'
306
- let notes = [...sampleNotes];
307
  let documents = [...sampleDocuments];
308
  let autoSaveTimer = null;
 
 
 
 
 
 
309
 
310
  // Initialize the app
311
  function initApp() {
@@ -313,11 +581,25 @@
313
  loginModal.classList.remove('hidden');
314
 
315
  // Populate notes and documents lists
316
- renderNotesList();
317
  renderDocumentsList();
318
 
319
  // Set up event listeners
320
  setupEventListeners();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  }
322
 
323
  // Set up all event listeners
@@ -361,6 +643,7 @@
361
  // New note buttons
362
  newNoteBtn.addEventListener('click', createNewNote);
363
  emptyNewNoteBtn.addEventListener('click', createNewNote);
 
364
 
365
  // Note editor events
366
  noteTitle.addEventListener('input', startAutoSave);
@@ -376,7 +659,7 @@
376
  dropZone.addEventListener(eventName, preventDefaults, false);
377
  });
378
 
379
- ['dragenter', 'dragover'].forEach(eventName => {
380
  dropZone.addEventListener(eventName, highlight, false);
381
  });
382
 
@@ -396,6 +679,50 @@
396
  searchBox.classList.toggle('hidden');
397
  });
398
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  // Close menus when clicking elsewhere
400
  document.addEventListener('click', function(e) {
401
  if (!userMenuBtn.contains(e.target) && !userMenu.contains(e.target)) {
@@ -439,219 +766,910 @@
439
  // For demo, we'll just add them to our documents array
440
  Array.from(files).forEach(file => {
441
  const newDoc = {
442
- id: documents.length + 1,
443
  name: file.name,
444
- type: file.type || 'Unknown',
445
  size: formatFileSize(file.size),
446
- date: new Date().toISOString().split('T')[0]
 
 
 
 
447
  };
448
- documents.unshift(newDoc);
 
 
 
 
 
 
 
 
449
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
 
451
- renderDocumentsList();
452
- renderDocumentsGrid();
 
 
 
 
 
 
 
 
453
 
454
- // Show success message
455
- alert(`${files.length} file(s) uploaded successfully!`);
 
 
456
  }
457
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
 
459
- // Format file size
460
- function formatFileSize(bytes) {
461
- if (bytes === 0) return '0 Bytes';
462
- const k = 1024;
463
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
464
- const i = Math.floor(Math.log(bytes) / Math.log(k));
465
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
466
- }
467
 
468
- // Create a new note
469
- function createNewNote() {
470
- const newNote = {
471
- id: notes.length + 1,
472
- title: 'Untitled Note',
473
- content: '',
474
- lastUpdated: new Date().toISOString()
475
- };
476
-
477
- notes.unshift(newNote);
478
- renderNotesList();
479
- openNote(newNote.id);
480
-
481
- // Focus on title field
482
- setTimeout(() => {
483
- noteTitle.focus();
484
- }, 100);
485
- }
486
 
487
- // Open a note by ID
488
- function openNote(noteId) {
489
- currentNote = notes.find(note => note.id === noteId);
490
- if (currentNote) {
491
- emptyState.classList.add('hidden');
492
- noteEditor.classList.remove('hidden');
493
- documentsView.classList.add('hidden');
494
- currentView = 'notes';
495
-
496
- noteTitle.value = currentNote.title;
497
- noteContent.innerHTML = currentNote.content.replace(/\n/g, '<br>');
498
- lastSaved.textContent = formatDate(currentNote.lastUpdated);
499
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  }
501
-
502
- // Start auto-save timer
503
- function startAutoSave() {
504
- if (autoSaveTimer) {
505
- clearTimeout(autoSaveTimer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  }
507
 
508
- autoSaveTimer = setTimeout(() => {
509
- saveCurrentNote();
510
- }, 2000);
 
 
 
 
 
 
511
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
 
513
- // Save current note
514
- function saveCurrentNote() {
515
- if (currentNote) {
516
- currentNote.title = noteTitle.value;
517
- currentNote.content = noteContent.innerHTML.replace(/<br>/g, '\n');
518
- currentNote.lastUpdated = new Date().toISOString();
 
 
 
 
 
 
 
519
 
520
- // Update last saved time
521
- lastSaved.textContent = 'Just now';
 
 
 
 
 
522
 
523
- // Update the note in the sidebar list
524
- renderNotesList();
525
- }
526
- }
527
-
528
- // Delete current note
529
- function deleteCurrentNote() {
530
- if (currentNote && confirm('Are you sure you want to delete this note?')) {
531
- notes = notes.filter(note => note.id !== currentNote.id);
532
- renderNotesList();
533
  closeNoteEditor();
 
534
  }
535
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
 
537
- // Close note editor
538
- function closeNoteEditor() {
539
- emptyState.classList.remove('hidden');
540
- noteEditor.classList.add('hidden');
541
- currentNote = null;
542
- }
543
 
544
- // Render notes list in sidebar
545
- function renderNotesList() {
546
- notesList.innerHTML = '';
547
-
548
- notes.forEach(note => {
549
- const noteItem = document.createElement('li');
550
- noteItem.className = 'note-card bg-gray-700 hover:bg-gray-600 rounded-md px-3 py-2 cursor-pointer transition';
551
- noteItem.innerHTML = `
552
- <div class="flex justify-between items-center">
553
- <div class="truncate">${note.title}</div>
554
- <i class="fas fa-chevron-right text-xs text-gray-400"></i>
555
- </div>
556
- <div class="text-xs text-gray-400 mt-1">${formatDate(note.lastUpdated)}</div>
557
- `;
558
- noteItem.addEventListener('click', () => openNote(note.id));
559
- notesList.appendChild(noteItem);
 
 
 
 
 
 
 
 
 
 
 
560
  });
561
  }
562
 
563
- // Render documents list in sidebar
564
- function renderDocumentsList() {
565
- documentsList.innerHTML = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
 
567
- documents.slice(0, 3).forEach(doc => {
 
568
  const docItem = document.createElement('li');
569
- docItem.className = 'bg-gray-700 hover:bg-gray-600 rounded-md px-3 py-2 cursor-pointer';
 
570
  docItem.innerHTML = `
571
- <div class="flex items-center space-x-2">
572
- <i class="fas fa-file text-blue-400"></i>
573
- <span class="truncate">${doc.name}</span>
574
- </div>
 
 
575
  `;
576
- docItem.addEventListener('click', () => showDocumentsView());
577
- documentsList.appendChild(docItem);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  });
579
 
580
- if (documents.length > 3) {
581
- const moreItem = document.createElement('li');
582
- moreItem.className = 'text-gray-400 text-sm px-3 py-1';
583
- moreItem.textContent = `+${documents.length - 3} more...`;
584
- moreItem.addEventListener('click', () => showDocumentsView());
585
- documentsList.appendChild(moreItem);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
  }
587
  }
 
 
 
 
 
 
 
588
 
589
- // Show documents view
590
- function showDocumentsView() {
591
- emptyState.classList.add('hidden');
592
- noteEditor.classList.add('hidden');
593
- documentsView.classList.remove('hidden');
594
- currentView = 'documents';
595
- renderDocumentsGrid();
 
 
 
 
 
 
 
 
 
 
 
 
596
  }
597
 
598
- // Render documents grid
599
- function renderDocumentsGrid() {
600
- documentsGrid.innerHTML = '';
601
-
602
- if (documents.length === 0) {
603
- documentsGrid.innerHTML = `
604
- <div class="text-center py-8 text-gray-500">
605
- <i class="fas fa-folder-open text-3xl mb-2"></i>
606
- <p>No documents uploaded yet</p>
607
- </div>
608
- `;
609
- return;
 
 
 
 
 
610
  }
611
 
612
- documents.forEach(doc => {
613
- const docRow = document.createElement('div');
614
- docRow.className = 'grid grid-cols-12 gap-4 px-4 py-3 hover:bg-gray-50 items-center';
615
- docRow.innerHTML = `
616
- <div class="col-span-6 flex items-center space-x-3">
617
- <i class="fas fa-file text-blue-500"></i>
618
- <span>${doc.name}</span>
619
- </div>
620
- <div class="col-span-2 text-sm text-gray-500">${doc.type}</div>
621
- <div class="col-span-2 text-sm text-gray-500">${doc.size}</div>
622
- <div class="col-span-2 text-sm text-gray-500">${doc.date}</div>
623
- `;
624
- documentsGrid.appendChild(docRow);
625
- });
626
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
627
 
628
- // Format date for display
629
- function formatDate(dateString) {
630
- const date = new Date(dateString);
631
- const now = new Date();
632
- const diffInDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));
633
-
634
- if (diffInDays === 0) {
635
- return 'Today';
636
- } else if (diffInDays === 1) {
637
- return 'Yesterday';
638
- } else if (diffInDays < 7) {
639
- return `${diffInDays} days ago`;
640
- } else {
641
- return date.toLocaleDateString();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
  }
643
  }
644
 
645
- // Reset app state
646
- function resetAppState() {
647
- currentNote = null;
648
- emptyState.classList.remove('hidden');
649
- noteEditor.classList.add('hidden');
650
- documentsView.classList.add('hidden');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  }
652
 
653
- // Initialize the app when the page loads
654
- window.addEventListener('DOMContentLoaded', initApp);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
  </script>
656
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=lwmecham/useful-space" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
657
  </html>
 
6
  <title>MySecureNotes | Personal Information Hub</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <!-- PDF.js for document preview -->
10
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
11
+ <!-- SortableJS for drag and drop -->
12
+ <script src="https://cdn.jsdelivr.net/npm/sortablejs@1.14.0/Sortable.min.js"></script>
13
  <style>
14
  .sidebar {
15
  transition: all 0.3s ease;
16
+ height: 100vh;
17
+ display: flex;
18
+ flex-direction: column;
19
+ }
20
+ .sidebar-content {
21
+ flex: 1;
22
+ overflow-y: auto;
23
+ scrollbar-width: thin;
24
+ scrollbar-color: #4a5568 #2d3748;
25
+ }
26
+ .sidebar-content::-webkit-scrollbar {
27
+ width: 8px;
28
+ }
29
+ .sidebar-content::-webkit-scrollbar-track {
30
+ background: #2d3748;
31
+ }
32
+ .sidebar-content::-webkit-scrollbar-thumb {
33
+ background-color: #4a5568;
34
+ border-radius: 4px;
35
  }
36
  .note-content {
37
  min-height: 70vh;
 
59
  border-color: #4299e1;
60
  background-color: #ebf8ff;
61
  }
62
+ .document-preview {
63
+ height: 200px;
64
+ overflow: hidden;
65
+ position: relative;
66
+ background-color: #f5f5f5;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ }
71
+ .document-preview img {
72
+ max-width: 100%;
73
+ max-height: 100%;
74
+ object-fit: contain;
75
+ }
76
+ .document-preview canvas {
77
+ max-width: 100%;
78
+ max-height: 100%;
79
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
80
+ }
81
+ .document-preview .file-icon {
82
+ font-size: 48px;
83
+ color: #6b7280;
84
+ }
85
+ .document-preview .preview-text {
86
+ position: absolute;
87
+ bottom: 0;
88
+ left: 0;
89
+ right: 0;
90
+ background: rgba(0,0,0,0.7);
91
+ color: white;
92
+ padding: 5px;
93
+ font-size: 12px;
94
+ text-align: center;
95
+ }
96
+ .document-grid {
97
+ display: grid;
98
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
99
+ gap: 20px;
100
+ }
101
+ .document-card {
102
+ background: white;
103
+ border-radius: 8px;
104
+ overflow: hidden;
105
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
106
+ transition: transform 0.2s, box-shadow 0.2s;
107
+ }
108
+ .document-card:hover {
109
+ transform: translateY(-5px);
110
+ box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1);
111
+ }
112
+ .document-info {
113
+ padding: 12px;
114
+ }
115
+ .document-actions {
116
+ display: flex;
117
+ justify-content: space-between;
118
+ padding: 8px 12px;
119
+ border-top: 1px solid #eee;
120
+ }
121
+ .sortable-ghost {
122
+ opacity: 0.5;
123
+ background: #c8ebfb;
124
+ }
125
+ .notebook {
126
+ margin-left: 12px;
127
+ border-left: 2px solid #e2e8f0;
128
+ padding-left: 8px;
129
+ }
130
+ .notebook-header {
131
+ cursor: pointer;
132
+ user-select: none;
133
+ }
134
+ .notebook-header:hover {
135
+ background-color: #f7fafc;
136
+ }
137
+ .note-page {
138
+ margin-left: 24px;
139
+ padding-left: 8px;
140
+ border-left: 2px solid #e2e8f0;
141
+ }
142
+ .note-page:hover {
143
+ background-color: #f7fafc;
144
+ }
145
+ .drag-handle {
146
+ cursor: move;
147
+ margin-right: 8px;
148
+ color: #a0aec0;
149
+ }
150
+ .document-tags {
151
+ display: flex;
152
+ flex-wrap: wrap;
153
+ gap: 4px;
154
+ margin-top: 8px;
155
+ }
156
+ .document-tag {
157
+ background-color: #ebf8ff;
158
+ color: #3182ce;
159
+ padding: 2px 6px;
160
+ border-radius: 4px;
161
+ font-size: 12px;
162
+ }
163
+ .document-dropzone {
164
+ height: 10px;
165
+ background-color: #ebf8ff;
166
+ margin: 5px 0;
167
+ border-radius: 4px;
168
+ transition: all 0.2s;
169
+ }
170
+ .document-dropzone.active {
171
+ height: 30px;
172
+ background-color: #bee3f8;
173
+ }
174
+ .edit-notebook-input {
175
+ background: transparent;
176
+ border: none;
177
+ outline: none;
178
+ width: 100%;
179
+ font-weight: 600;
180
+ }
181
+ .document-in-notebook {
182
+ background-color: #f0f9ff;
183
+ border-left: 3px solid #3b82f6;
184
+ }
185
+ .active-notebook {
186
+ background-color: rgba(59, 130, 246, 0.1);
187
+ }
188
+ .note-page.drag-over {
189
+ background-color: #ebf8ff;
190
+ border-left: 3px solid #3b82f6;
191
+ }
192
+ /* New styles for scrollable sections */
193
+ .directory-section {
194
+ overflow-y: auto;
195
+ max-height: 40vh; /* Adjust this value as needed */
196
+ scrollbar-width: thin;
197
+ scrollbar-color: #4a5568 #2d3748;
198
+ }
199
+ .directory-section::-webkit-scrollbar {
200
+ width: 6px;
201
+ }
202
+ .directory-section::-webkit-scrollbar-track {
203
+ background: #2d3748;
204
+ }
205
+ .directory-section::-webkit-scrollbar-thumb {
206
+ background-color: #4a5568;
207
+ border-radius: 4px;
208
+ }
209
  </style>
210
  </head>
211
  <body class="bg-gray-100 font-sans">
 
270
  </div>
271
  </div>
272
 
273
+ <div class="flex flex-col space-y-2 mb-6">
274
+ <button id="newNotebookBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md flex items-center justify-center space-x-2">
275
+ <i class="fas fa-plus"></i>
276
+ <span>New Notebook</span>
277
+ </button>
278
+ <button id="newNoteBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md flex items-center justify-center space-x-2">
279
+ <i class="fas fa-plus"></i>
280
+ <span>New Note</span>
281
+ </button>
 
 
 
 
282
  </div>
283
 
284
+ <div class="sidebar-content">
285
+ <div class="mb-4">
286
+ <div class="flex items-center justify-between text-gray-400 mb-2">
287
+ <span class="text-sm font-medium">MY NOTES</span>
288
+ </div>
289
+ <div class="directory-section">
290
+ <ul id="notesList" class="space-y-1">
291
+ <!-- Notes will be populated here -->
292
+ </ul>
293
+ </div>
294
+ </div>
295
+
296
+ <div class="mb-4">
297
+ <div class="flex items-center justify-between text-gray-400 mb-2">
298
+ <span class="text-sm font-medium">DOCUMENTS</span>
299
+ <i class="fas fa-chevron-down text-xs"></i>
300
+ </div>
301
+ <div class="directory-section">
302
+ <ul id="documentsList" class="space-y-1">
303
+ <!-- Documents will be populated here -->
304
+ </ul>
305
+ </div>
306
  </div>
 
 
 
307
  </div>
308
 
309
+ <div class="pt-4 border-t border-gray-700">
310
  <button id="logoutBtn" class="flex items-center space-x-2 text-gray-400 hover:text-white w-full">
311
  <i class="fas fa-sign-out-alt"></i>
312
  <span>Logout</span>
 
349
  <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Profile</a>
350
  <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Settings</a>
351
  <div class="border-t border-gray-200"></div>
352
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Logout</a>
353
  </div>
354
  </div>
355
  </div>
 
401
  <div id="documentsView" class="hidden">
402
  <div class="flex justify-between items-center mb-6">
403
  <h2 class="text-xl font-semibold text-gray-800">My Documents</h2>
404
+ <div class="flex space-x-2">
405
+ <div class="relative">
406
+ <select id="sortDocuments" class="appearance-none bg-white border border-gray-300 rounded-md px-3 py-2 pr-8 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
407
+ <option value="name-asc">Sort by: Name (A-Z)</option>
408
+ <option value="name-desc">Sort by: Name (Z-A)</option>
409
+ <option value="date-new">Sort by: Date (Newest)</option>
410
+ <option value="date-old">Sort by: Date (Oldest)</option>
411
+ <option value="size-large">Sort by: Size (Large)</option>
412
+ <option value="size-small">Sort by: Size (Small)</option>
413
+ </select>
414
+ <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
415
+ <i class="fas fa-chevron-down text-xs"></i>
416
+ </div>
417
+ </div>
418
+ <div class="file-upload">
419
+ <button class="bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 flex items-center space-x-2">
420
+ <i class="fas fa-upload"></i>
421
+ <span>Upload Document</span>
422
+ </button>
423
+ <input type="file" id="fileInput" class="hidden" multiple>
424
+ </div>
425
+ </div>
426
+ </div>
427
+
428
+ <div class="mb-4 flex items-center space-x-2">
429
+ <input type="text" id="documentSearch" placeholder="Search documents..." class="flex-1 px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500">
430
+ <button id="addTagBtn" class="bg-gray-200 text-gray-700 py-2 px-3 rounded-md hover:bg-gray-300">
431
+ <i class="fas fa-tag"></i>
432
+ </button>
433
+ <div id="tagDropdown" class="hidden absolute right-0 mt-10 w-48 bg-white rounded-md shadow-lg z-10 p-2">
434
+ <div class="flex flex-wrap gap-2">
435
+ <span class="document-tag cursor-pointer" data-tag="work">work</span>
436
+ <span class="document-tag cursor-pointer" data-tag="personal">personal</span>
437
+ <span class="document-tag cursor-pointer" data-tag="important">important</span>
438
+ <span class="document-tag cursor-pointer" data-tag="finance">finance</span>
439
+ <span class="document-tag cursor-pointer" data-tag="archive">archive</span>
440
+ </div>
441
+ <input type="text" id="newTagInput" placeholder="Add new tag" class="mt-2 w-full px-2 py-1 text-sm border border-gray-300 rounded">
442
+ <button id="saveTagBtn" class="mt-2 w-full bg-blue-500 text-white py-1 px-2 rounded text-sm">Add</button>
443
  </div>
444
  </div>
445
 
 
449
  <p class="text-gray-500 mt-1">or click to browse files</p>
450
  </div>
451
 
452
+ <div class="document-grid" id="documentsGrid">
453
+ <!-- Documents will be listed here as cards -->
454
+ <div class="text-center py-8 text-gray-500 col-span-full">
455
+ <i class="fas fa-folder-open text-3xl mb-2"></i>
456
+ <p>No documents uploaded yet</p>
 
 
 
 
 
 
 
 
457
  </div>
458
  </div>
459
  </div>
 
462
  </div>
463
 
464
  <script>
465
+ // Set PDF.js worker path
466
+ pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.min.js';
467
+
468
  // Sample data for demonstration
469
+ const sampleNotebooks = [
470
+ {
471
+ id: 1,
472
+ title: 'Work',
473
+ isOpen: true,
474
+ pages: [
475
+ { id: 101, title: 'Project Ideas', content: '1. Personal finance tracker\n2. Recipe organizer app\n3. Travel journal website', lastUpdated: '2023-06-10T14:45:00' },
476
+ { id: 102, title: 'Meeting Notes', content: 'Discussed new features\n- User authentication\n- Dashboard design\n- API endpoints', lastUpdated: '2023-06-12T09:30:00' }
477
+ ],
478
+ documents: []
479
+ },
480
+ {
481
+ id: 2,
482
+ title: 'Personal',
483
+ isOpen: false,
484
+ pages: [
485
+ { id: 201, title: 'Shopping List', content: '- Milk\n- Eggs\n- Bread\n- Fruits\n- Vegetables', lastUpdated: '2023-06-05T09:15:00' },
486
+ { id: 202, title: 'Books to Read', content: '1. Atomic Habits\n2. Deep Work\n3. The Psychology of Money', lastUpdated: '2023-05-28T16:20:00' }
487
+ ],
488
+ documents: []
489
+ }
490
  ];
491
 
492
+ // Sample documents with preview images (in a real app, these would be generated from actual files)
493
  const sampleDocuments = [
494
+ {
495
+ id: 1,
496
+ name: 'Resume.pdf',
497
+ type: 'PDF',
498
+ size: '2.4 MB',
499
+ date: '2023-05-20',
500
+ tags: ['work', 'important'],
501
+ previewUrl: 'https://example.com/previews/resume.jpg', // This would be generated in a real app
502
+ notebookId: null // Track which notebook this document belongs to
503
+ },
504
+ {
505
+ id: 2,
506
+ name: 'Contract.docx',
507
+ type: 'Word',
508
+ size: '1.1 MB',
509
+ date: '2023-04-15',
510
+ tags: ['work', 'finance'],
511
+ previewUrl: null, // No preview for non-PDF files
512
+ notebookId: 1 // Belongs to Work notebook
513
+ },
514
+ {
515
+ id: 3,
516
+ name: 'Budget.xlsx',
517
+ type: 'Excel',
518
+ size: '3.2 MB',
519
+ date: '2023-03-10',
520
+ tags: ['personal', 'finance'],
521
+ previewUrl: null, // No preview for non-PDF files
522
+ notebookId: 2 // Belongs to Personal notebook
523
+ }
524
  ];
525
 
526
  // DOM Elements
 
534
  const notesList = document.getElementById('notesList');
535
  const documentsList = document.getElementById('documentsList');
536
  const newNoteBtn = document.getElementById('newNoteBtn');
537
+ const newNotebookBtn = document.getElementById('newNotebookBtn');
538
  const emptyNewNoteBtn = document.getElementById('emptyNewNoteBtn');
539
  const emptyState = document.getElementById('emptyState');
540
  const noteEditor = document.getElementById('noteEditor');
 
554
  const searchBtn = document.getElementById('searchBtn');
555
  const searchBox = document.getElementById('searchBox');
556
  const lastSaved = document.getElementById('lastSaved');
557
+ const sortDocuments = document.getElementById('sortDocuments');
558
+ const documentSearch = document.getElementById('documentSearch');
559
+ const addTagBtn = document.getElementById('addTagBtn');
560
+ const tagDropdown = document.getElementById('tagDropdown');
561
+ const newTagInput = document.getElementById('newTagInput');
562
+ const saveTagBtn = document.getElementById('saveTagBtn');
563
 
564
  // Current state
565
  let currentNote = null;
566
+ let currentNotebook = null;
567
  let currentView = 'notes'; // 'notes' or 'documents'
568
+ let notebooks = [...sampleNotebooks];
569
  let documents = [...sampleDocuments];
570
  let autoSaveTimer = null;
571
+ let uploadedFiles = {}; // Store uploaded files for download
572
+ let currentSort = 'name-asc';
573
+ let currentTags = [];
574
+ let allTags = ['work', 'personal', 'important', 'finance', 'archive'];
575
+ let editingNotebookId = null;
576
+ let lastActiveNotebook = null; // Track the last active notebook
577
 
578
  // Initialize the app
579
  function initApp() {
 
581
  loginModal.classList.remove('hidden');
582
 
583
  // Populate notes and documents lists
584
+ renderNotebooksList();
585
  renderDocumentsList();
586
 
587
  // Set up event listeners
588
  setupEventListeners();
589
+
590
+ // Initialize Sortable for document grid
591
+ new Sortable(documentsGrid, {
592
+ animation: 150,
593
+ ghostClass: 'sortable-ghost',
594
+ onEnd: function(evt) {
595
+ // Update documents order in our state
596
+ const items = Array.from(documentsGrid.children);
597
+ const newOrder = items.map(item => parseInt(item.querySelector('.download-btn').getAttribute('data-id')));
598
+
599
+ // Reorder documents array
600
+ documents.sort((a, b) => newOrder.indexOf(a.id) - newOrder.indexOf(b.id));
601
+ }
602
+ });
603
  }
604
 
605
  // Set up all event listeners
 
643
  // New note buttons
644
  newNoteBtn.addEventListener('click', createNewNote);
645
  emptyNewNoteBtn.addEventListener('click', createNewNote);
646
+ newNotebookBtn.addEventListener('click', createNewNotebook);
647
 
648
  // Note editor events
649
  noteTitle.addEventListener('input', startAutoSave);
 
659
  dropZone.addEventListener(eventName, preventDefaults, false);
660
  });
661
 
662
+ ['dragenter', 'dragoover'].forEach(eventName => {
663
  dropZone.addEventListener(eventName, highlight, false);
664
  });
665
 
 
679
  searchBox.classList.toggle('hidden');
680
  });
681
 
682
+ // Document sorting
683
+ sortDocuments.addEventListener('change', function() {
684
+ currentSort = this.value;
685
+ renderDocumentsGrid();
686
+ });
687
+
688
+ // Document search
689
+ documentSearch.addEventListener('input', function() {
690
+ renderDocumentsGrid();
691
+ });
692
+
693
+ // Tag management
694
+ addTagBtn.addEventListener('click', function(e) {
695
+ e.stopPropagation();
696
+ tagDropdown.classList.toggle('hidden');
697
+ });
698
+
699
+ document.addEventListener('click', function(e) {
700
+ if (!addTagBtn.contains(e.target) && !tagDropdown.contains(e.target)) {
701
+ tagDropdown.classList.add('hidden');
702
+ }
703
+ });
704
+
705
+ // Tag selection
706
+ tagDropdown.addEventListener('click', function(e) {
707
+ if (e.target.classList.contains('document-tag') && e.target.getAttribute('data-tag')) {
708
+ const tag = e.target.getAttribute('data-tag');
709
+ if (!currentTags.includes(tag)) {
710
+ currentTags.push(tag);
711
+ renderDocumentsGrid();
712
+ }
713
+ }
714
+ });
715
+
716
+ // Add new tag
717
+ saveTagBtn.addEventListener('click', function() {
718
+ const newTag = newTagInput.value.trim().toLowerCase();
719
+ if (newTag && !allTags.includes(newTag)) {
720
+ allTags.push(newTag);
721
+ newTagInput.value = '';
722
+ renderTagDropdown();
723
+ }
724
+ });
725
+
726
  // Close menus when clicking elsewhere
727
  document.addEventListener('click', function(e) {
728
  if (!userMenuBtn.contains(e.target) && !userMenu.contains(e.target)) {
 
766
  // For demo, we'll just add them to our documents array
767
  Array.from(files).forEach(file => {
768
  const newDoc = {
769
+ id: Date.now(), // Use timestamp as unique ID
770
  name: file.name,
771
+ type: file.type || getFileType(file.name),
772
  size: formatFileSize(file.size),
773
+ date: new Date().toISOString().split('T')[0],
774
+ tags: currentTags.length > 0 ? [...currentTags] : [],
775
+ previewUrl: null,
776
+ file: file, // Store the actual file for download
777
+ notebookId: null // Initially not in any notebook
778
  };
779
+
780
+ // Store the file for download
781
+ uploadedFiles[newDoc.id] = file;
782
+
783
+ // Generate preview for PDF files
784
+ if (file.type === 'application/pdf') {
785
+ generatePdfPreview(file).then(previewUrl => {
786
+ newDoc.previewUrl = previewUrl;
787
+ renderDocumentsGrid();
788
  });
789
+ }
790
+
791
+ documents.unshift(newDoc);
792
+ currentTags = []; // Reset current tags after upload
793
+ });
794
+
795
+ renderDocumentsList();
796
+ renderDocumentsGrid();
797
+
798
+ // Show success message
799
+ alert(`${files.length} file(s) uploaded successfully!`);
800
+ }
801
+ }
802
+
803
+ // Get file type from extension
804
+ function getFileType(filename) {
805
+ const extension = filename.split('.').pop().toLowerCase();
806
+ const types = {
807
+ 'pdf': 'PDF',
808
+ 'doc': 'Word',
809
+ 'docx': 'Word',
810
+ 'xls': 'Excel',
811
+ 'xlsx': 'Excel',
812
+ 'jpg': 'Image',
813
+ 'jpeg': 'Image',
814
+ 'png': 'Image',
815
+ 'gif': 'Image'
816
+ };
817
+ return types[extension] || 'File';
818
+ }
819
+
820
+ // Generate PDF preview
821
+ async function generatePdfPreview(file) {
822
+ return new Promise((resolve) => {
823
+ const reader = new FileReader();
824
+ reader.onload = async function(e) {
825
+ try {
826
+ const typedArray = new Uint8Array(e.target.result);
827
+ const pdf = await pdfjsLib.getDocument(typedArray).promise;
828
+ const page = await pdf.getPage(1);
829
 
830
+ const viewport = page.getViewport({ scale: 0.5 });
831
+ const canvas = document.createElement('canvas');
832
+ const context = canvas.getContext('2d');
833
+ canvas.height = viewport.height;
834
+ canvas.width = viewport.width;
835
+
836
+ await page.render({
837
+ canvasContext: context,
838
+ viewport: viewport
839
+ }).promise;
840
 
841
+ resolve(canvas.toDataURL('image/jpeg'));
842
+ } catch (error) {
843
+ console.error('Error generating PDF preview:', error);
844
+ resolve(null);
845
  }
846
+ };
847
+ reader.readAsArrayBuffer(file);
848
+ });
849
+ }
850
+
851
+ // Format file size
852
+ function formatFileSize(bytes) {
853
+ if (bytes === 0) return '0 Bytes';
854
+ const k = 1024;
855
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
856
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
857
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
858
+ }
859
+
860
+ // Create a new note
861
+ function createNewNote() {
862
+ // Determine which notebook to add to
863
+ let targetNotebook = null;
864
+
865
+ // If we have a current notebook, use that
866
+ if (currentNotebook) {
867
+ targetNotebook = notebooks.find(nb => nb.id === currentNotebook);
868
+ }
869
+ // Otherwise use the last active notebook
870
+ else if (lastActiveNotebook) {
871
+ targetNotebook = notebooks.find(nb => nb.id === lastActiveNotebook);
872
+ }
873
+ // Otherwise create a new notebook
874
+ else if (notebooks.length > 0) {
875
+ targetNotebook = notebooks[0]; // Default to first notebook
876
+ } else {
877
+ // No notebooks exist, create one
878
+ const newNotebook = {
879
+ id: Date.now() + 1,
880
+ title: 'New Notebook',
881
+ isOpen: true,
882
+ pages: [],
883
+ documents: []
884
+ };
885
+ notebooks.unshift(newNotebook);
886
+ targetNotebook = newNotebook;
887
+ }
888
+
889
+ const newNote = {
890
+ id: Date.now(), // Use timestamp as unique ID
891
+ title: 'Untitled Note',
892
+ content: '',
893
+ lastUpdated: new Date().toISOString()
894
+ };
895
+
896
+ if (targetNotebook) {
897
+ targetNotebook.pages.unshift(newNote);
898
+ lastActiveNotebook = targetNotebook.id; // Update last active notebook
899
 
900
+ // Make sure notebook is open
901
+ targetNotebook.isOpen = true;
 
 
 
 
 
 
902
 
903
+ renderNotebooksList();
904
+ openNote(newNote.id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
905
 
906
+ // Focus on title field
907
+ setTimeout(() => {
908
+ noteTitle.focus();
909
+ }, 100);
910
+ }
911
+ }
912
+
913
+ // Create a new notebook
914
+ function createNewNotebook() {
915
+ const newNotebook = {
916
+ id: Date.now(),
917
+ title: 'New Notebook',
918
+ isOpen: true,
919
+ pages: [],
920
+ documents: []
921
+ };
922
+
923
+ notebooks.unshift(newNotebook);
924
+ renderNotebooksList();
925
+
926
+ // Start editing the notebook name immediately
927
+ startEditingNotebookName(newNotebook.id);
928
+ }
929
+
930
+ // Start editing notebook name
931
+ function startEditingNotebookName(notebookId) {
932
+ editingNotebookId = notebookId;
933
+ renderNotebooksList();
934
+
935
+ // Focus on the input field
936
+ setTimeout(() => {
937
+ const input = document.querySelector(`.notebook-header[data-id="${notebookId}"] .edit-notebook-input`);
938
+ if (input) {
939
+ input.focus();
940
+ input.select();
941
  }
942
+ }, 100);
943
+ }
944
+
945
+ // Save notebook name
946
+ function saveNotebookName(notebookId, newName) {
947
+ const notebook = notebooks.find(nb => nb.id === notebookId);
948
+ if (notebook && newName.trim()) {
949
+ notebook.title = newName.trim();
950
+ editingNotebookId = null;
951
+ renderNotebooksList();
952
+ }
953
+ }
954
+
955
+ // Open a note by ID
956
+ function openNote(noteId) {
957
+ // Find the note in any notebook
958
+ for (const notebook of notebooks) {
959
+ const note = notebook.pages.find(page => page.id === noteId);
960
+ if (note) {
961
+ currentNote = note;
962
+ currentNotebook = notebook.id;
963
+ lastActiveNotebook = notebook.id; // Update last active notebook
964
+
965
+ // Open the notebook if it's closed
966
+ if (!notebook.isOpen) {
967
+ notebook.isOpen = true;
968
+ renderNotebooksList();
969
  }
970
 
971
+ emptyState.classList.add('hidden');
972
+ noteEditor.classList.remove('hidden');
973
+ documentsView.classList.add('hidden');
974
+ currentView = 'notes';
975
+
976
+ noteTitle.value = currentNote.title;
977
+ noteContent.innerHTML = currentNote.content.replace(/\n/g, '<br>');
978
+ lastSaved.textContent = formatDate(currentNote.lastUpdated);
979
+ return;
980
  }
981
+ }
982
+ }
983
+
984
+ // Toggle notebook open/closed
985
+ function toggleNotebook(notebookId) {
986
+ const notebook = notebooks.find(nb => nb.id === notebookId);
987
+ if (notebook && editingNotebookId !== notebookId) {
988
+ notebook.isOpen = !notebook.isOpen;
989
+ lastActiveNotebook = notebookId; // Update last active notebook
990
+ renderNotebooksList();
991
+ }
992
+ }
993
+
994
+ // Start auto-save timer
995
+ function startAutoSave() {
996
+ if (autoSaveTimer) {
997
+ clearTimeout(autoSaveTimer);
998
+ }
999
+
1000
+ autoSaveTimer = setTimeout(() => {
1001
+ saveCurrentNote();
1002
+ }, 2000);
1003
+ }
1004
+
1005
+ // Save current note
1006
+ function saveCurrentNote() {
1007
+ if (currentNote) {
1008
+ currentNote.title = noteTitle.value;
1009
+ currentNote.content = noteContent.innerHTML.replace(/<br>/g, '\n');
1010
+ currentNote.lastUpdated = new Date().toISOString();
1011
+
1012
+ // Update last saved time
1013
+ lastSaved.textContent = 'Just now';
1014
 
1015
+ // Update the note in the sidebar list
1016
+ renderNotebooksList();
1017
+ }
1018
+ }
1019
+
1020
+ // Delete current note
1021
+ function deleteCurrentNote() {
1022
+ if (currentNote && confirm('Are you sure you want to delete this note?')) {
1023
+ // Find and remove the note from its notebook
1024
+ for (const notebook of notebooks) {
1025
+ const noteIndex = notebook.pages.findIndex(page => page.id === currentNote.id);
1026
+ if (noteIndex !== -1) {
1027
+ notebook.pages.splice(noteIndex, 1);
1028
 
1029
+ // If notebook is now empty, delete it too
1030
+ if (notebook.pages.length === 0 && notebook.documents.length === 0) {
1031
+ const notebookIndex = notebooks.findIndex(nb => nb.id === notebook.id);
1032
+ if (notebookIndex !== -1) {
1033
+ notebooks.splice(notebookIndex, 1);
1034
+ }
1035
+ }
1036
 
1037
+ renderNotebooksList();
 
 
 
 
 
 
 
 
 
1038
  closeNoteEditor();
1039
+ return;
1040
  }
1041
  }
1042
+ }
1043
+ }
1044
+
1045
+ // Close note editor
1046
+ function closeNoteEditor() {
1047
+ emptyState.classList.remove('hidden');
1048
+ noteEditor.classList.add('hidden');
1049
+ currentNote = null;
1050
+ currentNotebook = null;
1051
+ }
1052
+
1053
+ // Render notebooks and notes in sidebar
1054
+ function renderNotebooksList() {
1055
+ notesList.innerHTML = '';
1056
+
1057
+ if (notebooks.length === 0) {
1058
+ notesList.innerHTML = `
1059
+ <li class="text-gray-400 text-sm px-3 py-2">
1060
+ No notebooks yet. Create one to get started.
1061
+ </li>
1062
+ `;
1063
+ return;
1064
+ }
1065
+
1066
+ notebooks.forEach(notebook => {
1067
+ const notebookItem = document.createElement('li');
1068
+ notebookItem.className = 'notebook';
1069
 
1070
+ // Notebook header
1071
+ const notebookHeader = document.createElement('div');
1072
+ notebookHeader.className = `notebook-header flex items-center justify-between px-2 py-1 rounded-md ${notebook.id === lastActiveNotebook ? 'active-notebook' : ''}`;
1073
+ notebookHeader.setAttribute('data-id', notebook.id);
 
 
1074
 
1075
+ if (editingNotebookId === notebook.id) {
1076
+ notebookHeader.innerHTML = `
1077
+ <div class="flex items-center w-full">
1078
+ <i class="fas fa-folder-open text-yellow-400 mr-2"></i>
1079
+ <input type="text" value="${notebook.title}"
1080
+ class="edit-notebook-input"
1081
+ onblur="saveNotebookName(${notebook.id}, this.value)"
1082
+ onkeydown="if(event.key === 'Enter') { this.blur(); }">
1083
+ </div>
1084
+ `;
1085
+ } else {
1086
+ notebookHeader.innerHTML = `
1087
+ <div class="flex items-center">
1088
+ <i class="fas ${notebook.isOpen ? 'fa-folder-open' : 'fa-folder'} text-yellow-400 mr-2"></i>
1089
+ <span class="truncate">${notebook.title}</span>
1090
+ </div>
1091
+ <div class="flex items-center">
1092
+ <span class="text-xs text-gray-400 mr-2">${notebook.pages.length + notebook.documents.length}</span>
1093
+ <i class="fas fa-chevron-${notebook.isOpen ? 'down' : 'right'} text-xs text-gray-400"></i>
1094
+ </div>
1095
+ `;
1096
+
1097
+ // Add double click to edit notebook name
1098
+ notebookHeader.addEventListener('dblclick', (e) => {
1099
+ if (!e.target.classList.contains('fa-ellipsis-v')) {
1100
+ startEditingNotebookName(notebook.id);
1101
+ }
1102
  });
1103
  }
1104
 
1105
+ notebookHeader.addEventListener('click', () => toggleNotebook(notebook.id));
1106
+
1107
+ notebookItem.appendChild(notebookHeader);
1108
+
1109
+ // Notebook pages (notes) and documents
1110
+ if (notebook.isOpen) {
1111
+ const contentList = document.createElement('ul');
1112
+ contentList.className = 'mt-1';
1113
+
1114
+ // Make notebook content sortable
1115
+ new Sortable(contentList, {
1116
+ animation: 150,
1117
+ ghostClass: 'sortable-ghost',
1118
+ handle: '.drag-handle',
1119
+ onEnd: function(evt) {
1120
+ // Update order in our state
1121
+ const items = Array.from(contentList.children);
1122
+
1123
+ // Separate notes and documents
1124
+ const newNoteOrder = [];
1125
+ const newDocOrder = [];
1126
+
1127
+ items.forEach(item => {
1128
+ const id = parseInt(item.getAttribute('data-id'));
1129
+ if (item.classList.contains('note-page')) {
1130
+ newNoteOrder.push(id);
1131
+ } else if (item.classList.contains('document-in-notebook')) {
1132
+ newDocOrder.push(id);
1133
+ }
1134
+ });
1135
+
1136
+ // Reorder notebook pages array
1137
+ notebook.pages.sort((a, b) => newNoteOrder.indexOf(a.id) - newNoteOrder.indexOf(b.id));
1138
+
1139
+ // Reorder notebook documents array
1140
+ notebook.documents.sort((a, b) => newDocOrder.indexOf(a.id) - newDocOrder.indexOf(b.id));
1141
+ }
1142
+ });
1143
+
1144
+ // Add drop zones between items
1145
+ function addDropZone(container, position) {
1146
+ const dropZone = document.createElement('li');
1147
+ dropZone.className = 'document-dropzone';
1148
+ dropZone.setAttribute('data-dropzone', position);
1149
+
1150
+ dropZone.addEventListener('dragover', (e) => {
1151
+ e.preventDefault();
1152
+ dropZone.classList.add('active');
1153
+ });
1154
+
1155
+ dropZone.addEventListener('dragleave', () => {
1156
+ dropZone.classList.remove('active');
1157
+ });
1158
+
1159
+ dropZone.addEventListener('drop', (e) => {
1160
+ e.preventDefault();
1161
+ dropZone.classList.remove('active');
1162
+
1163
+ const docId = e.dataTransfer.getData('text/plain');
1164
+ if (docId) {
1165
+ moveDocumentToNotebook(parseInt(docId), notebook.id, position);
1166
+ }
1167
+ });
1168
+
1169
+ container.appendChild(dropZone);
1170
+ }
1171
+
1172
+ // Initial drop zone at top
1173
+ addDropZone(contentList, 'top');
1174
+
1175
+ // Add notes
1176
+ notebook.pages.forEach(page => {
1177
+ const pageItem = document.createElement('li');
1178
+ pageItem.className = 'note-page flex items-center px-2 py-1 rounded-md';
1179
+ pageItem.setAttribute('data-id', page.id);
1180
+ pageItem.innerHTML = `
1181
+ <i class="fas fa-grip-lines drag-handle mr-2"></i>
1182
+ <i class="fas fa-file-alt text-blue-400 mr-2"></i>
1183
+ <span class="truncate flex-1">${page.title}</span>
1184
+ <span class="text-xs text-gray-400">${formatDate(page.lastUpdated)}</span>
1185
+ `;
1186
+
1187
+ // Add drag and drop events for linking documents
1188
+ pageItem.addEventListener('dragover', (e) => {
1189
+ e.preventDefault();
1190
+ pageItem.classList.add('drag-over');
1191
+ });
1192
+
1193
+ pageItem.addEventListener('dragleave', () => {
1194
+ pageItem.classList.remove('drag-over');
1195
+ });
1196
+
1197
+ pageItem.addEventListener('drop', (e) => {
1198
+ e.preventDefault();
1199
+ pageItem.classList.remove('drag-over');
1200
+
1201
+ const docId = e.dataTransfer.getData('text/plain');
1202
+ if (docId) {
1203
+ linkDocumentToNote(parseInt(docId), page.id);
1204
+ }
1205
+ });
1206
+
1207
+ pageItem.addEventListener('click', (e) => {
1208
+ // Don't open note if clicking on drag handle
1209
+ if (!e.target.classList.contains('drag-handle') && !e.target.classList.contains('fa-grip-lines')) {
1210
+ openNote(page.id);
1211
+ }
1212
+ });
1213
+
1214
+ // Make draggable
1215
+ pageItem.draggable = true;
1216
+ pageItem.addEventListener('dragstart', (e) => {
1217
+ e.dataTransfer.setData('text/plain', page.id);
1218
+ e.dataTransfer.effectAllowed = 'move';
1219
+ });
1220
+
1221
+ contentList.appendChild(pageItem);
1222
+
1223
+ // Add drop zone after each note
1224
+ addDropZone(contentList, page.id);
1225
+ });
1226
 
1227
+ // Add documents
1228
+ notebook.documents.forEach(doc => {
1229
  const docItem = document.createElement('li');
1230
+ docItem.className = 'document-in-notebook flex items-center px-2 py-1 rounded-md';
1231
+ docItem.setAttribute('data-id', doc.id);
1232
  docItem.innerHTML = `
1233
+ <i class="fas fa-grip-lines drag-handle mr-2"></i>
1234
+ <i class="fas ${getFileIcon(doc.type)} text-blue-400 mr-2"></i>
1235
+ <span class="truncate flex-1">${doc.name}</span>
1236
+ <button class="remove-doc-btn text-red-500 hover:text-red-700 text-xs">
1237
+ <i class="fas fa-times"></i>
1238
+ </button>
1239
  `;
1240
+
1241
+ // Make draggable
1242
+ docItem.draggable = true;
1243
+ docItem.addEventListener('dragstart', (e) => {
1244
+ e.dataTransfer.setData('text/plain', doc.id);
1245
+ e.dataTransfer.effectAllowed = 'move';
1246
+ });
1247
+
1248
+ // Add click to open document
1249
+ docItem.addEventListener('click', (e) => {
1250
+ if (!e.target.classList.contains('remove-doc-btn') &&
1251
+ !e.target.classList.contains('fa-times') &&
1252
+ !e.target.classList.contains('drag-handle') &&
1253
+ !e.target.classList.contains('fa-grip-lines')) {
1254
+ showDocumentsView();
1255
+ }
1256
+ });
1257
+
1258
+ // Add remove button
1259
+ const removeBtn = docItem.querySelector('.remove-doc-btn');
1260
+ removeBtn.addEventListener('click', (e) => {
1261
+ e.stopPropagation();
1262
+ removeDocumentFromNotebook(doc.id, notebook.id);
1263
+ });
1264
+
1265
+ contentList.appendChild(docItem);
1266
+
1267
+ // Add drop zone after each document
1268
+ addDropZone(contentList, doc.id);
1269
  });
1270
 
1271
+ notebookItem.appendChild(contentList);
1272
+ }
1273
+
1274
+ notesList.appendChild(notebookItem);
1275
+ });
1276
+ }
1277
+
1278
+ // Link document to note (create a reference/link)
1279
+ function linkDocumentToNote(docId, noteId) {
1280
+ const doc = documents.find(d => d.id === docId);
1281
+ if (!doc) return;
1282
+
1283
+ const note = findNoteById(noteId);
1284
+ if (!note) return;
1285
+
1286
+ // In a real app, you would create a proper link/reference
1287
+ // For demo, we'll just add a link to the note content
1288
+ const docLink = `[${doc.name}](${docId})`;
1289
+
1290
+ // If note is currently open, update the editor
1291
+ if (currentNote && currentNote.id === noteId) {
1292
+ noteContent.innerHTML += `<p>${docLink}</p>`;
1293
+ saveCurrentNote();
1294
+ } else {
1295
+ // Otherwise update the note content directly
1296
+ note.content += `\n${docLink}`;
1297
+ note.lastUpdated = new Date().toISOString();
1298
+ renderNotebooksList();
1299
+ }
1300
+
1301
+ alert(`Document "${doc.name}" linked to note "${note.title}"`);
1302
+ }
1303
+
1304
+ // Find note by ID
1305
+ function findNoteById(noteId) {
1306
+ for (const notebook of notebooks) {
1307
+ const note = notebook.pages.find(page => page.id === noteId);
1308
+ if (note) return note;
1309
+ }
1310
+ return null;
1311
+ }
1312
+
1313
+ // Move document to notebook at specific position
1314
+ function moveDocumentToNotebook(docId, notebookId, position) {
1315
+ // Find the document
1316
+ const doc = documents.find(d => d.id === docId);
1317
+ if (!doc) return;
1318
+
1319
+ // Remove from current notebook if it's in one
1320
+ if (doc.notebookId) {
1321
+ const currentNotebook = notebooks.find(nb => nb.id === doc.notebookId);
1322
+ if (currentNotebook) {
1323
+ const docIndex = currentNotebook.documents.findIndex(d => d.id === docId);
1324
+ if (docIndex !== -1) {
1325
+ currentNotebook.documents.splice(docIndex, 1);
1326
  }
1327
  }
1328
+ }
1329
+
1330
+ // Add to new notebook
1331
+ const notebook = notebooks.find(nb => nb.id === notebookId);
1332
+ if (notebook) {
1333
+ // Update document's notebook reference
1334
+ doc.notebookId = notebookId;
1335
 
1336
+ // Find position to insert
1337
+ if (position === 'top') {
1338
+ notebook.documents.unshift(doc);
1339
+ } else {
1340
+ // Find the item (note or document) with this ID
1341
+ const itemIndex = notebook.pages.findIndex(p => p.id === position);
1342
+ if (itemIndex !== -1) {
1343
+ // Insert after this note
1344
+ notebook.documents.splice(itemIndex + 1, 0, doc);
1345
+ } else {
1346
+ // Maybe it's after a document
1347
+ const docIndex = notebook.documents.findIndex(d => d.id === position);
1348
+ if (docIndex !== -1) {
1349
+ notebook.documents.splice(docIndex + 1, 0, doc);
1350
+ } else {
1351
+ // Default to adding at the end
1352
+ notebook.documents.push(doc);
1353
+ }
1354
+ }
1355
  }
1356
 
1357
+ renderNotebooksList();
1358
+ renderDocumentsGrid();
1359
+ }
1360
+ }
1361
+
1362
+ // Remove document from notebook
1363
+ function removeDocumentFromNotebook(docId, notebookId) {
1364
+ const notebook = notebooks.find(nb => nb.id === notebookId);
1365
+ if (notebook) {
1366
+ const docIndex = notebook.documents.findIndex(d => d.id === docId);
1367
+ if (docIndex !== -1) {
1368
+ notebook.documents.splice(docIndex, 1);
1369
+
1370
+ // Update document's notebook reference
1371
+ const doc = documents.find(d => d.id === docId);
1372
+ if (doc) {
1373
+ doc.notebookId = null;
1374
  }
1375
 
1376
+ renderNotebooksList();
1377
+ renderDocumentsGrid();
 
 
 
 
 
 
 
 
 
 
 
 
1378
  }
1379
+ }
1380
+ }
1381
+
1382
+ // Render documents list in sidebar
1383
+ function renderDocumentsList() {
1384
+ documentsList.innerHTML = '';
1385
+
1386
+ documents.slice(0, 3).forEach(doc => {
1387
+ const docItem = document.createElement('li');
1388
+ docItem.className = 'bg-gray-700 hover:bg-gray-600 rounded-md px-3 py-2 cursor-pointer';
1389
+ docItem.innerHTML = `
1390
+ <div class="flex items-center space-x-2">
1391
+ <i class="fas ${getFileIcon(doc.type)} text-blue-400"></i>
1392
+ <span class="truncate">${doc.name}</span>
1393
+ </div>
1394
+ `;
1395
+ docItem.addEventListener('click', () => showDocumentsView());
1396
+ documentsList.appendChild(docItem);
1397
+ });
1398
+
1399
+ if (documents.length > 3) {
1400
+ const moreItem = document.createElement('li');
1401
+ moreItem.className = 'text-gray-400 text-sm px-3 py-1';
1402
+ moreItem.textContent = `+${documents.length - 3} more...`;
1403
+ moreItem.addEventListener('click', () => showDocumentsView());
1404
+ documentsList.appendChild(moreItem);
1405
+ }
1406
+ }
1407
+
1408
+ // Get appropriate file icon
1409
+ function getFileIcon(fileType) {
1410
+ const icons = {
1411
+ 'PDF': 'fa-file-pdf',
1412
+ 'Word': 'fa-file-word',
1413
+ 'Excel': 'fa-file-excel',
1414
+ 'Image': 'fa-file-image'
1415
+ };
1416
+ return icons[fileType] || 'fa-file';
1417
+ }
1418
+
1419
+ // Show documents view
1420
+ function showDocumentsView() {
1421
+ emptyState.classList.add('hidden');
1422
+ noteEditor.classList.add('hidden');
1423
+ documentsView.classList.remove('hidden');
1424
+ currentView = 'documents';
1425
+ renderDocumentsGrid();
1426
+ }
1427
+
1428
+ // Sort documents based on current sort option
1429
+ function sortDocumentsList(docs) {
1430
+ const searchTerm = documentSearch.value.toLowerCase();
1431
+
1432
+ // Filter by search term if provided
1433
+ let filteredDocs = docs;
1434
+ if (searchTerm) {
1435
+ filteredDocs = docs.filter(doc =>
1436
+ doc.name.toLowerCase().includes(searchTerm) ||
1437
+ (doc.tags && doc.tags.some(tag => tag.includes(searchTerm)))
1438
+ );
1439
+ }
1440
+
1441
+ // Filter by tags if any are selected
1442
+ if (currentTags.length > 0) {
1443
+ filteredDocs = filteredDocs.filter(doc =>
1444
+ doc.tags && currentTags.every(tag => doc.tags.includes(tag))
1445
+ );
1446
+ }
1447
+
1448
+ // Apply sorting
1449
+ return filteredDocs.sort((a, b) => {
1450
+ switch (currentSort) {
1451
+ case 'name-asc':
1452
+ return a.name.localeCompare(b.name);
1453
+ case 'name-desc':
1454
+ return b.name.localeCompare(a.name);
1455
+ case 'date-new':
1456
+ return new Date(b.date) - new Date(a.date);
1457
+ case 'date-old':
1458
+ return new Date(a.date) - new Date(b.date);
1459
+ case 'size-large':
1460
+ return parseFloat(b.size) - parseFloat(a.size);
1461
+ case 'size-small':
1462
+ return parseFloat(a.size) - parseFloat(b.size);
1463
+ default:
1464
+ return 0;
1465
+ }
1466
+ });
1467
+ }
1468
+
1469
+ // Render documents grid as cards with previews
1470
+ function renderDocumentsGrid() {
1471
+ documentsGrid.innerHTML = '';
1472
+
1473
+ const sortedDocuments = sortDocumentsList(documents);
1474
+
1475
+ if (sortedDocuments.length === 0) {
1476
+ documentsGrid.innerHTML = `
1477
+ <div class="text-center py-8 text-gray-500 col-span-full">
1478
+ <i class="fas fa-folder-open text-3xl mb-2"></i>
1479
+ <p>No documents found</p>
1480
+ </div>
1481
+ `;
1482
+ return;
1483
+ }
1484
+
1485
+ sortedDocuments.forEach(doc => {
1486
+ const docCard = document.createElement('div');
1487
+ docCard.className = `document-card ${doc.notebookId ? 'border-2 border-blue-400' : ''}`;
1488
+ docCard.setAttribute('draggable', 'true');
1489
+ docCard.setAttribute('data-id', doc.id);
1490
 
1491
+ // Preview section
1492
+ let previewContent = '';
1493
+ if (doc.previewUrl) {
1494
+ previewContent = `<img src="${doc.previewUrl}" alt="${doc.name} preview" class="w-full h-full object-cover">`;
1495
+ } else {
1496
+ const icon = getFileIcon(doc.type);
1497
+ previewContent = `
1498
+ <div class="flex flex-col items-center justify-center h-full">
1499
+ <i class="fas ${icon} text-4xl text-gray-500"></i>
1500
+ <p class="mt-2 text-sm text-gray-500">No preview available</p>
1501
+ </div>
1502
+ `;
1503
+ }
1504
+
1505
+ // Tags section
1506
+ let tagsContent = '';
1507
+ if (doc.tags && doc.tags.length > 0) {
1508
+ tagsContent = `
1509
+ <div class="document-tags">
1510
+ ${doc.tags.map(tag => `<span class="document-tag">${tag}</span>`).join('')}
1511
+ </div>
1512
+ `;
1513
+ }
1514
+
1515
+ // Notebook info if in a notebook
1516
+ let notebookInfo = '';
1517
+ if (doc.notebookId) {
1518
+ const notebook = notebooks.find(nb => nb.id === doc.notebookId);
1519
+ if (notebook) {
1520
+ notebookInfo = `
1521
+ <div class="flex items-center text-xs text-blue-600 mt-1">
1522
+ <i class="fas fa-folder mr-1"></i>
1523
+ <span class="truncate">${notebook.title}</span>
1524
+ </div>
1525
+ `;
1526
  }
1527
  }
1528
 
1529
+ docCard.innerHTML = `
1530
+ <div class="document-preview">
1531
+ ${previewContent}
1532
+ <div class="preview-text">${doc.name}</div>
1533
+ </div>
1534
+ <div class="document-info">
1535
+ <h3 class="font-medium truncate">${doc.name}</h3>
1536
+ <div class="flex justify-between text-sm text-gray-500 mt-1">
1537
+ <span>${doc.type}</span>
1538
+ <span>${doc.size}</span>
1539
+ </div>
1540
+ ${notebookInfo}
1541
+ ${tagsContent}
1542
+ </div>
1543
+ <div class="document-actions">
1544
+ <span class="text-xs text-gray-500">${doc.date}</span>
1545
+ <div class="flex space-x-2">
1546
+ <button class="delete-doc-btn text-red-600 hover:text-red-800" data-id="${doc.id}">
1547
+ <i class="fas fa-trash"></i>
1548
+ </button>
1549
+ <button class="download-btn text-blue-600 hover:text-blue-800" data-id="${doc.id}">
1550
+ <i class="fas fa-download"></i>
1551
+ </button>
1552
+ </div>
1553
+ </div>
1554
+ `;
1555
+
1556
+ // Add drag events
1557
+ docCard.addEventListener('dragstart', (e) => {
1558
+ e.dataTransfer.setData('text/plain', doc.id);
1559
+ e.dataTransfer.effectAllowed = 'move';
1560
+ });
1561
+
1562
+ documentsGrid.appendChild(docCard);
1563
+ });
1564
+
1565
+ // Add event listeners to download buttons
1566
+ document.querySelectorAll('.download-btn').forEach(btn => {
1567
+ btn.addEventListener('click', (e) => {
1568
+ e.stopPropagation();
1569
+ const docId = parseInt(btn.getAttribute('data-id'));
1570
+ downloadDocument(docId);
1571
+ });
1572
+ });
1573
+
1574
+ // Add event listeners to delete buttons
1575
+ document.querySelectorAll('.delete-doc-btn').forEach(btn => {
1576
+ btn.addEventListener('click', (e) => {
1577
+ e.stopPropagation();
1578
+ const docId = parseInt(btn.getAttribute('data-id'));
1579
+ deleteDocument(docId);
1580
+ });
1581
+ });
1582
+ }
1583
+
1584
+ // Render tag dropdown
1585
+ function renderTagDropdown() {
1586
+ const tagContainer = tagDropdown.querySelector('.flex-wrap');
1587
+ tagContainer.innerHTML = '';
1588
+
1589
+ allTags.forEach(tag => {
1590
+ const tagElement = document.createElement('span');
1591
+ tagElement.className = 'document-tag cursor-pointer';
1592
+ tagElement.setAttribute('data-tag', tag);
1593
+ tagElement.textContent = tag;
1594
+ tagContainer.appendChild(tagElement);
1595
+ });
1596
+ }
1597
+
1598
+ // Download document
1599
+ function downloadDocument(docId) {
1600
+ const doc = documents.find(d => d.id === docId);
1601
+ if (!doc) return;
1602
+
1603
+ // Check if we have the actual file (for uploaded files)
1604
+ if (uploadedFiles[docId]) {
1605
+ const file = uploadedFiles[docId];
1606
+ const url = URL.createObjectURL(file);
1607
+ const a = document.createElement('a');
1608
+ a.href = url;
1609
+ a.download = file.name;
1610
+ document.body.appendChild(a);
1611
+ a.click();
1612
+ document.body.removeChild(a);
1613
+ URL.revokeObjectURL(url);
1614
+ } else {
1615
+ // For demo files, we can't actually download them
1616
+ alert(`Downloading ${doc.name}`);
1617
+ }
1618
+ }
1619
+
1620
+ // Delete document
1621
+ function deleteDocument(docId) {
1622
+ if (confirm('Are you sure you want to delete this document?')) {
1623
+ // Remove from documents array
1624
+ documents = documents.filter(doc => doc.id !== docId);
1625
+
1626
+ // Remove from any notebook it might be in
1627
+ notebooks.forEach(notebook => {
1628
+ notebook.documents = notebook.documents.filter(doc => doc.id !== docId);
1629
+ });
1630
+
1631
+ // Remove from uploaded files if it exists there
1632
+ if (uploadedFiles[docId]) {
1633
+ delete uploadedFiles[docId];
1634
  }
1635
 
1636
+ renderDocumentsList();
1637
+ renderDocumentsGrid();
1638
+ renderNotebooksList();
1639
+ }
1640
+ }
1641
+
1642
+ // Format date for display
1643
+ function formatDate(dateString) {
1644
+ const date = new Date(dateString);
1645
+ const now = new Date();
1646
+ const diffInDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));
1647
+
1648
+ if (diffInDays === 0) {
1649
+ return 'Today';
1650
+ } else if (diffInDays === 1) {
1651
+ return 'Yesterday';
1652
+ } else if (diffInDays < 7) {
1653
+ return `${diffInDays} days ago`;
1654
+ } else {
1655
+ return date.toLocaleDateString();
1656
+ }
1657
+ }
1658
+
1659
+ // Reset app state
1660
+ function resetAppState() {
1661
+ currentNote = null;
1662
+ currentNotebook = null;
1663
+ emptyState.classList.remove('hidden');
1664
+ noteEditor.classList.add('hidden');
1665
+ documentsView.classList.add('hidden');
1666
+ }
1667
+
1668
+ // Initialize the app when the page loads
1669
+ window.addEventListener('DOMContentLoaded', initApp);
1670
+
1671
+ // Global functions for inline event handlers
1672
+ window.saveNotebookName = saveNotebookName;
1673
  </script>
1674
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=lwmecham/useful-space" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1675
  </html>
prompts.txt CHANGED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Make a preview of the uploaded documents first page. And add a download button to retrive the documents later.
2
+ Create a way to sort and organize documents that are uploaded. Also create a way to delete uploaded documets. In the "MY NOTES" section create a hiarical structure so note pages are held in note books in the hierach and that note pages order can be changed by the user.
3
+ Add a way for the user to edit the notebook names. Add a way to drag and drop the uploaded documents into the Notebook between the note pages as selected by the user.
4
+ Make a button like called "+ New Notebook" similar to "+ New Note" to add the notebooks instead of using the "+" button. When the "+ New Note" button is clicked it should add a notebook page to the active (most recently selected) notebook. I want to be able to move the uploaded documents from the documents list up into the notebook for easy referance and selection within the notebook. I want to be able to select where the document appears in a selected notebook. Add a slider bar to the left directory so I can scroll when the directory gets long.
5
+ Make the "+ New Notebook" button apear the same color and above the "+ New Note" button. Add a sroll bar on the left side ribbon to scroll up and down onthe "MY NOTES" and "DOCUMENTS" directory. Allow the user to drag the uploaded file over a note page and drop it. The action should be a link that opens the uploaded file.
6
+ Please add a scroll bar to the "MY NOTES" and "DOCUMENTS" left side directory.