BMI calculator

let data = signal({ height: 1.8, weight: 78 });

let bmi = signalFn(
  withInputSignals(
    () => data,
    ({ height, weight }) => weight / (height * height)
  )
);

let diagnose = signalFn(
  withInputSignals(
    () => bmi,
    bmi => {
      if (bmi < 18.5) return "underweight";
      if (bmi < 25) return "healthy";
      if (bmi < 30) return "overweight";
      return "obese";
    }
  )
);

let color = signalFn(
  withInputSignals(
    () => diagnose,
    diagnose => {
      switch (diagnose) {
        case "underweight":
        case "overweight":
          return "orange";
        case "healthy":
          return "green";
        default:
          return "red";
      }
    }
  )
);

function slider(key, value, min, max, step = 1) {
  return h("input", {
    attrs: {
      type: "range",
      value,
      min,
      max,
      step
    },
    style: { width: "100%" },
    on: {
      input: function(e) {
        data.update(data => ({
          ...data,
          [key]: e.target.value
        }));
      }
    }
  });
}

function calculator([data, bmi, diagnose, color]) {
  let { height, weight } = data;

  return h("div.bmi", [
    h("h3", "BMI calculator"),
    h("div", [`Height: ${height}m`, slider("height", height, 1.0, 2.2, 0.01)]),
    h("div", [`Weight: ${weight}kg`, slider("weight", weight, 30, 200)]),
    h("p", [
      `BMI: ${Math.round(bmi)}`,
      " - ",
      h("strong", { style: { color: color } }, diagnose)
    ])
  ]);
}

mount(
  mountPoint,
  withInputSignals(() => [data, bmi, diagnose, color], calculator)
);