docs + fix: Leads module doc, badges onsite doc, license access fix, QR log cleanup

- Add MODULE__AE_Events_Exhibitor_Leads.md — full module reference (auth model, tabs,
  data model, routes, offline/PWA notes, OSIT admin notes)
- Add MODULE__AE_Events_Badges_Onsite.md — onsite printing guide (browser settings,
  CUPS/Linux setup, Zebra ZC10L section with test results, Epson stub, troubleshooting)
- Archive PROJECT__AE_Events_Exhibitor_Leads_v3*.md + Zebra test day doc → history/
- Fix leads license management access: ae_tab__manage.svelte license section now visible
  to administrator_access OR shared-passcode sign-in (type === 'shared'); matches spec
- Add type field to LeadsLocState.auth_exhibit_kv interface (was set at runtime but missing from type)
- Silence QR code console noise: entry log gated at log_lvl >= 2, data URL log removed
- vite.config.ts: exclude documentation/ and tests/ from Vite HMR file watcher

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-20 12:58:57 -04:00
parent 9673cbefe3
commit 14c2635df4
11 changed files with 462 additions and 12 deletions

View File

@@ -0,0 +1,175 @@
Aether Events Exhibitor Leads v3
=======
## Overview:
* Mobile first!
* Offline caching for spotty network connections
* Clean and simple
* Exhibitors have between 0 and X license
* Sign in and "claim" an assigned license linked to an Exhibitor
* Collect and manage Leads per Exhibitor
* Export Leads data to CSV or XLSX
* Exhibitors will have the link to their Exhibit sent to them or they can use the Exhibit Search to find their Exhibit and sign in with the shared passcode or their assigned licensed user credentials.
---
## Primary Leads Pages/Tabs
1. start - Sign In / Licenses
* Exhibit passcode sign in
* Exhibitor Leads user sign in
* Payment - Leads Payment
2. add - Add (Search/QR)
* Text search
* QR scan
3. leads - Leads List
* List of Attendees (Event Badge ID) linked to Exhibit
* Click to view/edit Exhibit Tracking entry
4. manage - Leads (app and exhibit) Manage
---
## Exhibitor Sign In and Licenses:
* An Exhibit needs to have a "Shared exhibit passcode" for primary sign in.
* A Licensed Exhibit staff person needs to have a License assigned to them. It is important that the email address not be changed per license. Or if they do, be aware of the affects on tracked attendees. They can then sign in with that email address and passcode assigned. And/Or we need to make the email sign in link work as well.
* Once signed in with the Exhibit passcode, they can change it (passcode) and assign Exhibit Leads licenses once they have paid.
* An exhibitor marked as "priority" means they have paid. Only OSIT admins can mark them as paid.
* Should at least claim/assign one initial user license so an Exhibit related staff can sign in (without the shared Exhibit passcode). Then add, update, or remove licenses based on max allowed per Exhitibor.
Payment:
* Not Paid: <span class="fas fa-question text-red-500 m-1"></span> <span class="fas fa-credit-card mx-1"></span> Waiting for payment
* Paid: <span class="fas fa-check text-green-500 m-1"></span> <span class="fas fa-credit-card mx-1"></span> Marked as paid
### Licenses:
A client staff (Trusted Access or above) or someone signed in with an Exhibit passcode can add/edit/remove icenses.
License:
* full_name
* email
* passcode
---
## Structure Overview
* There are 4 primary tabs for the Event Exhibit Leads module.
* The overall header/footer should hide by default once signed in.
* If not signed in, only the first tab, to start and sign in is shown.
---
## [tab 1] Start / Sign In / Payment
* Only shows when not signed in as Exhibit Licensed Leads User
* Sign in with Exhibit passcode
* This will then allow them to Manage the Exhibit License
* Sign in with Exhibit Licensed user
### [tab section] Payment
* Shows if signed in with Exhibit Passcode and not marked as paid / priority
* Field for license info - event_exhibit.license_li_json
* Use Exhibit passcode first?
* Select number of licenses
* Select number of small/large devices
* Make payment (Stripe)
### [tab section] Licensed Users
* Shows if signed in with Exhibit Passcode and are marked as paid / priority
* Fill in Exhibit staff users per max licenses
## [tab 2] Add - Search / QR Scan
* One button that toggles between showing and hiding the QR add mode? The text search is always shown above or below the QR scan camera image area.
* Search - Essentially the same as the Badge search. Full name, email, affiliations, ID, etc
* QR Scan - Allow for auto add toggle instead of confirming per scan. Allow for manual entire of Badge ID
* The QR scan is basically just using the Event Badge ID encoded in the persons QR code on their badge. In fact it can probably just populate the text search field?
* Must include the Leads licensed user's email address when adding to the Exhibitor Tracking list. Linked using event_exhibit_tracking with the Licensed user's email address.
## [tab 3] Leads - List of Attendee Leads for Exhibitor
* Allow for toggle between showing all per Exhibit and per licensed user based on their email address. Not perfect, but works well enough.
* Allow for easy edit or remove
* Button to Export Data - CSV or XLSX
* Toggle for show/hide Hidden records
* Select options for sorting: Newest added first, Oldest added first, Alpha ascending, Alpha descending, Last updated first
## [tab 4] Manage / Config
### Exhibit Specific
* Priority/payment toggle - Administrator Access or above
* Max licenses (number) - readonly or edit for Administrator Access or above
* Small devices (number) - readonly or edit for Administrator Access or above
* Large devices (number) - readonly or edit for Administrator Access or above
* Exhibit (shared) Passcode
* Same Exhibit Leads License list component as the Start tab's Licensed Users section
### App Specific
* Show/Hide Payment Tab
* Additional Settings:
* List refresh interval in seconds - default 25 seconds; 1 second to 2 minutes (120000)
* Basic reload/refresh
* Clear Indexed DB
* Clear localStorage
* Auto hide header/footer on sign in - default true
* (?) Turn on iframe mode
* (?) Show or hide additional details - Use "$events_loc.show_details"?
## [page] View / Edit Tracked Attendee (event_exhbit_id, event_badge_id
* Able to edit the obvious things
* Can add custom exhibitor_notes and custom responses_json
* Can set Priority (Star/Flag)
* Can set Sort (number)
* Can set Hide (toggle)
---
## App Specific - Leads Module Config Options and Stored Data
* Signed in using Shared Exhibit Passcode
* Can make payment and manage user licenses
* Need to be able to sign in with Shared Passcode and Leads License passcode.
* Signed in using one Leads License slot they were assigned to
* Things will be tied to their email address
* Can add, edit, remove, etc the Leads specific to an Exhibit.
* This list is shared among all Licensed staff for a specific Exhibit. It is recommended they stay toggled to only showing their additions by default.
* Need to be able to sign in with Shared Passcode and Leads License passcode.
* Show and Hide payment tab (override sort of)
* Show and Hide header/footer (override sort of)
* Use iframe mode??
* Light and Dark mode??
* List refresh interval
* Tracking list sorting
* Show and hide hidden records
* Show and hide enabled records (Administrator Access or above)
There are essentially 3 ways to "Sign In":
1. Aether Platform in general using a defined Core User or using a Client Site specific passcode.
2. Exhibit shared passcode for general Exhibitor management. Should only be briefly needed to pay and assign license slots
3. Licensed Leads User using the email address and passcode assigned by the Exhibitor manager or OSIT/client staff person.
---
## First Steps for Leads v3
Create stub directories, pages, and other supporting files for each primary tab, and each primary section within each tab, and for viewing a specific Lead (Exhibit Tracking).
Once we have that looking good, then we can add the functionality. So we are kind of laying out the framework and pre-documenting (commenting) the files as we go.
---
## For Reference if Needed
Known goodish reference version of Leads v2ish:
d1021e28227db6d49b16cc48e324872b1a322da3 November 19, 2025 at 10:45 PM
Hopefully that is not needed...

