Enhance note-taking features by adding label support, improving modal styles, and refining CSS for better responsiveness. Update login page title and adjust password management UI for better usability.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
try { $pdo->exec("ALTER TABLE notes ADD COLUMN color TEXT DEFAULT NULL"); } catch(Exception $e) {}
|
||||
try { $pdo->exec("ALTER TABLE notes ADD COLUMN image_path TEXT DEFAULT NULL"); } catch(Exception $e) {}
|
||||
try { $pdo->exec("ALTER TABLE notes ADD COLUMN updated_at DATETIME DEFAULT NULL"); } catch(Exception $e) {}
|
||||
try { $pdo->exec("ALTER TABLE notes ADD COLUMN label_name TEXT DEFAULT NULL"); } catch(Exception $e) {}
|
||||
try {
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS notes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -40,8 +41,8 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if(move_uploaded_file($_FILES['note_image']['tmp_name'], $dest)) $image_path = $dest;
|
||||
}
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO notes (title, content, owner_id, color, image_path) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$_POST['title'] ?? 'Untitled', $_POST['content'], $user_id, $_POST['color'] ?? null, $image_path]);
|
||||
$stmt = $pdo->prepare("INSERT INTO notes (title, content, owner_id, color, image_path, label_name) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$_POST['title'] ?? 'Untitled', $_POST['content'], $user_id, $_POST['color'] ?? null, $image_path, trim($_POST['label_name'] ?? '') ?: null]);
|
||||
}
|
||||
|
||||
if(isset($_POST['update_note'])) {
|
||||
@@ -64,8 +65,8 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if($image_path && file_exists($image_path)) @unlink($image_path);
|
||||
$image_path = null;
|
||||
}
|
||||
$stmt = $pdo->prepare("UPDATE notes SET title=?, content=?, color=?, image_path=?, updated_at=CURRENT_TIMESTAMP WHERE id=? AND owner_id=?");
|
||||
$stmt->execute([$_POST['title'] ?? 'Untitled', $_POST['content'], $_POST['color'] ?? null, $image_path, $_POST['note_id'], $user_id]);
|
||||
$stmt = $pdo->prepare("UPDATE notes SET title=?, content=?, color=?, image_path=?, label_name=?, updated_at=CURRENT_TIMESTAMP WHERE id=? AND owner_id=?");
|
||||
$stmt->execute([$_POST['title'] ?? 'Untitled', $_POST['content'], $_POST['color'] ?? null, $image_path, trim($_POST['label_name'] ?? '') ?: null, $_POST['note_id'], $user_id]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +112,12 @@ $notes = $stmt->fetchAll();
|
||||
|
||||
$all_users = query("SELECT id, username FROM users WHERE id != ?", [$user_id])->fetchAll();
|
||||
$all_groups = query("SELECT * FROM groups")->fetchAll();
|
||||
$label_names = [];
|
||||
foreach($notes as $n) {
|
||||
$lbl = trim((string)($n['label_name'] ?? ''));
|
||||
if($lbl !== '') $label_names[strtolower($lbl)] = $lbl;
|
||||
}
|
||||
natcasesort($label_names);
|
||||
|
||||
// Define note colors — Google Keep inspired
|
||||
$note_colors = [
|
||||
@@ -122,31 +129,53 @@ $note_colors = [
|
||||
'#b3e5fc' => ['bg'=>'#b3e5fc', 'label'=>'Sky', 'hex'=>'#b3e5fc'],
|
||||
'#cce5ff' => ['bg'=>'#cce5ff', 'label'=>'Blue', 'hex'=>'#cce5ff'],
|
||||
'#e2d9f3' => ['bg'=>'#e2d9f3', 'label'=>'Lavender', 'hex'=>'#e2d9f3'],
|
||||
'#f3e5f5' => ['bg'=>'#f3e5f5', 'label'=>'Orchid', 'hex'=>'#f3e5f5'],
|
||||
'#f8d7da' => ['bg'=>'#f8d7da', 'label'=>'Rose', 'hex'=>'#f8d7da'],
|
||||
'#ef9a9a' => ['bg'=>'#ef9a9a', 'label'=>'Red', 'hex'=>'#ef9a9a'],
|
||||
'#ffcc80' => ['bg'=>'#ffcc80', 'label'=>'Peach', 'hex'=>'#ffcc80'],
|
||||
'#fde8d8' => ['bg'=>'#fde8d8', 'label'=>'Orange', 'hex'=>'#fde8d8'],
|
||||
'#d7ccc8' => ['bg'=>'#d7ccc8', 'label'=>'Sand', 'hex'=>'#d7ccc8'],
|
||||
'#f5f5f5' => ['bg'=>'#f5f5f5', 'label'=>'Stone', 'hex'=>'#f5f5f5'],
|
||||
'#e8f5e9' => ['bg'=>'#e8f5e9', 'label'=>'Mint', 'hex'=>'#e8f5e9'],
|
||||
'#fff3e0' => ['bg'=>'#fff3e0', 'label'=>'Apricot', 'hex'=>'#fff3e0'],
|
||||
'#fce4ec' => ['bg'=>'#fce4ec', 'label'=>'Pink', 'hex'=>'#fce4ec'],
|
||||
'#ede7f6' => ['bg'=>'#ede7f6', 'label'=>'Violet', 'hex'=>'#ede7f6'],
|
||||
'#e0f7fa' => ['bg'=>'#e0f7fa', 'label'=>'Cyan', 'hex'=>'#e0f7fa'],
|
||||
'#fffde7' => ['bg'=>'#fffde7', 'label'=>'Butter', 'hex'=>'#fffde7'],
|
||||
];
|
||||
?>
|
||||
|
||||
<div style="display:flex; justify-content:flex-end; align-items:center; margin-bottom:1rem;">
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:1rem; gap:0.75rem; flex-wrap:wrap;">
|
||||
<button class="btn" onclick="document.getElementById('new-note-modal').classList.add('active')">
|
||||
<i class="fa fa-plus"></i> New Note
|
||||
</button>
|
||||
<div style="display:flex; align-items:center; gap:0.5rem; flex-wrap:wrap;">
|
||||
<input type="text" id="notes-search-input" class="form-control" placeholder="Search notes..." style="width:200px; padding:0.45rem 0.6rem; font-size:0.84rem;" oninput="filterNotes()">
|
||||
<select id="notes-label-filter" class="form-control" style="width:180px; padding:0.45rem 0.6rem; font-size:0.84rem;" onchange="filterNotes()">
|
||||
<option value="">All labels</option>
|
||||
<?php foreach($label_names as $lbl): ?>
|
||||
<option value="<?= htmlspecialchars(strtolower($lbl)) ?>"><?= htmlspecialchars($lbl) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── New Note Modal ─────────────────────────────────────────────────────── -->
|
||||
<div class="modal-overlay" id="new-note-modal">
|
||||
<div class="modal-content" style="max-width:580px; max-height:92vh; overflow-y:auto; padding:1.5rem;">
|
||||
<div class="modal-content note-modal-compact" style="max-width:760px; max-height:92vh; overflow-y:auto;">
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:1rem;">
|
||||
<h3 style="font-size:1rem; font-weight:700;">New Note</h3>
|
||||
<button type="button" style="background:none;border:none;color:var(--text-light);cursor:pointer;font-size:1.2rem;" onclick="document.getElementById('new-note-modal').classList.remove('active')">×</button>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data" id="new-note-form">
|
||||
<input type="hidden" name="create_note" value="1">
|
||||
<div class="form-group">
|
||||
<input type="text" name="title" class="form-control" placeholder="Title..." id="new-note-title" style="font-weight:600; font-size:1rem;">
|
||||
<div class="note-modal-top-fields" style="display:grid; grid-template-columns:2fr 1fr; gap:0.75rem;">
|
||||
<div class="form-group">
|
||||
<input type="text" name="title" class="form-control" placeholder="Title..." id="new-note-title" style="font-weight:600; font-size:1rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" name="label_name" class="form-control" id="new-note-label" placeholder="Tag/Label name">
|
||||
</div>
|
||||
</div>
|
||||
<!-- WYSIWYG Toolbar -->
|
||||
<div class="note-editor-toolbar" id="new-note-toolbar">
|
||||
@@ -196,13 +225,21 @@ $note_colors = [
|
||||
|
||||
<!-- ── Edit Note Modal ────────────────────────────────────────────────────── -->
|
||||
<div class="modal-overlay" id="edit-note-modal">
|
||||
<div class="modal-content" style="max-width:600px; max-height:90vh; overflow-y:auto;">
|
||||
<h3 style="margin-bottom:1rem;">Edit Note</h3>
|
||||
<div class="modal-content note-modal-compact" style="max-width:760px; max-height:90vh; overflow-y:auto;">
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:1rem;">
|
||||
<h3 style="margin:0;">Edit Note</h3>
|
||||
<button type="button" style="background:none;border:none;color:var(--text-light);cursor:pointer;font-size:1.2rem;" onclick="document.getElementById('edit-note-modal').classList.remove('active')">×</button>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data" id="edit-note-form">
|
||||
<input type="hidden" name="update_note" value="1">
|
||||
<input type="hidden" name="note_id" id="edit-note-id">
|
||||
<div class="form-group">
|
||||
<input type="text" name="title" id="edit-note-title" class="form-control" placeholder="Title..." style="font-weight:600; font-size:1rem;">
|
||||
<div class="note-modal-top-fields" style="display:grid; grid-template-columns:2fr 1fr; gap:0.75rem;">
|
||||
<div class="form-group">
|
||||
<input type="text" name="title" id="edit-note-title" class="form-control" placeholder="Title..." style="font-weight:600; font-size:1rem;">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" name="label_name" id="edit-note-label" class="form-control" placeholder="Tag/Label name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-editor-toolbar">
|
||||
<button type="button" class="note-toolbar-btn" onclick="formatNote('edit-note-content','bold')"><b>B</b></button>
|
||||
@@ -307,11 +344,13 @@ $note_colors = [
|
||||
$preview = strip_tags(isset($n['content']) ? (function_exists('marked') ? $n['content'] : $n['content']) : '');
|
||||
$preview = mb_substr($preview, 0, 120) . (mb_strlen($preview) > 120 ? '...' : '');
|
||||
?>
|
||||
<div class="note-card"
|
||||
<div class="note-card note-filter-item"
|
||||
style="background:<?= htmlspecialchars($bg) ?>;"
|
||||
data-id="<?= $n['id'] ?>"
|
||||
data-title="<?= htmlspecialchars(addslashes((string)$n['title'])) ?>"
|
||||
data-content="<?= htmlspecialchars(addslashes((string)$n['content'])) ?>"
|
||||
data-label="<?= htmlspecialchars(strtolower(trim((string)($n['label_name'] ?? '')))) ?>"
|
||||
data-label-raw="<?= htmlspecialchars(trim((string)($n['label_name'] ?? ''))) ?>"
|
||||
data-color="<?= htmlspecialchars((string)$n['color']) ?>"
|
||||
data-image="<?= htmlspecialchars((string)($n['image_path'] ?? '')) ?>"
|
||||
data-mine="<?= $n['is_mine'] ?>"
|
||||
@@ -322,6 +361,11 @@ $note_colors = [
|
||||
<?php if($n['title']): ?>
|
||||
<div class="note-card-title"><?= htmlspecialchars($n['title']) ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if(!empty($n['label_name'])): ?>
|
||||
<div style="display:inline-flex; align-items:center; gap:0.35rem; width:max-content; max-width:100%; padding:3px 8px; border-radius:999px; background:rgba(var(--primary-rgb),0.12); color:var(--primary); font-size:0.7rem; font-weight:600;">
|
||||
<i class="fa fa-tag" style="font-size:0.65rem;"></i> <?= htmlspecialchars($n['label_name']) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="note-card-preview"><?= htmlspecialchars($preview) ?></div>
|
||||
<div class="note-card-footer">
|
||||
<div style="display:flex; align-items:center; gap:0.4rem;">
|
||||
@@ -403,12 +447,14 @@ function openNote(card) {
|
||||
const title = card.dataset.title;
|
||||
const content = card.dataset.content;
|
||||
const color = card.dataset.color;
|
||||
const label = card.dataset.labelRaw || '';
|
||||
const image = card.dataset.image;
|
||||
const isMine = card.dataset.mine === '1';
|
||||
|
||||
document.getElementById('edit-note-id').value = id;
|
||||
document.getElementById('edit-note-title').value = title;
|
||||
document.getElementById('edit-note-content').value = content;
|
||||
document.getElementById('edit-note-label').value = label;
|
||||
document.getElementById('edit-note-color-input').value = color;
|
||||
document.getElementById('edit-note-preview').style.display = 'none';
|
||||
document.getElementById('edit-note-content').style.display = 'block';
|
||||
@@ -449,6 +495,19 @@ function openNote(card) {
|
||||
document.getElementById('edit-note-modal').classList.add('active');
|
||||
}
|
||||
|
||||
function filterNotes() {
|
||||
const q = (document.getElementById('notes-search-input')?.value || '').toLowerCase().trim();
|
||||
const lbl = (document.getElementById('notes-label-filter')?.value || '').trim();
|
||||
document.querySelectorAll('.note-filter-item').forEach(card => {
|
||||
const t = (card.dataset.title || '').toLowerCase();
|
||||
const c = (card.dataset.content || '').toLowerCase();
|
||||
const cl = (card.dataset.label || '').toLowerCase();
|
||||
const okText = !q || t.includes(q) || c.includes(q) || cl.includes(q);
|
||||
const okLabel = !lbl || cl === lbl;
|
||||
card.style.display = (okText && okLabel) ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
function deleteNote(id) {
|
||||
if(!confirm('Delete this note permanently?')) return;
|
||||
document.getElementById('delete-note-id').value = id;
|
||||
|
||||
Reference in New Issue
Block a user