Ga naar hoofdinhoud

PRD: Frontend Design Improvement Initiative

Status: Draft Author: Product & Engineering Date: 2026-03-17 Version: 1.0


1. Context & Why Now

Market & User Context

  • Den Hartog ZE-ERE is the primary ERE (Emissie Reductie Eenheden) administration portal for EV charging certificates in the Netherlands. The portal serves both B2C (particulier) and B2B (bedrijf) users who manage renewable energy certificates for their charging infrastructure.
  • The frontend was built function-first: every feature works, but visual polish and UX consistency took a back seat to shipping capabilities. The overall design quality scores 6.4/10 across ~70 pages analyzed by 6 independent review agents.
  • The admin team uses the portal daily for verification workflows. As the user base grows, admin efficiency directly impacts processing throughput and revenue realization.
  • The Capacitor mobile app (iOS + Android) wraps the same SPA, meaning every improvement benefits three platforms simultaneously.

Why Now

  • Auth page first impression: Every new user lands on Login or Register. These pages score 3-5/10 for distinctiveness -- plain gray backgrounds, no brand atmosphere. This is the single highest-leverage conversion touchpoint.
  • Admin efficiency ceiling: No bulk actions, no dashboard charts, poor mobile table responsiveness. The admin team is growing and hitting workflow bottlenecks that design improvements can solve without backend changes.
  • Design system maturity: Tailwind v4 @theme tokens, a Button component, Modal with focus trap, BentoCard system, AnimateOnScroll, and Recharts are all already installed and partially used. The foundation exists; it needs consistent application.
  • Cost of delay: Every week without auth page polish means continued friction at the acquisition funnel entry point. Every week without bulk admin actions means linear admin team scaling instead of leveraged scaling.

2. Users & Jobs-to-Be-Done

Persona 1: Nieuwe Gebruiker (New User -- Particulier or Bedrijf)

Description: First-time visitor arriving from the landing page, WordPress site, or referral link. Evaluating whether to register.

JTBD: "When I arrive at the login or registration page, I want to see a professional, trustworthy portal that matches the quality of the landing page, so I can feel confident entrusting my energy certificate administration to this company."

Current alternative: The landing page (8/10) sets an expectation that auth pages (3-5/10) fail to meet. The visual cliff between landing and login erodes trust.

Persona 2: Actieve Gebruiker (Active User -- Particulier or Bedrijf)

Description: Registered user who uploads documents, manages charging points, submits kWh records, and tracks ERE claims. Returns monthly or quarterly.

JTBD: "When I need to upload documents or check my dashboard, I want to complete my tasks quickly with clear feedback, so I can get back to my day without frustration."

Current alternative: File uploads use basic <input type="file"> without drag-and-drop. Dashboard shows only numbers without trend context. Document lists lack search.

Persona 3: Admin Medewerker (Admin Team Member)

Description: Den Hartog employee who verifies documents, reviews kWh records, manages authorizations, and handles user support. Uses the portal all day, every day.

JTBD: "When I have 50 pending verifications to process, I want to select multiple items and act on them in bulk, and see my progress on a dashboard with charts, so I can work efficiently and report on trends."

Current alternative: Each verification requires individual page navigation. Dashboard is numbers-only with no sparklines or trend charts despite Recharts being installed. Tables don't collapse on mobile, preventing field work.

Persona 4: Organisatie Eigenaar (Organization Owner -- Bedrijf)

Description: Business user managing a holding structure with subsidiaries, multiple EAN codes, and team members.

JTBD: "When I manage my holding company's charging infrastructure, I want to see the organizational hierarchy visually and navigate between subsidiaries intuitively, so I can oversee the entire portfolio."

Current alternative: Holding structure is a flat list. No tree/org-chart visualization. Deep navigation has no breadcrumbs.


3. Business Goals & Success Metrics

Leading Indicators (move within days/weeks)

MetricCurrent BaselineTargetTimeframe
Login page bounce rate[Assumption: ~15-20% based on industry avg for plain auth pages]<10%4 weeks post Phase 1
Registration completion rate[Assumption: ~60-70%]+15% relative improvement6 weeks post Phase 1
Avg time to upload a document[Assumption: ~45s with file picker]<20s with drag-and-drop2 weeks post Phase 2
Admin actions per hour (verifications)[Assumption: ~12-15 per hour per admin]+40% with bulk actions4 weeks post Phase 3

