mindful-journal-1 / index.html
Howie254's picture
Add 3 files
5af82a3 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mindful Journal</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
.glass {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.18);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}
.gradient-bg {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.entry-content img {
max-width: 100%;
border-radius: 8px;
margin: 1rem 0;
}
.markdown-preview h1, .markdown-preview h2, .markdown-preview h3 {
margin: 1rem 0;
font-weight: bold;
}
.markdown-preview h1 {
font-size: 1.8rem;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 0.3rem;
}
.markdown-preview h2 {
font-size: 1.5rem;
}
.markdown-preview h3 {
font-size: 1.3rem;
}
.markdown-preview ul, .markdown-preview ol {
padding-left: 1.5rem;
margin: 1rem 0;
}
.markdown-preview ul {
list-style-type: disc;
}
.markdown-preview ol {
list-style-type: decimal;
}
.markdown-preview blockquote {
border-left: 4px solid #c3cfe2;
padding-left: 1rem;
color: #4a5568;
margin: 1rem 0;
}
.markdown-preview pre {
background: #2d3748;
color: #f7fafc;
padding: 1rem;
border-radius: 0.5rem;
overflow-x: auto;
margin: 1rem 0;
}
.markdown-preview code {
background: #edf2f7;
padding: 0.2rem 0.4rem;
border-radius: 0.3rem;
font-family: monospace;
}
.markdown-preview a {
color: #4299e1;
text-decoration: underline;
}
.confirmation-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.confirmation-content {
background: white;
padding: 2rem;
border-radius: 0.5rem;
max-width: 400px;
width: 100%;
}
</style>
</head>
<body class="gradient-bg min-h-screen font-sans antialiased">
<div id="app" class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="glass p-6 mb-8 flex justify-between items-center">
<div>
<h1 class="text-3xl font-bold text-indigo-800">Mindful Journal</h1>
<p class="text-gray-600">Capture your thoughts, reflect, and grow</p>
</div>
<div class="flex items-center space-x-4">
<button id="newEntryBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg transition duration-200 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
New Entry
</button>
<button id="toggleThemeBtn" class="p-2 rounded-full bg-gray-200 hover:bg-gray-300 transition duration-200">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd" />
</svg>
</button>
</div>
</header>
<!-- Main Content -->
<main class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Entries List -->
<div class="lg:col-span-1 glass p-4">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Your Entries</h2>
<div class="relative">
<input type="text" id="searchEntries" placeholder="Search..." class="bg-white/50 border border-gray-200 rounded-lg px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
</div>
<div id="entriesList" class="space-y-2 max-h-[600px] overflow-y-auto pr-2">
<!-- Entries will be loaded here -->
</div>
</div>
<!-- Entry Editor/Viewer -->
<div class="lg:col-span-2 glass p-6">
<div id="emptyState" class="flex flex-col items-center justify-center h-full text-center py-16">
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<h3 class="text-xl font-medium text-gray-700 mt-4">No entry selected</h3>
<p class="text-gray-500 mt-2 max-w-md">Select an existing entry from the list or create a new one to get started.</p>
<button id="emptyStateNewEntryBtn" class="mt-6 bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg transition duration-200">
Create New Entry
</button>
</div>
<div id="entryEditor" class="hidden">
<div class="flex justify-between items-center mb-6">
<input type="text" id="entryTitle" placeholder="Entry Title" class="text-2xl font-bold bg-transparent border-b border-gray-300 focus:outline-none focus:border-indigo-500 w-full py-2">
<div class="flex space-x-2">
<button id="deleteEntryBtn" class="text-sm bg-red-100 hover:bg-red-200 text-red-800 px-3 py-1 rounded-lg transition duration-200 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
Delete
</button>
<button id="togglePreviewBtn" class="text-sm bg-gray-200 hover:bg-gray-300 px-3 py-1 rounded-lg transition duration-200">
Preview
</button>
<button id="saveEntryBtn" class="text-sm bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded-lg transition duration-200">
Save
</button>
</div>
</div>
<div id="editorContainer">
<textarea id="entryContent" placeholder="Write your thoughts here... Markdown is supported!" class="w-full h-96 p-4 bg-white/50 rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"></textarea>
<div class="mt-2 flex flex-wrap gap-2">
<button data-md="**Bold**" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">B</button>
<button data-md="*Italic*" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">I</button>
<button data-md="[Link](url)" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">Link</button>
<button data-md="![Image](url)" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">Image</button>
<button data-md="# Heading" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">H1</button>
<button data-md="## Heading" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">H2</button>
<button data-md="- List item" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">List</button>
<button data-md="1. Numbered item" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">1.</button>
<button data-md="> Blockquote" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">Quote</button>
<button data-md="```\nCode\n```" class="text-xs bg-gray-200 hover:bg-gray-300 px-2 py-1 rounded transition duration-200">Code</button>
</div>
</div>
<div id="previewContainer" class="hidden markdown-preview entry-content bg-white/70 p-6 rounded-lg"></div>
<div class="mt-6 flex justify-between items-center">
<div>
<label class="text-sm text-gray-600">Mood:</label>
<select id="entryMood" class="ml-2 bg-white/50 border border-gray-300 rounded-lg px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<option value="😊">😊 Happy</option>
<option value="😐">😐 Neutral</option>
<option value="😔">😔 Sad</option>
<option value="😠">😠 Angry</option>
<option value="😲">😲 Surprised</option>
<option value="😴">😴 Tired</option>
<option value="🤩">🤩 Excited</option>
<option value="😌">😌 Peaceful</option>
</select>
</div>
<div class="text-sm text-gray-500" id="entryDate"></div>
</div>
<div class="mt-6">
<label class="text-sm text-gray-600">Tags (comma separated):</label>
<input type="text" id="entryTags" placeholder="e.g. work, ideas, personal" class="w-full mt-1 bg-white/50 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
</div>
</div>
</main>
<!-- Stats Section -->
<section class="glass p-6 mt-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Journal Insights</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white/50 p-4 rounded-lg text-center">
<div class="text-2xl font-bold text-indigo-600" id="totalEntries">0</div>
<div class="text-sm text-gray-600">Total Entries</div>
</div>
<div class="bg-white/50 p-4 rounded-lg text-center">
<div class="text-2xl font-bold text-indigo-600" id="entriesThisMonth">0</div>
<div class="text-sm text-gray-600">This Month</div>
</div>
<div class="bg-white/50 p-4 rounded-lg text-center">
<div class="text-2xl font-bold text-indigo-600" id="avgEntries">0</div>
<div class="text-sm text-gray-600">Avg/Month</div>
</div>
<div class="bg-white/50 p-4 rounded-lg text-center">
<div class="text-2xl font-bold text-indigo-600" id="streakDays">0</div>
<div class="text-sm text-gray-600">Day Streak</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="mt-12 text-center text-gray-600 text-sm pb-6">
<p>Mindful Journal &copy; 2025 | Your thoughts are safe with us</p>
<p class="mt-1">Data is stored locally in your browser</p>
</footer>
</div>
<!-- Confirmation Modal -->
<div id="confirmationModal" class="confirmation-modal hidden">
<div class="confirmation-content glass">
<h3 class="text-lg font-medium text-gray-900 mb-4">Confirm Deletion</h3>
<p class="text-gray-600 mb-6">Are you sure you want to delete this entry? This action cannot be undone.</p>
<div class="flex justify-end space-x-3">
<button id="cancelDeleteBtn" class="px-4 py-2 text-sm bg-gray-200 hover:bg-gray-300 rounded-lg transition duration-200">
Cancel
</button>
<button id="confirmDeleteBtn" class="px-4 py-2 text-sm bg-red-600 hover:bg-red-700 text-white rounded-lg transition duration-200">
Delete Entry
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const app = document.getElementById('app');
const entriesList = document.getElementById('entriesList');
const emptyState = document.getElementById('emptyState');
const entryEditor = document.getElementById('entryEditor');
const entryTitle = document.getElementById('entryTitle');
const entryContent = document.getElementById('entryContent');
const entryDate = document.getElementById('entryDate');
const entryMood = document.getElementById('entryMood');
const entryTags = document.getElementById('entryTags');
const previewContainer = document.getElementById('previewContainer');
const editorContainer = document.getElementById('editorContainer');
const newEntryBtn = document.getElementById('newEntryBtn');
const emptyStateNewEntryBtn = document.getElementById('emptyStateNewEntryBtn');
const saveEntryBtn = document.getElementById('saveEntryBtn');
const togglePreviewBtn = document.getElementById('togglePreviewBtn');
const deleteEntryBtn = document.getElementById('deleteEntryBtn');
const searchEntries = document.getElementById('searchEntries');
const toggleThemeBtn = document.getElementById('toggleThemeBtn');
const totalEntriesEl = document.getElementById('totalEntries');
const entriesThisMonthEl = document.getElementById('entriesThisMonth');
const avgEntriesEl = document.getElementById('avgEntries');
const streakDaysEl = document.getElementById('streakDays');
const confirmationModal = document.getElementById('confirmationModal');
const cancelDeleteBtn = document.getElementById('cancelDeleteBtn');
const confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
// State
let entries = JSON.parse(localStorage.getItem('journalEntries')) || [];
let currentEntryId = null;
let isPreviewMode = false;
let isDarkMode = false;
// Initialize
updateStats();
renderEntriesList();
checkEmptyState();
// Event Listeners
newEntryBtn.addEventListener('click', createNewEntry);
emptyStateNewEntryBtn.addEventListener('click', createNewEntry);
saveEntryBtn.addEventListener('click', saveEntry);
togglePreviewBtn.addEventListener('click', togglePreview);
deleteEntryBtn.addEventListener('click', showDeleteConfirmation);
searchEntries.addEventListener('input', filterEntries);
toggleThemeBtn.addEventListener('click', toggleTheme);
cancelDeleteBtn.addEventListener('click', hideDeleteConfirmation);
confirmDeleteBtn.addEventListener('click', deleteCurrentEntry);
// Markdown shortcuts
document.querySelectorAll('[data-md]').forEach(button => {
button.addEventListener('click', function() {
const textToInsert = this.getAttribute('data-md');
const startPos = entryContent.selectionStart;
const endPos = entryContent.selectionEnd;
const selectedText = entryContent.value.substring(startPos, endPos);
// If text is selected, wrap it with the markdown syntax
if (selectedText) {
let newText;
if (textToInsert.includes('**')) {
newText = textToInsert.replace('**', selectedText);
} else if (textToInsert.includes('*')) {
newText = textToInsert.replace('*', selectedText);
} else if (textToInsert.includes('url')) {
newText = `[${selectedText}](url)`;
} else {
newText = selectedText + '\n' + textToInsert;
}
entryContent.value = entryContent.value.substring(0, startPos) + newText + entryContent.value.substring(endPos);
} else {
// Just insert the markdown syntax
entryContent.value = entryContent.value.substring(0, startPos) + textToInsert + entryContent.value.substring(endPos);
}
// Focus back on the textarea
entryContent.focus();
// Set cursor position
if (textToInsert.includes('url')) {
const newCursorPos = startPos + newText.indexOf('url');
entryContent.setSelectionRange(newCursorPos, newCursorPos + 3);
} else if (textToInsert.includes('**') || textToInsert.includes('*')) {
const newCursorPos = startPos + newText.length;
entryContent.setSelectionRange(newCursorPos, newCursorPos);
}
});
});
// Functions
function createNewEntry() {
currentEntryId = Date.now().toString();
entryTitle.value = '';
entryContent.value = '';
entryDate.textContent = formatDate(new Date());
entryMood.value = '😐';
entryTags.value = '';
emptyState.classList.add('hidden');
entryEditor.classList.remove('hidden');
isPreviewMode = false;
editorContainer.classList.remove('hidden');
previewContainer.classList.add('hidden');
togglePreviewBtn.textContent = 'Preview';
entryTitle.focus();
}
function saveEntry() {
const title = entryTitle.value.trim();
const content = entryContent.value.trim();
const mood = entryMood.value;
const tags = entryTags.value.split(',').map(tag => tag.trim()).filter(tag => tag);
const now = new Date();
if (!title) {
alert('Please enter a title for your entry');
return;
}
const entryData = {
id: currentEntryId,
title,
content,
mood,
tags,
createdAt: now.toISOString(),
updatedAt: now.toISOString()
};
// Check if this is an existing entry
const existingIndex = entries.findIndex(entry => entry.id === currentEntryId);
if (existingIndex !== -1) {
// For existing entries, preserve the original creation date
entryData.createdAt = entries[existingIndex].createdAt;
entries[existingIndex] = entryData;
} else {
entries.unshift(entryData);
}
// Save to localStorage
localStorage.setItem('journalEntries', JSON.stringify(entries));
// Update UI
renderEntriesList();
updateStats();
// Show success message
const originalText = saveEntryBtn.textContent;
saveEntryBtn.textContent = 'Saved!';
setTimeout(() => {
saveEntryBtn.textContent = originalText;
}, 2000);
}
function renderEntriesList(filter = '') {
entriesList.innerHTML = '';
const filteredEntries = entries.filter(entry =>
entry.title.toLowerCase().includes(filter.toLowerCase()) ||
entry.content.toLowerCase().includes(filter.toLowerCase()) ||
entry.tags.some(tag => tag.toLowerCase().includes(filter.toLowerCase()))
);
if (filteredEntries.length === 0) {
entriesList.innerHTML = `
<div class="text-center py-8 text-gray-500">
${filter ? 'No entries match your search' : 'No entries yet'}
</div>
`;
return;
}
filteredEntries.forEach(entry => {
const entryDate = new Date(entry.createdAt);
const entryEl = document.createElement('div');
entryEl.className = `p-3 rounded-lg cursor-pointer hover:bg-white/50 transition duration-200 ${currentEntryId === entry.id ? 'bg-white/70 border-l-4 border-indigo-500' : 'bg-white/30'}`;
entryEl.innerHTML = `
<div class="flex justify-between items-start">
<h3 class="font-medium truncate">${entry.title}</h3>
<span class="text-2xl ml-2">${entry.mood}</span>
</div>
<p class="text-sm text-gray-600 mt-1 truncate">${entry.content.substring(0, 60)}${entry.content.length > 60 ? '...' : ''}</p>
<div class="flex justify-between items-center mt-2">
<div class="text-xs text-gray-500">${formatDate(entryDate)}</div>
<div class="flex space-x-1">
${entry.tags.slice(0, 2).map(tag => `<span class="text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded-full">${tag}</span>`).join('')}
${entry.tags.length > 2 ? `<span class="text-xs bg-gray-200 text-gray-800 px-2 py-1 rounded-full">+${entry.tags.length - 2}</span>` : ''}
</div>
</div>
`;
entryEl.addEventListener('click', () => loadEntry(entry.id));
entriesList.appendChild(entryEl);
});
}
function loadEntry(id) {
const entry = entries.find(entry => entry.id === id);
if (!entry) return;
currentEntryId = entry.id;
entryTitle.value = entry.title;
entryContent.value = entry.content;
entryDate.textContent = formatDate(new Date(entry.createdAt));
entryMood.value = entry.mood;
entryTags.value = entry.tags.join(', ');
emptyState.classList.add('hidden');
entryEditor.classList.remove('hidden');
isPreviewMode = false;
editorContainer.classList.remove('hidden');
previewContainer.classList.add('hidden');
togglePreviewBtn.textContent = 'Preview';
// Highlight the selected entry in the list
renderEntriesList(searchEntries.value);
}
function togglePreview() {
isPreviewMode = !isPreviewMode;
if (isPreviewMode) {
previewContainer.innerHTML = marked.parse(entryContent.value);
editorContainer.classList.add('hidden');
previewContainer.classList.remove('hidden');
togglePreviewBtn.textContent = 'Edit';
} else {
editorContainer.classList.remove('hidden');
previewContainer.classList.add('hidden');
togglePreviewBtn.textContent = 'Preview';
}
}
function filterEntries() {
renderEntriesList(searchEntries.value);
}
function checkEmptyState() {
if (entries.length === 0 && !currentEntryId) {
emptyState.classList.remove('hidden');
entryEditor.classList.add('hidden');
}
}
function formatDate(date) {
const options = {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
};
return date.toLocaleDateString('en-US', options);
}
function updateStats() {
// Total entries
totalEntriesEl.textContent = entries.length;
// Entries this month
const currentMonth = new Date().getMonth();
const currentYear = new Date().getFullYear();
const thisMonthEntries = entries.filter(entry => {
const entryDate = new Date(entry.createdAt);
return entryDate.getMonth() === currentMonth && entryDate.getFullYear() === currentYear;
});
entriesThisMonthEl.textContent = thisMonthEntries.length;
// Average entries per month
if (entries.length > 0) {
const firstEntryDate = new Date(entries[entries.length - 1].createdAt);
const monthsDiff = (new Date().getFullYear() - firstEntryDate.getFullYear()) * 12 +
(new Date().getMonth() - firstEntryDate.getMonth()) + 1;
const avg = Math.round(entries.length / Math.max(monthsDiff, 1));
avgEntriesEl.textContent = avg;
}
// Streak (consecutive days with entries)
let streak = 0;
const today = new Date();
today.setHours(0, 0, 0, 0);
const entryDates = entries.map(entry => {
const date = new Date(entry.createdAt);
date.setHours(0, 0, 0, 0);
return date.getTime();
});
const uniqueEntryDates = [...new Set(entryDates)].sort((a, b) => b - a);
let checkDate = new Date(today);
while (uniqueEntryDates.includes(checkDate.getTime())) {
streak++;
checkDate.setDate(checkDate.getDate() - 1);
}
streakDaysEl.textContent = streak;
}
function toggleTheme() {
isDarkMode = !isDarkMode;
if (isDarkMode) {
app.classList.remove('gradient-bg');
app.classList.add('bg-gray-900');
document.body.classList.remove('gradient-bg');
document.body.classList.add('bg-gray-900');
toggleThemeBtn.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>
`;
} else {
app.classList.add('gradient-bg');
app.classList.remove('bg-gray-900');
document.body.classList.add('gradient-bg');
document.body.classList.remove('bg-gray-900');
toggleThemeBtn.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd" />
</svg>
`;
}
}
function showDeleteConfirmation() {
confirmationModal.classList.remove('hidden');
}
function hideDeleteConfirmation() {
confirmationModal.classList.add('hidden');
}
function deleteCurrentEntry() {
if (!currentEntryId) return;
// Remove the entry from the array
entries = entries.filter(entry => entry.id !== currentEntryId);
// Save to localStorage
localStorage.setItem('journalEntries', JSON.stringify(entries));
// Update UI
hideDeleteConfirmation();
currentEntryId = null;
checkEmptyState();
renderEntriesList();
updateStats();
// Show success message
const toast = document.createElement('div');
toast.className = 'fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded-lg shadow-lg';
toast.textContent = 'Entry deleted successfully';
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
});
</script>
<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=Howie254/mindful-journal-1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>