Appearance
customer-portal — feature queue
Repo: Adalen-Truck/customer-portal · Path: /Users/Shared/moltis/repos/customer-portal Audit branch: develop (⚠️ the remote default is main — never fall back to origin/HEAD) Stack: Vue 3 + <script setup>, PrimeVue, Tailwind 4 (ÅDALEN semantic tokens), TanStack Query/DB, CASL abilities, vue-i18n (en/nb), Capacitor mobile wrapper
✅ Inventory built from
develop@693a76con 2026-07-30, after fast-forwarding one commit (#24, "Improve sidebar navigation and mobile tab bar") that rewroterouter/index.tsand addedadmin/SyncPage.vue.
Derived from apps/web/src/router/index.ts (59 page components). This is the post-consolidation "One App": the former web, internal and admin apps now share one router, one AppLayout and one guard, with sections gated by CASL abilities and role names. Grouping follows the app's own sidebar sections (AppLayout.vue menuItems) rather than an invented taxonomy.
Redirect-only routes are excluded: bookings → service-overview, locations-contacts → locations, admin/access-denied → forbidden.
Ordered by user impact: public and auth paths first, then money paths (marketplace/bids/trade-in), then core customer work, then internal, then admin.
| # | Feature | Routes | Patterns | Status |
|---|---|---|---|---|
| 1 | Warranty submission (public) | warranty.submit | forms/form-validation, forms/file-input, media/image-upload, user-feedback/notification | drafted |
| 2 | Sign in | auth.sign-in | authentication/login, forms/password, forms/form-validation | drafted |
| 3 | Sign up | auth.sign-up | authentication/signup, forms/password, forms/form-validation | drafted |
| 4 | Password reset | auth.forgot-password, auth.reset-password | authentication/password-reset, forms/password | drafted |
| 5 | Email verification | verify-email | authentication/signup, user-feedback/notification, user-feedback/empty-states | drafted |
| 6 | Onboarding | onboard | advanced/wizard, user-feedback/progress-indicator, forms/form-validation | drafted |
| 7 | Account selection | select-account | forms/selection-input, data-display/list-view | drafted |
| 8 | Landing page | home.index | navigation/link, forms/button | drafted |
| 9 | Marketplace | marketplace.index, marketplace.detail | data-display/card-grid, e-commerce/product-card, data-display/filter-panel | drafted |
| 10 | Bids | marketplace.bids, bids.detail | forms/currency-input, data-display/table, user-feedback/notification | drafted |
| 11 | Trade-in machines | trade-in-machines.index, trade-in-machines.create, trade-in-machines.detail | advanced/wizard, media/image-upload, forms/form-validation | drafted |
| 12 | Catalog | catalog.products.index, catalog.products.detail | data-display/card-grid, e-commerce/product-card, forms/search-field | drafted |
| 13 | Dashboard | dashboard | data-display/dashboard, data-display/statistics, user-feedback/skeleton | drafted |
| 14 | Customer assets | customer-assets.index, customer-assets.detail, live-tracking | data-display/table, data-display/card-grid, user-feedback/empty-states | drafted |
| 15 | Service overview | service-overview, bookings.detail | data-display/timeline, data-display/table, data-display/filter-panel | drafted |
| 16 | Book service | book-service | advanced/wizard, forms/date-picker, forms/form-validation | drafted |
| 17 | Service plans & checklist builder | service-plans, checklist-builder.new, checklist-builder.edit | content-management/drag-and-drop, forms/form-validation, advanced/wizard | drafted |
| 18 | Work orders | orders, orders.detail | data-display/table, data-display/timeline, data-display/filter-panel | drafted |
| 19 | Partner service orders | partner-orders.index, partner-orders.detail | data-display/table, data-display/filter-panel | drafted |
| 20 | Locations | locations | data-display/table, user-feedback/empty-states | drafted |
| 21 | Contacts | contacts | data-display/table, forms/phone-number, user-feedback/empty-states | drafted |
| 22 | Skills & employees | skills, skills.employee | data-display/table, authentication/user-profile | drafted |
| 23 | Terms | terms | content-management/accordion, content-management/expandable-text | drafted |
| 24 | Profile | profile | authentication/user-profile, authentication/account-settings | drafted |
| 25 | Contact Aadalen | contact | forms/form-validation, forms/textarea, user-feedback/notification | drafted |
| 26 | Orders logistics (internal) | orders.logistics, orders.logistics.sandboxed | data-display/kanban-board, data-display/table, content-management/drag-and-drop | drafted |
| 27 | Shipping orders (internal) | shipping-orders, shipping-orders.detail | data-display/table, forms/signature-pad | drafted |
| 28 | Warehouse take-out (internal) | warehouse.take-out | forms/search-field, forms/multi-select-input, data-display/list-view | drafted |
| 29 | Charging (internal) | charging | forms/form-validation, data-display/list-view | drafted |
| 30 | Admin analytics | admin.analytics | data-display/dashboard, data-display/chart, data-display/statistics | drafted |
| 31 | Sync monitoring (admin) | admin.sync, admin.sync-runs, admin.sync-events, admin.sync-failures | navigation/tabs, data-display/table, data-display/filter-panel | drafted |
| 32 | Commands (admin) | admin.commands | data-display/table, user-feedback/notification | drafted |
| 33 | Emails (admin) | admin.emails | data-display/table, user-feedback/empty-states | drafted |
| 34 | User administration (admin) | admin.users, admin.user-links | data-display/table, forms/search-field, authentication/user-profile | drafted |
| 35 | Roles & permissions (admin) | admin.permissions, admin.permissions.detail | data-display/table, forms/checkbox, data-display/tree-view | drafted |
| 36 | Admin configuration | admin.settings, admin.standards, admin.terms | authentication/account-settings, forms/form-validation, forms/rich-text-editor | drafted |
| 37 | Error states | forbidden | user-feedback/empty-states, navigation/link | drafted |
37 features to audit. None started.
Inventory-level observations
Recorded here, not as findings — they need a proper audit run to confirm against the baseline. Flagged now so the relevant audits look for them.
- No catch-all 404 route.
router/index.tshas no/:pathMatch(.*)*record and there is noNotFoundPage.vue(grep confirms zero hits forpathMatch,NotFoundor404inrouter/andpages/). An unmatched URL therefore matches no record and renders an empty layout rather than a recoverable error page. Belongs to #37 Error states; playout has this covered vianot-found, so it is likely a cross-project inconsistency. live-trackingis a hidden feature. The route resolves and is ability-gated, but its sidebar entry is hardcodedvisible: false(AppLayout.vue:122) pending release. Audit it as reachable-by-deep-link only, and do not report the missing nav entry as a defect.- Account selection reads
localStorage. The guard keys multi-account selection offlocalStorage.getItem("admin-selected-account")(router/index.ts:683,:700). Not a token, so it does not breach the repo's own "no tokens in localStorage" rule, but the persistence and clear-on-sign-out behaviour is worth checking in #7. - Ability failures are deliberately fail-open on a transient
/meerror (router/index.ts:722-729, with a comment explaining the trade-off). Backend enforces authorization, so this is UX-only by design — do not file it as a security finding without reading that comment first.
Suggested next: #1 Warranty submission — the only fully public, token-gated route in the app, so it is the one surface where frontend UX failures have no authenticated fallback and no sidebar to escape to. It also exercises file upload and validation, which seeds rules reusable across the other three projects.