feat(badges): print/review pages, 4-button list, Lucide icons, permissions doc

Badge search results list (ae_comp__badge_obj_li):
- 4 action buttons per row: Print, Review (nav link), Copy Link (clipboard), Email Link
- Visibility rules: unprinted-only for non-edit mode; all non-hidden for trusted+edit
- Plain name display (User/EyeOff icon) — name is no longer a print link
- Obscured email for non-trusted users
- Debug row (ID, CR, UP, PC, FP, LP) in edit mode
- All icons converted to Lucide (Font Awesome removed)

Badge print page (/print):
- 3 header action buttons: Print Now, Review (nav), Email Link
- Removed old [badge_id]/+page.svelte placeholder (moved to trash)
- Added is_trusted, is_edit_mode, print state derived vars
- "Already printed Nx — last [timestamp]" warning inline with name
- Removed unused imports (browser, onMount, events_slct)

Badge review page (/review):
- 3 header action buttons: Print (nav), Copy Link (clipboard), Email Link
- Added events_loc for email placeholder + title event name
- Added is_edit_mode, print_count, is_printed, copy_status
- FA icons replaced with Lucide (ShieldCheck, UserCheck, User)
- Title now includes event name (was missing)

Infrastructure:
- print/+page.ts and review/+page.ts added (non-blocking badge loaders)
- ae_comp__badge_review_form.svelte stub created (fields pending)
- Fixed: components no longer write to $ae_loc.edit_mode (critical bug)

Docs:
- NEW: AE__Permissions_and_Security.md — full permissions hierarchy reference
- NEW: PROJECT__AE_Events_Badges_Review_Print.md — agent task brief for review form + print font controls
- UPDATED: MODULE__AE_Events_Badges.md rev 5 — field permissions spec, header buttons, still-needed list by priority

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-02-27 15:12:22 -05:00
parent ee500a9ad5
commit c4e85b1fe3
15 changed files with 2046 additions and 412 deletions

View File

