website/hub/services/templates/calculator/csp_roi_calculator.html

694 lines
45 KiB
HTML
Raw Normal View History

2025-07-16 15:12:25 +02:00
{% extends 'base.html' %}
{% load static %}
{% block title %}CSP ROI Calculator{% endblock %}
{% block extra_head %}
<meta name="csrf-token" content="{{ csrf_token }}">
{% endblock %}
2025-07-16 15:12:25 +02:00
{% block extra_css %}
2025-07-21 16:04:53 +02:00
<link rel="stylesheet" type="text/css" href='{% static "css/roi-calculator.css" %}'>
{% endblock %}
2025-07-16 15:15:34 +02:00
2025-07-21 16:04:53 +02:00
{% block extra_js %}
<script src="{% static "js/chart.umd.min.js" %}"></script>
<script src="{% static "js/jspdf.umd.min.js" %}"></script>
<!-- ROI Calculator Modules -->
<script src="{% static "js/roi-calculator/input-utils.js" %}"></script>
<script src="{% static "js/roi-calculator/calculator-core.js" %}"></script>
<script src="{% static "js/roi-calculator/chart-manager.js" %}"></script>
<script src="{% static "js/roi-calculator/ui-manager.js" %}"></script>
<script src="{% static "js/roi-calculator/export-manager.js" %}"></script>
<script src="{% static "js/roi-calculator/roi-calculator-app.js" %}"></script>
<script>
// Global function wrappers for HTML onclick handlers
function updateCalculations() { window.ROICalculatorApp?.updateCalculations(); }
function exportToPDF() { window.ROICalculatorApp?.exportToPDF(); }
function exportToCSV() { window.ROICalculatorApp?.exportToCSV(); }
function handleInvestmentAmountInput(input) { InputUtils.handleInvestmentAmountInput(input); }
function updateInvestmentAmount(value) { window.ROICalculatorApp?.updateInvestmentAmount(value); }
function updateRevenuePerInstance(value) { window.ROICalculatorApp?.updateRevenuePerInstance(value); }
function updateServalaShare(value) { window.ROICalculatorApp?.updateServalaShare(value); }
function updateGracePeriod(value) { window.ROICalculatorApp?.updateGracePeriod(value); }
function updateLoanRate(value) { window.ROICalculatorApp?.updateLoanRate(value); }
function updateCoreServiceRevenue(value) { window.ROICalculatorApp?.updateCoreServiceRevenue(value); }
function updateScenarioChurn(scenarioKey, churnRate) { window.ROICalculatorApp?.updateScenarioChurn(scenarioKey, churnRate); }
function updateScenarioPhase(scenarioKey, phaseIndex, newInstancesPerMonth) { window.ROICalculatorApp?.updateScenarioPhase(scenarioKey, phaseIndex, newInstancesPerMonth); }
function resetAdvancedParameters() { window.ROICalculatorApp?.resetAdvancedParameters(); }
function toggleScenario(scenarioKey) { window.ROICalculatorApp?.toggleScenario(scenarioKey); }
2025-07-23 11:42:22 +02:00
function updateMonthlyBreakdownFilters() { window.ROICalculatorApp?.updateMonthlyBreakdownFilters(); }
function toggleCollapsible(elementId) { window.ROICalculatorApp?.toggleCollapsible(elementId); }
function resetCalculator() { window.ROICalculatorApp?.resetCalculator(); }
2025-07-23 11:16:15 +02:00
// toggleInvestmentModel function removed - both models calculated simultaneously
function logout() { window.ROICalculatorApp?.logout(); }
2025-07-22 17:30:37 +02:00
// Manual toggle functions for collapse elements
function toggleAdvancedControls() {
const element = document.getElementById('advancedControls');
const button = document.getElementById('advancedToggleBtn');
console.log('Toggling advanced controls, current classes:', element.className);
if (element.style.display === 'none' || element.style.display === '') {
element.style.display = 'block';
button.innerHTML = '<i class="bi bi-gear"></i> Less';
console.log('Showing advanced controls');
} else {
element.style.display = 'none';
button.innerHTML = '<i class="bi bi-gear"></i> More';
console.log('Hiding advanced controls');
}
}
function toggleDataCollapse() {
const element = document.getElementById('dataCollapse');
const button = document.getElementById('dataToggleBtn');
console.log('Toggling data collapse, current style:', element.style.display);
if (element.style.display === 'none' || element.style.display === '') {
element.style.display = 'block';
button.classList.remove('collapsed');
button.setAttribute('aria-expanded', 'true');
console.log('Showing data collapse');
} else {
element.style.display = 'none';
button.classList.add('collapsed');
button.setAttribute('aria-expanded', 'false');
console.log('Hiding data collapse');
}
}
// Initialize collapse states
document.addEventListener('DOMContentLoaded', function() {
// Ensure both sections start collapsed
const advancedControls = document.getElementById('advancedControls');
const dataCollapse = document.getElementById('dataCollapse');
if (advancedControls) {
advancedControls.style.display = 'none';
}
if (dataCollapse) {
dataCollapse.style.display = 'none';
}
console.log('Collapse elements initialized as hidden');
});
</script>
2025-07-16 15:12:25 +02:00
{% endblock %}
{% block content %}
2025-07-22 17:30:37 +02:00
<div class="container-fluid p-0" style="min-height: 100vh;">
<!-- Minimal Header with Controls -->
<div class="bg-light border-bottom sticky-top" style="z-index: 1030;">
<div class="container-fluid">
<!-- Title Row -->
<div class="row py-2 border-bottom">
<div class="col-md-6">
<h4 class="mb-0">CSP ROI Calculator</h4>
<small class="text-muted">Real-time investment analysis</small>
2025-07-16 15:12:25 +02:00
</div>
2025-07-22 17:30:37 +02:00
<div class="col-md-6 text-end">
<button type="button" class="btn btn-sm btn-outline-primary me-1" onclick="exportToPDF()">
2025-07-21 16:14:32 +02:00
<i class="bi bi-file-pdf"></i> PDF
</button>
2025-07-22 17:30:37 +02:00
<button type="button" class="btn btn-sm btn-outline-success me-1" onclick="exportToCSV()">
2025-07-21 16:14:32 +02:00
<i class="bi bi-file-csv"></i> CSV
</button>
2025-07-23 11:48:10 +02:00
<button type="button" class="btn btn-sm btn-outline me-1" onclick="resetCalculator()">
2025-07-16 15:12:25 +02:00
<i class="bi bi-arrow-clockwise"></i> Reset
</button>
2025-07-22 17:30:37 +02:00
<button type="button" class="btn btn-sm btn-danger" onclick="logout()">
2025-07-16 15:12:25 +02:00
<i class="bi bi-box-arrow-right"></i> Logout
</button>
</div>
</div>
2025-07-22 17:30:37 +02:00
<!-- Main Configuration Section -->
<div class="py-4">
<div class="row">
2025-07-23 14:35:15 +02:00
<!-- Left Column: Configuration Fields -->
<div class="col-lg-8 col-xl-7">
<div class="main-config-fields">
<!-- Investment Amount -->
<div class="mb-4">
<label class="form-label fw-semibold mb-2">Initial Investment</label>
<div class="input-group input-group-lg">
<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-3" id="investment-slider"
min="100000" max="2000000" step="50000" value="500000"
onchange="updateInvestmentAmount(this.value)">
<div class="d-flex justify-content-between mt-1">
<small class="text-muted">CHF 100K</small>
<small class="text-muted">CHF 2M</small>
</div>
2025-07-23 11:16:15 +02:00
</div>
2025-07-23 14:35:15 +02:00
<!-- Analysis Period & Service Revenue Row -->
<div class="row mb-4">
<div class="col-md-6">
<label class="form-label fw-semibold mb-2">Analysis Period</label>
<select class="form-select form-select-lg" id="timeframe" onchange="updateCalculations()">
<option value="1">1 Year</option>
<option value="2">2 Years</option>
<option value="3" selected>3 Years</option>
<option value="4">4 Years</option>
<option value="5">5 Years</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold mb-2">Service Revenue per Instance</label>
<div class="input-group input-group-lg">
<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/month</span>
</div>
<input type="range" class="form-range mt-3" id="revenue-slider"
min="20" max="200" step="5" value="50"
onchange="updateRevenuePerInstance(this.value)">
<div class="d-flex justify-content-between mt-1">
<small class="text-muted">CHF 20</small>
<small class="text-muted">CHF 200</small>
</div>
</div>
2025-07-23 11:16:15 +02:00
</div>
2025-07-23 14:35:15 +02:00
<!-- Growth Scenarios -->
<div class="mb-4">
<label class="form-label fw-semibold mb-3">Growth Scenarios</label>
<div class="d-flex gap-4 flex-wrap">
<div class="form-check form-check-lg">
<input class="form-check-input" type="checkbox" id="conservative-enabled" checked onchange="toggleScenario('conservative')">
<label class="form-check-label fw-medium" for="conservative-enabled" data-bs-toggle="tooltip" title="Conservative: 2% churn, steady growth">
<span class="text-success fs-4"></span> Conservative
</label>
</div>
<div class="form-check form-check-lg">
<input class="form-check-input" type="checkbox" id="moderate-enabled" checked onchange="toggleScenario('moderate')">
<label class="form-check-label fw-medium" for="moderate-enabled" data-bs-toggle="tooltip" title="Moderate: 3% churn, balanced growth">
<span class="text-warning fs-4"></span> Moderate
</label>
</div>
<div class="form-check form-check-lg">
<input class="form-check-input" type="checkbox" id="aggressive-enabled" checked onchange="toggleScenario('aggressive')">
<label class="form-check-label fw-medium" for="aggressive-enabled" data-bs-toggle="tooltip" title="Aggressive: 5% churn, rapid growth">
<span class="text-danger fs-4"></span> Aggressive
</label>
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="d-flex gap-3 flex-wrap">
<button class="btn btn-outline-info btn-lg" type="button" onclick="toggleAdvancedControls()" id="advancedToggleBtn">
<i class="bi bi-gear"></i> Advanced Settings
</button>
<a href="{% url 'services:roi_calculator_help' %}" class="btn btn-outline-secondary btn-lg" target="_blank">
<i class="bi bi-question-circle"></i> Help
</a>
2025-07-23 11:16:15 +02:00
</div>
2025-07-22 17:30:37 +02:00
</div>
2025-07-23 11:16:15 +02:00
</div>
2025-07-23 14:35:15 +02:00
<!-- Right Column: Real-Time Results -->
<div class="col-lg-4 col-xl-5">
<div class="results-panel h-100">
<div class="card h-100 border-0 shadow">
<div class="card-header bg-primary text-white">
<h5 class="mb-0"><i class="bi bi-graph-up"></i> Real-Time Results</h5>
<small class="opacity-75">Live calculations based on your parameters</small>
2025-07-23 11:16:15 +02:00
</div>
2025-07-23 14:35:15 +02:00
<div class="card-body d-flex flex-column justify-content-center">
<!-- Direct Investment Results -->
<div class="result-item mb-4">
<div class="d-flex align-items-center mb-2">
<div class="result-icon bg-success text-white rounded-circle me-3 d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-rocket"></i>
</div>
<div>
<h6 class="mb-0 text-success fw-bold">Direct Investment</h6>
<small class="text-muted">Performance-based returns</small>
</div>
</div>
<div class="result-metrics bg-light rounded p-3">
<div class="row text-center">
<div class="col-6">
<div class="h4 mb-1 text-success fw-bold" id="net-position-direct">CHF 0</div>
<small class="text-muted">Net Profit</small>
</div>
<div class="col-6">
<div class="h4 mb-1 text-primary fw-bold" id="roi-percentage-direct">0%</div>
<small class="text-muted">Total ROI</small>
</div>
</div>
</div>
</div>
<!-- Loan Model Results -->
<div class="result-item">
<div class="d-flex align-items-center mb-2">
<div class="result-icon bg-warning text-dark rounded-circle me-3 d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="bi bi-bank"></i>
</div>
<div>
<h6 class="mb-0 text-warning fw-bold">Loan Model</h6>
<small class="text-muted">Fixed guaranteed returns</small>
</div>
</div>
<div class="result-metrics bg-light rounded p-3">
<div class="row text-center">
<div class="col-6">
<div class="h4 mb-1 text-success fw-bold" id="net-position-loan">CHF 0</div>
<small class="text-muted">Net Profit</small>
</div>
<div class="col-6">
<div class="h4 mb-1 text-primary fw-bold" id="roi-percentage-loan">0%</div>
<small class="text-muted">Total ROI</small>
</div>
</div>
</div>
</div>
2025-07-23 11:16:15 +02:00
</div>
</div>
2025-07-22 17:30:37 +02:00
</div>
2025-07-16 15:12:25 +02:00
</div>
</div>
2025-07-22 17:30:37 +02:00
</div>
<!-- Advanced Controls Section -->
2025-07-22 17:30:37 +02:00
<div class="collapse" id="advancedControls">
<div class="bg-light border-top py-4">
<div class="container-fluid">
<h6 class="text-primary mb-4"><i class="bi bi-gear"></i> Advanced Configuration</h6>
<!-- Investment Model Parameters -->
<div class="row mb-4">
<div class="col-12">
<h6 class="text-secondary mb-3">Investment Model Settings</h6>
</div>
<!-- Loan Rate -->
<div class="col-lg-3 col-md-6 mb-3">
<label class="form-label fw-semibold mb-2">Loan Interest Rate</label>
<div class="input-group">
<input type="number" class="form-control" id="loan-interest-rate"
min="3" max="8" step="0.1" value="5.0" onchange="updateCalculations()">
<span class="input-group-text">% annual</span>
</div>
<input type="range" class="form-range mt-2" id="loan-rate-slider"
min="3" max="8" step="0.1" value="5.0" onchange="updateLoanRate(this.value)">
<div class="d-flex justify-content-between">
<small class="text-muted">3%</small>
<small class="text-muted">8%</small>
</div>
</div>
<!-- Servala Share -->
<div class="col-lg-3 col-md-6 mb-3">
<label class="form-label fw-semibold mb-2">Servala Revenue Share</label>
<div class="input-group">
<input type="number" class="form-control" id="servala-share"
min="10" max="40" step="1" value="25" onchange="updateCalculations()">
<span class="input-group-text">%</span>
</div>
<input type="range" class="form-range mt-2" id="share-slider"
min="10" max="40" step="1" value="25" onchange="updateServalaShare(this.value)">
<div class="d-flex justify-content-between">
<small class="text-muted">10%</small>
<small class="text-muted">40%</small>
</div>
</div>
<!-- Grace Period -->
<div class="col-lg-3 col-md-6 mb-3">
<label class="form-label fw-semibold mb-2">Grace Period</label>
<div class="input-group">
<input type="number" class="form-control" id="grace-period"
min="0" max="24" step="1" value="6" onchange="updateCalculations()">
<span class="input-group-text">months</span>
</div>
<input type="range" class="form-range mt-2" id="grace-slider"
min="0" max="24" step="1" value="6" onchange="updateGracePeriod(this.value)">
<div class="d-flex justify-content-between">
<small class="text-muted">0</small>
<small class="text-muted">24</small>
</div>
</div>
<!-- Core Service Revenue -->
<div class="col-lg-3 col-md-6 mb-3">
<label class="form-label fw-semibold mb-2">Core Service Revenue</label>
<div class="input-group">
<input type="number" class="form-control" id="core-service-revenue"
min="0" max="500" step="5" value="0" onchange="updateCalculations()">
<span class="input-group-text">CHF/month</span>
</div>
<input type="range" class="form-range mt-2" id="core-revenue-slider"
min="0" max="500" step="5" value="0" onchange="updateCoreServiceRevenue(this.value)">
<div class="d-flex justify-content-between">
<small class="text-muted">CHF 0</small>
<small class="text-muted">CHF 500</small>
</div>
<small class="text-muted">Additional compute/storage revenue per instance</small>
</div>
</div>
<!-- Scenario Parameters -->
<div class="row mb-4">
<div class="col-12">
<h6 class="text-secondary mb-3">Growth Scenario Tuning</h6>
</div>
<!-- Conservative Scenario -->
<div class="col-lg-4 mb-4">
<div class="card h-100">
<div class="card-header bg-success text-white">
<h6 class="mb-0"><i class="bi bi-shield-check"></i> Conservative Scenario</h6>
</div>
<div class="card-body">
<!-- Churn Rate -->
<div class="mb-3">
<label class="form-label fw-semibold mb-2">Monthly Churn Rate</label>
<div class="input-group input-group-sm">
<input type="number" class="form-control" id="conservative-churn"
min="0" max="10" step="0.1" value="2.0" onchange="updateScenarioChurn('conservative', this.value)">
<span class="input-group-text">%</span>
</div>
</div>
<!-- Phase Growth Parameters -->
<label class="form-label fw-semibold mb-2">Instance Growth per Phase</label>
<div class="row g-2">
<div class="col-6">
<label class="form-label small">Phase 1 (6mo)</label>
<input type="number" class="form-control form-control-sm" id="conservative-phase-0"
min="10" max="200" value="50" onchange="updateScenarioPhase('conservative', 0, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 2 (6mo)</label>
<input type="number" class="form-control form-control-sm" id="conservative-phase-1"
min="10" max="200" value="75" onchange="updateScenarioPhase('conservative', 1, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 3 (12mo)</label>
<input type="number" class="form-control form-control-sm" id="conservative-phase-2"
min="10" max="300" value="100" onchange="updateScenarioPhase('conservative', 2, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 4 (12mo)</label>
<input type="number" class="form-control form-control-sm" id="conservative-phase-3"
min="10" max="300" value="150" onchange="updateScenarioPhase('conservative', 3, this.value)">
</div>
</div>
</div>
</div>
</div>
<!-- Moderate Scenario -->
<div class="col-lg-4 mb-4">
<div class="card h-100">
<div class="card-header bg-warning text-dark">
<h6 class="mb-0"><i class="bi bi-speedometer2"></i> Moderate Scenario</h6>
</div>
<div class="card-body">
<!-- Churn Rate -->
<div class="mb-3">
<label class="form-label fw-semibold mb-2">Monthly Churn Rate</label>
<div class="input-group input-group-sm">
<input type="number" class="form-control" id="moderate-churn"
min="0" max="10" step="0.1" value="3.0" onchange="updateScenarioChurn('moderate', this.value)">
<span class="input-group-text">%</span>
</div>
</div>
<!-- Phase Growth Parameters -->
<label class="form-label fw-semibold mb-2">Instance Growth per Phase</label>
<div class="row g-2">
<div class="col-6">
<label class="form-label small">Phase 1 (6mo)</label>
<input type="number" class="form-control form-control-sm" id="moderate-phase-0"
min="20" max="300" value="100" onchange="updateScenarioPhase('moderate', 0, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 2 (6mo)</label>
<input type="number" class="form-control form-control-sm" id="moderate-phase-1"
min="20" max="400" value="200" onchange="updateScenarioPhase('moderate', 1, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 3 (12mo)</label>
<input type="number" class="form-control form-control-sm" id="moderate-phase-2"
min="20" max="500" value="300" onchange="updateScenarioPhase('moderate', 2, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 4 (12mo)</label>
<input type="number" class="form-control form-control-sm" id="moderate-phase-3"
min="20" max="600" value="400" onchange="updateScenarioPhase('moderate', 3, this.value)">
</div>
</div>
</div>
</div>
</div>
<!-- Aggressive Scenario -->
<div class="col-lg-4 mb-4">
<div class="card h-100">
<div class="card-header bg-danger text-white">
<h6 class="mb-0"><i class="bi bi-rocket"></i> Aggressive Scenario</h6>
</div>
<div class="card-body">
<!-- Churn Rate -->
<div class="mb-3">
<label class="form-label fw-semibold mb-2">Monthly Churn Rate</label>
<div class="input-group input-group-sm">
<input type="number" class="form-control" id="aggressive-churn"
min="0" max="15" step="0.1" value="5.0" onchange="updateScenarioChurn('aggressive', this.value)">
<span class="input-group-text">%</span>
</div>
</div>
<!-- Phase Growth Parameters -->
<label class="form-label fw-semibold mb-2">Instance Growth per Phase</label>
<div class="row g-2">
<div class="col-6">
<label class="form-label small">Phase 1 (6mo)</label>
<input type="number" class="form-control form-control-sm" id="aggressive-phase-0"
min="50" max="500" value="200" onchange="updateScenarioPhase('aggressive', 0, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 2 (6mo)</label>
<input type="number" class="form-control form-control-sm" id="aggressive-phase-1"
min="50" max="600" value="400" onchange="updateScenarioPhase('aggressive', 1, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 3 (12mo)</label>
<input type="number" class="form-control form-control-sm" id="aggressive-phase-2"
min="50" max="800" value="600" onchange="updateScenarioPhase('aggressive', 2, this.value)">
</div>
<div class="col-6">
<label class="form-label small">Phase 4 (12mo)</label>
<input type="number" class="form-control form-control-sm" id="aggressive-phase-3"
min="50" max="1000" value="800" onchange="updateScenarioPhase('aggressive', 3, this.value)">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Reset Button -->
<div class="row">
<div class="col-12 text-center">
<button type="button" class="btn btn-outline-secondary" onclick="resetAdvancedParameters()">
<i class="bi bi-arrow-clockwise"></i> Reset to Defaults
</button>
</div>
2025-07-16 15:12:25 +02:00
</div>
</div>
</div>
</div>
2025-07-22 17:30:37 +02:00
2025-07-16 15:12:25 +02:00
</div>
2025-07-22 17:30:37 +02:00
</div>
2025-07-16 15:12:25 +02:00
2025-07-22 17:30:37 +02:00
<!-- CHARTS - Maximum Space -->
<div class="container-fluid px-3 py-3" style="background: #f8f9fa;">
<!-- Loading Spinner -->
<div class="loading-spinner text-center py-5" id="loading-spinner" style="display: none;">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Calculating...</span>
2025-07-16 15:12:25 +02:00
</div>
2025-07-22 17:30:37 +02:00
<p class="mt-2">Calculating scenarios...</p>
</div>
2025-07-16 15:12:25 +02:00
2025-07-22 17:30:37 +02:00
<!-- PRIMARY CHART - Full Width, Large Height -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-0 pb-0">
<h5 class="mb-1"><i class="bi bi-graph-up-arrow text-primary"></i> ROI Progression Over Time</h5>
<p class="small text-muted mb-0">Investment profitability timeline - when you'll break even and achieve target returns</p>
</div>
<div class="card-body pt-3">
<canvas id="instanceGrowthChart" style="height: 500px; width: 100%;"></canvas>
2025-07-16 15:12:25 +02:00
</div>
</div>
</div>
2025-07-22 17:30:37 +02:00
</div>
2025-07-16 15:12:25 +02:00
2025-07-22 17:30:37 +02:00
<!-- SECONDARY CHARTS - Side by Side, Large -->
<div class="row mb-4">
<div class="col-xl-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-0 pb-0">
<h5 class="mb-1"><i class="bi bi-cash-stack text-success"></i> Net Financial Position</h5>
<p class="small text-muted mb-0">Cumulative profit/loss over time</p>
2025-07-16 15:12:25 +02:00
</div>
2025-07-22 17:30:37 +02:00
<div class="card-body pt-3">
<canvas id="revenueChart" style="height: 400px; width: 100%;"></canvas>
2025-07-16 15:12:25 +02:00
</div>
</div>
</div>
2025-07-22 17:30:37 +02:00
<div class="col-xl-6 mb-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-header bg-white border-0 pb-0">
<h5 class="mb-1"><i class="bi bi-bar-chart text-warning"></i> Performance Comparison</h5>
<p class="small text-muted mb-0">ROI performance across growth scenarios</p>
</div>
<div class="card-body pt-3">
<canvas id="cashFlowChart" style="height: 400px; width: 100%;"></canvas>
2025-07-21 17:06:29 +02:00
</div>
</div>
</div>
2025-07-22 17:30:37 +02:00
</div>
2025-07-21 17:06:29 +02:00
2025-07-22 17:30:37 +02:00
<!-- TERTIARY CHART - Full Width -->
<div class="row mb-4">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white border-0 pb-0">
<h5 class="mb-1"><i class="bi bi-graph-up text-info"></i> Investment Model Comparison</h5>
<p class="small text-muted mb-0">Net profit comparison: Fixed loan returns vs. performance-based direct investment across scenarios</p>
</div>
<div class="card-body pt-3">
<canvas id="modelComparisonChart" style="height: 400px; width: 100%;"></canvas>
2025-07-16 15:12:25 +02:00
</div>
</div>
</div>
2025-07-22 17:30:37 +02:00
</div>
2025-07-16 15:12:25 +02:00
2025-07-22 17:30:37 +02:00
<!-- DATA TABLE - Collapsible to Save Space -->
<div class="row mb-4">
<div class="col-12">
<div class="accordion" id="dataAccordion">
<div class="accordion-item border-0 shadow-sm">
<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
</button>
</h2>
<div id="dataCollapse" class="accordion-collapse collapse" aria-labelledby="dataHeading" data-bs-parent="#dataAccordion">
<div class="accordion-body">
2025-07-23 11:16:15 +02:00
<!-- Improved Scenario Performance Summary -->
<h6 class="mb-3">Investment Model Comparison by Scenario</h6>
2025-07-22 17:30:37 +02:00
<div class="table-responsive mb-4">
2025-07-23 11:16:15 +02:00
<table class="table table-sm table-hover" id="comparison-table">
2025-07-22 17:30:37 +02:00
<thead class="table-dark">
<tr>
<th>Scenario</th>
2025-07-23 11:16:15 +02:00
<th>Investment Model</th>
2025-07-22 17:30:37 +02:00
<th>Final Scale</th>
2025-07-23 11:16:15 +02:00
<th>Your Net Profit</th>
<th>Total ROI</th>
<th>Break-even Time</th>
<th>Key Features</th>
2025-07-22 17:30:37 +02:00
</tr>
</thead>
<tbody id="comparison-tbody">
<!-- Dynamic content -->
</tbody>
</table>
</div>
2025-07-23 11:16:15 +02:00
<!-- Monthly Financial Flow -->
<h6 class="mb-3">Monthly Financial Breakdown</h6>
2025-07-23 11:42:22 +02:00
<!-- Breakdown Filter Controls -->
<div class="row mb-3 breakdown-filters">
<div class="col-md-6">
<label class="form-label small fw-semibold mb-2">Investment Models</label>
<div class="d-flex gap-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="breakdown-direct-enabled" checked onchange="updateMonthlyBreakdownFilters()">
<label class="form-check-label small fw-medium text-success" for="breakdown-direct-enabled">
Direct Investment
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="breakdown-loan-enabled" checked onchange="updateMonthlyBreakdownFilters()">
<label class="form-check-label small fw-medium text-warning" for="breakdown-loan-enabled">
Loan Model
</label>
</div>
</div>
</div>
<div class="col-md-6">
<label class="form-label small fw-semibold mb-2">Growth Scenarios</label>
<div class="d-flex gap-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="breakdown-conservative-enabled" checked onchange="updateMonthlyBreakdownFilters()">
<label class="form-check-label small fw-medium" for="breakdown-conservative-enabled">
<span class="text-success"></span> Conservative
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="breakdown-moderate-enabled" checked onchange="updateMonthlyBreakdownFilters()">
<label class="form-check-label small fw-medium" for="breakdown-moderate-enabled">
<span class="text-warning"></span> Moderate
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="breakdown-aggressive-enabled" checked onchange="updateMonthlyBreakdownFilters()">
<label class="form-check-label small fw-medium" for="breakdown-aggressive-enabled">
<span class="text-danger"></span> Aggressive
</label>
</div>
</div>
</div>
2025-07-23 11:16:15 +02:00
</div>
<div class="table-responsive" style="max-height: 500px; overflow-y: auto;">
2025-07-16 15:12:25 +02:00
<table class="table table-sm table-striped" id="monthly-table">
<thead class="table-dark sticky-top">
<tr>
<th>Month</th>
<th>Scenario</th>
2025-07-23 11:16:15 +02:00
<th>Model</th>
<th>Instances</th>
<th>Service Revenue</th>
<th>Core Revenue</th>
<th>Total Revenue</th>
2025-07-22 09:16:40 +02:00
<th>Your Share</th>
2025-07-23 11:42:22 +02:00
<th>Servala Share</th>
2025-07-23 11:16:15 +02:00
<th>Cumulative Net Position</th>
2025-07-16 15:12:25 +02:00
</tr>
</thead>
<tbody id="monthly-tbody">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
2025-07-22 17:30:37 +02:00
{% endblock %}