View File

@@ -0,0 +1,153 @@
Aether Events Exhibitor Leads v3 - Details
=======
## [root page] Leads for Exhibitors Main Landing
* Has a search for Exhibits section that allows for searching Exhibits by name or code.
* Results can be sortable. They can be sorted by name, booth number, or last created/updated.
* This is for exhibitors to find their Exhibit and sign in with the shared passcode or their assigned licensed user credentials.
* If not signed in with Administrator Access or above, then only show results for Exhibitors that have been marked as "priority" (paid). Otherwise show all Exhibitors (to admins).
* Has a list of Exhibits with basic info and link to Exhibit Leads management page for each Exhibit. Do not show results by default or if less than 3 characters in search and they are not signed in with Trusted Access or above.
## [exhibit_id page] Exhibit Leads Module
* This is minimalistic. Only the tabs and content needed.
### Header/Footer
* Overall header/footer should hide by default once signed in. Use Aether iframe mode?
* Leads module header should show the Exhibit name and booth number. It should also have a button to toggle the Add Lead tab and Lead List tab. There should also be a button to show the Manage/Config tab for the Exhibit.
Header: [Name and Booth # text] [Add Lead / Lead List toggle] [Manage/Config button]
### Tabs:
I am probably using the term "tab" loosely here. It may just be sections that show/hide based on buttons or whatever. The main thing is to keep the UI simple and not overwhelm the user with too many options at once. The main flow should be to easily add leads and then view/manage those leads. The Manage/Config tab is more for the person managing the Exhibit and should be separate from the lead capture and management interface.
1. Start - Sign In / Licenses / Payment
2. Add - Search/QR
3. Leads - List of Attendee Leads for Exhibitor
4. Manage - Leads (app and exhibit) Manage
### [tab 1] Start / Sign In / Payment
* Only shows when not signed in as Exhibit Licensed Leads User
* Show notification and or message that this is a PWA and can be installed on their device for easier access.
* Sign in with Exhibit passcode
* This will then allow them to Manage the Exhibit License
* Sign in with Exhibit Licensed user
* This will then allow them to Manage the Exhibit License
* Payment - Leads Payment
* Not Paid: <span class="fas fa-question text-red-500 m-1"></span> <span class="fas fa-credit-card mx-1"></span> Waiting for payment
* Paid: <span class="fas fa-check text-green-500 m-1"></span> <span class="fas fa-credit-card mx-1"></span> Marked as paid
* Need to switch to Lucide icons
* Sections:
* Sign in with Exhibit "shared" passcode
* This will then allow them to Manage the Exhibit License
* Change to Sign Out once signed in
* Once signed in, show message to the Exhibit person. Allow them to select number of Licenses, make a payment, and manage the Licenses if paid.
* Sign in with Exhibit Licensed user
* This will then allow them to Manage the Exhibit License
* Change to Sign Out once signed in
* Once signed in, show message to the Leads user. A big button should allow them to then start adding leads.
* Payment (Stripe) - Leads Payment
* Only show if signed in with Exhibit "shared" passcode and not marked as paid.
* Licenses (table):
* A client staff (Trusted Access or above) or someone signed in with an Exhibit passcode can add/edit/remove licenses.
* License:
* full_name
* email
* passcode
* Buttons and Inputs:
* Sign in with Exhibit passcode
* Sign in with Exhibit Licensed user
* Payment - Leads Payment
* Add/Edit/Remove Licenses (if signed in with Exhibit passcode or Trusted Access or above)
### [tab 2] Add - Search/QR
* Show only when signed in as Exhibit Licensed Leads User or Trusted Access or above.
* Allow for text search of Attendee Badge ID, QR code, name, email, or affiliations.
* Allow for QR code scan to add Attendee Badge as Lead.
* Once found, show basic Attendee Badge info and button to "Add as Lead".
* If already added as Lead, show message and button to "View Lead".
* Sections:
* Text search
* QR scan
* Results with "Add as Lead" or "View Lead" button
* Buttons and Inputs:
* Text input for search
* Button to trigger search
* Button to trigger QR scan (opens camera and scans QR code on badge)
* Button to "Add as Lead" if Attendee Badge found and not already a Lead
* Button to "View Lead" if Attendee Badge found and already a Lead
Functions needed:
* Search function to find Attendee Badge by Badge ID, QR code, name, email, or affiliations.
* QR code scan function to read QR code and find Attendee Badge.
* Add Lead function to create Exhibit_tracking entry linking Exhibit and Attendee Badge.
### [tab 3] Leads - List of Attendee Leads for Exhibitor
* Allow for toggle between showing all per Exhibit and per licensed user based on their email address. Not perfect, but works well enough.
* Allow for easy edit or remove
* Sections:
* List of Leads with basic info and buttons to Edit or Remove
* Options:
* Filter by Licensed user email address (dropdown of emails that have added leads for this Exhibit)
* Toggle for show/hide Hidden records
* Select options for sorting: Newest added first, Oldest added first, Alpha ascending, Alpha descending, Last updated first
* Buttons and Inputs:
* Button to Export Data - CSV or XLSX
* Toggle for show/hide Hidden records
* Select options for sorting: Newest added first, Oldest added first, Alpha ascending, Alpha descending, Last updated first
* Should it have a text search?
* NOTE: It is probably easiest for them to us the search tab to find a lead that has already been added. It will show "View Lead" button if already added.
Functions needed:
* Load Leads function to get Exhibit_tracking entries for the Exhibit.
* Filter function to filter by Licensed user email address.
* Sort function to sort by selected option.
* Export function to export displayed Leads to CSV or XLSX.
### [tab 4] Manage - Leads (app and exhibit) Manage / Config
#### Exhibit Specific
* Priority/payment toggle - Administrator Access or above
* Max licenses (number) - readonly or edit for Administrator Access or above
* Small devices (number) - readonly or edit for Administrator Access or above
* Large devices (number) - readonly or edit for Administrator Access or above
* Exhibit (shared) Passcode
* Same Exhibit Leads License list component as the Start tab's Licensed Users section
#### App Specific
* Show/Hide Payment Tab
* Additional Settings:
* List refresh interval in seconds - default 25 seconds; 1 second to 2 minutes (120000)
* Basic reload/refresh
* Clear Indexed DB
* Clear localStorage
* Auto hide header/footer on sign in - default true
* (?) Turn on iframe mode
* (?) Show or hide additional details - Use "$events_loc.show_details"?
* Sections:
* Exhibit Specific Manage/Config
* App Specific Manage/Config
* Buttons and Inputs:
* Exhibit Specific:
* Priority/payment toggle - Administrator Access or above
* Max licenses (number) - readonly or edit for Administrator Access or above
* Small devices (number) - readonly or edit for Administrator Access or above
* Large devices (number) - readonly or edit for Administrator Access or above
* Exhibit (shared) Passcode
* Same Exhibit Leads License list component as the Start tab's Licensed Users section
* App Specific:
* Show/Hide Payment Tab
* Show last refresh time and counter for next refresh based on the List refresh interval setting.
* Additional Settings:
* List refresh interval in seconds - default 25 seconds; 1 second to 2 minutes (120000)
* Basic reload/refresh (F5)
* Clear Indexed DB
* Clear localStorage
* Auto hide header/footer on sign in - default true
* (?) Turn on iframe mode
* (?) Show or hide additional details - Use "$events_loc.show_details"?
* Functions:
* Update Exhibit configuration function to update the Exhibit with the new settings.
* Update App configuration function to update the app-wide settings for the Leads module.

View File

@@ -0,0 +1,200 @@
# PROJECT: Zebra ZC10L Hardware Test Day
**Created:** 2026-03-12
**Planned date:** ~week of 2026-03-16 (printer rented for one day)
**Hardware:** Zebra ZC10L, 3.5" × 5.5" PVC card stock
**Goal:** Validate real-world badge printing before Axonius (NYC, mid-April 2026)
**Owner:** Scott Idem / One Sky IT
---
## Before the Printer Arrives — Pre-Test Checklist
These must be done before the printer is on-site so you're not burning rental time on setup.
- [ ] **Remove debug outlines** from `print/+page.svelte` print CSS.
The lime/blue/red/orange/purple/cyan debug outlines are still in the file. Remove the
entire `TEMPORARY DEBUG OUTLINES` block. Commit before the test day.
- [ ] **Zebra ZC10L Linux driver** — install CUPS driver ahead of time.
- Check Zebra's site for the Linux CUPS driver for ZC10L.
- Install, configure in CUPS (`http://localhost:631`), do a test page print with a spare card.
- Confirm the card feeds without jam and ink/dye-sub layer applies cleanly.
- Driver may need the printer set to the correct card stock size (3.5" × 5.5").
- [ ] **Wire `style_href`** — add `<link rel="stylesheet" href={...}>` to `<svelte:head>` in
`print/+page.svelte` when `$lq__event_badge_template_obj?.style_href` is set.
Without this, any client-specific external CSS won't load.
See `documentation/MODULE__AE_Events_Badge_Templates.md` → "External CSS Approach".
- [ ] **Confirm single-sided print (duplex=0)**`duplex` backend field doesn't exist yet.
For PVC cards, the badge back must NOT print. Verify this works by checking that
`.badge_back` is hidden in `@media print` when the layout is `badge_3.5x5.5_pvc`.
The PVC CSS (`badge_layout_zebra_zc10l_pvc.css`) may already handle this — confirm.
If not, add a print rule: `[data-layout="badge_3.5x5.5_pvc"] .badge_back { display: none !important; }`
- [ ] **Test event + template in dev DB** — create/confirm:
- Event with `mod_badges_json` configured
- PVC template: `layout: badge_3.5x5.5_pvc`, `duplex: 0` (once backend supports it),
`header_path` set to a real image URL, `badge_type_list` JSON populated
- Test badge records (see "Test Data Set" below)
- [ ] **Test data set** — create badge records covering:
- Short name: "Kim Lee"
- Long name: "Bartholomew Vandenberghe-Christopoulos"
- HTML in name: `<b>Dr.</b> Patricia Adams`
- HTML in affiliations: `University of Minnesota<br>Dept. of Surgery`
- Badge with no affiliations, no location
- Badge with all 8 ticket codes set
- Three different badge_type_codes (e.g. member, staff, guest) — to verify footer
stripe color for each
- [ ] **Browser setup on kiosk machine** — confirm Chrome and Firefox both installed.
Test print dialog settings once driver is working:
- Chrome: Margins → None (required), paper size set to 3.5×5.5 if available
- Firefox: should just work — `@page { size: 3.5in 5.5in }` is honored
---
## Test Day Checklist
### 1. Basic Print Path
- [ ] Card feeds and prints without jam
- [ ] Badge fills the card edge-to-edge (no white border, no clipping)
- [ ] Content horizontally centered on the card
- [ ] Content vertically centered on the card
- [ ] No debug outlines visible (confirm cleanup commit applied)
**Chrome:**
- [ ] Print → Margins: **None** → correct output
- [ ] Print → Margins: **Default** → bad (expected — documents the known issue)
- [ ] Print → Margins: **Minimum** → correct output
- [ ] "More settings" → paper size: does selecting 3.5×5.5 matter, or does Zebra driver override?
**Firefox:**
- [ ] Print → just works out of the box
### 2. Single-Sided PVC
- [ ] Only the front face prints — back does NOT print
- [ ] No second card ejected or blank card printed for the back
### 3. Visual Quality
- [ ] Font sizes readable at 3.5×5.5 physical scale (name, title, affiliations, location)
- [ ] Auto-scaling text (v2) — does it look natural, not crunched?
- [ ] Header image renders correctly (colors, resolution, no pixelation)
- [ ] Footer stripe color correct for each badge_type_code tested
- [ ] HTML in name/affiliations renders correctly (bold, line break, etc.)
- [ ] Badge with no affiliations — no awkward blank space
### 4. Edge Cases — Badge Content
- [ ] Long name auto-scales without overflow or clipping
- [ ] HTML markup in name field: `<b>Dr.</b>` renders bold on the physical card
- [ ] HTML line break in affiliations: two-line org renders cleanly
- [ ] Badge with no location — layout doesn't break
- [ ] Badge with all 8 ticket/option codes — back of badge (if applicable) lays out cleanly
### 5. Print Tracking
- [ ] `print_count` increments after printing via the **Print Badge** button
- [ ] `print_first_datetime` set on first print
- [ ] "Printed N×" amber chip appears in print page header after first print
- [ ] Reprint via Re-print shortcut (trusted + edit mode) does NOT increment count
- [ ] Second print via Print Badge button DOES increment count (to 2)
### 6. QR Code
- [ ] QR on printed card is scannable with a phone camera
- [ ] QR scans to the correct badge ID (test with `/events/[id]/badges` search by QR scan)
- [ ] QR on back (if `show_qr_back=1`) also scans correctly
- [ ] If `show_qr_back=0` — no QR code visible on back
### 7. Font Size Controls
- [ ] Manual font size override (+ / in controls panel) changes the badge render live
- [ ] Change is visible on the physical printed card
- [ ] Reset (↺) returns to auto-sizing
- [ ] Auto-sizing produces a reasonable default for all test names without manual adjustment
### 8. Edit Fields at Kiosk
- [ ] Badge info editable before printing: change full_name_override, verify change appears on card
- [ ] Save change → re-print → new value printed
- [ ] Cancel reverts to saved value
- [ ] Badge type dropdown changes footer stripe color on the rendered badge
---
## Known Limitations on Test Day
These are not bugs — just gaps that won't be addressed during the test day:
- **`style_href` external CSS**: Must be wired before test day (see pre-checklist). If not
done, client-specific CSS from the template won't load — fall back to default styles.
- **`duplex` backend field**: Not yet in the backend schema. Single-sided behavior depends
on the PVC CSS hiding `.badge_back` in print. Verify manually.
- **Per-template print margins (`print_margin_cfg`)**: UI doesn't exist yet. If the card
needs a physical offset for the Zebra's feed, apply a manual CSS tweak to the PVC layout
CSS file and revert after testing.
- **Kiosk attendee editing (TASK 4.0)**: Edit panel is currently trusted_access only.
Attendee self-edit at kiosk isn't finished — staff will need to do all edits on test day.
- **`@page { size }` in Chrome**: Chrome ignores the CSS page size for Save as PDF.
For physical Zebra printing the driver controls paper size — this is fine.
---
## Known Print Dialog Behavior (for reference)
| Browser | Save to PDF | Physical Printer |
|---|---|---|
| Firefox | Paper size locked to CSS `@page { size }` ✅ | Can select paper size in dialog |
| Chrome | Paper size = system default (letter/A4) ❌ | Can select paper size under "More settings" |
| Chrome Margin Setting | Result |
|---|---|
| Default | ❌ Inserts URL/date/page chrome, offsets badge centering |
| None | ✅ Badge centered correctly |
| Minimum | ✅ Badge centered correctly |
---
## Things to Note / Capture During Testing
Use this section to log observations on the day:
```
DATE: ___________
Driver version: ___________
Card stock type: ___________
CUPS printer name: ___________
Observations:
-
-
-
Font size adjustments needed:
Name default: was __px, adjusted to __px
Title default: was __px, adjusted to __px
Affiliations: was __px, adjusted to __px
Location: was __px, adjusted to __px
Physical offset needed (crop/margin): ___________
Bugs found:
-
-
```
---
## Follow-Up After Test Day
- [ ] Update font size defaults in `ae_comp__badge_print_controls.svelte` based on observations
- [ ] Note any physical margin/offset needed into `cfg_json: { print_margin: {...} }` once that UI exists
- [ ] Document driver version and CUPS config that worked in this file
- [ ] Commit any fixes, re-run `npx svelte-check`, commit clean