Lagging Indicators (business outcomes)

MetricCurrent BaselineTargetTimeframe
Onboarding funnel completion[Measured via AdminAnalyticsPage]+10% relative improvement3 months
Monthly active user retention (30-day)[Assumption: ~65-70%]>80%6 months
Admin team satisfaction (internal survey)[Assumption: not measured]>4.0/5.0After Phase 3
Support tickets related to "how do I upload?"[Assumption: exists]-50%After Phase 2

4. Functional Requirements

Phase 1: First Impression & Design Foundation

FR-1: Auth Page Visual Upgrade

  • Description: Redesign Login, Register, ForgotPassword, and ResetPassword pages to match the landing page quality (8/10). Replace plain bg-gray-50 backgrounds with branded atmospheric design using existing navy/green theme tokens. Add subtle background elements (gradient, pattern, or illustration) and ensure the card floats visually.
  • Acceptance Criteria:
    • All four auth pages use a shared AuthLayout component with branded background (navy gradient or split layout)
    • Logo is prominently displayed with consistent sizing (h-20 as current)
    • Background uses existing @theme tokens (--color-navy, --color-primary-*) instead of hardcoded grays
    • Card uses .card or .bento-card system with elevation (shadow-lg or higher)
    • Visual design matches landing page quality level (subjective review by 2+ stakeholders)
    • All pages remain fully functional on mobile (min-width: 320px)
    • Capacitor mobile build renders correctly (safe area insets respected)
    • Page load performance: LCP < 1.5s (no heavy image assets)
  • Priority: P0

FR-2: Password Strength Indicator on ResetPassword

  • Description: The Register page has a PasswordRequirements component showing live validation. The ResetPassword page lacks this, creating an inconsistent experience where users don't know if their new password meets requirements until form submission.
  • Acceptance Criteria:
    • PasswordRequirements component is rendered on ResetPassword page below the password field
    • Component shows the same criteria as the Register page
    • Confirm password match is validated live (if confirm field exists on ResetPassword)
  • Priority: P1

FR-3: Color Token Consolidation

  • Description: Several pages use hardcoded Tailwind colors (green-600, red-50, blue-100) instead of the semantic design tokens defined in @theme (primary-600, danger-50, success-100). This creates visual inconsistency and makes future theme changes expensive.
  • Acceptance Criteria:
    • Audit identifies all hardcoded color references that should use @theme tokens
    • StatusBadge component uses semantic tokens: success-100/success-700 for positive states, warning-* for pending, danger-* for negative, gray-* for neutral
    • No page uses green-600/green-700 where primary-600/primary-700 is semantically correct
    • No page uses red-50/red-100 where danger-50 is semantically correct
    • Visual diff confirms no unintended color changes
  • Priority: P1

FR-4: Icon Sizing Standardization

  • Description: Icons use a mix of h-4 w-4, h-5 w-5, and h-6 w-6 with no clear pattern tied to context. Define and apply a consistent sizing convention.
  • Acceptance Criteria:
    • Documented convention: inline text icons = h-4 w-4, card/section header icons = h-5 w-5, hero/empty state icons = h-8 w-8 or h-12 w-12
    • All lucide-react icon usages reviewed and corrected where they deviate from convention
    • StatusBadge icon sizes remain consistent with badge size prop (sm: h-3 w-3, md: h-3.5 w-3.5)
  • Priority: P2

FR-5: Button Component Adoption

  • Description: The codebase has a Button component (components/common/Button.tsx) with 6 variants and loading state, but many pages still use raw <button className="btn btn-primary">. Migrate to the component for consistency and to reduce inline Tailwind duplication.
  • Acceptance Criteria:
    • All new code in this initiative uses the Button component exclusively
    • Existing pages touched by other FRs in this phase are migrated to Button component
    • Raw .btn class usage is not increased by this initiative
  • Priority: P2

Phase 2: Core UX Improvements

