Overview
Field work (audits, check-in/out, lookups) happens on phones next to physical equipment. Competitors ship native apps; a PWA with camera QR scanning covers most of that value at a fraction of the cost.
What to Build
- PWA: web manifest (name, icons, theme), installability, service worker with sensible caching (app shell cached; API network-first) — Next.js 15 conventions
- Camera scanning: a scan button (topbar on mobile + check-in/out and audit pages) opening a camera view using
BarcodeDetector where available with a JS fallback library; decoded asset QR navigates to /scan/[assetId] ([FE-14])
- Mobile polish on core flows: assets list, asset detail, check-in/out usable at 375px width
Conventions to Follow
- API calls: add a typed client in
frontend/lib/api/ (see frontend/lib/api/assets.ts for the pattern) — never call axios directly from components
- Data fetching: TanStack Query hooks in
frontend/lib/query/hooks/ with keys registered in frontend/lib/query/keys.ts
- UI: reuse
frontend/components/ui/ (button, input, confirm-dialog, toast) and the badge/modal patterns in frontend/components/assets/
- Route goes under
frontend/app/(dashboard)/ and gets a sidebar entry in frontend/components/layout/sidebar.tsx
- Forms: React Hook Form + Zod resolver, matching the existing create-asset modal
References
- Blocked by [FE-14]; pairs with existing open issue [BE-69] (QR generation)
- Note:
19b5baa (mobile drawer nav) existed pre-reset — reuse ideas via git show 19b5baa
Acceptance Criteria
Overview
Field work (audits, check-in/out, lookups) happens on phones next to physical equipment. Competitors ship native apps; a PWA with camera QR scanning covers most of that value at a fraction of the cost.
What to Build
BarcodeDetectorwhere available with a JS fallback library; decoded asset QR navigates to/scan/[assetId]([FE-14])Conventions to Follow
frontend/lib/api/(seefrontend/lib/api/assets.tsfor the pattern) — never call axios directly from componentsfrontend/lib/query/hooks/with keys registered infrontend/lib/query/keys.tsfrontend/components/ui/(button, input, confirm-dialog, toast) and the badge/modal patterns infrontend/components/assets/frontend/app/(dashboard)/and gets a sidebar entry infrontend/components/layout/sidebar.tsxReferences
19b5baa(mobile drawer nav) existed pre-reset — reuse ideas viagit show 19b5baaAcceptance Criteria