Building a Browser-Only Calculator With Reproducible Offers
A calculator becomes a different kind of application when somebody needs to explain its result, print it, and return to the same offer later. Recalculating the current screen is easy. Preserving what was actually offered takes a more deliberate data model.
In my gold and silver valuation app, I kept the frontend static and put the working state in the browser. That removed a backend from the deployment, but it made state boundaries particularly important.
Start with units, then calculate
The interface accepts weights, purity, prices, and purchase or sale adjustments. These quantities should never be interchangeable just because they are all JavaScript numbers.
A simplified calculation for a purchase item is:
fine weight = gross weight ร purity fraction
reference value = fine weight ร reference price per gram
offer value = reference value ร (1 โ purchase discount)
This example assumes a reference price for pure metal, expressed per gram. A price quoted per troy ounce must be converted before entering that formula. Purity also needs an explicit representation: a fraction and a number expressed in thousandths are different inputs.
I keep conversion and calculation concerns separate from translated labels. Changing the interface language must not change a numeric result. Rounding should happen at defined presentation and offer boundaries, rather than repeatedly after each intermediate operation.
A live quote and a locked offer are different objects
Refreshing a reference price should update the editable working calculation. A previously locked offer needs its own snapshot.
That snapshot needs enough information to explain the result: item weights, purity, reference price, currency, adjustments, calculated values, and creation time. An old offer should not silently recalculate against today's market input.
The application supports time-limited offer locks and a local offer history. Those are workflow features, not a tamper-resistant accounting ledger. Local browser storage can be changed or cleared, and a local clock is not a trusted financial time source.
The customer display is a projection
A second-screen view should show the selected offer without exposing editing controls. The app uses a browser messaging channel where available to propagate changes to that display.
The useful boundary is between the editable state and its presentation. Both screens should render the same values; neither should invent a second pricing implementation. A display reload also needs a way to recover a current snapshot instead of depending entirely on messages that were sent before it opened.
Handle unavailable prices without inventing zero
The optional price refresh is an external dependency. When it fails, replacing the reference price with zero would produce a valid-looking but meaningless offer.
The existing design keeps previously entered values and allows manual input. That preserves the ability to work while making the source of the price a separate concern.
For this application, staying backend-free is practical. The tradeoff is explicit: local persistence provides convenience and continuity on that browser, while shared records, centralized backup, and authoritative auditing would require another storage boundary.