FR-6: Drag-and-Drop File Upload Component

  • Description: Create a reusable FileDropZone component that wraps file upload interactions. The DocumentsPage already has drag-and-drop event handling at the card level; this FR extracts it into a dedicated component and adds visual feedback (border highlight, icon animation, file type validation preview).
  • Acceptance Criteria:
    • FileDropZone component supports: single file, multiple files, accepted MIME types, max file size
    • Visual states: idle (dashed border), hover/dragover (primary-colored border, background tint), uploading (progress indication), error (red border + message)
    • Clicking the zone opens the native file picker
    • Displays accepted file types to the user (e.g., "PDF, JPG, PNG")
    • Shows file name and size after selection, before upload begins
    • Integrated into: DocumentsPage, OnboardingDocuments, ProfilePage (avatar upload), KwhBulkImportPage
    • Works on touch devices (Capacitor mobile) -- fallback to tap-to-select
    • Preserves existing upload API calls unchanged (component is purely presentational + event handling)
  • Priority: P0

FR-7: User Dashboard Charts

  • Description: Add trend visualization to the user DashboardPage. The page currently shows numeric stats (kWh, ERE claims, earnings) without any temporal context. Recharts is installed and already used on the admin dashboard. The DashboardPage already imports LazyBarChart, LazyAreaChart, and Bar, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend from recharts but [Assumption: may not render them for all users or may only show them conditionally].
  • Acceptance Criteria:
    • User dashboard shows a kWh trend chart (monthly bar or area chart) for the current year
    • Chart uses the existing LazyChartWrapper for code-split loading
    • Chart uses the existing CustomTooltip and ChartGradients components for visual consistency with admin dashboard
    • Empty state handled gracefully when user has < 2 months of data (show EmptyChart component)
    • Chart is responsive and renders well at mobile widths (300px+)
    • Chart colors use @theme tokens (primary-600 for bars, navy for accents)
  • Priority: P0

FR-8: Search on User-Facing Lists

  • Description: Add the existing SearchInput component to DocumentsPage, ConversationsPage, and ChargingPointsPage. These pages currently lack client-side or server-side search, forcing users to scroll through lists.
  • Acceptance Criteria:
    • SearchInput component is rendered at the top of the list section on DocumentsPage, ConversationsPage, and ChargingPointsPage
    • DocumentsPage: filters by document type name, filename, or status
    • ConversationsPage: filters by subject or last message content
    • ChargingPointsPage: filters by charging point name, brand, model, or location
    • Search is debounced (300ms) to prevent excessive re-renders
    • Clearing search restores the full list
    • Empty search results show the EmptyState component with a "no results" message
  • Priority: P1

FR-9: Inline Document Preview Modal

  • Description: The DocumentsPage currently has a DocumentPreviewModal component but document preview for images/PDFs should be enhanced with zoom, rotation for images, and in-modal pagination for multi-page PDFs. Currently the modal opens but the experience is basic.
  • Acceptance Criteria:
    • Image preview supports pinch-to-zoom on mobile and scroll-to-zoom on desktop
    • Image preview supports 90-degree rotation
    • PDF preview renders inline in the modal (using browser native <object> or <iframe>)
    • Download button is always visible in the modal header
    • Modal size is xl (max-w-4xl) for adequate preview space
    • Non-previewable files show a clear "Preview niet beschikbaar" message with download link
  • Priority: P2

FR-10: Onboarding Progress Bar Enhancement

  • Description: The StepIndicator component already has a horizontal stepper with connecting lines and a mobile progress bar. Enhance it with: a completed-step count fraction (e.g., "3/6"), step descriptions on hover (desktop), and a subtle animation when transitioning between steps.
  • Acceptance Criteria:
    • Desktop: hovering a step circle shows a tooltip with the step description
    • Desktop: connecting line animates (fills) when a step is completed
    • Mobile: progress bar shows fraction text (e.g., "3 van 6 voltooid") below the bar
    • Transition between steps includes a subtle slide animation on the main content
    • All changes are backwards-compatible with existing OnboardingProvider state management
  • Priority: P2

Phase 3: Admin Efficiency

