app / index.html
sumitjangir's picture
Add 3 files
cb2f81c verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Note Taking App</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.note-content {
min-height: 200px;
border: 1px solid #e2e8f0;
padding: 1rem;
border-radius: 0.5rem;
outline: none;
}
.dark .note-content {
background-color: #1e293b;
border-color: #475569;
color: #f8fafc;
}
.dark .note-content:focus {
border-color: #60a5fa;
}
.ql-toolbar.ql-snow {
border-radius: 0.5rem 0.5rem 0 0;
}
.ql-container.ql-snow {
border-radius: 0 0 0.5rem 0.5rem;
min-height: 200px;
}
.dark .ql-toolbar.ql-snow {
background-color: #1e293b;
border-color: #475569;
}
.dark .ql-container.ql-snow {
background-color: #1e293b;
border-color: #475569;
color: #f8fafc;
}
.dark .ql-editor {
color: #f8fafc;
}
.tag {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.tag-remove {
margin-left: 0.25rem;
cursor: pointer;
}
.transition-all {
transition: all 0.3s ease;
}
.note-card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.note-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.dark .note-card:hover {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
}
</style>
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
</head>
<body class="bg-gray-50 dark:bg-gray-900 transition-all">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 dark:text-white">
<i class="fas fa-book mr-2"></i> Notes App
</h1>
<div class="flex items-center space-x-4">
<button id="theme-toggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200">
<i class="fas fa-moon dark:hidden"></i>
<i class="fas fa-sun hidden dark:inline"></i>
</button>
<button id="new-note-btn" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition-colors">
<i class="fas fa-plus mr-2"></i> New Note
</button>
</div>
</header>
<!-- Search and Filter -->
<div class="mb-6 flex flex-col md:flex-row gap-4">
<div class="relative flex-grow">
<input type="text" id="search-notes" placeholder="Search notes..."
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-white">
<i class="fas fa-search absolute right-3 top-3 text-gray-400"></i>
</div>
<div class="flex gap-2">
<select id="filter-tags" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-white">
<option value="">All Tags</option>
</select>
<select id="sort-notes" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-white">
<option value="newest">Newest First</option>
<option value="oldest">Oldest First</option>
<option value="title-asc">Title (A-Z)</option>
<option value="title-desc">Title (Z-A)</option>
</select>
</div>
</div>
<!-- Main Content -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Notes List -->
<div class="lg:col-span-1 bg-white dark:bg-gray-800 rounded-lg shadow p-4 h-fit max-h-[600px] overflow-y-auto">
<h2 class="text-xl font-semibold mb-4 text-gray-800 dark:text-white">Your Notes</h2>
<div id="notes-list" class="space-y-3">
<!-- Notes will be added here dynamically -->
<div class="text-center py-8 text-gray-500 dark:text-gray-400">
<i class="fas fa-sticky-note text-4xl mb-2"></i>
<p>No notes yet. Create your first note!</p>
</div>
</div>
</div>
<!-- Note Editor -->
<div class="lg:col-span-2 bg-white dark:bg-gray-800 rounded-lg shadow p-6">
<div id="empty-state" class="text-center py-16 text-gray-500 dark:text-gray-400">
<i class="fas fa-edit text-5xl mb-4"></i>
<h3 class="text-xl font-medium mb-2">Select or create a note</h3>
<p>Start writing your thoughts, ideas, and reminders</p>
</div>
<div id="editor-container" class="hidden">
<input type="text" id="note-title" placeholder="Note Title"
class="w-full px-4 py-3 text-2xl font-bold border-b border-gray-200 dark:border-gray-700 mb-4 focus:outline-none dark:bg-gray-800 dark:text-white">
<div class="flex flex-wrap gap-2 mb-4" id="tags-container">
<input type="text" id="tag-input" placeholder="Add tags..."
class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-white">
</div>
<!-- Rich Text Editor -->
<div id="editor" class="note-content dark:bg-gray-800"></div>
<div class="flex justify-between items-center mt-6">
<div class="text-sm text-gray-500 dark:text-gray-400" id="note-date">
Created: Just now
</div>
<div class="space-x-2">
<button id="delete-note" class="px-4 py-2 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors">
<i class="fas fa-trash mr-2"></i> Delete
</button>
<button id="save-note" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg transition-colors">
<i class="fas fa-save mr-2"></i> Save
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize theme
if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
// Theme toggle
document.getElementById('theme-toggle').addEventListener('click', function() {
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
});
// Initialize Quill editor
const quill = new Quill('#editor', {
theme: 'snow',
modules: {
toolbar: [
[{ 'header': [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
['link', 'image'],
['clean']
]
},
placeholder: 'Write your note here...'
});
// Notes data
let notes = JSON.parse(localStorage.getItem('notes')) || [];
let currentNoteId = null;
let allTags = new Set();
// Initialize the app
function initApp() {
updateNotesList();
updateTagFilter();
// Set up event listeners
document.getElementById('new-note-btn').addEventListener('click', createNewNote);
document.getElementById('save-note').addEventListener('click', saveNote);
document.getElementById('delete-note').addEventListener('click', deleteNote);
document.getElementById('search-notes').addEventListener('input', searchNotes);
document.getElementById('filter-tags').addEventListener('change', filterNotesByTag);
document.getElementById('sort-notes').addEventListener('change', sortNotes);
// Tag input
const tagInput = document.getElementById('tag-input');
tagInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && tagInput.value.trim()) {
addTag(tagInput.value.trim());
tagInput.value = '';
}
});
}
// Create a new note
function createNewNote() {
const newNote = {
id: Date.now().toString(),
title: 'Untitled Note',
content: '',
tags: [],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
notes.unshift(newNote);
currentNoteId = newNote.id;
localStorage.setItem('notes', JSON.stringify(notes));
showEditor(newNote);
updateNotesList();
document.getElementById('note-title').focus();
}
// Save the current note
function saveNote() {
if (!currentNoteId) return;
const noteIndex = notes.findIndex(note => note.id === currentNoteId);
if (noteIndex === -1) return;
const title = document.getElementById('note-title').value;
const content = quill.root.innerHTML;
const tags = Array.from(document.querySelectorAll('.tag')).map(tag => tag.textContent.replace('×', '').trim());
notes[noteIndex].title = title;
notes[noteIndex].content = content;
notes[noteIndex].tags = tags;
notes[noteIndex].updatedAt = new Date().toISOString();
localStorage.setItem('notes', JSON.stringify(notes));
updateNotesList();
updateTagFilter();
// Show success message
const saveBtn = document.getElementById('save-note');
const originalText = saveBtn.innerHTML;
saveBtn.innerHTML = '<i class="fas fa-check mr-2"></i> Saved!';
setTimeout(() => {
saveBtn.innerHTML = originalText;
}, 2000);
}
// Delete the current note
function deleteNote() {
if (!currentNoteId || !confirm('Are you sure you want to delete this note?')) return;
notes = notes.filter(note => note.id !== currentNoteId);
localStorage.setItem('notes', JSON.stringify(notes));
currentNoteId = null;
document.getElementById('editor-container').classList.add('hidden');
document.getElementById('empty-state').classList.remove('hidden');
updateNotes
</html>