/home/devscfvi/crypto.devsquantum.com/js/mistakes.js
// ============================================
// MISTAKES LIBRARY MODULE
// ============================================
// Render Mistakes Library
function renderMistakes() {
if (!state.mistakes) {
return `
<div class="min-h-screen p-4">
<div class="max-w-2xl mx-auto">
<div class="mb-6 pt-4">
<h1 class="text-2xl font-bold text-white">Mistakes Library</h1>
<p class="text-violet-300">Loading your mistakes...</p>
</div>
<div class="flex items-center justify-center py-12">
<div class="spinner"></div>
</div>
</div>
</div>
`;
}
const hasData = state.mistakes.mistakes && state.mistakes.mistakes.length > 0;
return `
<div class="min-h-screen p-4">
<div class="max-w-4xl mx-auto">
<!-- Header -->
<div class="mb-6 pt-4">
<h1 class="text-2xl font-bold text-white mb-1">Mistakes Library</h1>
<p class="text-sm text-violet-300">Learn from your errors and improve</p>
</div>
${!hasData ? renderEmptyMistakes() : `
<!-- Tab Navigation -->
<div class="glass rounded-2xl p-2 mb-6 border border-violet-500/20">
<div class="grid grid-cols-3 gap-2">
<button onclick="switchMistakesTab('analysis')"
id="mistake-tab-analysis"
class="mistakes-tab py-3 rounded-xl font-semibold transition text-sm">
Analysis
</button>
<button onclick="switchMistakesTab('library')"
id="mistake-tab-library"
class="mistakes-tab py-3 rounded-xl font-semibold transition text-sm">
Library
</button>
<button onclick="switchMistakesTab('patterns')"
id="mistake-tab-patterns"
class="mistakes-tab py-3 rounded-xl font-semibold transition text-sm">
Patterns
</button>
</div>
</div>
<!-- Tab Content -->
<div id="mistakes-content"></div>
`}
</div>
</div>
`;
}
// Empty state
function renderEmptyMistakes() {
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="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<p class="text-lg text-white mb-2">No Mistakes Yet</p>
<p class="text-sm text-slate-400 mb-4">Start tracking mistakes to see insights</p>
<button onclick="navigateTo('history')"
class="gradient-bg text-white px-6 py-3 rounded-xl font-semibold active:scale-95 transition">
View Trades
</button>
</div>
`;
}
// Switch between tabs
let currentMistakesTab = 'analysis';
function switchMistakesTab(tab) {
currentMistakesTab = tab;
// Update tab buttons
document.querySelectorAll('.mistakes-tab').forEach(btn => {
const btnTab = btn.id.replace('mistake-tab-', '');
if (btnTab === tab) {
btn.classList.add('bg-violet-600', 'text-white');
btn.classList.remove('bg-slate-900/50', 'text-slate-400');
} else {
btn.classList.remove('bg-violet-600', 'text-white');
btn.classList.add('bg-slate-900/50', 'text-slate-400');
}
});
// Render content
const container = document.getElementById('mistakes-content');
if (!container) return;
switch(tab) {
case 'analysis':
container.innerHTML = renderMistakesAnalysis();
setTimeout(() => initMistakesCharts(), 100);
break;
case 'library':
container.innerHTML = renderMistakesLibrary();
break;
case 'patterns':
container.innerHTML = renderMistakesPatterns();
break;
}
}
// ============================================
// ANALYSIS TAB
// ============================================
function renderMistakesAnalysis() {
const mistakes = state.mistakes.mistakes || [];
// Map database columns to expected format
const formattedMistakes = mistakes.map(m => ({
mistake_type: m.mistake_type,
count: parseInt(m.occurrence_count || m.count || 0),
total_impact: parseFloat(m.total_loss_amount || m.total_impact || 0) * -1 // Make negative for display
}));
// Calculate totals
const totalMistakes = formattedMistakes.reduce((sum, m) => sum + m.count, 0);
const totalImpact = formattedMistakes.reduce((sum, m) => sum + m.total_impact, 0);
const costPerMistake = totalMistakes > 0 ? totalImpact / totalMistakes : 0;
// Get worst mistake
const worstMistake = formattedMistakes.length > 0
? formattedMistakes.reduce((worst, m) => m.total_impact < worst.total_impact ? m : worst)
: null;
return `
<div class="space-y-4">
<!-- Summary Cards -->
<div class="grid grid-cols-3 gap-4">
<div class="glass rounded-2xl p-5 border border-red-500/20">
<p class="text-xs text-red-300 mb-1">Total Mistakes</p>
<p class="text-4xl font-bold text-red-400">${totalMistakes}</p>
<p class="text-xs text-slate-400 mt-1">${formattedMistakes.length} types</p>
</div>
<div class="glass rounded-2xl p-5 border border-red-500/20">
<p class="text-xs text-red-300 mb-1">Total Impact</p>
<p class="text-3xl font-bold text-red-400">${formatCurrency(totalImpact)}</p>
<p class="text-xs text-slate-400 mt-1">Lost to mistakes</p>
</div>
<div class="glass rounded-2xl p-5 border border-orange-500/20">
<p class="text-xs text-orange-300 mb-1">Cost Per Mistake</p>
<p class="text-3xl font-bold text-orange-400">${formatCurrency(costPerMistake)}</p>
<p class="text-xs text-slate-400 mt-1">Average loss</p>
</div>
</div>
${worstMistake ? `
<!-- Biggest Problem -->
<div class="glass rounded-3xl p-6 border border-red-500/20 bg-red-500/5">
<div class="flex items-start justify-between">
<div>
<p class="text-sm text-red-300 mb-2">🚨 Your Biggest Problem</p>
<p class="text-2xl font-bold text-white mb-2">${worstMistake.mistake_type}</p>
<p class="text-sm text-slate-400">${worstMistake.count} times • ${formatCurrency(worstMistake.total_impact)} impact</p>
</div>
<button onclick="viewMistakeDetails('${worstMistake.mistake_type}')"
class="bg-red-600 text-white px-4 py-2 rounded-xl text-sm font-semibold hover:bg-red-700 transition">
Fix This
</button>
</div>
</div>
` : ''}
<!-- Mistakes by Frequency -->
<div class="glass rounded-3xl p-6 border border-violet-500/20">
<h3 class="text-lg font-semibold text-white mb-4">Mistakes by Frequency</h3>
${formattedMistakes.length > 0 ? `
<div class="space-y-3">
${formattedMistakes.sort((a, b) => b.count - a.count).map(mistake => `
<div class="bg-slate-900/50 rounded-xl p-4 border border-red-500/20">
<div class="flex items-center justify-between mb-2">
<div class="flex-1">
<p class="text-lg font-bold text-white">${mistake.mistake_type}</p>
<p class="text-xs text-slate-400 mt-1">${mistake.count} occurrences</p>
</div>
<div class="text-right">
<p class="text-xl font-bold text-red-400">${formatCurrency(mistake.total_impact)}</p>
<p class="text-xs text-slate-400">impact</p>
</div>
</div>
<div class="w-full bg-slate-800 rounded-full h-2 mt-2">
<div class="h-2 rounded-full bg-red-500"
style="width: ${totalMistakes > 0 ? (mistake.count / totalMistakes * 100).toFixed(0) : 0}%"></div>
</div>
</div>
`).join('')}
</div>
` : '<p class="text-slate-400 text-center py-4">No mistakes data</p>'}
</div>
<!-- Mistakes Chart -->
${formattedMistakes.length > 0 ? `
<div class="glass rounded-3xl p-6 border border-violet-500/20">
<h3 class="text-lg font-semibold text-white mb-4">Impact Breakdown</h3>
<div style="height: 300px;">
<canvas id="mistakesChart"></canvas>
</div>
</div>
` : ''}
</div>
`;
}
function initMistakesCharts() {
const mistakes = state.mistakes.mistakes || [];
if (mistakes.length === 0) return;
// Format data to match database columns
const formattedMistakes = mistakes.map(m => ({
mistake_type: m.mistake_type,
count: parseInt(m.occurrence_count || m.count || 0),
total_impact: Math.abs(parseFloat(m.total_loss_amount || m.total_impact || 0))
}));
const canvas = document.getElementById('mistakesChart');
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (window.mistakesChart && typeof window.mistakesChart.destroy === 'function') {
window.mistakesChart.destroy();
}
window.mistakesChart = new Chart(ctx, {
type: 'bar',
data: {
labels: formattedMistakes.map(m => m.mistake_type),
datasets: [{
label: 'Financial Impact',
data: formattedMistakes.map(m => m.total_impact),
backgroundColor: '#ef4444',
borderRadius: 8
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: 12,
callbacks: {
label: (context) => '-$' + context.parsed.y.toFixed(2)
}
}
},
scales: {
y: {
beginAtZero: true,
grid: { color: 'rgba(139, 92, 246, 0.1)' },
ticks: {
color: '#a78bfa',
callback: (value) => '$' + value.toFixed(0)
}
},
x: {
grid: { display: false },
ticks: {
color: '#a78bfa',
font: { size: 10 },
maxRotation: 45,
minRotation: 45
}
}
}
}
});
}
// ============================================
// LIBRARY TAB
// ============================================
function renderMistakesLibrary() {
const mistakeTypes = state.mistakes.mistakeTypes || [];
// Group by category
const categories = {};
mistakeTypes.forEach(mistake => {
if (!categories[mistake.category]) {
categories[mistake.category] = [];
}
categories[mistake.category].push(mistake);
});
const categoryColors = {
'Timing': 'blue',
'Risk Management': 'red',
'Profit Management': 'green',
'Psychology': 'purple',
'Planning': 'yellow',
'Analysis': 'orange'
};
return `
<div class="space-y-4">
<div class="glass rounded-2xl p-4 border border-violet-500/20">
<p class="text-sm text-slate-300">
📚 Complete library of common trading mistakes with solutions and prevention tips.
Use this as a reference when reviewing trades.
</p>
</div>
${Object.keys(categories).map(category => `
<div class="glass rounded-3xl p-6 border border-violet-500/20">
<div class="flex items-center gap-2 mb-4">
<div class="w-3 h-3 rounded-full bg-${categoryColors[category] || 'violet'}-500"></div>
<h3 class="text-lg font-semibold text-white">${category}</h3>
<span class="text-xs text-slate-400">(${categories[category].length} mistakes)</span>
</div>
<div class="space-y-3">
${categories[category].map(mistake => `
<div class="bg-slate-900/50 rounded-xl p-4 border border-${categoryColors[category] || 'violet'}-500/20">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<p class="text-base font-bold text-white">${mistake.mistake_name}</p>
<p class="text-sm text-slate-400 mt-1">${mistake.description}</p>
</div>
</div>
<div class="mt-3 p-3 bg-green-500/10 rounded-lg border border-green-500/20">
<p class="text-xs text-green-300 font-semibold mb-1">💡 Solution:</p>
<p class="text-sm text-green-200">${mistake.solution}</p>
</div>
</div>
`).join('')}
</div>
</div>
`).join('')}
</div>
`;
}
// ============================================
// PATTERNS TAB
// ============================================
function renderMistakesPatterns() {
const mistakes = state.mistakes.mistakes || [];
if (mistakes.length === 0) {
return `
<div class="glass rounded-3xl p-12 text-center border border-violet-500/20">
<p class="text-slate-400">Not enough data to identify patterns yet.</p>
<p class="text-sm text-slate-500 mt-2">Keep tracking mistakes to see patterns emerge.</p>
</div>
`;
}
// Group by category for pattern analysis
const mistakeTypes = state.mistakes.mistakeTypes || [];
const categoryGroups = {};
mistakes.forEach(m => {
const mistakeType = mistakeTypes.find(mt => mt.mistake_name === m.mistake_type);
const category = mistakeType ? mistakeType.category : 'Other';
if (!categoryGroups[category]) {
categoryGroups[category] = { count: 0, impact: 0 };
}
categoryGroups[category].count += parseInt(m.count);
categoryGroups[category].impact += parseFloat(m.total_impact || 0);
});
return `
<div class="space-y-4">
<!-- Pattern Overview -->
<div class="glass rounded-3xl p-6 border border-violet-500/20">
<h3 class="text-lg font-semibold text-white mb-4">Mistake Categories</h3>
<div class="space-y-3">
${Object.entries(categoryGroups).map(([category, data]) => `
<div class="bg-slate-900/50 rounded-xl p-4 border border-violet-500/20">
<div class="flex items-center justify-between mb-2">
<p class="text-base font-bold text-white">${category}</p>
<p class="text-sm font-semibold text-red-400">${formatCurrency(data.impact)}</p>
</div>
<div class="flex items-center justify-between text-xs text-slate-400">
<span>${data.count} occurrences</span>
<span>Avg: ${formatCurrency(data.impact / data.count)}</span>
</div>
<div class="w-full bg-slate-800 rounded-full h-2 mt-2">
<div class="h-2 rounded-full bg-red-500"
style="width: ${Math.min(100, Math.abs(data.impact / 100) * 10)}%"></div>
</div>
</div>
`).join('')}
</div>
</div>
<!-- Insights -->
<div class="glass rounded-3xl p-6 border border-blue-500/20">
<h3 class="text-lg font-semibold text-white mb-4">💡 Key Insights</h3>
<div class="space-y-3">
${(() => {
const sortedCategories = Object.entries(categoryGroups)
.sort(([,a], [,b]) => a.impact - b.impact);
const worstCategory = sortedCategories[0];
const mostFrequent = Object.entries(categoryGroups)
.sort(([,a], [,b]) => b.count - a.count)[0];
return `
<div class="bg-red-500/10 rounded-xl p-4 border border-red-500/20">
<p class="text-sm text-red-300 font-semibold mb-2">⚠️ Biggest Impact Category</p>
<p class="text-lg font-bold text-white">${worstCategory[0]}</p>
<p class="text-sm text-slate-400 mt-1">
${worstCategory[1].count} mistakes costing ${formatCurrency(worstCategory[1].impact)}
</p>
</div>
<div class="bg-orange-500/10 rounded-xl p-4 border border-orange-500/20">
<p class="text-sm text-orange-300 font-semibold mb-2">🔄 Most Frequent Pattern</p>
<p class="text-lg font-bold text-white">${mostFrequent[0]}</p>
<p class="text-sm text-slate-400 mt-1">
Happened ${mostFrequent[1].count} times - needs immediate attention
</p>
</div>
<div class="bg-blue-500/10 rounded-xl p-4 border border-blue-500/20">
<p class="text-sm text-blue-300 font-semibold mb-2">📊 Recommendation</p>
<p class="text-sm text-slate-300">
Focus on ${worstCategory[0].toLowerCase()} mistakes first.
Review your ${mostFrequent[0].toLowerCase()} pattern and implement
preventive measures from the Library tab.
</p>
</div>
`;
})()}
</div>
</div>
</div>
`;
}
// View mistake details
function viewMistakeDetails(mistakeType) {
const mistakeTypes = state.mistakes.mistakeTypes || [];
const mistake = mistakeTypes.find(m => m.mistake_name === mistakeType);
if (!mistake) return;
const modal = createModal(`
<div class="p-6">
<h2 class="text-2xl font-bold text-white mb-4">${mistake.mistake_name}</h2>
<div class="space-y-4">
<div>
<p class="text-sm text-slate-400 mb-1">Category</p>
<p class="text-base text-white">${mistake.category}</p>
</div>
<div>
<p class="text-sm text-slate-400 mb-1">Description</p>
<p class="text-base text-white">${mistake.description}</p>
</div>
<div class="p-4 bg-green-500/10 rounded-xl border border-green-500/20">
<p class="text-sm text-green-300 font-semibold mb-2">💡 Solution</p>
<p class="text-base text-green-200">${mistake.solution}</p>
</div>
<div class="p-4 bg-blue-500/10 rounded-xl border border-blue-500/20">
<p class="text-sm text-blue-300 font-semibold mb-2">📝 Action Items</p>
<ul class="text-sm text-blue-200 space-y-1 list-disc list-inside">
<li>Review trades where this mistake occurred</li>
<li>Add reminder to your trading checklist</li>
<li>Practice prevention in demo account</li>
</ul>
</div>
</div>
<button onclick="closeAllModals()"
class="w-full mt-6 gradient-bg text-white py-3 rounded-xl font-semibold">
Got It
</button>
</div>
`);
}
// Initialize Mistakes
function initMistakesCharts() {
switchMistakesTab(currentMistakesTab || 'analysis');
}
// Make functions global
window.renderMistakes = renderMistakes;
window.initMistakesCharts = initMistakesCharts;
window.switchMistakesTab = switchMistakesTab;
window.viewMistakeDetails = viewMistakeDetails;