FR-11: Bulk Admin Actions

  • Description: Add bulk selection and batch operations to admin table pages. Priority tables: AdminDocumentsPage, AdminKwhEntriesPage, AdminEREClaimsPage. Admins currently process items one-by-one.
  • Acceptance Criteria:
    • Checkbox column added to AdminDocumentsPage, AdminKwhEntriesPage, AdminEREClaimsPage tables
    • "Select all on page" checkbox in table header
    • Floating action bar appears when 1+ items selected, showing: count, available actions, "Deselect all"
    • AdminDocumentsPage bulk actions: Verify Selected, Reject Selected (with shared rejection reason)
    • AdminKwhEntriesPage bulk actions: Verify Selected, Reject Selected
    • AdminEREClaimsPage bulk actions: Submit Selected, Reject Selected
    • Confirmation modal before bulk state changes with count of affected items
    • Success/error toast after bulk operation with count of succeeded/failed
    • Selection state is preserved during pagination (across pages) [Assumption: acceptable to clear on filter change]
    • Backend already supports individual PATCH operations; bulk is implemented as parallel API calls with error aggregation
  • Priority: P0

FR-12: Admin Dashboard Charts Enhancement

  • Description: The AdminDashboard already has a DashboardCharts component. Ensure it renders monthly kWh and revenue trend charts for the selected year. Add a user growth sparkline to the KeyMetrics section.
  • Acceptance Criteria:
    • DashboardCharts renders bar chart for monthly kWh and area chart for monthly revenue
    • Charts use consistent color scheme from @theme tokens
    • User count metric in KeyMetrics includes a small sparkline showing 6-month trend
    • Charts handle empty data gracefully (EmptyChart component)
    • Year selector controls all charts (already wired via selectedYear prop)
  • Priority: P1

FR-13: Mobile Table Responsiveness

  • Description: Admin tables with 6-9 columns don't collapse on mobile viewports. Implement a responsive table pattern that works for the admin table pages.
  • Acceptance Criteria:
    • Tables with >5 columns switch to a card-based layout on viewports < 768px
    • Card layout shows: primary identifier (name/email), status badge, key metric, and an expand/detail button
    • Expanded card shows all columns in a key-value list format
    • Sort and filter controls remain accessible on mobile
    • Pattern implemented as a reusable ResponsiveTable component or mixin
    • Applied to: AdminUsersPage, AdminDocumentsPage, AdminKwhEntriesPage, AdminEREClaimsPage, AdminChargingPointsPage, AdminOrganizationsPage
  • Priority: P1

FR-14: Charging Point Map View (Admin)

  • Description: Add a map view toggle to AdminChargingPointsPage. The project already has @react-google-maps/api installed and a ChargingPointsMapView component exists in components/charging-points/.
  • Acceptance Criteria:
    • Toggle button (list view / map view) in the page header
    • Map view renders all charging points as markers using @react-google-maps/api
    • Clicking a marker shows an info window with: name, brand/model, owner, status
    • Map defaults to Netherlands bounding box, auto-zooms to fit all markers
    • Filter state from the list view applies to the map view (same dataset)
    • Map view does not load on initial page load (lazy loaded on toggle)
  • Priority: P2

Phase 4: Polish & Consistency

FR-15: Breadcrumb Navigation

  • Description: Deep pages (AdminUserDetailPage, AdminOrganizationDetailPage, AdminChargingPointDetailPage, AdminEANCodeDetailPage, ConversationDetailPage) don't show their position in the navigation hierarchy. Add a breadcrumb component.
  • Acceptance Criteria:
    • Breadcrumb component renders a horizontal path: Home > Section > Item Name
    • Each breadcrumb segment is a link except the current page
    • Component integrates with react-router-dom for path-based breadcrumb generation
    • Applied to all detail pages (minimum 6 pages listed above)
    • Mobile: breadcrumbs truncate with "..." for long paths, showing at minimum the parent and current page
  • Priority: P1

FR-16: Modal Component Consolidation

  • Description: There are 20+ modal implementations across the codebase. Many use inline fixed inset-0 bg-black/50 patterns instead of the centralized Modal component with focus trap. Migrate all inline modals to use the shared Modal component.
  • Acceptance Criteria:
    • Audit identifies all inline modal implementations (search for fixed inset-0)
    • All modals use the Modal component from components/common/Modal.tsx
    • Focus trap works correctly in all migrated modals
    • Escape key closes all modals
    • Scroll lock is applied when any modal is open
    • No visual regressions in any migrated modal
  • Priority: P1

