Skip to content

fix(frontend): expose LAN addresses for customer display pairing - #1163

Merged
khaira777 merged 4 commits into
mainfrom
codex/display-lan-addresses
Oct 15, 2026
Merged

khaira777 merged 4 commits into
mainfrom
codex/display-lan-addresses

Conversation

@khaira777

Copy link
Copy Markdown
Contributor

Intent

Fix issue #1147 so customer-display Settings exposes usable LAN addresses for pairing from another device. Reuse the existing authenticated /api/pos-info response, which reports the actual API-serving port, and do not use KDS-gated KDS info, a hardcoded port, a new public endpoint, a new dependency, or a Next.js API handler. Show the primary LAN address prominently and allow selecting other discovered IP and mDNS addresses plus a clearly labelled this-computer-only local preview. Both the display URL and pairing link must use the selected origin. Address selection occurs before pairing and switching origins must preserve the same pair token and device identity; do not mint another token. Preserve fragment-scoped access, one-time token visibility, reload behavior, and revocation. If no LAN address exists, state that clearly and offer local preview. If network lookup fails, show an explicit error and retry; never silently present localhost as LAN. Load network information once when the settings card opens and only again on explicit retry. Preserve the #1149 authentication and clipboard safeguards when rebasing. Do not duplicate the separately owned #1141 clipboard work or redo the merged #1105 pairing repair. Update canonical docs only if necessary and maintain translation completeness. Keep the desktop static-export boundary. The approved issue is #1147 and the resulting PR must close it.

What Changed

  • Updated CustomerDisplayCard to fetch POS network addresses once from GET /api/pos-info, defaulting to the primary LAN origin while allowing selection of alternate interface IPs, mDNS addresses, or a labelled local preview origin for both the display URL and the one-time #token= pairing link without minting additional tokens.
  • Handled unavailable LAN and failed /api/pos-info lookup states explicitly with local-preview fallback messaging and an on-demand retry action, instead of silently presenting window.location.origin as a LAN address.
  • Added locale strings across all 24 translation files, updated docs/architecture/frontend.md, and added Playwright E2E coverage for customer display pairing address selection and fallback states.

Risk Assessment

✅ Low: The change is well-bounded to CustomerDisplayCard, its translations, documentation, and E2E tests, and the Round 1 fix cleanly resolved the DOM/locator collisions with existing E2E suites.

Testing

Built the backend and static desktop frontend, ran focused backend and translation suites (test:customer-display-config, test:customer-display-settings-route, test:customer-display-pairing, test:api-path-casing-auth, test:translations), executed Playwright E2E specs (customer-display-pairing-addresses.spec.ts, customer-display-pairing.spec.ts, and settings-request-budget.spec.ts) on isolated ports 43001-43003, and drove the live product on ports 43011-43013 to capture six visual screenshots covering primary LAN selection with the actual serving port, origin switching with token preservation, network lookup failure and retry, no-LAN fallback, unauthenticated display board pairing/reload, and revocation; physical cross-device testing on a second LAN device remains manual verification as no second hardware device is attached to this runner.

  • Live validation: ✅ go - 7 of 8 scenarios driven live against the product
