Skip to main content

Cash Register

Cash Register Project Mobile UI Preview Cash Register Project Mobile UI Preview

The Project

Cash Register developed with vanilla JavaScript and OOP architecture, implementing greedy algorithms, precise integer calculations, and complete drawer state management. An application that demonstrates validation patterns, optimal change calculation, and skeuomorphic design.

Source Code

<!-- DESIGN
------
* This file contains the HTML structure of the Cash Register application.
* The architecture follows this flow:
* - Head with meta tags and the Google Font 'Roboto Mono', was chosen as the font to realistically simulate the
* monospaced, dot-matrix style of a thermal receipt printer
* - Body containing a <main> element
* - Inside <main>, a primary <div> ".receipt-container" is used to display the SVG background (the paper receipt)
* - A child <div> ".receipt-content" is nested inside the container to hold all the actual UI content (text, form, etc.).

* The UI content itself is semantically structured into three main blocks:
* - .receipt-header: Contains the main title and terminal ID
* - .receipt-body: Contains the core interactive elements (form, input, button) and the output area (#change-due)
* - .receipt-footer: Contains the closing messages and transaction ID.
-->

<!DOCTYPE html>
<html lang="en">
<head>
<title>Cash Register</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@300;400;700&display=swap" rel="stylesheet">
</head>

<body>

<!--
* freeCodeCamp instructions:
* - You should have an input element with an id of "cash"
* - You should have a div, span, or p element with an id of "change-due"
* - You should have a button element with an id of "purchase-btn"
-->

<main>

<div class="receipt-container">
<div class="receipt-content">
<div class="receipt-header">
<h1>CASH REGISTER</h1>
<p>TERMINAL #09-FCC</p>
</div>
<div class="receipt-body">
<div class="total">
<p>TOTAL</p>
<p>$19.50</p>
</div>
<p>-------------------------------</p>
<form id="cash-register-form">
<label for="cash">CASH PAID</label>
<div class="user-input">
<input type="number" id="cash" name="cash" placeholder="0.00" step="0.01" min="0" required>
</div>
<button type="button" id="purchase-btn" class="cta-button">PROCESS PAYMENT</button>
</form>
<p>-------------------------------</p>
<div id="change-due"></div>
<p>-------------------------------</p>
</div>
<div class="receipt-footer">
<p class="tribute"><a href="https://www.freecodecamp.org/" target="_blank" rel="noopener noreferrer" aria-label="Visit freeCodeCamp website (opens in new tab)">Trans. ID: FCC-CERT-PROJECT-09</a></p>
<p>THANKS FOR VISITING!</p>
</div>
</div>
</div>

</main>

<script src="script.js"></script>
</body>

</html>

The Achievement: Google UX Certificate

I earned the Google UX Certificate by completing the last 2 courses I was missing and creating the other 2 required projects to obtain it.
These were two very intense weeks and I'm really happy with what I accomplished.

The Cash Register Project

In certification projects like this one, I document most of the technical choices directly in the code, including discoveries made during development. There's not much to add here then.
Nevertheless, I want to highlight some aspects. First of all, I'm thrilled to have created incredibly lightweight images without sacrificing graphics.

The SVG Receipt - 2 KB:
The result was achieved thanks to Figma, where I created the receipt with a rectangle and the pen tool. Being native SVGs, I simply grouped the various elements and exported as SVG. Result: 2 KB!

The Optimized Background - 70 KB:
Initially I had chosen a different image: a table with a slice of bread and lettuce leaf. Unfortunately it didn't offer good contrast and weighed 2 MB. So I conducted a new search in stock photo libraries, taking the opportunity to update my Tools folder on the desktop with the best image tools.
I took inspiration from an illustration and used Imagen (tool in Gemini workspace). Since the initial quality was poor, I applied upscaling with one of the tools in the folder. Then, thanks to ImageOptim, the image further decreased in weight while maintaining intact aesthetics.
Result: highest quality with a weight of only 70 KB!

The Logic with OOP Classes:
I documented everything inside the code. I wanted to use classes to practice and fortunately it proved to be an excellent choice, although it's a more complex solution than necessary compared to what's required to pass the freeCodeCamp tests.

The Other Two Projects for Google UX

Maintenance App Website:
The first was a simple website. I decided not to follow other tracks, but rather to revisit the Maintenance App imagining I was selling that service. Here's the result:

Maintenance App Website, mobile and desktop version

Desktop Version

Maintenance App Desktop Website


Mobile Version

Maintenance App Mobile Website

Mosaic: The Heart Project

The third project for the certification was the most significant one: Mosaic, an AI tool for therapists. Given the depth of the visual design (Liquid Glass analysis, Accessibility) and the Open Source philosophy, I treated it as a standalone UI Design Concept.

Explore the Mosaic Concept

What I Learned

Advanced OOP Architecture:

  • ES6 classes to encapsulate complex operational logic
  • constructor() for initialization and data preparation
  • Private methods (#calculateChange) to protect internal logic
  • Separation of responsibilities between preparation and calculation

Modern Data Structures:

  • Map instead of objects for more consistent key-value management
  • Uniform data access: .get() and .set() vs mixed notations
  • Iteration with .forEach() on Map for cleaner logic

Greedy Algorithms:

  • "Best choice at the moment" strategy for optimal change calculation
  • Pre-sorting denominations from largest to smallest
  • while loop to dispense maximum number of each denomination
  • Understanding limitations: works only with standard monetary systems

Precise Calculations with Integers:

  • Floating-point problem: 0.1 + 0.2 !== 0.3 in JavaScript
  • Dollars → cents conversion at input for precision
  • Math.round() for safe rounding
  • Cents → dollars reconversion only at output

Robust Input Validation:

  • Guard clauses for precondition checks
  • isNaN() to validate numbers
  • Edge case handling: exact cash, insufficient, greater
  • Informative alerts for immediate feedback

Transaction State Management:

  • INSUFFICIENT_FUNDS status when impossible to give change
  • CLOSED status when change completely empties the drawer
  • OPEN status for standard transactions with partial change
  • Return of structured objects: {status, change}

Image Optimization:

  • Native SVGs from Figma: 2 KB for vector graphics
  • Imagen (Gemini) for illustration generation
  • AI upscaling to improve quality without weight
  • ImageOptim for final compression

Skeuomorphic Design:

  • Radial gradient to simulate input dots on receipt
  • background-size and background-repeat for patterns
  • Roboto Mono font to simulate thermal printer
  • Transform rotate for realistic imperfections

Mobile-First with CSS Variables:

  • All values centralized in :root variables
  • Media query that overrides only necessary variables
  • 100vh + 100dvh fallback to handle iOS dynamic URL bar
  • Conditional loading: different SVG receipts for mobile/desktop

Advanced Event Handling:

  • blur event for iOS scroll fix after input focus
  • keydown with Enter for alternative submit
  • preventDefault() to control form behavior
  • Class instance recreated at each click for freeCodeCamp tests

Functional Array Methods:

  • .find() to search denomination value in DENOMINATIONS
  • .forEach() to iterate on Map cashInDrawer
  • .map() to format change array into string
  • .join() to concatenate output strings

Next Project: Learn Fetch and Promises by Building an fCC Authors Page