MY KINGDOM JOURNAL

My Journal .entry h3, .entry p, .entry .meta { color: #ffffff; } :root } body { margin:0; font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background:var(--bg); color:var(--text); } header { padding:16px 20px; border-bottom:2px solid #222; display:flex; gap:12px; align-items:center; flex-wrap:wrap; } header h1 { margin:0; font-size:20px; font-weight:600; letter-spacing:0.3px; } .controls { display:flex; gap:8px; align-items:center; flex-wrap:wrap; } input, select, button, textarea { background:var(--panel); color:var(--text); border:1px solid #FFFFFF; border-radius:8px; padding:8px; } input, select, button { height:40px; } button { cursor:pointer; } button.primary { background:var(--accent); border-color:var(--accent); color:#1B0000; font-weight:600; } button.danger { background:var(--danger); border-color:var(--danger); color:#FFFFFF; } main { max-width:900px; margin:0 auto; padding:20px; display:grid; grid-template-columns:1fr; gap:16px; } .editor, .list, .stats { background:var(--panel); border:1px solid #2a2f3a; border-radius:12px; padding:16px; } .editor textarea { width:100%; min-height:140px; resize:vertical; } .row { display:flex; gap:8px; flex-wrap:wrap; margin-top:8px; } .tag { font-size:12px; color:var(--muted); margin-left:6px; } .entry { border:3px solid #FFFF; border-radius:10px; padding:12px; margin-bottom:10px; background:#2a2F3A; } .entry h3 { margin:0 0 6px; font-size:16px; } . meta { font-size:14px; color:var(--muted); margin-bottom:6px; } .entry .actions { display:flex; gap:6px; } .empty { color:var(--muted); font-style:italic; padding:10px; } .pill { padding:4px 8px; border:1px solid #2a2f3a; border-radius:999px; font-size:12px; color:var(--muted); } .grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:12px; } @media (min-width:980px){ main{ grid-template-columns:1.2fr 1fr; } .stats{ grid-column:1 / -1; } }

Journal

Filter by tag
<h2 style="color:#ffffff;"

New entry

How are you feeling? (optional) πŸ™‚ Peaceful πŸ˜„ Joyful 😐 Overwhelmed πŸ˜• Anxious πŸ˜” Sad 😀 Frustrated 🀩 Excited 😴 Tired πŸ€” Thoughtful πŸ˜‡ Grateful 😎 Confident πŸ₯³ Celebratory 😒 Lonely 😑 Angry 🀯 Overwhelmed ❀️ Loving πŸ€’ Unwell πŸ€— Hopeful <button id="saveBtn" class="primary"

Saved Entries

History
0 entries
β€” most common feelings
β€” top tag
const STORAGE_KEY = 'myJournalEntries_v1'; const els = { search: document.getElementById('search'), filterTag: document.getElementById('filterTag'), exportBtn: document.getElementById('exportBtn'), importFile: document.getElementById('importFile'), clearBtn: document.getElementById('clearBtn'), title: document.getElementById('titleInput'), content: document.getElementById('contentInput'), tags: document.getElementById('tagsInput'), mood: document.getElementById('moodInput'), save: document.getElementById('saveBtn'), entries: document.getElementById('entries'), countStat: document.getElementById('countStat'), moodStat: document.getElementById('moodStat'), tagStat: document.getElementById('tagStat'), }; function nowISO(){ return new Date().toISOString(); } function read(){ try{ return JSON.parse(localStorage.getItem(STORAGE_KEY)) || []; } catch{ return []; } } function write(data){ localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); } function uid(){ return Math.random().toString(36).slice(2) + Date.now().toString(36); } function addEntry(entry){ const data = read(); data.unshift(entry); write(data); render(); resetEditor(); } function updateEntry(id, updates){ const data = read().map(e => e.id === id ? { ...e, ...updates, updatedAt: nowISO() } : e); write(data); render(); } function deleteEntry(id){ const data = read().filter(e => e.id !== id); write(data); render(); } function resetEditor(){ els.title.value = ''; els.content.value = ''; els.tags.value = ''; els.mood.value = ''; els.content.focus(); } function render(){ const query = els.search.value.trim().toLowerCase(); const tagFilter = els.filterTag.value.trim().toLowerCase(); const data = read(); // Update tag filter options const tags = Array.from(new Set(data.flatMap(e => e.tags))); els.filterTag.innerHTML = 'Filter by tag' + tags.map(t => `${t}`).join(''); let list = data.filter(e => { const matchesQuery = !query || (e.title.toLowerCase().includes(query) || e.content.toLowerCase().includes(query) || e.tags.some(t=>t.includes(query))); const matchesTag = !tagFilter || e.tags.includes(tagFilter); return matchesQuery && matchesTag; }); if (!list.length){ els.entries.innerHTML = '
No entries yet. Write your first one above.
'; } else { els.entries.innerHTML = list.map(e => `

${e.title || 'Untitled'}

${new Date(e.createdAt).toLocaleString()}${e.updatedAt ? ' β€’ updated ' + new Date(e.updatedAt).toLocaleString() : ''} ${e.mood ? ' β€’ ' + e.mood : '' } ${e.tags.length ? ' β€’ tags: ' + e.tags.join(', ') : ''}

${escapeHtml(e.content).replace(/\n/g,'
')}

`).join(''); } // Stats els.countStat.textContent = data.length; els.moodStat.textContent = mode(data.map(e => e.mood).filter(Boolean)) || 'β€”'; els.tagStat.textContent = mode(data.flatMap(e => e.tags)) || 'β€”'; } function escapeHtml(s){ const map = { '&':'&', '':'>', '"':'"', "'":''' }; return s.replace(/[&"']/g, m => map[m]); } function mode(arr){ if (!arr.length) return null; const counts = {}; arr.forEach(v => counts[v] = (counts[v]||0)+1); return Object.entries(counts).sort((a,b)=>b[1]-a[1])[0][0]; } // Events els.save.addEventListener('click', () => { const title = els.title.value.trim(); const content = els.content.value.trim(); const tags = els.tags.value.split(',').map(t => t.trim().toLowerCase()).filter(Boolean); const mood = els.mood.value || null; if (!content){ alert('Write something first.'); return; } addEntry({ id: uid(), title, content, tags, mood, createdAt: nowISO(), updatedAt: null }); }); els.search.addEventListener('input', render); els.filterTag.addEventListener('change', render); els.entries.addEventListener('click', (ev) => { const btn = ev.target.closest('button'); if (!btn) return; const article = ev.target.closest('.entry'); const id = article.dataset.id; const data = read(); const entry = data.find(e => e.id === id); if (btn.dataset.action === 'delete'){ if (confirm('Delete this entry?')) deleteEntry(id); } else if (btn.dataset.action === 'edit'){ const newTitle = prompt('Title:', entry.title || ''); const newContent = prompt('Content:', entry.content); const newTags = prompt('Tags (comma separated):', entry.tags.join(', ')); const newMood = prompt('Mood (optional):', entry.mood || ''); updateEntry(id, { title: (newTitle||'').trim(), content: (newContent||'').trim(), tags: (newTags||'').split(',').map(t => t.trim().toLowerCase()).filter(Boolean), mood: (newMood||'').trim() || null }); } }); els.exportBtn.addEventListener('click', () => { const blob = new Blob([JSON.stringify(read(), null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'journal-export.json'; a.click(); URL.revokeObjectURL(url); }); els.importFile.addEventListener('change', async () => { const file = els.importFile.files[0]; if (!file) return; const text = await file.text(); try{ const data = JSON.parse(text); if (!Array.isArray(data)) throw new Error('Invalid file'); write(data); render(); alert('Imported successfully.'); } catch(e){ alert('Import failed: ' + e.message); } finally { els.importFile.value = ''; } }); els.clearBtn.addEventListener('click', () => { if (confirm('This will clear all entries on this device. Continue?')){function downloadFile(content, filename, type) { const blob = new Blob([content], { type }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); } localStorage.removeItem(STORAGE_KEY); render(); } }); // Initial render(); </body

Release. Renew. Restore. ReviveΒ