Add My Progress tab: personal ROI dashboard with phase tracker, ladder visualization, and milestone tracking

This commit is contained in:
Marty Bostick
2026-07-29 15:32:48 +00:00
parent c226591337
commit cfd0f47f50
+384 -4
View File
@@ -767,11 +767,202 @@
font-size: 0.75rem;
}
.calc-footer a {
color: var(--accent);
text-decoration: none;
color: var(--accent);
text-decoration: none;
}
.calc-footer a:hover {
text-decoration: underline;
}
/* ══════════════════════════════════════════════════════════
ROI DASHBOARD
ROI DASHBOARD
══════════════════════════════════════════════════════════ */
.roi-dashboard {
max-width: 720px;
margin: 0 auto;
padding: 10px 0;
}
.calc-footer a:hover {
text-decoration: underline;
.roi-dashboard h3 {
color: var(--accent);
font-size: 1.2rem;
margin: 0 0 4px;
}
.roi-subtitle {
font-size: 0.85rem;
color: var(--text-secondary);
margin: 0 0 20px;
}
.roi-inputs {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 20px;
}
@media (max-width: 560px) {
.roi-inputs { grid-template-columns: 1fr; }
}
.roi-field label {
display: block;
font-size: 0.78rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-secondary);
margin-bottom: 5px;
}
.roi-field input,
.roi-field select {
width: 100%;
padding: 10px 12px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--bg);
color: var(--text);
font-size: 0.95rem;
font-family: inherit;
box-sizing: border-box;
}
.roi-field select {
cursor: pointer;
}
.roi-field input:focus,
.roi-field select:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(108,92,231,0.2);
}
.roi-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 24px;
}
@media (max-width: 600px) {
.roi-stats { grid-template-columns: repeat(2, 1fr); }
}
.roi-stat-card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 14px 12px;
text-align: center;
}
.roi-stat-label {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--text-secondary);
margin-bottom: 6px;
}
.roi-stat-value {
font-size: 1.5rem;
font-weight: 700;
color: var(--accent);
}
.roi-stat-bar {
height: 5px;
background: var(--border);
border-radius: 3px;
margin-top: 10px;
overflow: hidden;
}
.roi-bar-fill {
height: 100%;
width: 0%;
background: linear-gradient(90deg, #6c5ce7, #a78bfa);
border-radius: 3px;
transition: width 0.4s ease;
}
.roi-phase-tracker {
margin-bottom: 24px;
}
.roi-phase-title {
font-size: 0.92rem;
font-weight: 600;
color: var(--text);
margin-bottom: 12px;
}
.roi-ladder {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.roi-ladder-step {
padding: 6px 14px;
border-radius: 20px;
font-size: 0.82rem;
font-weight: 600;
background: var(--bg);
border: 1px solid var(--border);
color: var(--text-muted);
opacity: 0.5;
transition: all 0.3s;
}
.roi-ladder-step.active {
background: rgba(108,92,231,0.2);
border-color: var(--accent);
color: var(--accent);
opacity: 1;
}
.roi-ladder-step.endgame {
border-color: #fbbf24;
color: #fbbf24;
opacity: 0.6;
}
.roi-ladder-step.endgame.active {
background: rgba(251,191,36,0.15);
border-color: #fbbf24;
color: #fbbf24;
opacity: 1;
}
.roi-ladder-step.passed {
opacity: 0.7;
color: #34d399;
border-color: #34d399;
}
.roi-milestones {
margin-bottom: 20px;
}
.roi-milestone-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.roi-milestone-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
font-size: 0.88rem;
}
.roi-milestone-icon {
font-size: 1.3rem;
flex-shrink: 0;
}
.roi-milestone-info {
flex: 1;
}
.roi-milestone-info .label {
font-weight: 600;
color: var(--text);
}
.roi-milestone-info .sub {
font-size: 0.8rem;
color: var(--text-secondary);
}
.roi-milestone-checked .milestone-check {
color: #34d399;
}
.roi-milestone-check {
font-size: 1.1rem;
flex-shrink: 0;
}
/* ══════════════════════════════════════════════════════════
@@ -1036,6 +1227,7 @@
<button class="tab-btn" data-tab="ladder">🪜 Full Ladder</button>
<button class="tab-btn" data-tab="comparison">⚖️ Compare</button>
<button class="tab-btn" data-tab="guide">📖 Sponsor Guide</button>
<button class="tab-btn" data-tab="progress">💰 My Progress</button>
</div>
<div class="results active" id="tab-overview">
@@ -1109,6 +1301,83 @@
</div>
</div>
<div class="results" id="tab-progress">
<div class="roi-dashboard">
<h3>💰 Your Personal ROI Dashboard</h3>
<p class="roi-subtitle">Track your progress from first deposit to 3× L7 endgame. All figures in USDT.</p>
<!-- Input Row -->
<div class="roi-inputs">
<div class="roi-field">
<label>Total Deposited (out-of-pocket)</label>
<input type="number" id="roiDeposits" value="450" step="10" min="0">
</div>
<div class="roi-field">
<label>Total Earned All Time</label>
<input type="number" id="roiTotalEarned" value="371.33" step="0.01" min="0">
</div>
<div class="roi-field">
<label>Campaign Phase</label>
<select id="roiPhase">
<option value="l4l3" selected>L4 + L3 Hybrid</option>
<option value="l5l3">L5 + L3 Hybrid</option>
<option value="l6l3">L6 + L3 Hybrid</option>
<option value="l7solo">L7 Solo</option>
<option value="l7x3">3× L7 Endgame</option>
</select>
</div>
<div class="roi-field">
<label>Cycles Completed This Phase</label>
<input type="number" id="roiCyclesDone" value="0" step="1" min="0">
</div>
</div>
<!-- Stats Cards Row -->
<div class="roi-stats">
<div class="roi-stat-card" id="roiStatROI">
<div class="roi-stat-label">ROI</div>
<div class="roi-stat-value">—</div>
<div class="roi-stat-bar"><div class="roi-bar-fill" id="roiBarROI"></div></div>
</div>
<div class="roi-stat-card" id="roiStatRecouped">
<div class="roi-stat-label">Recouped</div>
<div class="roi-stat-value">—</div>
</div>
<div class="roi-stat-card" id="roiStatRemaining">
<div class="roi-stat-label">To Breakeven</div>
<div class="roi-stat-value">—</div>
</div>
<div class="roi-stat-card" id="roiStatPhase">
<div class="roi-stat-label">Phase Progress</div>
<div class="roi-stat-value">—</div>
<div class="roi-stat-bar"><div class="roi-bar-fill" id="roiBarPhase"></div></div>
</div>
</div>
<!-- Phase Tracker -->
<div class="roi-phase-tracker">
<div class="roi-phase-title">🪜 Your Ladder — Where You Are vs Endgame</div>
<div class="roi-ladder" id="roiLadder">
<div class="roi-ladder-step" data-phase="l1">L1</div>
<div class="roi-ladder-step" data-phase="l2">L2</div>
<div class="roi-ladder-step" data-phase="l3">L3</div>
<div class="roi-ladder-step" data-phase="l4">L4</div>
<div class="roi-ladder-step active" data-phase="l4l3">L4+L3</div>
<div class="roi-ladder-step" data-phase="l5l3">L5+L3</div>
<div class="roi-ladder-step" data-phase="l6l3">L6+L3</div>
<div class="roi-ladder-step" data-phase="l7solo">L7</div>
<div class="roi-ladder-step endgame" data-phase="l7x3">🏆 3× L7</div>
</div>
</div>
<!-- Milestones -->
<div class="roi-milestones">
<div class="roi-phase-title">🏁 Milestones</div>
<div class="roi-milestone-list" id="roiMilestones"></div>
</div>
</div>
</div>
<div class="results" id="tab-guide">
<div style="max-width:680px;margin:0 auto;padding:8px 0;">
<h3 style="margin:0 0 10px;color:var(--accent);font-size:1.15rem;">📖 How to Use This Calculator as a Sponsor</h3>
@@ -1802,6 +2071,117 @@ function copyPlan() {
});
setTimeout(generatePlan, 100);
// ─── ROI Dashboard ──────────────────────────────────────
function updateROI() {
const deposits = parseFloat(document.getElementById('roiDeposits').value) || 0;
const earned = parseFloat(document.getElementById('roiTotalEarned').value) || 0;
const phase = document.getElementById('roiPhase').value;
const cyclesDone = parseInt(document.getElementById('roiCyclesDone').value) || 0;
// Phase data: [cycles_this_phase, cycles_needed_for_next, profit_per_cycle, next_phase_label]
const PHASE_DATA = {
l4l3: { cycles: 5, profitPer: 133.20, nextLabel: 'L5+L3', needsCapital: 660 },
l5l3: { cycles: 3, profitPer: 222.00, nextLabel: 'L6+L3', needsCapital: 1320 },
l6l3: { cycles: 3, profitPer: 399.60, nextLabel: 'L7 Solo', needsCapital: 2640 },
l7solo: { cycles: 7, profitPer: 840.00, nextLabel: '3× L7 Endgame', needsCapital: 7200 },
l7x3: { cycles: 999, profitPer: 2520.00, nextLabel: null, needsCapital: 0 },
};
// ROI stats
const roiPct = deposits > 0 ? Math.min((earned / deposits) * 100, 100) : 0;
const recouped = Math.min(earned, deposits);
const remaining = Math.max(deposits - earned, 0);
document.getElementById('roiStatROI').querySelector('.roi-stat-value').textContent = roiPct.toFixed(1) + '%';
document.getElementById('roiStatRecouped').querySelector('.roi-stat-value').textContent = '$' + recouped.toFixed(2);
document.getElementById('roiStatRemaining').querySelector('.roi-stat-value').textContent = '$' + remaining.toFixed(2);
document.getElementById('roiBarROI').style.width = roiPct + '%';
// Phase progress
const pd = PHASE_DATA[phase];
let phasePct = 0;
let phaseLabel = '';
if (phase === 'l7x3') {
phasePct = 100;
phaseLabel = '🏆 Endgame Reached';
} else {
phasePct = Math.min((cyclesDone / pd.cycles) * 100, 100);
phaseLabel = `Cycle ${cyclesDone} of ${pd.cycles}`;
}
document.getElementById('roiStatPhase').querySelector('.roi-stat-value').textContent = phaseLabel;
document.getElementById('roiBarPhase').style.width = phasePct + '%';
// Ladder visualization
const ladderOrder = ['l1','l2','l3','l4','l4l3','l5l3','l6l3','l7solo','l7x3'];
const phaseIndex = ladderOrder.indexOf(phase);
document.querySelectorAll('.roi-ladder-step').forEach(el => {
el.classList.remove('active', 'passed');
const idx = ladderOrder.indexOf(el.dataset.phase);
if (idx < phaseIndex) el.classList.add('passed');
else if (idx === phaseIndex) el.classList.add('active');
});
// Milestones
const milestones = [];
if (earned >= 112.50) milestones.push({ icon: '✅', label: '25% ROI Recouped', sub: 'Quarter of your capital back' });
if (earned >= 225) milestones.push({ icon: '✅', label: '50% ROI Recouped', sub: 'Half your capital is back' });
if (earned >= 337.50) milestones.push({ icon: '✅', label: '75% ROI Recouped', sub: 'Three quarters there' });
if (earned >= deposits) milestones.push({ icon: '💰', label: '100% ROI — Breakeven!', sub: 'Everything from here is pure profit' });
if (phase === 'l5l3' || phaseIndex > ladderOrder.indexOf('l5l3'))
milestones.push({ icon: '🏅', label: 'L5 Active', sub: 'You reached the serious scaling tier' });
if (phase === 'l6l3' || phaseIndex > ladderOrder.indexOf('l6l3'))
milestones.push({ icon: '🏅', label: 'L6 Active', sub: 'Double-digit clicks/day territory' });
if (phase === 'l7solo' || phaseIndex > ladderOrder.indexOf('l7solo'))
milestones.push({ icon: '🌟', label: 'L7 — The Big One', sub: '$840/cycle profit, $270/day clicks' });
if (phase === 'l7x3')
milestones.push({ icon: '🏆', label: '3× L7 Endgame', sub: '$2,520/cycle profit — the machine is running' });
// Add next phase preview
if (pd.nextLabel && cyclesDone >= pd.cycles) {
milestones.push({
icon: '🚀',
label: `Ready for ${pd.nextLabel}`,
sub: `You need ~$${pd.needsCapital.toLocaleString()} in available funds to start`
});
}
// Show unearned milestones as dimmed
const allMilestones = [
{ icon: '🔘', label: '25% ROI Recouped', sub: '$112.50', earned: earned >= 112.50 },
{ icon: '🔘', label: '50% ROI Recouped', sub: '$225.00', earned: earned >= 225 },
{ icon: '🔘', label: '75% ROI Recouped', sub: '$337.50', earned: earned >= 337.50 },
{ icon: '💰', label: '100% ROI — Breakeven', sub: `$${deposits.toFixed(2)}`, earned: earned >= deposits },
];
if (phase === 'l7x3') {
allMilestones.push({ icon: '🏆', label: '3× L7 Endgame Reached', sub: '$2,520/cycle passive', earned: true });
} else if (pd.nextLabel) {
allMilestones.push({ icon: '🚀', label: `Ready for ${pd.nextLabel}`, sub: `Need ~$${pd.needsCapital.toLocaleString()}`, earned: cyclesDone >= pd.cycles });
}
document.getElementById('roiMilestones').innerHTML = allMilestones.map(m => `
<div class="roi-milestone-item${m.earned ? ' roi-milestone-checked' : ''}" style="${m.earned ? '' : 'opacity:0.5;'}">
<span class="roi-milestone-check" style="font-size:1.1rem;flex-shrink:0;">${m.icon}</span>
<div class="roi-milestone-info">
<div class="label">${m.label}</div>
<div class="sub">${m.sub}</div>
</div>
</div>
`).join('');
}
// Wire up ROI inputs
['roiDeposits','roiTotalEarned','roiPhase','roiCyclesDone'].forEach(id => {
const el = document.getElementById(id);
el.addEventListener('input', updateROI);
el.addEventListener('change', updateROI);
});
// Initial render on page load (delayed to ensure DOM is ready)
setTimeout(updateROI, 150);
</script>
</body>
</html>