/home/devscfvi/web.devsquantum.com/js/journal.js
// ============================================
// DAILY JOURNAL MODULE
// ============================================
// Render Journal Dashboard
function renderJournal() {
const entries = state.journalEntries || [];
const hasEntries = entries.length > 0;
const todayEntry = entries.find(e => e.entry_date === new Date().toISOString().split('T')[0]);
return `
<div class="min-h-screen p-4">
<div class="max-w-4xl mx-auto">
<!-- Header -->
<div class="mb-6 pt-4 flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-white mb-1">Trading Journal</h1>
<p class="text-sm text-violet-300">Daily reflections and insights</p>
</div>
<button onclick="openJournalModal()"
class="gradient-bg text-white px-4 py-2 rounded-xl font-semibold flex items-center gap-2 active:scale-95 transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
</svg>
${todayEntry ? "Edit Today" : "New Entry"}
</button>
</div>
${!hasEntries ? renderEmptyJournal() : `
<!-- Today's Prompt -->
${!todayEntry ? `
<div class="glass rounded-2xl p-6 mb-6 border border-blue-500/30 bg-blue-500/5">
<div class="flex items-start gap-4">
<div class="w-12 h-12 rounded-xl bg-blue-500/20 flex items-center justify-center flex-shrink-0">
<svg class="w-6 h-6 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
</div>
<div class="flex-1">
<p class="text-base text-white font-semibold mb-2">📝 Haven't journaled today yet</p>
<p class="text-sm text-slate-300 mb-3">Take a moment to reflect on your trading day. What went well? What can improve?</p>
<button onclick="openJournalModal()"
class="text-sm bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-semibold transition">
Write Today's Entry
</button>
</div>
</div>
</div>
` : ''}
<!-- Journal Entries -->
<div class="space-y-4">
${entries.map(entry => renderJournalEntry(entry)).join('')}
</div>
`}
</div>
</div>
`;
}
// Empty state
function renderEmptyJournal() {
return `
<div class="glass rounded-3xl p-12 text-center border border-violet-500/20">
<svg class="w-16 h-16 mx-auto text-violet-400/50 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>
<p class="text-lg text-white mb-2">No Journal Entries Yet</p>
<p class="text-sm text-slate-400 mb-6">Start documenting your trading journey with daily reflections</p>
<button onclick="openJournalModal()"
class="gradient-bg text-white px-6 py-3 rounded-xl font-semibold active:scale-95 transition">
Write Your First Entry
</button>
</div>
`;
}
// Render individual journal entry
function renderJournalEntry(entry) {
const isToday = entry.entry_date === new Date().toISOString().split('T')[0];
const date = new Date(entry.entry_date + 'T00:00:00');
const dayName = date.toLocaleDateString('en-US', { weekday: 'long' });
const formattedDate = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
return `
<div class="glass rounded-3xl p-6 border border-violet-500/20 ${isToday ? 'border-blue-500/30 bg-blue-500/5' : ''}">
<!-- Header -->
<div class="flex items-start justify-between mb-4">
<div class="flex-1">
<div class="flex items-center gap-2 mb-2">
<h3 class="text-xl font-bold text-white">${dayName}</h3>
${isToday ? '<span class="text-xs px-2 py-1 rounded-full bg-blue-500/20 text-blue-400 border border-blue-500/30">Today</span>' : ''}
</div>
<p class="text-sm text-slate-400">${formattedDate}</p>
</div>
<button onclick="openJournalModal('${entry.entry_date}')"
class="text-blue-400 hover:text-blue-300 p-2 transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
</button>
</div>
<!-- Quick Stats -->
${(entry.market_condition || entry.overall_emotion || entry.energy_level) ? `
<div class="grid grid-cols-3 gap-3 mb-4">
${entry.market_condition ? `
<div class="bg-slate-900/50 rounded-xl p-3 text-center border border-violet-500/20">
<p class="text-xs text-slate-400 mb-1">Market</p>
<p class="text-sm font-semibold text-white">${entry.market_condition}</p>
</div>
` : ''}
${entry.overall_emotion ? `
<div class="bg-slate-900/50 rounded-xl p-3 text-center border border-violet-500/20">
<p class="text-xs text-slate-400 mb-1">Emotion</p>
<p class="text-sm font-semibold text-white">${entry.overall_emotion}</p>
</div>
` : ''}
${entry.energy_level ? `
<div class="bg-slate-900/50 rounded-xl p-3 text-center border border-violet-500/20">
<p class="text-xs text-slate-400 mb-1">Energy</p>
<p class="text-sm font-semibold text-violet-400">${entry.energy_level}/10</p>
</div>
` : ''}
</div>
` : ''}
<!-- Content Sections -->
${entry.what_went_well ? `
<div class="mb-4 p-4 bg-green-500/10 rounded-xl border border-green-500/20">
<p class="text-sm text-green-300 font-semibold mb-2">✅ What Went Well</p>
<p class="text-sm text-white whitespace-pre-wrap">${entry.what_went_well}</p>
</div>
` : ''}
${entry.what_went_wrong ? `
<div class="mb-4 p-4 bg-red-500/10 rounded-xl border border-red-500/20">
<p class="text-sm text-red-300 font-semibold mb-2">❌ What Went Wrong</p>
<p class="text-sm text-white whitespace-pre-wrap">${entry.what_went_wrong}</p>
</div>
` : ''}
${entry.lessons_learned ? `
<div class="mb-4 p-4 bg-blue-500/10 rounded-xl border border-blue-500/20">
<p class="text-sm text-blue-300 font-semibold mb-2">💡 Lessons Learned</p>
<p class="text-sm text-white whitespace-pre-wrap">${entry.lessons_learned}</p>
</div>
` : ''}
${entry.tomorrow_focus ? `
<div class="p-4 bg-violet-500/10 rounded-xl border border-violet-500/20">
<p class="text-sm text-violet-300 font-semibold mb-2">🎯 Tomorrow's Focus</p>
<p class="text-sm text-white whitespace-pre-wrap">${entry.tomorrow_focus}</p>
</div>
` : ''}
</div>
`;
}
// Open journal modal
function openJournalModal(date = null) {
const entryDate = date || new Date().toISOString().split('T')[0];
const entries = state.journalEntries || [];
const existingEntry = entries.find(e => e.entry_date === entryDate);
const isToday = entryDate === new Date().toISOString().split('T')[0];
const modalContent = `
<div class="p-6 max-h-[85vh] overflow-y-auto">
<h2 class="text-2xl font-bold text-white mb-2">
${existingEntry ? 'Edit' : 'New'} Journal Entry
</h2>
<p class="text-violet-300 text-sm mb-6">
${isToday ? 'Today' : new Date(entryDate + 'T00:00:00').toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' })}
</p>
<!-- Date -->
<input type="hidden" id="journal-date" value="${entryDate}">
<!-- Quick Stats -->
<div class="grid grid-cols-3 gap-4 mb-4">
<div>
<label class="block text-sm font-medium text-violet-200 mb-2">Market Condition</label>
<select id="journal-market"
class="w-full px-4 py-3 bg-slate-900/50 border border-violet-500/30 rounded-xl text-white">
<option value="">Select...</option>
<option value="Trending" ${existingEntry?.market_condition === 'Trending' ? 'selected' : ''}>Trending</option>
<option value="Range-bound" ${existingEntry?.market_condition === 'Range-bound' ? 'selected' : ''}>Range-bound</option>
<option value="Volatile" ${existingEntry?.market_condition === 'Volatile' ? 'selected' : ''}>Volatile</option>
<option value="Quiet" ${existingEntry?.market_condition === 'Quiet' ? 'selected' : ''}>Quiet</option>
<option value="Choppy" ${existingEntry?.market_condition === 'Choppy' ? 'selected' : ''}>Choppy</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-violet-200 mb-2">Overall Emotion</label>
<select id="journal-emotion"
class="w-full px-4 py-3 bg-slate-900/50 border border-violet-500/30 rounded-xl text-white">
<option value="">Select...</option>
<option value="Confident" ${existingEntry?.overall_emotion === 'Confident' ? 'selected' : ''}>Confident</option>
<option value="Calm" ${existingEntry?.overall_emotion === 'Calm' ? 'selected' : ''}>Calm</option>
<option value="Anxious" ${existingEntry?.overall_emotion === 'Anxious' ? 'selected' : ''}>Anxious</option>
<option value="Frustrated" ${existingEntry?.overall_emotion === 'Frustrated' ? 'selected' : ''}>Frustrated</option>
<option value="Excited" ${existingEntry?.overall_emotion === 'Excited' ? 'selected' : ''}>Excited</option>
<option value="FOMO" ${existingEntry?.overall_emotion === 'FOMO' ? 'selected' : ''}>FOMO</option>
<option value="Greedy" ${existingEntry?.overall_emotion === 'Greedy' ? 'selected' : ''}>Greedy</option>
<option value="Fearful" ${existingEntry?.overall_emotion === 'Fearful' ? 'selected' : ''}>Fearful</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-violet-200 mb-2">Energy Level</label>
<input type="number" id="journal-energy" min="1" max="10"
value="${existingEntry?.energy_level || ''}"
placeholder="1-10"
class="w-full px-4 py-3 bg-slate-900/50 border border-violet-500/30 rounded-xl text-white">
</div>
</div>
<!-- Reflection Questions -->
<div class="mb-4">
<label class="block text-sm font-medium text-green-300 mb-2">✅ What Went Well Today?</label>
<textarea id="journal-well" rows="3"
class="w-full px-4 py-3 bg-slate-900/50 border border-green-500/30 rounded-xl text-white placeholder-slate-500 focus:border-green-400"
placeholder="Wins, good decisions, moments of discipline...">${existingEntry?.what_went_well || ''}</textarea>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-red-300 mb-2">❌ What Went Wrong Today?</label>
<textarea id="journal-wrong" rows="3"
class="w-full px-4 py-3 bg-slate-900/50 border border-red-500/30 rounded-xl text-white placeholder-slate-500 focus:border-red-400"
placeholder="Losses, mistakes, poor decisions...">${existingEntry?.what_went_wrong || ''}</textarea>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-blue-300 mb-2">💡 Lessons Learned</label>
<textarea id="journal-lessons" rows="3"
class="w-full px-4 py-3 bg-slate-900/50 border border-blue-500/30 rounded-xl text-white placeholder-slate-500 focus:border-blue-400"
placeholder="What did you learn? What patterns do you notice?">${existingEntry?.lessons_learned || ''}</textarea>
</div>
<div class="mb-6">
<label class="block text-sm font-medium text-violet-300 mb-2">🎯 Tomorrow's Focus</label>
<textarea id="journal-focus" rows="2"
class="w-full px-4 py-3 bg-slate-900/50 border border-violet-500/30 rounded-xl text-white placeholder-slate-500 focus:border-violet-400"
placeholder="What will you focus on tomorrow?">${existingEntry?.tomorrow_focus || ''}</textarea>
</div>
<!-- Buttons -->
<button onclick="saveJournalEntry()"
class="w-full gradient-bg text-white py-4 rounded-xl font-bold text-lg shadow-lg active:scale-95 transition mb-3">
Save Entry
</button>
<button onclick="closeAllModals()"
class="w-full bg-slate-700 hover:bg-slate-600 text-white py-3 rounded-xl font-semibold active:scale-95 transition">
Cancel
</button>
</div>
`;
createModal(modalContent, 'max-w-3xl');
}
// Save journal entry
async function saveJournalEntry() {
const entryData = {
entryDate: document.getElementById('journal-date').value,
marketCondition: document.getElementById('journal-market').value || null,
overallEmotion: document.getElementById('journal-emotion').value || null,
energyLevel: document.getElementById('journal-energy').value || null,
whatWentWell: document.getElementById('journal-well').value,
whatWentWrong: document.getElementById('journal-wrong').value,
lessonsLearned: document.getElementById('journal-lessons').value,
tomorrowFocus: document.getElementById('journal-focus').value
};
const result = await apiPost('saveJournalEntry', entryData);
if (result.success) {
showToast('Journal entry saved! 📖', 'success');
closeAllModals();
loadJournal();
} else {
showToast('Failed to save entry', 'error');
}
}
// Initialize Journal
function initJournalCharts() {
// Placeholder for future analytics on journal data
}
// Make functions global
window.renderJournal = renderJournal;
window.initJournalCharts = initJournalCharts;
window.openJournalModal = openJournalModal;
window.saveJournalEntry = saveJournalEntry;