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) :...