Files
cannabis-dosing/dist/index.html
2019-08-31 14:14:41 -07:00

192 lines
6.0 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="./static/mini-default.css">
<style>
input,
select {
width: 95%;
}
</style>
<title>Cannabis Dosing Calculator</title>
</head>
<body>
<div id="app">
<h1>Dosing Calculator</h1>
<fieldset>
<legend>Ingredients</legend>
<div class="container">
<div class="row">
<div class="col-sm-6 col-md-3">
<label for="thc-per">THC Amt (%)</label>
<input type="text" id="thc-per" value="10" />
</div>
<div class="col-sm-6 col-md-3">
<label for="cbd-per">CBD Amt (%)</label>
<input type="text" id="cbd-per" value="0" />
</div>
<div class="col-sm-6 col-md-3">
<label for="weight">Material (g)</label>
<input type="text" id="weight" value="3.5" />
</div>
<div class="col-sm-6 col-md-3">
<label for="oil-amount">Oil (cups)</label>
<input type="text" id="oil-amount" value=".25" />
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend>Results</legend>
<div class="container">
<div class="row">
<div class="col-sm-6 col-md-3">
<label for="dose-amount">Dose</label>
<input type="text" id="dose-amount" value="1" />
</div>
<div class="col-sm-6 col-md-3">
<label for="dose-type">Volume</label>
<select id="dose-type" value="ml">
<option value="ml">mL</option>
<option value="tsp">tsp</option>
<option value="tbsp">Tbsp</option>
<option value="cup">Cup</option>
</select>
</div>
<div class="col-sm-6 col-md-3">
<label for="thc-dose">THC Dose (mg)</label>
<input type="text" id="thc-dose" value="" />
</div>
<div class="col-sm-6 col-md-3">
<label for="cbd-dose">CBD Dose (mg)</label>
<input type="text" id="cbd-dose" value="" />
</div>
</div>
<div class="row">
<div class="col-sm-6 col-md-3">
<label for="thc-total">THC Content (mg)</label>
<input readonly type="text" id="thc-total" value="" />
</div>
<div class="col-sm-6 col-md-3">
<label for="cbd-total">CBD Content (mg)</label>
<input readonly type="text" id="cbd-total" value="" />
</div>
<div class="col-sm-6 col-md-3">
<label for="absorb-per">Absorb (%)</label>
<select id="absorb-per">
<option value="80">80%</option>
<option value="85" selected>85%</option>
<option value="90">90%</option>
<option value="95">95%</option>
<option value="100">100%</option>
</select>
</div>
</div>
</div>
</fieldset>
</div>
<script>
(function app() {
// create map of values and input ids
const inputMap = {
thcPercent: '#thc-per',
cbdPercent: '#cbd-per',
weight: '#weight',
oil: '#oil-amount',
doseAmount: '#dose-amount',
doseType: '#dose-type',
thcDose: '#thc-dose',
cbdDose: '#cbd-dose',
thcTotal: '#thc-total',
cbdTotal: '#cbd-total',
absorbPercent: '#absorb-per',
};
// cache input selectors
const inputs = Object.keys(inputMap).reduce((acc, name) => {
const val = document.querySelector(inputMap[name]);
acc[name] = val;
return acc;
}, {});
// helper functions
function round(val, dec = 2) {
const mult = Math.pow(10, dec);
return Math.round(val * mult) / mult;
}
function saveForm() {
const data = Object.entries(inputs).reduce((acc, [name, input]) => {
acc[name] = input.value;
return acc;
}, {});
localStorage.setItem('data', JSON.stringify(data));
}
function restoreForm() {
const data = JSON.parse(localStorage.getItem('data') || '{}');
Object.entries(data).forEach(([name, value]) => {
inputs[name].value = value;
});
}
// recalculate form values on change
function handleChange() {
// persist inputs to localstorage
saveForm();
// collect data
const totalTHC = inputs.weight.value * inputs.thcPercent.value / 100;
const totalCBD = inputs.weight.value * inputs.cbdPercent.value / 100;
const absorbFactor = inputs.absorbPercent.value / 100;
const dosefactor = (() => {
const type = inputs.doseType.value;
if (type === 'tsp') return 0.20289;
if (type === 'tbsp') return 0.06762;
if (type === 'cup') return 0.00422;
return 1; // mL
})();
// update total amounts
inputs.thcTotal.value = round(totalTHC * absorbFactor * 1000);
inputs.cbdTotal.value = round(totalCBD * absorbFactor * 1000);
// update dose amounts
const volumeML = inputs.oil.value * 236.58813;
inputs.thcDose.value = round(totalTHC / volumeML * absorbFactor * inputs.doseAmount.value * 1000 / dosefactor);
inputs.cbdDose.value = round(totalCBD / volumeML * absorbFactor * inputs.doseAmount.value * 1000 / dosefactor);
}
// listen for changes on all inputs
document.querySelectorAll('#app input').forEach(el => {
el.addEventListener('keyup', (ev) => handleChange(el, ev));
});
// listen for changes on all selects
document.querySelectorAll('#app select').forEach(el => {
el.addEventListener('change', (ev) => handleChange(el, ev));
});
// restore input values
restoreForm();
// update form on load
handleChange();
})();
</script>
</body>
</html>