308 lines
No EOL
14 KiB
HTML
308 lines
No EOL
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" data-theme="light">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Daily Log - {{ log.date.strftime('%B %d, %Y') }} - Bullet Journal</title>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Lexend:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
</head>
|
|
<body>
|
|
<div class="page-surface">
|
|
<!-- Header -->
|
|
<header class="page-header">
|
|
<h1 class="page-header__title">Bullet Journal</h1>
|
|
<nav class="header-nav">
|
|
<a href="{{ url_for('main.log_list') }}" class="btn btn-secondary btn-sm">All Logs</a>
|
|
<a href="{{ url_for('main.settings') }}" class="btn btn-secondary btn-sm">Settings</a>
|
|
<a href="{{ url_for('auth.logout') }}" class="btn btn-secondary btn-sm">Logout</a>
|
|
</nav>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<main class="page-main">
|
|
<div class="daily-log-layout">
|
|
<!-- Left Column: Current Day -->
|
|
<section class="daily-log__current">
|
|
<article class="card">
|
|
<p class="card__eyebrow">Daily Log</p>
|
|
<h2>{{ log.date.strftime('%B %d, %Y') }}</h2>
|
|
|
|
<!-- Prompt -->
|
|
<div class="form-group">
|
|
<label for="prompt">Prompt</label>
|
|
<textarea id="prompt" name="prompt" rows="3" aria-describedby="prompt-help">{{ log.prompt or '' }}</textarea>
|
|
<span id="prompt-help" class="form-help">What's on your mind today?</span>
|
|
</div>
|
|
|
|
<!-- Notes -->
|
|
<div class="form-group">
|
|
<label for="notes">Notes</label>
|
|
<textarea id="notes" name="notes" rows="4" aria-describedby="notes-help">{{ log.notes or '' }}</textarea>
|
|
<span id="notes-help" class="form-help">Free-form notes for the day.</span>
|
|
</div>
|
|
|
|
<!-- Bullets / Items -->
|
|
<div class="bullets-section">
|
|
<h3>Bullets & Insights</h3>
|
|
<div id="bullets-list" class="bullets-list">
|
|
{% for item in log.items %}
|
|
<div class="bullet-item" data-item-id="{{ item.id }}">
|
|
<div class="bullet-item__row">
|
|
<select class="bullet-item__type" aria-label="Item type" data-item-id="{{ item.id }}">
|
|
<option value="bullet" {% if item.type == 'bullet' %}selected{% endif %}>Bullet</option>
|
|
<option value="task" {% if item.type == 'task' %}selected{% endif %}>Task</option>
|
|
<option value="note" {% if item.type == 'note' %}selected{% endif %}>Note</option>
|
|
</select>
|
|
<select class="bullet-item__symbol" aria-label="Symbol" data-item-id="{{ item.id }}">
|
|
<option value="•" {% if item.symbol == '•' %}selected{% endif %}>•</option>
|
|
<option value="-" {% if item.symbol == '-' %}selected{% endif %}>-</option>
|
|
<option value="o" {% if item.symbol == 'o' %}selected{% endif %}>o</option>
|
|
<option value="X" {% if item.symbol == 'X' %}selected{% endif %}>X</option>
|
|
</select>
|
|
<input type="text" class="bullet-item__text" value="{{ item.text }}" placeholder="Add a bullet..." aria-label="Bullet text" data-item-id="{{ item.id }}">
|
|
<select class="bullet-item__status" aria-label="Status" data-item-id="{{ item.id }}">
|
|
<option value="todo" {% if item.status == 'todo' %}selected{% endif %}>Todo</option>
|
|
<option value="doing" {% if item.status == 'doing' %}selected{% endif %}>Doing</option>
|
|
<option value="done" {% if item.status == 'done' %}selected{% endif %}>Done</option>
|
|
<option value="cancelled" {% if item.status == 'cancelled' %}selected{% endif %}>Cancelled</option>
|
|
</select>
|
|
<button class="btn btn-icon btn-delete" data-item-id="{{ item.id }}" aria-label="Delete bullet">×</button>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
<button class="btn btn-secondary" id="add-bullet-btn">+ Add Bullet</button>
|
|
</div>
|
|
|
|
<!-- Gratitude -->
|
|
<div class="gratitude-section">
|
|
<h3>Gratitude (3 things)</h3>
|
|
<div class="gratitude-grid">
|
|
{% set grat = log.gratitude_list %}
|
|
<div class="gratitude-item">
|
|
<label for="gratitude_0">1.</label>
|
|
<input type="text" id="gratitude_0" name="gratitude_0" value="{{ grat[0] if grat else '' }}" placeholder="I'm grateful for..." aria-label="Gratitude 1">
|
|
</div>
|
|
<div class="gratitude-item">
|
|
<label for="gratitude_1">2.</label>
|
|
<input type="text" id="gratitude_1" name="gratitude_1" value="{{ grat[1] if grat and grat|length > 1 else '' }}" placeholder="I'm grateful for..." aria-label="Gratitude 2">
|
|
</div>
|
|
<div class="gratitude-item">
|
|
<label for="gratitude_2">3.</label>
|
|
<input type="text" id="gratitude_2" name="gratitude_2" value="{{ grat[2] if grat and grat|length > 2 else '' }}" placeholder="I'm grateful for..." aria-label="Gratitude 3">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sleep -->
|
|
<div class="sleep-section">
|
|
<h3>Sleep</h3>
|
|
<div class="sleep-grid">
|
|
<div class="sleep-item">
|
|
<label for="bedtime">Bedtime</label>
|
|
<input type="text" id="bedtime" name="bedtime" value="{{ log.bedtime or '' }}" placeholder="e.g., 23:00" aria-label="Bedtime">
|
|
</div>
|
|
<div class="sleep-item">
|
|
<label for="wake_time">Wake time</label>
|
|
<input type="text" id="wake_time" name="wake_time" value="{{ log.wake_time or '' }}" placeholder="e.g., 07:00" aria-label="Wake time">
|
|
</div>
|
|
<div class="sleep-item">
|
|
<label for="sleep_quality">Sleep quality</label>
|
|
<select id="sleep_quality" name="sleep_quality" aria-label="Sleep quality">
|
|
<option value="">Select...</option>
|
|
<option value="poor" {% if log.sleep_quality == 'poor' %}selected{% endif %}>Poor</option>
|
|
<option value="fair" {% if log.sleep_quality == 'fair' %}selected{% endif %}>Fair</option>
|
|
<option value="good" {% if log.sleep_quality == 'good' %}selected{% endif %}>Good</option>
|
|
<option value="excellent" {% if log.sleep_quality == 'excellent' %}selected{% endif %}>Excellent</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mood -->
|
|
<div class="mood-section">
|
|
<h3>Mood</h3>
|
|
<div class="mood-selector">
|
|
<label for="mood">How are you feeling?</label>
|
|
<select id="mood" name="mood" aria-label="Mood">
|
|
<option value="">Select mood...</option>
|
|
<option value="great" {% if log.mood == 'great' %}selected{% endif %}>Great</option>
|
|
<option value="good" {% if log.mood == 'good' %}selected{% endif %}>Good</option>
|
|
<option value="okay" {% if log.mood == 'okay' %}selected{% endif %}>Okay</option>
|
|
<option value="bad" {% if log.mood == 'bad' %}selected{% endif %}>Bad</option>
|
|
<option value="terrible" {% if log.mood == 'terrible' %}selected{% endif %}>Terrible</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Save Button -->
|
|
<button type="button" class="btn btn-primary btn-block" id="save-log-btn">Save Log</button>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- Right Column: Coming Soon -->
|
|
<aside class="daily-log__future">
|
|
<article class="card card--future">
|
|
<p class="card__eyebrow">Coming Soon</p>
|
|
<h3>Calendar</h3>
|
|
<p class="future-text">Monthly grid view for quick navigation between logs.</p>
|
|
<div class="future-placeholder">
|
|
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
|
|
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
|
|
<line x1="16" y1="2" x2="16" y2="6"></line>
|
|
<line x1="8" y1="2" x2="8" y2="6"></line>
|
|
<line x1="3" y1="10" x2="21" y2="10"></line>
|
|
</svg>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="card card--future">
|
|
<p class="card__eyebrow">Coming Soon</p>
|
|
<h3>Task List</h3>
|
|
<p class="future-text">Cross-day task management with priorities and deadlines.</p>
|
|
<div class="future-placeholder">
|
|
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
|
|
<path d="M9 11l3 3L22 4"></path>
|
|
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
|
|
</svg>
|
|
</div>
|
|
</article>
|
|
</aside>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Footer -->
|
|
<footer class="page-footer">
|
|
<a href="{{ url_for('main.log_list') }}" class="btn btn-secondary">All Logs</a>
|
|
<a href="{{ url_for('main.export_logs') }}" class="btn btn-secondary">Export JSON</a>
|
|
<a href="{{ url_for('main.settings') }}" class="btn btn-secondary">Settings</a>
|
|
</footer>
|
|
</div>
|
|
|
|
<script>
|
|
// Add new bullet
|
|
document.getElementById('add-bullet-btn').addEventListener('click', function() {
|
|
const list = document.getElementById('bullets-list');
|
|
const newItem = document.createElement('div');
|
|
newItem.className = 'bullet-item';
|
|
newItem.dataset.itemId = '';
|
|
newItem.innerHTML = `
|
|
<div class="bullet-item__row">
|
|
<select class="bullet-item__type" aria-label="Item type">
|
|
<option value="bullet" selected>Bullet</option>
|
|
<option value="task">Task</option>
|
|
<option value="note">Note</option>
|
|
</select>
|
|
<select class="bullet-item__symbol" aria-label="Symbol">
|
|
<option value="•" selected>•</option>
|
|
<option value="-">-</option>
|
|
<option value="o">o</option>
|
|
<option value="X">X</option>
|
|
</select>
|
|
<input type="text" class="bullet-item__text" placeholder="Add a bullet..." aria-label="Bullet text">
|
|
<select class="bullet-item__status" aria-label="Status">
|
|
<option value="todo" selected>Todo</option>
|
|
<option value="doing">Doing</option>
|
|
<option value="done">Done</option>
|
|
<option value="cancelled">Cancelled</option>
|
|
</select>
|
|
<button class="btn btn-icon btn-delete" aria-label="Delete bullet">×</button>
|
|
</div>
|
|
`;
|
|
list.appendChild(newItem);
|
|
newItem.querySelector('.bullet-item__text').focus();
|
|
});
|
|
|
|
// Delete bullet
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.classList.contains('btn-delete')) {
|
|
const itemId = e.target.dataset.itemId;
|
|
if (itemId) {
|
|
fetch('/logs/items/' + itemId, { method: 'DELETE' })
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
e.target.closest('.bullet-item').remove();
|
|
}
|
|
});
|
|
} else {
|
|
e.target.closest('.bullet-item').remove();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Save log
|
|
document.getElementById('save-log-btn').addEventListener('click', function() {
|
|
const btn = this;
|
|
btn.textContent = 'Saving...';
|
|
btn.disabled = true;
|
|
|
|
// Collect bullets data
|
|
const bullets = [];
|
|
document.querySelectorAll('.bullet-item').forEach(function(item) {
|
|
bullets.push({
|
|
id: item.dataset.itemId || '',
|
|
type: item.querySelector('.bullet-item__type').value,
|
|
symbol: item.querySelector('.bullet-item__symbol').value,
|
|
text: item.querySelector('.bullet-item__text').value,
|
|
status: item.querySelector('.bullet-item__status').value
|
|
});
|
|
});
|
|
|
|
// Build form data
|
|
const formData = new FormData();
|
|
formData.append('date', '{{ log.date.isoformat() }}');
|
|
formData.append('prompt', document.getElementById('prompt').value);
|
|
formData.append('notes', document.getElementById('notes').value);
|
|
formData.append('bedtime', document.getElementById('bedtime').value);
|
|
formData.append('wake_time', document.getElementById('wake_time').value);
|
|
formData.append('sleep_quality', document.getElementById('sleep_quality').value);
|
|
formData.append('mood', document.getElementById('mood').value);
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
formData.append('gratitude_' + i, document.getElementById('gratitude_' + i).value);
|
|
}
|
|
|
|
bullets.forEach(function(bullet, index) {
|
|
formData.append('item_id[]', bullet.id);
|
|
formData.append('item_type[]', bullet.type);
|
|
formData.append('item_symbol[]', bullet.symbol);
|
|
formData.append('item_text[]', bullet.text);
|
|
formData.append('item_status[]', bullet.status);
|
|
});
|
|
|
|
fetch('/logs/{{ log.id }}/edit', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => {
|
|
btn.textContent = 'Save Log';
|
|
btn.disabled = false;
|
|
if (response.ok) {
|
|
window.location.reload();
|
|
} else {
|
|
alert('Failed to save log.');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
btn.textContent = 'Save Log';
|
|
btn.disabled = false;
|
|
alert('Failed to save log: ' + error.message);
|
|
});
|
|
});
|
|
|
|
// Auto-save on input change
|
|
document.querySelectorAll('input, textarea, select').forEach(function(el) {
|
|
if (el.id !== 'save-log-btn') {
|
|
el.addEventListener('change', function() {
|
|
// Trigger save on field change
|
|
document.getElementById('save-log-btn').click();
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |