PageSourceSearch

https://nimbusvalue.com/rm-calculator.js

js nimbusvalue.com collected 2026-10-03 21:14:45 UTC 7,537 bytes, 173 lines download raw bytes

1/* ══════════════════════════════════════
2   Nimbus RM Impact Calculator — Modal
3   Shows revenue impact from higher win rates,
4   larger deals, and productivity improvement.
5   ══════════════════════════════════════ */
6
7(function () {
8  'use strict';
9
10  var overlay = document.getElementById('rm-calc-modal-overlay');
11  if (!overlay) return;
12
13  var calc = overlay.querySelector('.calc-modal');
14  var openBtn = document.getElementById('open-rm-calc-modal');
15  var closeBtn = document.getElementById('rm-calc-modal-close');
16  var revenueInput = calc.querySelector('#rm-calc-revenue');
17  var dealsInput = calc.querySelector('#rm-calc-deals');
18  var winRateInput = calc.querySelector('#rm-calc-winrate');
19  var winRateToggle = calc.querySelector('#rm-toggle-winrate');
20  var dealSizeToggle = calc.querySelector('#rm-toggle-dealsize');
21  var productivityToggle = calc.querySelector('#rm-toggle-productivity');
22  var calculateBtn = calc.querySelector('#rm-calc-btn');
23  var resultsPanel = calc.querySelector('.calc-results');
24  var disclaimer = calc.querySelector('.calc-disclaimer');
25
26  /* ── Modal open / close ── */
27  function openModal() {
28    overlay.classList.add('open');
29    overlay.setAttribute('aria-hidden', 'false');
30    document.body.style.overflow = 'hidden';
31    revenueInput.focus();
32  }
33
34  function closeModal() {
35    overlay.classList.remove('open');
36    overlay.setAttribute('aria-hidden', 'true');
37    document.body.style.overflow = '';
38  }
39
40  if (openBtn) openBtn.addEventListener('click', openModal);
41  closeBtn.addEventListener('click', closeModal);
42
43  overlay.addEventListener('click', function (e) {
44    if (e.target === overlay) closeModal();
45  });
46
47  document.addEventListener('keydown', function (e) {
48    if (e.key === 'Escape' && overlay.classList.contains('open')) closeModal();
49  });
50
51  /* ── Calculator logic ── */
52  function formatCurrency(num) {
53    if (num >= 1e9) return '$' + (num / 1e9).toFixed(2) + 'B';
54    if (num >= 1e6) return '$' + (num / 1e6).toFixed(2) + 'M';
55    if (num >= 1e3) return '$' + (num / 1e3).toFixed(1) + 'K';
56    return '$' + num.toLocaleString('en-US', { maximumFractionDigits: 0 });
57  }
58
59  function calculate() {
60    var mrr = parseFloat(revenueInput.value.replace(/[^0-9.]/g, ''));
61    var dealsWon = parseInt(dealsInput.value.replace(/[^0-9]/g, ''), 10);
62    var winRate = parseFloat(winRateInput.value.replace(/[^0-9.]/g, ''));
63
64    if (!mrr || mrr <= 0 || !dealsWon || dealsWon <= 0 || !winRate || winRate <= 0 || winRate > 100) {
65      resultsPanel.innerHTML = '<p class="calc-error">Please enter valid values for all fields.</p>';
66      resultsPanel.classList.add('visible');
67      disclaimer.classList.remove('visible');
68      return;
69    }
70
71    // Annualize MRR for calculations
72    var arr = mrr * 12;
73    var currentWinRate = winRate / 100;
74    var currentDealSize = arr / dealsWon;
75    var currentDealsWon = dealsWon;
76
77    var hasWinRate = winRateToggle.checked;
78    var hasDealSize = dealSizeToggle.checked;
79    var hasProductivity = productivityToggle.checked;
80
81    // Start with current values
82    var projectedWinRate = currentWinRate;
83    var projectedDealSize = currentDealSize;
84    var projectedDealsWon = currentDealsWon;
85
86    // 27% higher win rates → more deals won from same pipeline
87    if (hasWinRate) {
88      projectedWinRate = currentWinRate * 1.27;
89      if (projectedWinRate > 1) projectedWinRate = 1;
90      projectedDealsWon = Math.round(currentDealsWon * (projectedWinRate / currentWinRate));
91    }
92
93    // 38% larger deal sizes
94    if (hasDealSize) {
95      projectedDealSize = currentDealSize * 1.38;
96    }
97
98    // 55% sales productivity → reps work more deals, so more deals won
99    if (hasProductivity) {
100      projectedDealsWon = Math.round(projectedDealsWon * 1.55);
101    }
102
103    var projectedARR = projectedDealsWon * projectedDealSize;
104    var projectedMRR = projectedARR / 12;
105
106    var html = '';
107    html += '<div class="calc-scenario-grid">';
108
109    // Today baseline
110    html += '<div class="calc-scenario today">';
111    html += '<div class="calc-scenario-label">Today</div>';
112    html += '<div class="calc-scenario-value">' + formatCurrency(mrr) + '<span style="font-size:.6em;font-weight:500;color:var(--n-text-mute);"> /mo</span></div>';
113    html += '<div class="calc-scenario-detail">' + formatCurrency(arr) + '/yr · ' + currentDealsWon + ' deals · ' + formatCurrency(currentDealSize) + ' avg</div>';
114    html += '</div>';
115
116    // With NimbusRM
117    html += '<div class="calc-scenario base">';
118    html += '<div class="calc-scenario-label">With Nimbus RM</div>';
119    html += '<div class="calc-scenario-value">' + formatCurrency(projectedMRR) + '<span style="font-size:.6em;font-weight:500;color:var(--n-text-mute);"> /mo</span></div>';
120    html += '<div class="calc-scenario-detail">' + formatCurrency(projectedARR) + '/yr · ' + projectedDealsWon + ' deals · ' + formatCurrency(projectedDealSize) + ' avg</div>';
121    html += '</div>';
122
123    // Breakdown cards for active toggles
124    if (hasWinRate) {
125      html += '<div class="calc-scenario competency">';
126      html += '<div class="calc-scenario-label">Win Rate Impact</div>';
127      html += '<div class="calc-scenario-value">' + (currentWinRate * 100).toFixed(0) + '% → ' + (projectedWinRate * 100).toFixed(0) + '%</div>';
128      html += '<div class="calc-scenario-detail">27% higher win rates</div>';
129      html += '</div>';
130    }
131
132    if (hasDealSize) {
133      html += '<div class="calc-scenario cosell">';
134      html += '<div class="calc-scenario-label">Deal Size Impact</div>';
135      html += '<div class="calc-scenario-value">' + formatCurrency(currentDealSize) + ' → ' + formatCurrency(projectedDealSize) + '</div>';
136      html += '<div class="calc-scenario-detail">38% larger deal sizes</div>';
137      html += '</div>';
138    }
139
140    if (hasProductivity) {
141      html += '<div class="calc-scenario competency">';
142      html += '<div class="calc-scenario-label">Productivity Impact</div>';
143      var preProductivityDeals = hasWinRate ? Math.round(currentDealsWon * (projectedWinRate / currentWinRate)) : currentDealsWon;
144      html += '<div class="calc-scenario-value">' + preProductivityDeals + ' → ' + projectedDealsWon + ' deals won</div>';
145      html += '<div class="calc-scenario-detail">55% sales productivity improvement</div>';
146      html += '</div>';
147    }
148
149    html += '</div>';
150
151    // Growth summary — show both monthly and annual
152    var growthMultiple = (projectedARR / arr).toFixed(1);
153    var growthMRR = projectedMRR - mrr;
154    var growthARR = projectedARR - arr;
155    html += '<div class="calc-summary">';
156    html += '<span class="calc-summary-label">Potential Impact</span>';
157    html += '<span class="calc-summary-value">' + formatCurrency(projectedMRR) + '/mo · ' + formatCurrency(projectedARR) + '/yr</span>';
158    html += '<span class="calc-summary-multiple">' + growthMultiple + 'x your current revenue · +' + formatCurrency(growthMRR) + '/mo · +' + formatCurrency(growthARR) + '/yr</span>';
159    html += '</div>';
160
161    resultsPanel.innerHTML = html;
162    resultsPanel.classList.add('visible');
163    disclaimer.classList.add('visible');
164  }
165
166  calculateBtn.addEventListener('click', calculate);
167
168  [revenueInput, dealsInput, winRateInput].forEach(function (input) {
169    input.addEventListener('keydown', function (e) {
170      if (e.key === 'Enter') calculate();
171    });
172  });
173})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.