Add My Progress tab: personal ROI dashboard with phase tracker, ladder visualization, and milestone tracking
This commit is contained in:
+384
-4
@@ -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>
|
||||
Reference in New Issue
Block a user