pricing
by Tyler Brown
HTML
<div class="cbs">
</div>
<table id="results">
<thead>
<tr>
<th>Employee Cap</th>
<th>Total</th>
<th>
<input type="checkbox" id="cb-match" checked data-feature="match" />
<label for="cb-match">Match</label>
</th>
<th>
<input type="checkbox" id="cb-intl" checked data-feature="intl" />
<label for="cb-intl">International</label>
</th>
<th>
<input type="checkbox" id="cb-vol" checked data-feature="vol" />
<label for="cb-vol">Volunteering</label>
</th>
<th>
<input type="checkbox" id="cb-groups" checked data-feature="groups" />
<label for="cb-groups">Groups</label>
</th>
<th>
<input type="checkbox" id="cb-analytics" checked data-feature="analytics" />
<label for="cb-analytics">Analytics</label>
</th>
<th>
<input type="checkbox" id="cb-sso" checked data-feature="sso" />
<label for="cb-sso">SSO</label>
</th>
<th>
<input type="checkbox" id="cb-payroll" data-feature="payroll" />
<label for="cb-payroll">Payroll</label>
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
CSS
html, body {
margin: 0;
padding: 0;
font-family: Arial;
}
body {
padding: 24px;
}
table {
width: 100%;
text-align: right;
border-collapse: separate;
border-spacing: 0;
border: 1px solid #DDD;
border-width: 1px 0 0 1px;
}
td, th {
font-weight: normal;
padding: 12px;
border: 1px solid #DDD;
border-width: 0 1px 1px 0;
}
th:nth-child(2), td:nth-child(2) {
font-weight: bold;
}
th {
position: sticky;
top: 0;
background-color: white;
}
tr:hover td {
background-color: #DEF;
}
JavaScript
const pricing = (() => {
const absMin = 0;
const pricePoints = [
{cap: 100, price: 3015},
{cap: 150, price: 4266},
{cap: 200, price: 5474},
{cap: 250, price: 6558},
{cap: 300, price: 7467},
{cap: 350, price: 8260},
{cap: 400, price: 8968},
{cap: 450, price: 9599},
{cap: 500, price: 10145},
{cap: 600, price: 11472},
{cap: 700, price: 12376},
{cap: 800, price: 13264},
{cap: 900, price: 13905},
{cap: 1000, price: 14680},
{cap: 1250, price: 16125},
{cap: 1500, price: 17175},
{cap: 1750, price: 18638},
{cap: 2000, price: 20100},
{cap: 2500, price: 23200},
{cap: 3000, price: 26340},
{cap: 3500, price: 29120},
{cap: 4000, price: 31200},
{cap: 4500, price: 34515},
{cap: 5000, price: 37650},
{cap: 5500, price: 40590},
{cap: 6000, price: 43440},
{cap: 6500, price: 46020},
{cap: 7000, price: 48580},
{cap: 8000, price: 54400},
{cap: 9000, price: 60030},
{cap: 10000, price: 65300},
{cap: 15000, price: 85500},
{cap: 20000, price: 93000},
];
const percents = {
intl: 0.10,
vol: (empCount) => (empCount > 300) ? 0.3 : 0.3,
volNoMatch: 0.80,
groups: 0.25,
analytics: 0.20,
sso: (empCount) => (empCount > 300) ? 0.10 : 0.05,
payroll: 0.20,
};
const getPrice = (empCount=0, {match=false, intl=false, vol=false, groups=false, analytics=false, sso=false, payroll=false, madness=false} = {}) => {
if (empCount > 20000) return null;
const pricePoint = pricePoints.find(mp => mp.cap >= empCount);
if (!pricePoint) return null;
const basePrice = pricePoint.price;
const priceFromPercent = (percentage) => Math.round(basePrice * percentage);
const hasMatch = !!(match || intl);
const volPercentage = hasMatch ? percents.vol(empCount) :...