Your mission
Build the first browser view of your Course 02 order program. Preserve its confirmed pricing rules. Start with your own reading-order sketch and acceptance table, then create the files yourself using the concepts and short examples from the preceding lessons.
Set up your practice folder
- Create a new folder for this project.
- Copy your own Course 02 pricing, validation and regression tests into a domain subfolder. Adjust their imports if needed.
- Create package.json with
"type": "module", following Course 02's imports and exports lesson. This is the same Node configuration, not a new package to install. - Create index.html and styles.css using the semantic structure from lesson 2.
- Create sample-order.js with the input below. Add quote-view.js, render.js and main.js as you implement the responsibilities in the table.
- Run your existing domain tests before and after adding the interface:
node domain/tests.js.
export const sampleOrder = {
id: "QUOTE-001",
customer: { name: "Sara", type: "premium", active: true },
items: [{ name: "Everyday bag", unitPriceCents: 15000, quantity: 1 }]
};
Serve the page locally
Use your editor's local HTTP preview to serve the practice folder. If Python is already installed, an alternative is to run python -m http.server 4173 --bind 127.0.0.1 in that folder, then visit http://127.0.0.1:4173. Use python3 if that is your installation's command. Keep the terminal open and stop it with Ctrl+C when finished.
Use an HTTP URL, not a file URL, for browser modules. In index.html, load main.js with type="module". Check the browser console and Network panel if a module does not load. See the local testing server guide if you need help configuring a preview.
A local static preview only serves files. It does not save orders or implement an API. Do not run node serve.js unless you have actually written such a server; one is not required for this exercise.
Define responsibilities before implementation
| File | Responsibility you implement |
|---|---|
| domain/pricing.js | Your existing quote calculation |
| domain/validation.js | Your existing order validation |
| domain/tests.js | Your existing pricing regression checks |
| sample-order.js | The explicit input above |
| quote-view.js | Return a ready state with formatted amounts or an error state |
| render.js | Clear previous content and display the selected state |
| main.js | Import the input, create the view state and render it |
| index.html and styles.css | Document meaning and presentation |
Build in small, checkable steps
- Call your pricing function on the sample order and check the numeric result before touching the DOM.
- In quote-view.js, call that function inside try/catch. On success return a ready state with the customer, items and amounts. On failure return an error state with a clear message. Do not return a zero total for failure.
- Format cents only for display. For example, use
new Intl.NumberFormat("en-GB", { minimumFractionDigits: 2, maximumFractionDigits: 2 })to format cents divided by 100, then add the label "units." - In render.js, select your required elements. Clear the item list and previous amount breakdown on every render. Use createElement, append and textContent to construct the visible content; do not insert customer text with innerHTML.
- Show only the content appropriate to the state. Use the hidden property to hide an unavailable breakdown and reveal the error message.
- Connect these steps in main.js. Load the page through your local preview and inspect both the result and the console.
Keep the first version read-only. Modifying sample-order.js and reloading is enough to test these decisions. Events and forms will be introduced in later modules; do not add buttons whose behavior you cannot yet explain.
Establish the baseline
The sample customer is active and premium. One item costs 15,000 cents. Expect subtotal 150.00, discount 15.00, exercise tax 27.00 and total 162.00 units. The page says that it is a quote preview, not a purchase.
Confirm these values on paper, in the domain result and in the browser. Agreement across these layers is useful evidence; appearance alone cannot verify a pricing rule.
Introduce counterexamples
Change one value in your sample-order.js file, reload the page and compare with the expected behavior:
| Change | Expected visible behavior |
|---|---|
| Price becomes 10000, still premium | No discount; total 120.00 units |
| Customer becomes inactive | Quote unavailable, no numeric breakdown |
| Quantity becomes 0 | Quote unavailable with an explanation |
Customer name contains <strong>Sara</strong> |
Literal text; no injected bold element |
| Item name becomes very long | Text wraps and amounts remain readable |
Restore your baseline data after each investigation. Then call your renderer in sequence with a ready state, an error state and another ready state. Check that old amounts disappear on failure and the error disappears on success. Record the expected and observed outcomes in your test notes.
Review accessibility and layout
Check reading order, heading hierarchy, narrow width and 200% zoom. Use the keyboard to move through the actual links. If you add optional controls after learning events, verify that every input has a visible label and every action is keyboard-accessible. The initial read-only version does not require form controls. A missing tab stop on ordinary text is normal; not every displayed value should become focusable.
Check that the unavailable state uses words rather than color alone. If you have assistive technology available, inspect the failure announcement too. Automated tests and markup conventions do not replace that review.
Critique an AI-generated proposal
A generated solution reads the displayed subtotal text, converts it to a number, recalculates a discount in an event handler and writes a customer name through innerHTML. It looks convincing in a screenshot.
Before accepting it, identify the hidden assumptions and propose evidence that would reveal a problem.
Correction and reasoning
Formatted text is not an authoritative numeric input. A duplicate discount calculation can disagree with the tested domain policy. Customer text should not be interpreted as markup. Check a threshold case, a text-containing-markup case and a failure after a success. Evaluate the behavior regardless of whether the code came from a person or an AI tool.
Independent change request
The user asks to show "Amount before discount" instead of "Subtotal." Explain which file should change and which tests should remain unchanged. Then consider "premium customers qualify at 10000 cents or more." Is that the same kind of change?
Correction and reasoning
The label is a presentation change in render.js. Pricing results and original domain tests should remain unchanged. The threshold is a business-policy change: update the confirmed rule, expected examples and domain implementation together, then verify the interface displays the new result. Do not change the threshold in this lab's baseline silently.
Deliverable
Submit the page, preserved pricing tests, your acceptance table and a decision journal with one counterexample. Explain what you checked automatically and what you checked in the browser. Also state the current limits: no persistence, permissions, payment or remote service. Sample-data changes are local experiments, not saved orders.
Continue with the next constraint
Your first browser view is ready for an interaction. Continue to A Click Is an Intention, Not a Business Rule, where a quantity change introduces events and explicit application state.
The rest of this course develops the same program through forms, allowed transitions, local storage, HTTP, overlapping requests, server authority, accessibility and verification. You will assemble an order workbench, review a new business requirement and explain what a framework would help coordinate. These modules are available in the curriculum; build them in order so each new constraint extends a working checkpoint.