FR-17: Settings Page Tabs

  • Description: ProfilePage and OrganizationSettingsPage are long scrolling pages. Convert them to tabbed layouts using the existing Tabs component (components/common/Tabs.tsx).
  • Acceptance Criteria:
    • ProfilePage has tabs: Profiel, Beveiliging, Voorkeuren
    • OrganizationSettingsPage has tabs: Algemeen, Leden, Facturatie
    • Tab state is reflected in the URL hash (e.g., /profile#beveiliging) for deep linking
    • Tab content loads lazily (only the active tab's section is rendered)
    • Mobile: tabs are horizontally scrollable if they overflow
  • Priority: P2

FR-18: Holding Structure Visualization

  • Description: The HoldingManagementPage shows subsidiaries as a flat list. Add a tree/org-chart visualization for holding companies with subsidiaries.
  • Acceptance Criteria:
    • Holding company displayed as root node with subsidiaries as children
    • Each node shows: organization name, KVK number, status, member count
    • Nodes are clickable and navigate to the organization detail page
    • Tree handles up to 20 subsidiaries without performance issues
    • Mobile: tree collapses to an indented list view
    • No additional library required (built with CSS flexbox/grid + existing card components)
  • Priority: P2

FR-19: Status Badge Color Alignment

  • Description: Status badge colors are inconsistent between contexts: EREClaimsPage uses blue (bg-blue-100) for VERIFIED while DocumentsPage uses green (bg-success-100). The StatusBadge component defines a canonical mapping, but some pages override or bypass it.
  • Acceptance Criteria:
    • All pages use the StatusBadge component for status display (no inline badge rendering)
    • VERIFIED/APPROVED/ACTIVE always use success-* tokens (green family)
    • PENDING/SUBMITTED/IN_BEHANDELING always use warning-* tokens (yellow family)
    • REJECTED/FAILED/REVOKED always use danger-* tokens (red family)
    • IN_PROGRESS/PROCESSING/OPEN use info-* (blue family) -- distinguishable from success
    • CLOSED/EXPIRED/CANCELLED/INACTIVE use gray-* tokens
    • Visual audit confirms consistent colors across all pages
  • Priority: P1

FR-20: EmptyState Component Consistency

  • Description: The EmptyState component exists but is not used on all pages that can have empty lists. Some pages show plain text or nothing when no data exists.
  • Acceptance Criteria:
    • All list/table pages use EmptyState when data array is empty
    • Each EmptyState includes: relevant icon, message, and a primary action button (where applicable)
    • EmptyState messages are context-specific (not generic "No data found")
    • Applied to minimum 10 pages: DocumentsPage, ChargingPointsPage, EREClaimsPage, ConversationsPage, EANCodesPage, KwhEntryPage, and all admin list pages with missing EmptyState
  • Priority: P2

5. Non-Functional Requirements

Performance

  • Auth pages (Phase 1): LCP < 1.5s, no layout shift from background loading
  • Charts (Phase 2, 3): Recharts bundles are already lazy-loaded via LazyChartWrapper; maintain this pattern. Chart render time < 500ms for datasets up to 12 months.
  • Drag-and-drop (Phase 2): File selection to upload-start latency < 200ms
  • Bulk actions (Phase 3): UI remains responsive during parallel API calls; use request batching (max 10 concurrent)
  • Map view (Phase 3): Lazy-loaded Google Maps bundle; initial render < 2s for up to 500 markers

Scale

  • Current user base: [Assumption: hundreds of users, growing]. Design for up to 5,000 active users.
  • Admin tables: Must handle 10,000+ rows with pagination (already server-side paginated).
  • Bulk actions: Tested with selections up to 100 items.
  • Map view: Tested with up to 500 charging point markers. Use marker clustering if >200 visible.

SLOs/SLAs

  • N/A -- frontend-only changes. No backend SLA modifications.
  • Client-side error rate (tracked via Grafana Faro): maintain < 0.5% error rate after each phase rollout.
  • Bundle size budget: no phase should increase the main bundle by more than 50KB gzipped. Use code splitting for new components.

Privacy

  • No new PII collection or processing.
  • File drag-and-drop: files are sent via the existing multipart/form-data upload API. No client-side file storage or caching beyond the upload flow.
  • Map view: uses coordinates already stored in the database. No new geolocation collection from users.

Security

  • No new authentication or authorization flows.
  • Bulk admin actions: reuse existing per-item API endpoints with existing RBAC. No new admin-only endpoints needed.
  • File uploads: existing backend validation (MIME type, magic bytes, file size) remains unchanged.
  • Modal focus trap: already implemented in the shared Modal component. Migration ensures all modals get this security benefit (prevents interaction with background content).

Observability

  • Each phase includes Grafana Faro integration for error tracking (already configured globally).
  • New components should include data-testid attributes for E2E test targeting.
  • Console errors from new chart/map components should be caught and logged, not displayed to users.
  • [Assumption: No new server-side metrics needed for frontend-only changes.]

6. Scope

In Scope

  • Visual redesign of auth pages (Login, Register, ForgotPassword, ResetPassword)
  • Reusable FileDropZone component + integration on 4 pages
  • User dashboard chart additions
  • SearchInput integration on 3 user-facing list pages
  • Document preview modal enhancement
  • Onboarding step indicator polish
  • Bulk selection + batch actions on 3 admin table pages
  • Admin dashboard chart enhancements
  • Mobile-responsive table pattern for 6 admin pages
  • Admin charging point map view
  • Breadcrumb navigation on 6+ detail pages
  • Modal consolidation (migrate inline modals to shared Modal component)
  • Tabbed settings pages (ProfilePage, OrganizationSettingsPage)
  • Holding structure tree visualization
  • Status badge color alignment
  • EmptyState consistency
  • Color token, icon sizing, and button component consolidation

Out of Scope (and why)

  • Backend API changes: This initiative is frontend-only. Bulk actions use existing per-item endpoints. If backend bulk endpoints are needed for performance, that is a separate initiative.
  • New features / business logic: This PRD covers UX and design improvements to existing functionality. No new features are being added.
  • Form library migration (react-hook-form everywhere): The codebase mixes react-hook-form with uncontrolled state. Full migration is desirable but too large for this initiative. New code should use react-hook-form; existing code is migrated only when a page is already being touched.
  • Admin import profile visual mapping: Requires significant backend changes to support visual column preview. Deferred.
  • Real-time collaboration features: Out of scope for a design improvement initiative.
  • Landing page changes: Already scored 8/10. Not a priority.
  • Native mobile-specific UI (Capacitor plugins): All changes must work in the SPA web view. No platform-specific native UI.

Future Considerations

  • Design system documentation site: Once tokens and components are consolidated, create a Storybook or similar reference.
  • Dark mode support: The @theme token system would make this feasible after this initiative.
  • Backend bulk action endpoints: If parallel API calls for bulk actions prove too slow, purpose-built batch endpoints would be the next step.
  • Accessibility audit: This initiative maintains existing accessibility but does not systematically improve it. A focused a11y initiative should follow.
  • Animation library: If more complex animations are needed beyond CSS transitions, consider framer-motion.

7. Rollout Plan

Phase 1: First Impression & Design Foundation (Weeks 1-3)

Deliverables: FR-1 through FR-5

Gate criteria to proceed to Phase 2:

  • All four auth pages deployed with new AuthLayout
  • No increase in login error rate (Grafana Faro)
  • Stakeholder visual review approved
  • All E2E auth tests pass

Guardrails:

  • Login success rate: must not drop below current baseline
  • Auth page LCP: must stay < 1.5s
  • Mobile viewport rendering: verified on iOS Safari and Android Chrome via Capacitor build

Phase 2: Core UX Improvements (Weeks 4-7)

Deliverables: FR-6 through FR-10

Gate criteria to proceed to Phase 3:

  • FileDropZone deployed on all 4 target pages
  • Dashboard charts rendering for users with data
  • Search working on 3 user-facing list pages

Guardrails:

  • Upload success rate: must not drop (monitor via existing upload API error rates)
  • Bundle size: total increase < 30KB gzipped (charts are already code-split)
  • No new console errors on mobile devices

Phase 3: Admin Efficiency (Weeks 8-11)

Deliverables: FR-11 through FR-14

Gate criteria to proceed to Phase 4:

  • Bulk actions functional on 3 admin pages
  • Mobile table responsiveness verified on real devices
  • Admin team feedback collected (internal testing)

Guardrails:

  • Bulk action failure rate: < 5% of individual operations within a bulk batch
  • Admin page load times: no regression (monitor via Faro)
  • Map view: no Google Maps API quota spikes (monitor billing)

Phase 4: Polish & Consistency (Weeks 12-15)

Deliverables: FR-15 through FR-20

Gate criteria for completion:

  • All breadcrumbs deployed on detail pages
  • All inline modals migrated to shared Modal component
  • Status badge colors consistent across all pages
  • EmptyState used on all list pages

Guardrails:

  • No visual regressions (screenshot comparison via Playwright docs:screenshots)
  • E2E test suite passes without new failures
  • Client-side error rate remains < 0.5%

Kill Switch

  • Feature flags: Not currently in the codebase. For this initiative, changes are deployed behind the develop branch and tested before merging to main.
  • Rollback: Each phase is a set of commits on develop. If a phase causes issues post-merge-to-main, revert the merge commit. Frontend-only changes have zero database migration risk.
  • Emergency disable for map view: The Google Maps component is lazy-loaded. If API quota is exceeded, the toggle can be hidden with a simple condition check (environment variable or admin setting).

8. Risks & Open Questions

Known Risks

RiskProbabilityImpactMitigation
Auth page redesign reduces conversion temporarily (A/B test not feasible with current infra)LowHighDeploy to develop first, stakeholder review before main merge. Monitor login success rate for 1 week.
Bulk actions overload backend with parallel requestsMediumMediumImplement client-side request batching (max 10 concurrent). Add retry with exponential backoff for failed items.
Google Maps API costs increase with map view usageLowMediumLazy-load map only on toggle. Monitor billing. Set daily quota limit in Google Cloud Console.
Modal migration introduces subtle focus/scroll bugsMediumLowMigrate incrementally (5 modals at a time). Test each with keyboard navigation.
Mobile responsive tables look different from what admins expectLowMediumInternal admin preview and feedback before deployment.
Recharts bundle size impact on mobile performanceLowMediumAlready lazy-loaded via LazyChartWrapper. Verify no bundle regression.

Open Questions

QuestionOwnerNeeded BySuggested Resolution
What is the current login page bounce rate and registration completion rate?ProductBefore Phase 1 startsCheck Grafana Faro or analytics tool for baseline metrics
Does the admin team prefer card-based or horizontally-scrollable tables on mobile?Admin team leadBefore Phase 3Run a quick internal poll with mockups of both approaches
Should bulk actions use a new backend batch endpoint or parallel individual calls?Backend leadBefore Phase 3Start with parallel calls; add batch endpoint if performance is inadequate for >50 items
Is there a Google Maps API key already configured for production?DevOpsBefore Phase 3 (FR-14)Check .env.production for VITE_GOOGLE_MAPS_API_KEY
Should the AuthLayout use a static gradient or a subtle animated background?Design/ProductBefore Phase 1Recommend static gradient for performance; animated version as future enhancement

Dependencies & Assumptions

  • No backend changes required. All improvements are frontend-only. Bulk actions use existing per-item PATCH endpoints.
  • Recharts v3.5.1 is already installed and working. Used on AdminDashboard. No version upgrade needed.
  • @react-google-maps/api is already installed. ChargingPointsMapView component exists. Map view is an extension, not a net-new integration.
  • Tailwind v4 @theme tokens are already defined in index.css with navy, primary, success, warning, danger color scales.
  • The shared Modal component with focus trap exists and is production-ready at components/common/Modal.tsx.
  • The Button component exists at components/common/Button.tsx with all 6 variants.
  • The SearchInput component exists at components/common/SearchInput.tsx and is used on admin pages.
  • E2E tests exist for auth flows, dashboard, and key user journeys. All phases must pass the existing E2E suite.

Prioritization Rationale

The ordering follows this ROI logic:

  1. Phase 1 (Auth + Foundation): Highest leverage per engineering hour. Auth pages are the single point of entry for every new user. Design foundation work (tokens, icons, buttons) reduces cost of all subsequent phases.

  2. Phase 2 (Core UX): Drag-and-drop and dashboard charts address the two most frequent user complaints (file upload friction and "where am I?" dashboard context). Search on lists is low-effort with the existing SearchInput component.

  3. Phase 3 (Admin Efficiency): Bulk actions and mobile tables are the admin team's top requests. These directly translate to operational cost savings as the user base grows. Map view adds spatial context for a geographically distributed asset base.

  4. Phase 4 (Polish & Consistency): Breadcrumbs, modal consolidation, and status badge alignment are important for long-term codebase health but have lower immediate user impact. Grouping them last ensures they don't delay higher-impact work.