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;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
.calc-footer a {
|
.calc-footer a {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
text-decoration: none;
|
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 {
|
.roi-dashboard h3 {
|
||||||
text-decoration: underline;
|
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="ladder">🪜 Full Ladder</button>
|
||||||
<button class="tab-btn" data-tab="comparison">⚖️ Compare</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="guide">📖 Sponsor Guide</button>
|
||||||
|
<button class="tab-btn" data-tab="progress">💰 My Progress</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="results active" id="tab-overview">
|
<div class="results active" id="tab-overview">
|
||||||
@@ -1109,6 +1301,83 @@
|
|||||||
</div>
|
</div>
|
||||||
</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 class="results" id="tab-guide">
|
||||||
<div style="max-width:680px;margin:0 auto;padding:8px 0;">
|
<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>
|
<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);
|
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>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user