Add scenario-modeler-server example
Demo MCP App for SaaS financial planning with: - Interactive sliders for MRR, growth, churn, margin, and costs - 12-month projection charts (MRR, Gross Profit, Net Profit) - 5 pre-built scenario templates (Bootstrapped, VC Rocketship, etc.) - Template comparison overlay for strategy analysis - Light/dark theme support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f81d17f385
commit
79fa10097b
1 changed files with 1743 additions and 0 deletions
44
examples/scenario-modeler-server/src/lib/formatters.ts
Normal file
44
examples/scenario-modeler-server/src/lib/formatters.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Format a number as currency with abbreviated suffixes.
|
||||
* Examples: $50K, $1.2M, -$30K
|
||||
*/
|
||||
export function formatCurrency(value: number): string {
|
||||
const absValue = Math.abs(value);
|
||||
const sign = value < 0 ? "-" : "";
|
||||
|
||||
if (absValue >= 1_000_000) {
|
||||
const formatted = (absValue / 1_000_000).toFixed(
|
||||
absValue >= 10_000_000 ? 1 : 2,
|
||||
);
|
||||
// Remove trailing zeros after decimal
|
||||
const cleaned = formatted.replace(/\.?0+$/, "");
|
||||
return `${sign}$${cleaned}M`;
|
||||
}
|
||||
|
||||
if (absValue >= 1_000) {
|
||||
const formatted = (absValue / 1_000).toFixed(absValue >= 100_000 ? 0 : 1);
|
||||
const cleaned = formatted.replace(/\.?0+$/, "");
|
||||
return `${sign}$${cleaned}K`;
|
||||
}
|
||||
|
||||
return `${sign}$${Math.round(absValue)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a number as a percentage.
|
||||
* Examples: 5%, -2.5%, +12%
|
||||
*/
|
||||
export function formatPercent(value: number, showSign = false): string {
|
||||
const sign = showSign && value > 0 ? "+" : "";
|
||||
return `${sign}${value.toFixed(1).replace(/\.0$/, "")}%`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format currency for slider display (always show K suffix for consistency).
|
||||
*/
|
||||
export function formatCurrencySlider(value: number): string {
|
||||
if (value >= 1_000) {
|
||||
return `$${(value / 1_000).toFixed(0)}K`;
|
||||
}
|
||||
return `$${value}`;
|
||||
}
|
||||
Loading…
Reference in a new issue