brata's picture
make color red
f80c438 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>QuillScrawl Chronicles - Notes App</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.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;
}
.glass-effect {
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%);
background-color: rgba(255, 255, 255, 0.75);
}
.gradient-text {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
</head>
<body class="min-h-screen bg-gray-50">
<div id="vanta-bg" class="vanta-bg"></div>
<!-- Navigation -->
<nav class="glass-effect border-b border-gray-200 sticky top-0 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 items-center">
<div class="flex-shrink-0 flex items-center">
<i data-feather="edit-3" class="h-8 w-8 text-purple-600"></i>
<span class="ml-2 text-xl font-bold gradient-text">QuillScrawl Chronicles</span>
</div>
</div>
<div class="flex items-center space-x-4">
<button id="notes-tab" class="px-4 py-2 rounded-lg bg-purple-600 text-white font-medium transition-colors duration-200 hover:bg-purple-700">
<i data-feather="file-text" class="w-4 h-4 inline mr-2"></i>
Notes
</button>
<button id="history-tab" class="px-4 py-2 rounded-lg text-gray-600 font-medium transition-colors duration-200 hover:bg-gray-100">
<i data-feather="clock" class="w-4 h-4 inline mr-2"></i>
History
</button>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Notes Section -->
<section id="notes-section" class="space-y-6">
<!-- Note Input -->
<div class="glass-effect rounded-2xl p-6 shadow-lg border border-gray-100">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Create New Note</h2>
<form id="note-form" class="space-y-4">
<input type="text" id="note-title" placeholder="Note Title" class="w-full px-4 py-3 rounded-xl border border-gray-200 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200">
<textarea id="note-content" placeholder="Start writing your note here..." rows="6" class="w-full px-4 py-3 rounded-xl border border-gray-200 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 resize-none"></textarea>
<div class="flex justify-between items-center">
<button type="submit" class="px-6 py-3 bg-red-600 text-white rounded-xl font-medium hover:bg-red-700 transition-colors duration-200 flex items-center">
<i data-feather="save" class="w-4 h-4 mr-2"></i>
Save Note
</button>
<div class="flex items-center space-x-2 text-sm text-gray-500">
<i data-feather="clock" class="w-4 h-4"></i>
<span id="char-count">0 characters</span>
</div>
</div>
</form>
</div>
<!-- Notes Grid -->
<div id="notes-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Notes will be dynamically added here -->
</div>
</section>
<!-- History Section -->
<section id="history-section" class="hidden space-y-6">
<div class="glass-effect rounded-2xl p-6 shadow-lg border border-gray-100">
<h2 class="text-2xl font-bold text-gray-800 mb-6">Note History</h2>
<div id="history-list" class="space-y-4">
<!-- History items will be dynamically added here -->
</div>
</div>
</section>
</main>
<!-- Edit Note Modal -->
<div id="edit-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-20">
<div class="glass-effect rounded-2xl p-6 w-full max-w-2xl mx-4 shadow-2xl">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold text-gray-800">Edit Note</h3>
<button id="close-modal" class="text-gray-500 hover:text-gray-700">
<i data-feather="x" class="w-6 h-6"></i>
</button>
</div>
<form id="edit-form" class="space-y-4">
<input type="hidden" id="edit-id">
<input type="text" id="edit-title" placeholder="Note Title" class="w-full px-4 py-3 rounded-xl border border-gray-200 focus:ring-2 focus:ring-purple-500 focus:border-transparent">
<textarea id="edit-content" placeholder="Note Content" rows="6" class="w-full px-4 py-3 rounded-xl border border-gray-200 focus:ring-2 focus:ring-purple-500 focus:border-transparent resize-none"></textarea>
<div class="flex justify-end space-x-3">
<button type="button" id="cancel-edit" class="px-4 py-2 text-gray-600 hover:text-gray-800 transition-colors duration-200">
Cancel
</button>
<button type="submit" class="px-6 py-2 bg-purple-600 text-white rounded-xl hover:bg-purple-700 transition-colors duration-200">
Update Note
</button>
</div>
</form>
</div>
</div>
<script>
// Initialize Vanta.js background
VANTA.GLOBE({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x764ba2,
backgroundColor: 0xf8fafc
});
// Sample data
let notes = JSON.parse(localStorage.getItem('notes')) || [];
let history = JSON.parse(localStorage.getItem('history')) || [];
// DOM Elements
const notesSection = document.getElementById('notes-section');
const historySection = document.getElementById('history-section');
const notesTab = document.getElementById('notes-tab');
const historyTab = document.getElementById('history-tab');
const noteForm = document.getElementById('note-form');
const editForm = document.getElementById('edit-form');
const editModal = document.getElementById('edit-modal');
const notesGrid = document.getElementById('notes-grid');
const historyList = document.getElementById('history-list');
const charCount = document.getElementById('char-count');
const noteContent = document.getElementById('note-content');
// Tab switching
notesTab.addEventListener('click', () => {
notesSection.classList.remove('hidden');
historySection.classList.add('hidden');
notesTab.classList.add('bg-purple-600', 'text-white');
notesTab.classList.remove('text-gray-600', 'hover:bg-gray-100');
historyTab.classList.remove('bg-purple-600', 'text-white');
historyTab.classList.add('text-gray-600', 'hover:bg-gray-100');
});
historyTab.addEventListener('click', () => {
historySection.classList.remove('hidden');
notesSection.classList.add('hidden');
historyTab.classList.add('bg-purple-600', 'text-white');
historyTab.classList.remove('text-gray-600', 'hover:bg-gray-100');
notesTab.classList.remove('bg-purple-600', 'text-white');
notesTab.classList.add('text-gray-600', 'hover:bg-gray-100');
renderHistory();
});
// Character count
noteContent.addEventListener('input', () => {
charCount.textContent = `${noteContent.value.length} characters`;
});
// Save new note
noteForm.addEventListener('submit', (e) => {
e.preventDefault();
const title = document.getElementById('note-title').value;
const content = document.getElementById('note-content').value;
if (title.trim() && content.trim()) {
const newNote = {
id: Date.now(),
title: title.trim(),
content: content.trim(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
notes.unshift(newNote);
saveNotes();
addHistory('created', `Created note: "${title}"`);
renderNotes();
noteForm.reset();
charCount.textContent = '0 characters';
}
});
// Edit note
editForm.addEventListener('submit', (e) => {
e.preventDefault();
const id = parseInt(document.getElementById('edit-id').value);
const title = document.getElementById('edit-title').value;
const content = document.getElementById('edit-content').value;
if (title.trim() && content.trim()) {
const noteIndex = notes.findIndex(note => note.id === id);
if (noteIndex !== -1) {
const oldTitle = notes[noteIndex].title;
notes[noteIndex].title = title.trim();
notes[noteIndex].content = content.trim();
notes[noteIndex].updatedAt = new Date().toISOString();
saveNotes();
addHistory('updated', `Updated note: "${oldTitle}" to "${title}"`);
renderNotes();
closeModal();
}
}
});
// Modal controls
document.getElementById('close-modal').addEventListener('click', closeModal);
document.getElementById('cancel-edit').addEventListener('click', closeModal);
function openEditModal(note) {
document.getElementById('edit-id').value = note.id;
document.getElementById('edit-title').value = note.title;
document.getElementById('edit-content').value = note.content;
editModal.classList.remove('hidden');
}
function closeModal() {
editModal.classList.add('hidden');
}
// Delete note
function deleteNote(id) {
const note = notes.find(n => n.id === id);
if (note) {
notes = notes.filter(note => note.id !== id);
saveNotes();
addHistory('deleted', `Deleted note: "${note.title}"`);
renderNotes();
}
}
// Add history entry
function addHistory(action, description) {
const historyEntry = {
id: Date.now(),
action,
description,
timestamp: new Date().toISOString()
};
history.unshift(historyEntry);
localStorage.setItem('history', JSON.stringify(history));
}
// Save notes to localStorage
function saveNotes() {
localStorage.setItem('notes', JSON.stringify(notes));
}
// Render notes
function renderNotes() {
notesGrid.innerHTML = '';
notes.forEach(note => {
const noteElement = document.createElement('div');
noteElement.className = 'note-card glass-effect rounded-2xl p-6 shadow-lg border border-gray-100 hover:shadow-xl transition-all duration-300';
noteElement.innerHTML = `
<div class="flex justify-between items-start mb-3">
<h3 class="text-lg font-semibold text-gray-800 truncate">${note.title}</h3>
<div class="flex space-x-2">
<button onclick="openEditModal(${JSON.stringify(note).replace(/"/g, '&quot;')})" class="text-blue-600 hover:text-blue-800 transition-colors">
<i data-feather="edit-2" class="w-4 h-4"></i>
</button>
<button onclick="deleteNote(${note.id})" class="text-red-600 hover:text-red-800 transition-colors">
<i data-feather="trash-2" class="w-4 h-4"></i>
</button>
</div>
</div>
<p class="text-gray-600 text-sm mb-4 line-clamp-4">${note.content}</p>
<div class="text-xs text-gray-500 flex justify-between items-center">
<span>Created: ${new Date(note.createdAt).toLocaleDateString()}</span>
<span>Updated: ${new Date(note.updatedAt).toLocaleDateString()}</span>
</div>
`;
notesGrid.appendChild(noteElement);
});
feather.replace();
}
// Render history
function renderHistory() {
historyList.innerHTML = '';
history.forEach(entry => {
const historyElement = document.createElement('div');
historyElement.className = 'flex items-center space-x-4 p-4 bg-white rounded-xl shadow-sm border border-gray-100';
let icon = 'edit';
let color = 'text-blue-600';
if (entry.action === 'created') {
icon = 'plus';
color = 'text-green-600';
} else if (entry.action === 'deleted') {
icon = 'trash-2';
color = 'text-red-600';
}
historyElement.innerHTML = `
<div class="flex-shrink-0">
<i data-feather="${icon}" class="w-5 h-5 ${color}"></i>
</div>
<div class="flex-1">
<p class="text-gray-800">${entry.description}</p>
<p class="text-xs text-gray-500 mt-1">${new Date(entry.timestamp).toLocaleString()}</p>
</div>
`;
historyList.appendChild(historyElement);
});
feather.replace();
}
// Initialize
renderNotes();
feather.replace();
</script>
</body>
</html>