Scenario Result Live Evidence
Opening Customer display settings loads /api/pos-info once (even with KDS disabled), selects the primary LAN address with the actual serving port (43011), and exposes secondary LAN IPs, mDNS, and loca… ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-lan-addresses.png
Pairing a display and switching between primary LAN, secondary LAN IP, mDNS, and local preview updates both the display URL and one-time pairing link origin while preserving the same cdt_ token withou… ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-switched-origin-same-token.png
Opening the pairing link in an unauthenticated browser context consumes and strips the #token fragment, displays active orders across page reloads without staff login, rejects staff API access (/api/p… ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-paired-board.png
Revoking the active paired display clears its visible one-time pairing link in settings, removes its stored localStorage token on next poll/reload, and shows the unpaired screen ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-revoked-board.png
Network lookup failure on /api/pos-info displays an explicit error and Retry action without silently presenting localhost as a LAN address, and only reloads /api/pos-info on explicit retry ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-network-error.png
When /api/pos-info reports only loopback addresses and no LAN IP, settings states that LAN pairing is unavailable, omits mDNS, and leaves local preview unselected until explicitly chosen ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-no-lan-fallback.png
Unauthenticated requests to /api/pos-info and case variants (/API/pos-info) are rejected with 401, and both customer-display copy buttons handle missing, sync-throwing, and async-rejecting navigator.c… ✅ pass live frontend/e2e/customer-display-pairing.spec.ts and tests/api-path-casing-auth.test.ts
Opening the LAN or mDNS pairing link from a separate physical TV or tablet on the same Wi-Fi/LAN subnet pairs the second hardware device ⏸️ untested no Verified the live server's /api/pos-info LAN/mDNS URLs (http://192.168.1.44:43011, http://100.94.152.62:43011, http://flo.local:43011) and drove pairing in an isolated unauthenticated browser context…