@@ -3,7 +3,7 @@
**Module Path:** `src/routes/events/[event_id]/(badges)/badges/`
**API Module:** `src/lib/ae_events/ae_events__event_badge.ts`
**Database:** `db_events.badge` (Dexie IndexedDB table)
**Last Updated:** 2026-02-26 (rev 3)
**Last Updated:** 2026-02-27 (rev 5)
---
@@ -64,17 +64,23 @@ display_name = badge.full_name_override || badge.full_name || "-- no name --"
// ✅ Display still shows "Bob Smith"
```
### Override Fields (7 total)
### Override Fields
| Regular Field | Override Field | Purpose | Editable By |
|---|---|---|---|
| `pronouns` | `pronouns_override` | Preferred pronouns | Staff, Attendee |
| `professional_title` | `professional_title_override` | Job title display | Staff, Attendee |
| `full_name` | `full_name_override` | Preferred name, pronouns | Staff, Attendee |
| `full_name` | `full_name_override` | Preferred name display | Staff, Attendee |
| `affiliations` | `affiliations_override` | Organization display | Staff, Attendee |
| `phone` | `phone_override` | Phone number | Staff, Attendee |
| `email` | `email_override` | Contact email override | Staff only |
| `location` | `location_override` | City/State/Country display | Staff, Attendee |
| `badge_type` | `badge_type_override` | Badge category label (varies per Event/Template) | Staff only |
| `badge_type_code` | `badge_type_code_override` | Badge access level code (varies per Event/Template) | Staff only |
| `badge_type` | `badge_type_override` | Badge category label text | Staff only |
| `badge_type_code` | `badge_type_code_override` | Badge access level code | Staff only |
| `registration_type` | `registration_type_override` | Registration category label text | Staff only |
| `registration_type_code` | `registration_type_code_override` | Registration category code | Staff only |
> **Note:** `phone`, `phone_override`, `pronouns_override`, `registration_type`, `registration_type_code`, `registration_type_override`, `registration_type_code_override` may need to be confirmed against the DB schema via `ae_describe event_badge` and added to `properties_to_save` in `ae_events__event_badge.ts` if not already present.
### Sync Safety Rules
@@ -149,18 +155,39 @@ def sync_badge_from_external(external_badge_data, existing_badge):
6. **Manager** — All administrator + event configuration
7. **Super** — All manager + cross-event operations
### Current Implementation (v3)
### Current Implementation (v3) — 2026-02-27
**Quick Edit Feature** ([badge_id]/+page.svelte → ae_comp__badge_obj_view.svelte)
#### Badge Search Results Visibility
**Edit Mode Trigger:**
- URL hash `#review` enables edit mode
- Sets `$ae_loc.edit_mode = true`
- Shows Save/Cancel buttons
| Access Level | Sees |
| --- | --- |
| Below Trusted (incl. anonymous) | Only badges where `print_count < 1` and not hidden |
| Trusted, not Edit Mode | Only badges where `print_count < 1` and not hidden |
| Trusted + Edit Mode | All badges where `hide === false` (including already-printed) |
**Currently Editable Fields:**
#### Print Button Behavior (per result row)
| Access Level | Print Action |
| --- | --- |
| Below Trusted | No print action — name shown with User icon, non-interactive |
| Trusted, `print_count < 1` | Clickable link → `/print` page, Printer icon |
| Trusted, `print_count >= 1`, not Edit Mode | Disabled (already printed safety lock), shows `Nx` count |
| Trusted, `print_count >= 1`, Edit Mode | Clickable reprint — shows `Nx` count badge next to icon |
Print count displayed as `[Printer][2×] Name` when `print_count >= 1`.
#### Review Area Buttons (per result row, up to 3 buttons total)
| Button | Visible To | Behavior |
| --- | --- | --- |
| Email Review Link | All users | Placeholder `alert()` — will trigger email API |
| Review Link (clipboard) | Trusted + Edit Mode only | Copies `/review` URL to clipboard; shows `Copied!` feedback |
| *(direct Review link)* | *(future)* | *(not yet implemented as separate nav button)* |
#### Badge Edit Form (`ae_comp__badge_obj_view.svelte`)
**Currently editable fields (local `edit_mode_active`, not global `edit_mode`):**
```typescript
// Lines 90-96 in ae_comp__badge_obj_view.svelte
editable_full_name_override: string | null
editable_professional_title_override: string | null
editable_affiliations_override: string | null // textarea
@@ -170,37 +197,109 @@ editable_email: string | null
editable_badge_type_code: string | null
```
**UI Components:**
- Input fields shown when `edit_mode_active === true`
- Save button calls `handle_save_changes()` (Line 365)
- Cancel button calls `handle_cancel_changes()` (Line 450)
- Only changed fields sent to API (`update_ae_obj__event_badge`)
- Save button → `handle_save_changes()` — only changed fields sent to API
- Cancel button → `handle_cancel_changes()` — reverts to IDB values
- **IMPORTANT:** This component must NEVER write to `$ae_loc.edit_mode` — it uses its own local `edit_mode_active` flag only. (Bug fixed 2026-02-27)
### Future Planned Enhancement
#### Badge Review Form (`ae_comp__badge_review_form.svelte`)
**Event-Level Configuration:** `event.mod_badges_json.edit_permissions`
Form-based review (NOT a badge render). Used by the `/review` page.
- `can_edit_fields: string[]` prop controls which fields are editable per user level
- `['*']` = administrator (all fields)
- `is_staff: boolean` prop shows/hides the source-data panel
- Fields show "(overridden)" label when an override value differs from the base field
#### Badge Review Page — Header Buttons (implemented 2026-02-27)
| Button | Visible To | Behavior |
| --- | --- | --- |
| Back → Search (ArrowLeft) | Staff (`has_staff_access`) only | `<a href="/events/{id}/badges">` |
| Print (Printer icon) | Trusted+, not printed OR Trusted+Edit if printed | `<a href="/print">`, shows `Nx` count if reprinting |
| Copy Link (clipboard) | Trusted + Edit Mode only | Copies review URL to clipboard; `Copied!` feedback for 2s |
| Email Link (Mail icon) | All if not printed; Trusted+Edit if printed | Placeholder `alert()` — email API pending |
#### Badge Print Page — Header Buttons (implemented 2026-02-27)
| Button | Visible To | Behavior |
| --- | --- | --- |
| Back → Search (ArrowLeft) | Always (when badge loaded) | `<a href="/events/{id}/badges">` |
| Print Now (Printer icon) | Trusted+, not printed OR Trusted+Edit if printed | Calls `window.print()` directly (convenience duplicate); print count tracked by component button |
| Review (Eye icon) | Trusted + Edit Mode only | `<a href="/review">` nav link |
| Email Link (Mail icon) | All if not printed; Trusted+Edit if printed | Placeholder `alert()` — email API pending |
#### Badge Review Page — Display Sections (planned, not yet built)
In addition to the editable form, the review page will display:
1. **Print status** — print count + first/last print timestamps (read-only)
2. **QR Code** — the attendee's badge QR code for scanning at the badge kiosk (for automatic badge search + print flow). QR generation code may be recoverable from the legacy AE Badge version.
3. **Options** (`other_1_code` through `other_8_code`) — shown as `[✓] Option X` if the field has a value; hidden if empty
4. **Tickets** (`ticket_1_code` through `ticket_8_code`) — shown as `[✓] Ticket X` if the field has a value; hidden if empty
#### Default Field Permissions (hardcoded for now — Axonius first show, mid-April 2026)
These are hardcoded in `review/+page.svelte` pending connection to `mod_badges_json.edit_permissions`.
**Attendee (passcode-authenticated / anonymous with link):**
```typescript
[
'pronouns_override',
'full_name_override',
'professional_title_override',
'affiliations_override',
'phone_override',
'location_override',
'allow_tracking', // Exhibitor Leads opt-in
'agree_to_tc', // Terms & Conditions placeholder
]
```
**Trusted Staff and above:**
```typescript
[
'pronouns_override',
'full_name_override',
'professional_title_override',
'affiliations_override',
'email_override',
'phone_override',
'location_override',
'badge_type_code_override', // + badge_type_override (text label)
'registration_type_code_override', // + registration_type_override (text label)
'option_1' ... 'option_8', // i.e. other_1_code ... other_8_code
'ticket_1_code' ... 'ticket_8_code',
'allow_tracking',
'agree_to_tc',
'hide',
'priority',
'notes',
]
```
**Administrator**`can_edit_fields = ['*']` (all fields)
**Badge type options (hardcoded for now):** `member`, `non-member`, `guest`, `exhibitor`, `staff`, `test`
(In future: read from Event Badge Template's configured list)
**Registration type options:** Same list as badge type for now — identical select options.
#### Future: Per-Event Configuration
`event.mod_badges_json.edit_permissions` — placeholder settings UI exists in
`ae_comp__event_settings_badges_form.svelte`. Review page uses hardcoded defaults for now.
The settings form and review page are not yet connected.
```json
{
"authenticated": {
"can_edit": ["full_name_override", "professional_title_override", "affiliations_override", "location_override"],
"requires_approval": false
"can_edit": ["pronouns_override", "full_name_override", "professional_title_override", "affiliations_override", "phone_override", "location_override", "allow_tracking", "agree_to_tc"]
},
"trusted": {
"can_edit": ["full_name_override", "professional_title_override", "affiliations_override", "location_override", "email_override"],
"can_view_all": true,
"requires_approval": false
},
"administrator": {
"can_edit": "*",
"can_bulk_edit": true,
"can_delete": true
"can_edit": ["*attendee_fields", "email_override", "badge_type_code_override", "registration_type_code_override", "option_x", "ticket_x_code", "allow_tracking", "agree_to_tc", "hide", "priority", "notes"]
}
}
```
**Status:** Placeholder UI exists, JSON config not yet implemented.
---
## Search & Filter Capabilities
@@ -377,15 +476,14 @@ async function handle_print_badge() {
Button has `data-testid="badge-print-btn"` and shows loading/done/error states with icon feedback.
### Print Workflow
1. **Pre-Print:** Check `print_count` to warn if already printed
2. **Print:** `window.print()` — standard browser print dialog. Works well in Chrome, Chromium, and Firefox. Chrome is the recommended browser for onsite badge printing (most stable in production).
3. **Post-Print:** Handled by `handle_print_badge()` — count + timestamps updated
4. **Audit:** Print history available for staff review
1. **Pre-Print:** Badge print page (`/print`) shows "Already printed N times" warning in screen-only header if `print_count >= 1`
2. **Record:** `handle_print_badge()` updates `print_count`, `print_last_datetime`, and `print_first_datetime` (first print only) via API before printing
3. **Print:** `window.print()` — standard browser print dialog, wired and working (2026-02-27)
4. **Redirect:** After 1 second, `goto(/events/{id}/badges)` returns to search
5. **Audit:** `print_first_datetime` and `print_last_datetime` visible in Edit Mode debug row
**Browser vs Electron:** Badge printing does NOT require the Electron native app. The standard browser print dialog works well across Chrome, Chromium, and Firefox. The Electron native app is specialized for the **Events Pres Mgmt Launcher only** and should not be assumed available for badge stations.
**Current Status:** Button records print event and updates IDB. The `window.print()` call still needs to be wired to the button — see Future Enhancements.
---
## Database Schema
@@ -483,18 +581,42 @@ delete_ae_obj_id__event_badge({ event_badge_id, event_id, method })
### Route Structure
```
/events/[event_id]/(badges)/badges/
├── +layout.svelte # Layout wrapper (minimal)
├── +page.svelte # Badge list + search
├── ae_comp__badge_search.svelte # Search form + filters
├── ae_comp__badge_obj_li.svelte # Badge list display
├── +layout.svelte # Layout wrapper (minimal)
├── +page.svelte # Badge list + search
├── ae_comp__badge_search.svelte # Search form + filters
├── ae_comp__badge_obj_li.svelte # Badge list display (results)
├── ae_comp__badge_create_form.svelte # (Not actively used)
├── ae_comp__badge_upload_form.svelte # Bulk CSV upload
└── [badge_id]/
├── +page.svelte # Badge detail container
├── +page.ts # Badge loader (non-blocking)
── ae_comp__badge_obj_view.svelte # Badge display + edit
├── ae_comp__badge_obj_view.svelte # Badge rendering + staff edit + print button
├── ae_comp__badge_review_form.svelte # Form-based field review/edit (attendee + staff)
── print/
│ ├── +page.ts # Non-blocking badge loader (inc_template: true)
│ └── +page.svelte # Print-focused page — screen header + badge render
└── review/
├── +page.ts # Non-blocking badge loader (inc_template: false)
└── +page.svelte # Passcode-gated review page
```
> **Note:** The old `[badge_id]/+page.svelte` placeholder was removed (2026-02-27). The name link in the search results list now goes directly to `/print`.
#### Badge Print Page (`/print`)
- Screen-only header (`print:hidden`): "Back to Search" link + "Already printed N times" warning
- Badge rendered via `ae_comp__badge_obj_view` with `is_review_mode={false}`
- Print button inside `ae_comp__badge_obj_view` handles count update → `window.print()` → redirect to search
- Page `<title>` includes badge name + event name
#### Badge Review Page (`/review`)
- Passcode-gated for attendees — URL `?passcode=...` matched against `badge.person_passcode`
- **Note:** `person_passcode` field is not yet in the DB (as of 2026-02-27). Review page accessible to staff via `trusted_access` without a passcode.
- Access hierarchy (checked in order):
1. Administrator → full access (`can_edit_fields = ['*']`)
2. Trusted Staff → staff field set
3. Attendee with valid passcode → attendee field set
4. No access → passcode entry form shown
- Uses `ae_comp__badge_review_form.svelte` (NOT badge render)
- "Back to Search" link shown for staff only
### Key Components
**Badge List Page** (`+page.svelte`)
@@ -577,19 +699,45 @@ None — all current badge tests passing as of 2026-02-26 (f5e98b8c).
## Known Issues & Future Enhancements
### Known Issues
1. **Test Infrastructure:** Mock API routes not connecting to page requests
2. **Session Cold-Start:** Potential race condition on first load (same as pres mgmt module)
3. **Type Definitions:** Some TypeScript errors on external package types (pre-existing)
1. **Session Cold-Start:** Potential race condition on first load (same as pres mgmt module)
2. **Type Definitions:** Some pre-existing TypeScript errors on external package types (not introduced by badge work)
3. **`person_passcode` not in DB:** Attendee-gated review URL (`?passcode=...`) cannot function until this field is added to the `event_badge` schema. The review page falls back to passcode entry form for non-staff.
4. **Print page CSS:** Badge print rendering and `@page` print styles not yet fine-tuned — expected to need work
5. **`mod_badges_json.edit_permissions` not connected:** Settings UI exists but review page uses hardcoded field defaults
### Future Enhancements
1. **Access-Based Edit Permissions:** Implement JSON config for field-level access control
2. **Print Functionality:** Wire up `window.print()` to the print button. Standard browser print API — works well in Chrome/Chromium/Firefox for badge label printing. Electron is NOT needed.
3. **Batch Operations:** Bulk update, bulk print, bulk export
4. **Audit Log:** Track who edited which fields and when
5. **Photo Badges:** Support badge photo upload and display
6. **Custom Badge Layouts:** Dynamic template selection per badge type
7. **Real-Time Sync:** WebSocket updates for multi-device badge printing stations
8. **Approval Workflow:** Require manager approval for certain field changes
### Implemented (2026-02-27)
-`window.print()` wired to print button (records count first, then prints, then redirects)
- ✅ Dedicated `/print` page — replaces old `[badge_id]/+page.svelte` placeholder
- ✅ Dedicated `/review` page — passcode-gated, access-tiered
-`ae_comp__badge_review_form.svelte` — stub created, full form fields pending
- ✅ Badge search results visibility rules (unprinted-only for non-edit, all for trusted+edit)
- ✅ Badge list: 4 action buttons per row (Print, Review nav, Copy Link, Email Link) — all Lucide icons
- ✅ Print page: 3 action buttons in header (Print Now, Review nav, Email Link) — all Lucide icons
- ✅ Review page: 3 action buttons in header (Print nav, Copy Link, Email Link) — all Lucide icons
- ✅ Print button: not shown when already printed (unless Edit Mode)
- ✅ Print count shown as `Nx` badge next to printer icon
- ✅ Email obscuring for non-trusted users
- ✅ Email Review Link button (placeholder alert — email API pending)
- ✅ Direct Review Link clipboard copy (trusted + Edit Mode only)
- ✅ Fixed: components no longer write to `$ae_loc.edit_mode`
- ✅ Settings UI for `edit_permissions` per event (`ae_comp__event_settings_badges_form.svelte`)
- ✅ All badge module icons converted to Lucide (Font Awesome removed from badge routes)
### Still Needed — HIGH PRIORITY (first show: April 2026)
1. **Badge Review Form — actual fields:** `ae_comp__badge_review_form.svelte` is a stub. Needs full field rendering, edit inputs, save/cancel, and the display-only sections (QR code, print status, option/ticket checkmarks). See `PROJECT__AE_Events_Badges_Review_Print.md` for full spec.
2. **Badge Print Page — font size controls:** Screen-only controls to adjust font size for name, professional title, affiliations, and location sections before printing. See project brief.
### Still Needed — MEDIUM PRIORITY
1. **Email API for review links:** `send_review_email()` is a placeholder `alert()`. Needs actual email send endpoint.
2. **`person_passcode` DB field:** Add to `event_badge` schema to enable attendee-gated review URLs.
3. **Connect `edit_permissions` config:** Read `mod_badges_json.edit_permissions` in review page instead of hardcoded defaults.
4. **Print page CSS / `@page` styles:** Badge rendering, sizing, and print-specific stylesheet.
### Still Needed — FUTURE / LOW PRIORITY
1. **Batch Operations:** Bulk update, bulk print, bulk export
2. **Audit Log:** Track who edited which fields and when
3. **Photo Badges:** Support badge photo upload and display
4. **Real-Time Sync:** WebSocket updates for multi-device badge printing stations
---
@@ -646,6 +794,6 @@ db_events.badge.toArray().then(console.log)
---
**Document Status:** ✅ Complete
**Last Verified:** 2026-02-26 (rev 3all badge tests passing)
**Verified Against:** Code commit f5e98b8c (all data integrity tests passing)
**Document Status:** 🔄 In Progress
**Last Verified:** 2026-02-27 (rev 5field permissions spec added, header buttons implemented, review form fields pending)
**Verified Against:** Code as of 2026-02-27 (branch ae_app_3x_llm)