show both models at the same time

This commit is contained in:
Tobias Brunner 2025-07-23 11:16:15 +02:00
parent aa57082a1b
commit 4746cfac25
Signed by: tobru
SSH key fingerprint: SHA256:kOXg1R6c11XW3/Pt9dbLdQvOJGFAy+B2K6v6PtRWBGQ
6 changed files with 488 additions and 326 deletions

View file

@ -38,7 +38,7 @@ function resetAdvancedParameters() { window.ROICalculatorApp?.resetAdvancedParam
function toggleScenario(scenarioKey) { window.ROICalculatorApp?.toggleScenario(scenarioKey); }
function toggleCollapsible(elementId) { window.ROICalculatorApp?.toggleCollapsible(elementId); }
function resetCalculator() { window.ROICalculatorApp?.resetCalculator(); }
function toggleInvestmentModel() { window.ROICalculatorApp?.toggleInvestmentModel(); }
// toggleInvestmentModel function removed - both models calculated simultaneously
function logout() { window.ROICalculatorApp?.logout(); }
// Manual toggle functions for collapse elements
@ -123,100 +123,112 @@ document.addEventListener('DOMContentLoaded', function() {
</div>
</div>
<!-- Compact Controls Row -->
<div class="row py-3">
<!-- Core Investment Parameters -->
<div class="col-lg-2 col-md-3 mb-2">
<label class="form-label small fw-semibold mb-1">Investment</label>
<div class="input-group input-group-sm">
<span class="input-group-text">CHF</span>
<input type="text" class="form-control" id="investment-amount"
data-value="500000" value="500,000"
oninput="handleInvestmentAmountInput(this)"
onchange="updateCalculations()">
</div>
<input type="range" class="form-range mt-1" id="investment-slider"
min="100000" max="2000000" step="50000" value="500000"
onchange="updateInvestmentAmount(this.value)">
</div>
<div class="col-lg-1 col-md-2 mb-2">
<label class="form-label small fw-semibold mb-1">Years</label>
<select class="form-select form-select-sm" id="timeframe" onchange="updateCalculations()">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected>3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<!-- Investment Model -->
<div class="col-lg-2 col-md-3 mb-2">
<label class="form-label small fw-semibold mb-1">Model</label>
<div class="btn-group w-100" role="group">
<input type="radio" class="btn-check" name="investment-model" id="loan-model" value="loan" onchange="toggleInvestmentModel()">
<label class="btn btn-outline-warning btn-sm" for="loan-model">Loan</label>
<input type="radio" class="btn-check" name="investment-model" id="direct-model" value="direct" checked onchange="toggleInvestmentModel()">
<label class="btn btn-outline-success btn-sm" for="direct-model">Direct</label>
</div>
</div>
<!-- Revenue/Instance -->
<div class="col-lg-1 col-md-2 mb-2">
<label class="form-label small fw-semibold mb-1">Revenue</label>
<div class="input-group input-group-sm">
<input type="number" class="form-control" id="revenue-per-instance"
min="20" max="200" step="5" value="50" onchange="updateCalculations()">
<span class="input-group-text">CHF</span>
</div>
<input type="range" class="form-range mt-1" id="revenue-slider"
min="20" max="200" step="5" value="50"
onchange="updateRevenuePerInstance(this.value)">
</div>
<!-- Scenarios Toggle -->
<div class="col-lg-2 col-md-3 mb-2">
<label class="form-label small fw-semibold mb-1">Scenarios</label>
<div class="d-flex gap-1">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="conservative-enabled" checked onchange="toggleScenario('conservative')">
<label class="form-check-label small text-success" for="conservative-enabled" data-bs-toggle="tooltip" title="Conservative: 2% churn, steady growth">Safe</label>
<!-- Organized Controls Section -->
<div class="py-3">
<!-- Primary Controls Row -->
<div class="row align-items-end mb-3">
<!-- Investment Amount -->
<div class="col-lg-3 col-md-4 mb-2">
<label class="form-label small fw-semibold mb-1">Initial Investment</label>
<div class="input-group input-group-sm">
<span class="input-group-text">CHF</span>
<input type="text" class="form-control" id="investment-amount"
data-value="500000" value="500,000"
oninput="handleInvestmentAmountInput(this)"
onchange="updateCalculations()">
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="moderate-enabled" checked onchange="toggleScenario('moderate')">
<label class="form-check-label small text-warning" for="moderate-enabled" data-bs-toggle="tooltip" title="Moderate: 3% churn, balanced growth">Balanced</label>
<input type="range" class="form-range mt-1" id="investment-slider"
min="100000" max="2000000" step="50000" value="500000"
onchange="updateInvestmentAmount(this.value)">
</div>
<!-- Time & Revenue -->
<div class="col-lg-3 col-md-4 mb-2">
<div class="row">
<div class="col-6">
<label class="form-label small fw-semibold mb-1">Years</label>
<select class="form-select form-select-sm" id="timeframe" onchange="updateCalculations()">
<option value="1">1</option>
<option value="2">2</option>
<option value="3" selected>3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<div class="col-6">
<label class="form-label small fw-semibold mb-1">Revenue/Instance</label>
<div class="input-group input-group-sm">
<input type="number" class="form-control" id="revenue-per-instance"
min="20" max="200" step="5" value="50" onchange="updateCalculations()">
<span class="input-group-text">CHF</span>
</div>
<input type="range" class="form-range mt-1" id="revenue-slider"
min="20" max="200" step="5" value="50"
onchange="updateRevenuePerInstance(this.value)">
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="aggressive-enabled" checked onchange="toggleScenario('aggressive')">
<label class="form-check-label small text-danger" for="aggressive-enabled" data-bs-toggle="tooltip" title="Aggressive: 5% churn, rapid growth">Fast</label>
</div>
<!-- Actions -->
<div class="col-lg-2 col-md-4 mb-2">
<div class="d-flex justify-content-end gap-2">
<button class="btn btn-outline-info btn-sm" type="button" onclick="toggleAdvancedControls()" id="advancedToggleBtn">
<i class="bi bi-gear"></i> Advanced
</button>
<a href="{% url 'services:roi_calculator_help' %}" class="btn btn-outline-secondary btn-sm" target="_blank">
<i class="bi bi-question-circle"></i> Help
</a>
</div>
</div>
</div>
<!-- Advanced Controls Toggle -->
<div class="col-lg-2 col-md-3 mb-2">
<label class="form-label small fw-semibold mb-1">Controls</label>
<div class="d-flex gap-1">
<button class="btn btn-outline-info btn-sm" type="button" onclick="toggleAdvancedControls()" id="advancedToggleBtn">
<i class="bi bi-gear"></i> More
</button>
<a href="{% url 'services:roi_calculator_help' %}" class="btn btn-outline-secondary btn-sm" target="_blank">
<i class="bi bi-question-circle"></i> Help
</a>
</div>
</div>
<!-- Remaining space for metrics -->
<div class="col-lg-2 col-md-4 mb-2 text-end">
<div class="d-flex justify-content-end gap-3">
<div class="text-center">
<div class="fw-bold text-success" id="net-position" style="font-size: 1.1rem; white-space: nowrap; line-height: 1.2;">CHF 0</div>
<div style="font-size: 0.8rem;" class="text-muted">Net Position</div>
<!-- Scenarios & Results Row -->
<div class="row align-items-center">
<!-- Scenario Selection -->
<div class="col-lg-6 col-md-8 mb-2">
<label class="form-label small fw-semibold mb-2">Growth Scenarios</label>
<div class="d-flex gap-3 justify-content-center">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="conservative-enabled" checked onchange="toggleScenario('conservative')">
<label class="form-check-label small fw-medium" for="conservative-enabled" data-bs-toggle="tooltip" title="Conservative: 2% churn, steady growth">
<span class="text-success"></span> Conservative
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="moderate-enabled" checked onchange="toggleScenario('moderate')">
<label class="form-check-label small fw-medium" for="moderate-enabled" data-bs-toggle="tooltip" title="Moderate: 3% churn, balanced growth">
<span class="text-warning"></span> Moderate
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="aggressive-enabled" checked onchange="toggleScenario('aggressive')">
<label class="form-check-label small fw-medium" for="aggressive-enabled" data-bs-toggle="tooltip" title="Aggressive: 5% churn, rapid growth">
<span class="text-danger"></span> Aggressive
</label>
</div>
</div>
<div class="text-center">
<div class="fw-bold text-primary" id="roi-percentage" style="font-size: 1.1rem; white-space: nowrap; line-height: 1.2;">0%</div>
<div style="font-size: 0.8rem;" class="text-muted">ROI</div>
</div>
<!-- Model Results -->
<div class="col-lg-6 col-md-4 mb-2">
<div class="row">
<div class="col-6">
<div class="text-center p-2 border rounded model-result-box">
<div class="text-success fw-semibold small mb-1">Direct Investment</div>
<div class="fw-bold" id="net-position-direct" style="font-size: 1.1rem; line-height: 1.2;">CHF 0</div>
<div class="fw-bold text-primary" id="roi-percentage-direct" style="font-size: 0.9rem; line-height: 1.2;">0%</div>
<div style="font-size: 0.7rem;" class="text-muted">Net Position / ROI</div>
</div>
</div>
<div class="col-6">
<div class="text-center p-2 border rounded model-result-box">
<div class="text-warning fw-semibold small mb-1">Loan Model</div>
<div class="fw-bold" id="net-position-loan" style="font-size: 1.1rem; line-height: 1.2;">CHF 0</div>
<div class="fw-bold text-primary" id="roi-percentage-loan" style="font-size: 0.9rem; line-height: 1.2;">0%</div>
<div style="font-size: 0.7rem;" class="text-muted">Net Position / ROI</div>
</div>
</div>
</div>
</div>
</div>
@ -225,8 +237,8 @@ document.addEventListener('DOMContentLoaded', function() {
<!-- Collapsible Advanced Controls -->
<div class="collapse" id="advancedControls">
<div class="row py-2 bg-white border-top">
<!-- Loan Rate (conditional) -->
<div class="col-md-2" id="loan-rate-section" style="display: none;">
<!-- Loan Rate (for loan model calculations) -->
<div class="col-md-2" id="loan-rate-section">
<label class="form-label small mb-1">Loan Rate (%)</label>
<input type="number" class="form-control form-control-sm" id="loan-interest-rate"
min="3" max="8" step="0.1" value="5.0" onchange="updateCalculations()">
@ -288,33 +300,6 @@ document.addEventListener('DOMContentLoaded', function() {
<p class="mt-2">Calculating scenarios...</p>
</div>
<!-- Additional Key Metrics (Horizontal) -->
<div class="row mb-3" id="summary-metrics">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body py-3">
<div class="row text-center">
<div class="col-lg-3 col-md-6 mb-2">
<div class="h5 mb-0" id="csp-revenue">CHF 0</div>
<div class="small text-muted">Your Total Revenue</div>
</div>
<div class="col-lg-3 col-md-6 mb-2">
<div class="h5 mb-0" id="breakeven-time">N/A</div>
<div class="small text-muted">Break-Even Time</div>
</div>
<div class="col-lg-3 col-md-6 mb-2">
<div class="h5 mb-0 text-info" id="model-description-display">Direct Investment</div>
<div class="small text-muted">Investment Model</div>
</div>
<div class="col-lg-3 col-md-6 mb-2">
<div class="h5 mb-0 text-secondary">3 Scenarios</div>
<div class="small text-muted">Active Comparisons</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- PRIMARY CHART - Full Width, Large Height -->
<div class="row mb-4">
@ -380,25 +365,23 @@ document.addEventListener('DOMContentLoaded', function() {
<h2 class="accordion-header" id="dataHeading">
<button class="accordion-button collapsed" type="button" onclick="toggleDataCollapse()" id="dataToggleBtn">
<i class="bi bi-table me-2"></i> Detailed Financial Analysis
<span class="badge bg-secondary ms-2">Optional</span>
</button>
</h2>
<div id="dataCollapse" class="accordion-collapse collapse" aria-labelledby="dataHeading" data-bs-parent="#dataAccordion">
<div class="accordion-body">
<!-- Comparison Table -->
<h6 class="mb-3">Scenario Performance Summary</h6>
<!-- Improved Scenario Performance Summary -->
<h6 class="mb-3">Investment Model Comparison by Scenario</h6>
<div class="table-responsive mb-4">
<table class="table table-sm table-striped" id="comparison-table">
<table class="table table-sm table-hover" id="comparison-table">
<thead class="table-dark">
<tr>
<th>Scenario</th>
<th>Model</th>
<th>Investment Model</th>
<th>Final Scale</th>
<th>Total Revenue</th>
<th>Your Revenue</th>
<th>Servala Share</th>
<th>ROI & Bonuses</th>
<th>Break-even</th>
<th>Your Net Profit</th>
<th>Total ROI</th>
<th>Break-even Time</th>
<th>Key Features</th>
</tr>
</thead>
<tbody id="comparison-tbody">
@ -407,21 +390,26 @@ document.addEventListener('DOMContentLoaded', function() {
</table>
</div>
<!-- Monthly Breakdown -->
<h6 class="mb-3">Monthly Financial Flow</h6>
<div class="table-responsive" style="max-height: 400px; overflow-y: auto;">
<!-- Monthly Financial Flow -->
<h6 class="mb-3">Monthly Financial Breakdown</h6>
<div class="alert alert-info alert-sm">
<small>
<i class="bi bi-info-circle"></i>
This table shows month-by-month progression for all enabled scenarios and both investment models.
Use the scenario checkboxes above to filter results.
</small>
</div>
<div class="table-responsive" style="max-height: 500px; overflow-y: auto;">
<table class="table table-sm table-striped" id="monthly-table">
<thead class="table-dark sticky-top">
<tr>
<th>Month</th>
<th>Scenario</th>
<th>Growth</th>
<th>Churn</th>
<th>Scale</th>
<th>Model</th>
<th>Instances</th>
<th>Monthly Revenue</th>
<th>Your Share</th>
<th>Servala Share</th>
<th>Net Position</th>
<th>Cumulative Net Position</th>
</tr>
</thead>
<tbody id="monthly-tbody">