Customer display settings showing primary LAN address, secondary IP/mDNS/local preview options, and one-time pairing link on port 43011
Customer display settings after switching to mDNS address while preserving the same pairing token and device row
Customer display settings showing explicit network lookup error and Retry action without silently falling back to localhost as LAN
Customer display settings showing no-LAN notice and unselected local preview option after retry when only loopback addresses are returned
Paired customer display board in an unauthenticated browser context displaying live ready order after consuming #token fragment and reloading
Paired customer display board transitioning to unpaired state after token revocation

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed ✅
  • 🚨 frontend/src/components/settings/CustomerDisplayCard.tsx:257 - Rendering the pairing-address radio option origins inside <code> tags in CustomerDisplayCard.tsx:257, CustomerDisplayCard.tsx:279, and CustomerDisplayCard.tsx:297 breaks existing E2E selectors on the Kitchen Display settings tab (tab=kds): (1) in frontend/e2e/customer-display-pairing.spec.ts:265-268 (from fix(frontend): allow unauthenticated customer display pairing and guard clipboard copy #1149), card.locator('code') now matches 4+ elements instead of the 2 copyable URL <code> elements (CustomerDisplayCard.tsx:480 and CustomerDisplayCard.tsx:322), failing expect(codeElements).toHaveCount(2) and shifting codeElements.nth(1) from pairingLink.url to primaryOrigin (and in loopback-only environments where /api/pos-info has no LAN IP, CustomerDisplayCard.tsx:311 keeps Pair display disabled in frontend/e2e/customer-display-pairing.spec.ts:128 and :262 until the local preview radio is checked); (2) in frontend/e2e/settings-request-budget.spec.ts:1261 (called from :1286 on the Kitchen Display tab), page.getByText('http://10.42.0.25:3001', { exact: true }).locator('xpath=..') now matches both the KDS QR pairing card link parent and CustomerDisplayCard's otherOrigins radio label (CustomerDisplayCard.tsx:279), causing expect(localCard).toContainText(englishLocalHint) at frontend/e2e/settings-request-budget.spec.ts:1264 to fail with a Playwright strict-mode violation. Use <span dir="ltr" className="... font-mono ..."> for the radio option origin sublabels at CustomerDisplayCard.tsx:257, :279, and :297, scope localCard in frontend/e2e/settings-request-budget.spec.ts:1261 to page.getByRole('link', { name: localAddress, exact: true }).locator('xpath=..'), and ensure an address radio option is selected in frontend/e2e/customer-display-pairing.spec.ts:24 when opening the tab.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 7 of 8 scenarios driven live against the product
Scenario Result Live Evidence
Opening Customer display settings loads /api/pos-info once (even with KDS disabled), selects the primary LAN address with the actual serving port (43011), and exposes secondary LAN IPs, mDNS, and loca… ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-lan-addresses.png
Pairing a display and switching between primary LAN, secondary LAN IP, mDNS, and local preview updates both the display URL and one-time pairing link origin while preserving the same cdt_ token withou… ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-switched-origin-same-token.png
Opening the pairing link in an unauthenticated browser context consumes and strips the #token fragment, displays active orders across page reloads without staff login, rejects staff API access (/api/p… ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-paired-board.png
Revoking the active paired display clears its visible one-time pairing link in settings, removes its stored localStorage token on next poll/reload, and shows the unpaired screen ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-revoked-board.png
Network lookup failure on /api/pos-info displays an explicit error and Retry action without silently presenting localhost as a LAN address, and only reloads /api/pos-info on explicit retry ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-network-error.png
When /api/pos-info reports only loopback addresses and no LAN IP, settings states that LAN pairing is unavailable, omits mDNS, and leaves local preview unselected until explicitly chosen ✅ pass live ~/.no-mistakes/evidence/01M4YKJ7T758J7P2285MSMY3NR/customer-display-no-lan-fallback.png
Unauthenticated requests to /api/pos-info and case variants (/API/pos-info) are rejected with 401, and both customer-display copy buttons handle missing, sync-throwing, and async-rejecting navigator.c… ✅ pass live frontend/e2e/customer-display-pairing.spec.ts and tests/api-path-casing-auth.test.ts
Opening the LAN or mDNS pairing link from a separate physical TV or tablet on the same Wi-Fi/LAN subnet pairs the second hardware device ⏸️ untested no Verified the live server's /api/pos-info LAN/mDNS URLs (http://192.168.1.44:43011, http://100.94.152.62:43011, http://flo.local:43011) and drove pairing in an isolated unauthenticated browser context…
  • npm run build && npm run build:frontend
  • npm run test:customer-display-config
  • npm run test:customer-display-settings-route
  • npm run test:customer-display-pairing
  • npm run test:api-path-casing-auth
  • npm run test:translations
  • CI=1 E2E_BASE_URL=http://127.0.0.1:43001 E2E_KDS_BASE_URL=http://127.0.0.1:43002 E2E_SERVER_APP_BASE_URL=http://127.0.0.1:43003 npx --prefix frontend playwright test --config=frontend/playwright.config.ts --project=chromium frontend/e2e/customer-display-pairing-addresses.spec.ts frontend/e2e/customer-display-pairing.spec.ts -g "customer display|Customer display|Network pairing cards" frontend/e2e/settings-request-budget.spec.ts
  • Live Playwright Chromium verification against tests/e2e-server.cjs on isolated ports 43011/43012/43013 capturing 6 visual evidence screenshots
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: FreeOpenSourcePOS/FloCafe/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 37433f1d-cd5d-40e1-b6b2-fb8e282b374e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@khaira777

Copy link
Copy Markdown
Contributor Author

@greptile review

@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues were found.

Summary

The customer display settings now load addresses from the authenticated /api/pos-info endpoint and use the selected address for both display and pairing links.

  • Customer display links now use a selected POS network address.

Opening the default LAN display URL may require another login. Using the selected origin is explicitly intended by khaira777; the same-computer preview remains available without changing the pairing flow.

Diagram

sequenceDiagram
  participant Staff as Staff browser
  participant API as Express API
  participant Display as Display browser
  Staff->>API: GET /api/pos-info with staff authentication
  API-->>Staff: LAN addresses and actual serving port
  Staff->>Staff: Select an address
  Staff->>API: Create display token
  API-->>Staff: One-time token
  Staff->>Staff: Build pairing link using selected address
  Staff->>Staff: Switch address without creating another token
  Display->>Display: Read token from link fragment
  Display->>API: Request display feed with scoped token
Loading

Reviews (1) · Last reviewed commit: "no-mistakes(document): Format changed se..." · Reviewed by Greptile

@khaira777
khaira777 enabled auto-merge (squash) October 15, 2026 06:56
@khaira777
khaira777 merged commit c01af07 into main Oct 15, 2026
23 checks passed
@khaira777
khaira777 deleted the codex/display-lan-addresses branch October 15, 2026 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant