Pinned 2026 toolchains (Go 1.26, Rust 1.98/edition 2024, Python 3.14 + uv, Node 24, Zig 0.16, NixOS 26.05), postgres 18 / mongo 8, lockfiles built from, non-root runtimes, .dockerignore, per-project LICENSE, READMEs with the git.devai.io clone line, checkout@v7 CI. Security fixes in the legacy Rust APIs (any-password login, self-assigned admin, hard-coded JWT secret), JWT alg/exp/sub enforcement across the blog series, safe markdown links in the frontends, and many smaller bugs — every project was built, run and exercised end to end. Adds scripts/publish.sh + a CI publish job that splits every folder into its own repo at git.devai.io/templates/<folder>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01128fhuZbgivaSJvtMf4s1G
31 lines
1.2 KiB
JavaScript
31 lines
1.2 KiB
JavaScript
const billInput = document.getElementById("bill");
|
|
const tipInput = document.getElementById("tip");
|
|
const peopleInput = document.getElementById("people");
|
|
|
|
const tipLabel = document.getElementById("tipLabel");
|
|
const tipAmountEl = document.getElementById("tipAmount");
|
|
const perPersonEl = document.getElementById("perPerson");
|
|
|
|
const money = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
|
|
|
|
// The whole app is one loop: READ the inputs, do the MATH, WRITE the answers
|
|
// back onto the page.
|
|
function calculate() {
|
|
const bill = parseFloat(billInput.value) || 0; // an empty box counts as 0
|
|
const tipPct = parseInt(tipInput.value, 10);
|
|
const people = Math.max(1, parseInt(peopleInput.value, 10) || 1); // never divide by 0
|
|
|
|
const tip = bill * (tipPct / 100);
|
|
const perPerson = (bill + tip) / people;
|
|
|
|
tipLabel.textContent = tipPct + "%";
|
|
tipAmountEl.textContent = money.format(tip);
|
|
perPersonEl.textContent = money.format(perPerson);
|
|
}
|
|
|
|
// The key line: "whenever this input changes, run calculate()". That's what
|
|
// makes the page react as you type or drag — no framework, no magic.
|
|
for (const el of [billInput, tipInput, peopleInput]) {
|
|
el.addEventListener("input", calculate);
|
|
}
|
|
calculate();
|