1308 lines
77 KiB
Markdown
1308 lines
77 KiB
Markdown
|
|
---
|
||
|
|
stepsCompleted: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||
|
|
inputDocuments:
|
||
|
|
- '_bmad-output/planning-artifacts/product-brief-l-ami-fiduciaire-2026-03-10.md'
|
||
|
|
- '_bmad-output/planning-artifacts/prd.md'
|
||
|
|
- '_bmad-output/planning-artifacts/prd-validation-report.md'
|
||
|
|
- '_bmad-output/project-context.md'
|
||
|
|
- 'docs/index.md'
|
||
|
|
- 'docs/project-overview.md'
|
||
|
|
- 'docs/architecture.md'
|
||
|
|
- 'docs/development-guide.md'
|
||
|
|
- 'docs/source-tree-analysis.md'
|
||
|
|
---
|
||
|
|
|
||
|
|
# UX Design Specification L'Ami Fiduciaire
|
||
|
|
|
||
|
|
**Author:** Saad
|
||
|
|
**Date:** 2026-03-11
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
<!-- UX design content will be appended sequentially through collaborative workflow steps -->
|
||
|
|
|
||
|
|
## Executive Summary
|
||
|
|
|
||
|
|
### Project Vision
|
||
|
|
|
||
|
|
L'Ami Fiduciaire is a practice management orchestration platform for Moroccan fiduciary firms. It sits above existing accounting tools (Sage/JBS) and government portals (SIMPL/Damancom) to orchestrate the complete practice workflow -- tracking deadlines across dozens of clients, coordinating team workload, managing client document exchange, and ensuring nothing falls through the cracks. The platform targets Morocco's ~20,000+ small-to-mid-size fiduciary firms (majority under 10 staff) with a confirmed Experio partnership for distribution.
|
||
|
|
|
||
|
|
The product is a brownfield project with a Laravel 12 + Vue 3 + Inertia.js stack, using shadcn-vue components and Tailwind CSS 4. Core infrastructure (multi-tenant workspaces, client management, folder/dossier system, client portal, document exchange, messaging, email notifications, 2FA, activity logging) is already built. The MVP adds 5 phases: role system foundation, dashboard separation, collaboration/nudge features, workflow efficiency (bulk operations, advanced filtering), and a full archive system.
|
||
|
|
|
||
|
|
### Target Users
|
||
|
|
|
||
|
|
| Persona | Role | Usage Pattern | Tech Level | Primary Device |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| **Karim** (Owner/Manager) | Firm owner, 120+ clients, manages team | Morning dashboard check, escalation handling | Moderate | Desktop |
|
||
|
|
| **Rachid** (Chef de Mission) | Supervises 3 workers, 90 dossiers | Team coordination, workload balancing, reassignment | Moderate | Desktop |
|
||
|
|
| **Fatima** (Collaborateur) | Manages 45 client dossiers | All-day power user -- the primary platform user | Moderate | Desktop |
|
||
|
|
| **Hassan** (External Client) | SARL owner, non-technical | Drive-by: click link, upload document, leave | Low | Mobile (phone) |
|
||
|
|
| **Saad** (Platform Admin) | SaaS owner | Platform monitoring, support tickets | High | Desktop |
|
||
|
|
|
||
|
|
**Design priority:** Fatima is the heaviest daily user and the UX must be optimized for her workflow first. Karim/Rachid need command-center visibility. Hassan needs zero-friction, mobile-first portal interactions.
|
||
|
|
|
||
|
|
### Key Design Challenges
|
||
|
|
|
||
|
|
1. **Multi-role dashboard complexity** -- One app shell must serve 4 internal roles with dramatically different information needs. Navigation, sidebar, and dashboard content must adapt per role without fragmenting the product experience.
|
||
|
|
|
||
|
|
2. **Tables-first, density-first design** -- Moroccan fiduciary professionals work in Excel and think in rows/columns. The PRD mandates "tables over cards" and "practicality-first UI." Every screen must prioritize information density and task speed over visual aesthetics.
|
||
|
|
|
||
|
|
3. **Bulk operations at scale** -- Creating declarations for 50 clients simultaneously, scheduling bulk notifications. These power-user flows must be fast yet error-proof, with clear multi-select, type selection, and date picking patterns.
|
||
|
|
|
||
|
|
4. **Client portal for non-technical users** -- Hassan is on his phone, not tech-savvy, possibly on the go. The portal must be a single-action page with zero cognitive load: see what's needed, do it, leave. Mobile-first for this surface only.
|
||
|
|
|
||
|
|
5. **Information density vs. cognitive overload** -- Owners see 120+ clients, workers see 45+ declarations with deadlines. Dense data tables must use smart color coding, status badges, and priority indicators to enable scanning without overwhelming.
|
||
|
|
|
||
|
|
6. **Brownfield constraints** -- 31 existing Vue pages, shadcn-vue component library, Inertia.js page-based navigation patterns. UX design must extend and enhance what's built, not start from scratch.
|
||
|
|
|
||
|
|
### Design Opportunities
|
||
|
|
|
||
|
|
1. **"Morning command center" moment** -- A transformative dashboard experience where Karim sees his entire firm's status for the first time on one screen. Priority alerts (red/amber/green), deadline countdowns, and team activity create the "aha moment" that drives trial-to-paid conversion.
|
||
|
|
|
||
|
|
2. **Moroccan fiscal calendar intelligence** -- Pre-loaded TVA deadlines (20th), CNSS (10th), IS (quarterly) in bulk creation flows. The system knows the calendar so users don't have to remember it.
|
||
|
|
|
||
|
|
3. **Progressive disclosure for power features** -- Clean, simple defaults with advanced features (nudge system, archive, advanced filters) accessible but not in the way. Fatima discovers power features as she needs them.
|
||
|
|
|
||
|
|
4. **Consistent visual status language** -- A unified color/badge/icon system for declaration statuses across all views (dashboards, tables, archive, portal). Enables instant scanning -- Fatima can assess 45 declarations' health in seconds.
|
||
|
|
|
||
|
|
## Core User Experience
|
||
|
|
|
||
|
|
### Defining Experience
|
||
|
|
|
||
|
|
The core product loop for L'Ami Fiduciaire centers on the **declaration status scanning and action cycle**. Fatima (the primary daily user) opens her scoped dashboard, scans her declaration list, identifies what needs attention based on visual status indicators, and takes immediate action -- sending a client notification, updating a status, or escalating to a manager. This scan-identify-act loop happens dozens of times per day and must be optimized for speed and accuracy.
|
||
|
|
|
||
|
|
For Karim (Owner), the core experience is the **morning command center check** -- a single-screen view of the entire firm's health: which declarations are at risk, which clients are unresponsive, which workers are overloaded. The dashboard-to-action flow (seeing a problem and resolving it in minimal clicks) is the critical interaction to get right.
|
||
|
|
|
||
|
|
For Hassan (External Client), the core experience is the **single-action portal interaction** -- click a link, see what's needed, do it, leave. The entire interaction should complete in under 60 seconds.
|
||
|
|
|
||
|
|
### Platform Strategy
|
||
|
|
|
||
|
|
| Dimension | Decision | Rationale |
|
||
|
|
|---|---|---|
|
||
|
|
| **Primary platform** | Desktop web (Chrome/Firefox/Safari) | Fiduciary professionals work at desks in offices |
|
||
|
|
| **Secondary platform** | Mobile web (responsive) | Client portal for Hassan; no native app for MVP |
|
||
|
|
| **Input model** | Mouse/keyboard-first (firm users), touch-friendly (portal) | Dense tables and power workflows for professionals, simple tap interactions for clients |
|
||
|
|
| **Offline support** | Not required | Firm users always connected; client portal interactions are brief |
|
||
|
|
| **SPA model** | Inertia.js server-driven pages | Brownfield constraint -- full page transitions, server-side filtering, pagination. No infinite scroll or complex client-side state |
|
||
|
|
|
||
|
|
### Effortless Interactions
|
||
|
|
|
||
|
|
1. **Status scanning** -- Fatima opens her dashboard and knows in 2 seconds: "3 urgent, 5 on track, 2 waiting on clients." Color/badge visual language eliminates the need to read individual rows.
|
||
|
|
|
||
|
|
2. **One-click nudge** -- Karim sees a problem declaration, clicks the nudge icon on the row, selects an employee. Done. No modal forms, no extra navigation.
|
||
|
|
|
||
|
|
3. **Bulk declaration creation** -- Select 20 clients via checkboxes, pick declaration type (TVA Mensuel), set deadline (March 20), create. Three steps for 20 declarations.
|
||
|
|
|
||
|
|
4. **Client portal upload** -- Hassan clicks email link, sees one sentence explaining what's needed, taps upload, takes photo of document, confirms. Under 60 seconds total.
|
||
|
|
|
||
|
|
5. **Filter persistence** -- Fatima sets her preferred filters (Status = En cours, Assignee = Me) once. Filters persist across navigation until explicitly cleared.
|
||
|
|
|
||
|
|
### Critical Success Moments
|
||
|
|
|
||
|
|
| Moment | Persona | Description | Impact |
|
||
|
|
|---|---|---|---|
|
||
|
|
| **"Morning command center"** | Karim | First time seeing all 120+ clients' status on one screen | Trial-to-paid conversion trigger |
|
||
|
|
| **"My list is clear"** | Fatima | End of day, all declarations updated, all notifications sent | Daily satisfaction, retention |
|
||
|
|
| **"30-second upload"** | Hassan | Click link, upload document, see confirmation | Client portal adoption |
|
||
|
|
| **"Nothing fell through"** | Karim | End of month, zero penalty notices across all clients | Long-term retention moment |
|
||
|
|
| **"I can see everything"** | Rachid | Reassigns declaration from absent worker in 2 clicks | Team coordination value proof |
|
||
|
|
|
||
|
|
### Experience Principles
|
||
|
|
|
||
|
|
1. **Density is clarity** -- More information on screen is better, not worse. Accountants are trained to read dense data. The UX removes noise, not data. Every row, badge, and number earns its place.
|
||
|
|
|
||
|
|
2. **Action at the point of recognition** -- The moment a user recognizes something needs attention, the action should be available right there. Inline actions, row-level buttons, contextual menus. No navigate-to-another-page-to-do-the-thing.
|
||
|
|
|
||
|
|
3. **The system remembers, so you don't have to** -- Fiscal calendar awareness, filter persistence, status history, audit trails. The platform carries the cognitive load that currently lives in users' heads and Excel sheets.
|
||
|
|
|
||
|
|
4. **Zero-friction boundaries** -- Every boundary crossing (firm-to-client portal, dashboard-to-declaration detail, active-to-archive) should feel seamless. No dead ends, no "where was I?" moments.
|
||
|
|
|
||
|
|
5. **French-native, Morocco-aware** -- Not a translated product. UI language, date formats (dd/mm/yyyy), currency (MAD), fiscal calendar, and professional terminology are natively Moroccan French.
|
||
|
|
|
||
|
|
## Desired Emotional Response
|
||
|
|
|
||
|
|
### Primary Emotional Goals
|
||
|
|
|
||
|
|
| Persona | Primary Emotion | Emotional Shift |
|
||
|
|
|---|---|---|
|
||
|
|
| **Karim** (Owner) | In control, confident | From anxiety ("what's falling through?") to mastery ("I see everything") |
|
||
|
|
| **Fatima** (Worker) | Competent, unburdened | From overwhelmed ("45 clients in my head") to methodical ("I work the list") |
|
||
|
|
| **Hassan** (Client) | Respected, not confused | From friction ("another system to figure out") to ease ("that was quick") |
|
||
|
|
| **Rachid** (Manager) | Effective, empowered | From relay ("WhatsApp forwarding") to leader ("I coordinate, I don't chase") |
|
||
|
|
|
||
|
|
### Emotional Journey Mapping
|
||
|
|
|
||
|
|
| Stage | Desired Emotion | Anti-Emotion (Avoid) |
|
||
|
|
|---|---|---|
|
||
|
|
| First discovery / signup | Curiosity, "this is made for me" | Skepticism, "just another tool" |
|
||
|
|
| Onboarding (first 30 min) | Confidence, progressive competence | Overwhelm, confusion |
|
||
|
|
| First morning dashboard | Relief, revelation | Information overload |
|
||
|
|
| Daily use (Fatima's loop) | Flow state, productive rhythm | Tedium, friction |
|
||
|
|
| Bulk operations | Power, efficiency | Fear of mistakes at scale |
|
||
|
|
| Client portal (Hassan) | Ease, "that was quick" | Confusion, abandonment |
|
||
|
|
| Something goes wrong | Trust, "I can fix this" | Panic, blame, data loss fear |
|
||
|
|
| End of month review | Pride, accomplishment | Dread, surprise penalties |
|
||
|
|
| Returning next day | Familiarity, continuity | Disorientation, "where was I?" |
|
||
|
|
|
||
|
|
### Micro-Emotions
|
||
|
|
|
||
|
|
- **Confidence over confusion** -- Every screen immediately answers "where am I, what can I do here?" through role-based views, clear headings, and breadcrumbs.
|
||
|
|
- **Trust over skepticism** -- Data integrity signals throughout: timestamps, audit trails, upload confirmations, action feedback. Never leave users wondering if something worked.
|
||
|
|
- **Accomplishment over frustration** -- Progress indicators, completion states, visual reward as task lists clear through the day. Fatima's dashboard shifting from red to green is the emotional payoff.
|
||
|
|
- **Calm over anxiety** -- During peak season (bilan Jan-Mar), the platform reduces stress. No alarm fatigue, smart priority levels, achievable daily task scope. Not everything can be red.
|
||
|
|
|
||
|
|
### Design Implications
|
||
|
|
|
||
|
|
| Desired Emotion | UX Design Approach |
|
||
|
|
|---|---|
|
||
|
|
| **In control** (Karim) | Dashboard summary cards with real-time counts, color-coded priority system, no hidden information |
|
||
|
|
| **Unburdened** (Fatima) | Scoped view showing only assigned work, clear next-action indicators, persistent filters |
|
||
|
|
| **Respected** (Hassan) | Single-purpose portal pages, large touch targets, plain French copy, immediate confirmation feedback |
|
||
|
|
| **Effective** (Rachid) | One-click reassignment, team workload overview, nudge system with direct-link notifications |
|
||
|
|
| **Confident** (all internal) | Consistent layout patterns, breadcrumb navigation, undo/correction flows, visible activity logs |
|
||
|
|
| **Calm during peak** (all firm) | Smart alert prioritization, deadline countdown gradients (green to amber to red), manageable daily scope |
|
||
|
|
| **Trust** (all) | Timestamps on every action, explicit confirmations, archive as preservation (not deletion), accessible audit trail |
|
||
|
|
|
||
|
|
### Emotional Design Principles
|
||
|
|
|
||
|
|
1. **Professional calm, not consumer excitement** -- This is a daily-use B2B tool for accountants during high-stress periods. The design should feel reliable, structured, and calming -- like a well-organized filing cabinet, not a flashy app.
|
||
|
|
|
||
|
|
2. **Earned urgency only** -- Red alerts, warning badges, and urgent indicators must be meaningful and sparse. If the system cries wolf, users stop trusting it. Priority levels (critical/warning/info) must reflect real deadline proximity.
|
||
|
|
|
||
|
|
3. **Collaborative, not surveillance** -- Activity logs and nudges exist to coordinate work, not monitor employees. The nudge system should feel like a helpful tap on the shoulder, not a manager looking over your shoulder.
|
||
|
|
|
||
|
|
4. **Immediate feedback, always** -- Every user action gets visible confirmation. Uploads confirmed, status changes reflected, nudges acknowledged. Silence creates anxiety; feedback creates trust.
|
||
|
|
|
||
|
|
5. **Graceful degradation of pressure** -- As deadlines approach, the UI should communicate increasing urgency gradually (green to amber to red) rather than suddenly. Users should never be surprised by an overdue declaration -- the system warned them progressively.
|
||
|
|
|
||
|
|
## UX Pattern Analysis & Inspiration
|
||
|
|
|
||
|
|
### Inspiring Products Analysis
|
||
|
|
|
||
|
|
#### 1. Linear (Project/Issue Tracking)
|
||
|
|
|
||
|
|
**Why relevant:** Linear's issue tracker is the closest UX analog to Fatima's declaration list -- dense rows of work items with statuses, assignees, priorities, and deadlines. It's the gold standard for "tables-first, keyboard-driven B2B SaaS."
|
||
|
|
|
||
|
|
**What they do well:**
|
||
|
|
- **Scannable list views** -- Status icons (colored circles), priority indicators, and assignee avatars are visible at the row level without expanding anything. One glance tells you the state of each item.
|
||
|
|
- **Inline actions** -- Right-click context menus and keyboard shortcuts for status changes, assignment, priority updates. No page navigation required for common actions.
|
||
|
|
- **Filter bar with persistence** -- Filters sit above the list, stay active across sessions, and can be saved as custom views.
|
||
|
|
- **Progressive disclosure** -- Simple by default, powerful when you dig in. New users see a clean list; power users build custom workflows.
|
||
|
|
- **Sidebar navigation** -- Collapsible sidebar with workspace-level navigation. Clean, not cluttered.
|
||
|
|
|
||
|
|
**Transferable to L'Ami Fiduciaire:** Declaration list UX, filter persistence, inline row actions, sidebar navigation pattern, status icon system.
|
||
|
|
|
||
|
|
#### 2. Excel / Google Sheets (The Users' Mental Model)
|
||
|
|
|
||
|
|
**Why relevant:** This is how Fatima and Karim currently work. Excel is not a product to emulate but a mental model to respect. Users think in rows, columns, sorting, and filtering. Any table in L'Ami Fiduciaire must feel at least as natural as a spreadsheet.
|
||
|
|
|
||
|
|
**What they do well:**
|
||
|
|
- **Information density** -- Maximum data per screen. No wasted whitespace. Users are trained to scan dense grids.
|
||
|
|
- **Sort and filter as primary interaction** -- Click a column header to sort, filter dropdowns on columns. This is muscle memory.
|
||
|
|
- **Cell-level editing** -- Click a cell, change the value, move on. Minimal friction for status updates.
|
||
|
|
- **Familiarity** -- Zero learning curve for the basic interaction model.
|
||
|
|
|
||
|
|
**Transferable to L'Ami Fiduciaire:** Table density expectations, column sorting, filter-first navigation, minimal whitespace in data views. The UX should feel like "Excel that thinks for you" -- same density, but with status intelligence, deadline awareness, and collaboration built in.
|
||
|
|
|
||
|
|
#### 3. Sage (Accounting Software -- The Legacy Baseline)
|
||
|
|
|
||
|
|
**Why relevant:** Every firm user has Sage open daily. It's a Windows-era desktop application with a functional but dated UI. Understanding what users tolerate (and what frustrates them) about Sage informs what L'Ami Fiduciaire should avoid.
|
||
|
|
|
||
|
|
**What they tolerate:**
|
||
|
|
- Dense forms with many fields -- accountants are used to data-heavy screens
|
||
|
|
- Menu-driven navigation (File > Client > Dossier) -- hierarchical mental model
|
||
|
|
- Modal dialogs for data entry -- not ideal, but familiar
|
||
|
|
|
||
|
|
**What frustrates them:**
|
||
|
|
- No web access, no collaboration, no real-time updates
|
||
|
|
- No dashboard or overview -- you must drill into each client individually
|
||
|
|
- No notification system -- everything is manual recall
|
||
|
|
- Dated visual design that feels like work, not empowerment
|
||
|
|
|
||
|
|
**Lesson for L'Ami Fiduciaire:** Don't try to look like Sage. But respect the density and data-first expectations that Sage users carry. The platform should feel modern and web-native while maintaining the information density that accountants expect.
|
||
|
|
|
||
|
|
#### 4. Experio (AI Pre-Accounting -- The Partner Product)
|
||
|
|
|
||
|
|
**Why relevant:** Confirmed partnership. Many L'Ami Fiduciaire users will also be Experio users. Their UX is a cautionary reference.
|
||
|
|
|
||
|
|
**What to learn from their weaknesses:**
|
||
|
|
- Bad UX on core pages creates an opportunity -- L'Ami Fiduciaire can set a higher standard that makes the combined Experio + L'Ami stack feel premium
|
||
|
|
- If Experio's onboarding works (landing page is good), users arrive with expectations that the product behind the landing page will be equally polished
|
||
|
|
- Integration UX (future) must be seamless enough to compensate for Experio's own UX gaps
|
||
|
|
|
||
|
|
**Lesson for L'Ami Fiduciaire:** Be the product in the stack that users actually enjoy using. Set the UX bar for the Moroccan fiduciary SaaS ecosystem.
|
||
|
|
|
||
|
|
### Transferable UX Patterns
|
||
|
|
|
||
|
|
**Navigation Patterns:**
|
||
|
|
- **Collapsible sidebar with role-driven sections** (from Linear) -- Sidebar shows different nav items based on role. Owner/Manager sees "Dashboard, Clients, Declarations, Archive, Team, Settings." Worker sees "Dashboard, My Declarations, Archive, Settings." Clean separation without separate apps.
|
||
|
|
- **Breadcrumb trail for depth navigation** (standard B2B) -- Dashboard > Client Benani > TVA Janvier 2026. Always know where you are, always able to go back.
|
||
|
|
|
||
|
|
**Interaction Patterns:**
|
||
|
|
- **Inline status updates on table rows** (from Linear) -- Click a status badge directly on the declaration row to cycle through statuses or open a dropdown. No need to open the full detail page for common actions.
|
||
|
|
- **Row-level action menu** (from Linear) -- Three-dot menu or right-click on any declaration row reveals: Edit, Nudge, Reassign, View Detail, Archive. Actions at the point of recognition.
|
||
|
|
- **Bulk selection with action bar** (from Gmail/Linear) -- Checkboxes on rows, floating action bar appears: "23 selected: Create Declarations | Send Notifications | Change Status."
|
||
|
|
|
||
|
|
**Visual Patterns:**
|
||
|
|
- **Color-coded status badges** (from Linear/GitHub) -- Consistent colored dots/pills for declaration statuses across all views. Same color = same meaning everywhere.
|
||
|
|
- **Deadline proximity indicators** (unique to L'Ami) -- Days-remaining counter with color gradient: green (>7 days) → amber (3-7 days) → red (<3 days) → dark red (overdue). More informative than a simple date.
|
||
|
|
- **Summary cards above tables** (from dashboard patterns) -- "12 En cours | 3 En retard | 5 En attente client | 2 Urgent" as clickable cards that filter the table below.
|
||
|
|
|
||
|
|
**Data Patterns:**
|
||
|
|
- **Server-side pagination with page size control** (Inertia constraint) -- Standard pagination (25/50/100 rows per page) with persistent preference. Respects the server-driven SPA model.
|
||
|
|
- **Column sorting** (from Excel mental model) -- Click column headers to sort. Users expect this from their spreadsheet habits.
|
||
|
|
- **Persistent filter bar** (from Linear) -- Filter pills visible above the table, removable with X, persisted in session/URL params.
|
||
|
|
|
||
|
|
### Anti-Patterns to Avoid
|
||
|
|
|
||
|
|
1. **Card-based layouts for data lists** -- Cards waste space and break the row-scanning mental model accountants rely on. Declarations, clients, and archive items must be table rows, not cards. Cards are acceptable only for dashboard summary metrics.
|
||
|
|
|
||
|
|
2. **Over-modalization** -- Opening a modal for every action (edit status, send notification, reassign) creates friction. Prefer inline edits, dropdowns, and popovers over full modals. Reserve modals for destructive or multi-step actions only (bulk creation, delete confirmation).
|
||
|
|
|
||
|
|
3. **Hidden navigation behind hamburger menus** -- Desktop users expect a visible sidebar. Never hide the primary navigation behind a toggle on desktop viewports. The sidebar is always visible (collapsible to icons is acceptable).
|
||
|
|
|
||
|
|
4. **Alarm fatigue through over-notification** -- Not every declaration needs a red badge. Priority indicators must use 3-4 levels (critical/warning/info/neutral) with clear thresholds tied to deadline proximity. Default state is calm.
|
||
|
|
|
||
|
|
5. **Onboarding wizards that block usage** -- Multi-step setup wizards create friction. Prefer progressive onboarding: let users into the product immediately, guide them contextually. "Add your first client" prompt on an empty client list is better than a 5-step wizard.
|
||
|
|
|
||
|
|
6. **Whitespace-heavy "modern" design** -- Fiduciary professionals want density, not aesthetics. Large padding, oversized cards, and spacious layouts feel wasteful to users who work in Excel all day. Keep spacing tight and purposeful.
|
||
|
|
|
||
|
|
### Design Inspiration Strategy
|
||
|
|
|
||
|
|
**What to Adopt:**
|
||
|
|
- Linear's list view UX (scannable rows, inline actions, filter persistence) → Declaration and client list views
|
||
|
|
- Linear's sidebar navigation (collapsible, workspace-scoped) → App shell navigation
|
||
|
|
- Summary-cards-above-table pattern → Dashboard command center and list view headers
|
||
|
|
- Color-coded status badge system → Universal declaration status language
|
||
|
|
|
||
|
|
**What to Adapt:**
|
||
|
|
- Excel's density expectations → Adapt for web (slightly more spacing than a spreadsheet, but far less than typical SaaS)
|
||
|
|
- Linear's keyboard shortcuts → Start with mouse-first, add keyboard shortcuts as power-user feature post-MVP
|
||
|
|
- Gmail's bulk selection bar → Adapt for declaration bulk operations (create, notify, status change)
|
||
|
|
|
||
|
|
**What to Avoid:**
|
||
|
|
- Experio's core page UX patterns → Set a higher bar
|
||
|
|
- Sage's modal-heavy, menu-driven navigation → Use modern web navigation (sidebar + breadcrumbs)
|
||
|
|
- Card layouts for data → Tables everywhere except dashboard summaries
|
||
|
|
- Consumer SaaS aesthetic (Notion-like spaciousness) → Too sparse for accountant workflows
|
||
|
|
|
||
|
|
## Design System Foundation
|
||
|
|
|
||
|
|
### Design System Choice
|
||
|
|
|
||
|
|
**Selected:** shadcn-vue (reka-ui) + Tailwind CSS 4 -- extending the existing brownfield design system.
|
||
|
|
|
||
|
|
This is a brownfield project with 20+ shadcn-vue component groups already installed and 31 Vue pages built on them. The design system choice is to **confirm, extend, and customize** what exists rather than replace it.
|
||
|
|
|
||
|
|
**Component Library:** shadcn-vue (headless reka-ui primitives with Tailwind styling)
|
||
|
|
**Styling Framework:** Tailwind CSS 4 with CVA (Class Variance Authority) for component variants
|
||
|
|
**Icons:** Lucide (lucide-vue-next)
|
||
|
|
**Utility Layer:** `cn()` helper (clsx + tailwind-merge) in `resources/js/lib/utils.ts`
|
||
|
|
|
||
|
|
### Rationale for Selection
|
||
|
|
|
||
|
|
1. **Brownfield reality** -- 31 Vue pages and 20+ component groups already built on shadcn-vue. Migration cost would exceed any benefit of an alternative system.
|
||
|
|
2. **Density-compatible** -- Headless primitives with Tailwind styling allow full control over spacing and density. Unlike Material Design or Ant Design, there's no opinionated spacing to fight against.
|
||
|
|
3. **Accessibility built-in** -- reka-ui handles ARIA attributes, keyboard navigation, and focus management at the primitive level. Accessible by default without extra work.
|
||
|
|
4. **Tailwind 4 synergy** -- CVA-based component variants make it straightforward to create "compact" and "dense" variants of existing components for data-heavy views.
|
||
|
|
5. **No vendor lock-in** -- Components live in the project (`resources/js/components/ui/`), not in `node_modules`. Full ownership and customization capability.
|
||
|
|
6. **Team familiarity** -- Both developers (Saad + Ilyas) already work with this stack daily. Zero learning curve.
|
||
|
|
|
||
|
|
### Implementation Approach
|
||
|
|
|
||
|
|
**Extend, don't replace:**
|
||
|
|
- Existing `resources/js/components/ui/` components remain untouched (auto-generated via `npx shadcn-vue`)
|
||
|
|
- New custom components built in `resources/js/components/` (app-level) following the same Tailwind + CVA patterns
|
||
|
|
- Dense/compact variants added via CVA variant props (e.g., `size="compact"`) rather than separate components
|
||
|
|
|
||
|
|
**Component organization:**
|
||
|
|
- `resources/js/components/ui/` -- shadcn-vue base components (do not modify)
|
||
|
|
- `resources/js/components/` -- app-level business components (ClientForm, FolderForm, etc.)
|
||
|
|
- New dashboard, filter, and notification components added to `resources/js/components/`
|
||
|
|
|
||
|
|
### Customization Strategy
|
||
|
|
|
||
|
|
**1. Design Tokens (via Tailwind CSS 4 theme):**
|
||
|
|
- Declaration status colors (universal across all views)
|
||
|
|
- Priority level colors (deadline proximity gradient)
|
||
|
|
- Alert severity colors (critical/warning/info/neutral)
|
||
|
|
- Spacing scale optimized for density (tighter than default Tailwind)
|
||
|
|
|
||
|
|
**2. Component Variants to Create:**
|
||
|
|
- **Dense Table** -- Compact row height, tighter padding, optimized for 25-50 rows visible without scrolling
|
||
|
|
- **Status Badge** -- Color-coded pill with consistent mapping to declaration statuses
|
||
|
|
- **Priority Indicator** -- Days-remaining counter with deadline proximity color
|
||
|
|
- **Summary Card** -- Dashboard metric card with count, label, and click-to-filter behavior
|
||
|
|
- **Filter Bar** -- Persistent filter pills with dropdown selectors and clear-all action
|
||
|
|
- **Nudge Button** -- Inline row-level action for one-click team coordination
|
||
|
|
- **Bulk Action Bar** -- Floating bar that appears on multi-select with available bulk operations
|
||
|
|
|
||
|
|
**3. Layout Customizations:**
|
||
|
|
- Sidebar navigation adapted for role-driven sections
|
||
|
|
- Dashboard grid layout for command center summary cards
|
||
|
|
- Table-first page templates for Clients, Declarations, and Archive views
|
||
|
|
- Single-action portal page template for client-facing interactions
|
||
|
|
|
||
|
|
## Defining Core Experience
|
||
|
|
|
||
|
|
### The Defining Interaction
|
||
|
|
|
||
|
|
L'Ami Fiduciaire's defining experience is: **"Open the app and instantly know what needs your attention across all your clients."**
|
||
|
|
|
||
|
|
This is the interaction that drives trial-to-paid conversion, daily engagement, and word-of-mouth referral. Karim describes it as: "I open L'Ami Fiduciaire and I see everything -- which clients are at risk, which declarations are overdue, who needs to submit documents. Nothing surprises me." For Fatima: "I log in and my list tells me exactly what to do today."
|
||
|
|
|
||
|
|
### User Mental Model
|
||
|
|
|
||
|
|
| Persona | Mental Model | Primary Question | Design Implication |
|
||
|
|
|---|---|---|---|
|
||
|
|
| **Karim** (Owner) | Thinks in "risk" | "What's about to go wrong?" | Exception-based dashboard: surface problems first, details on drill-down |
|
||
|
|
| **Fatima** (Worker) | Thinks in "task lists" | "What do I need to do today?" | Ordered action list: next action per client, sorted by urgency |
|
||
|
|
| **Hassan** (Client) | Thinks in "requests" | "What do they want from me?" | Single-action page: one clear instruction, one button |
|
||
|
|
|
||
|
|
**Key mental model constraints:**
|
||
|
|
- Karim expects a command center that surfaces exceptions, not an exhaustive inventory. Summary cards for the big picture, alert lists for what needs attention.
|
||
|
|
- Fatima expects Excel-like table interactions: sort, filter, scan rows. Table patterns must support this muscle memory.
|
||
|
|
- Hassan needs explicit, action-oriented copy. "Telecharger votre releve bancaire de janvier" not "Documents requis."
|
||
|
|
|
||
|
|
### Success Criteria
|
||
|
|
|
||
|
|
| Criterion | Measure | Threshold |
|
||
|
|
|---|---|---|
|
||
|
|
| Time to situational awareness | Karim understands firm status after opening dashboard | < 10 seconds |
|
||
|
|
| Time to first action | Fatima identifies and starts working on most urgent item | < 30 seconds from login |
|
||
|
|
| Task completion rate | Hassan completes portal action without help | > 95% success rate |
|
||
|
|
| Scan accuracy | Fatima identifies 3 most urgent declarations from list of 45 | Instant via visual status language |
|
||
|
|
| Zero-miss rate | Priority alerts catch all approaching deadlines | 100% coverage |
|
||
|
|
|
||
|
|
### Pattern Innovation
|
||
|
|
|
||
|
|
The core experience uses **established interaction patterns combined in novel ways:**
|
||
|
|
|
||
|
|
- **Established:** Data tables with sorting/filtering (Excel mental model), status badges with color coding (Linear/GitHub), dashboard summary cards (standard B2B SaaS), bulk selection with action bars (Gmail)
|
||
|
|
- **Novel combination:** Deadline proximity indicators that auto-calculate days remaining and color-code based on Moroccan fiscal calendar awareness
|
||
|
|
- **Novel combination:** Summary cards that double as table filters -- clicking "3 En retard" filters the table below to overdue declarations only
|
||
|
|
- **Novel combination:** Role-based dashboard layouts serving different mental models (Karim's risk-first vs. Fatima's task-first) from the same underlying data
|
||
|
|
|
||
|
|
No user education required. Every pattern feels familiar to users of Excel, email, and basic web apps. The intelligence is in the system, not in asking users to learn new interactions.
|
||
|
|
|
||
|
|
### Experience Mechanics
|
||
|
|
|
||
|
|
**The Core Loop: Open → Scan → Act → Confirm**
|
||
|
|
|
||
|
|
**1. Initiation (Opening the App):**
|
||
|
|
- Owner/Manager lands on **Command Center Dashboard**: summary cards (active clients, declarations by status, overdue count, pending client actions), priority alert list, recent activity feed
|
||
|
|
- Worker lands on **Scoped Dashboard**: same structure filtered to assigned clients only, "My Declarations" as primary view
|
||
|
|
- Data is server-rendered (Inertia) -- no loading spinners for primary content
|
||
|
|
|
||
|
|
**2. Scanning (Identifying What Needs Attention):**
|
||
|
|
- Visual hierarchy: red = overdue (act now), amber = approaching deadline (plan), green = on track (ignore), gray = completed/archived
|
||
|
|
- Summary cards are clickable filters: click "3 En retard" → table filters to overdue declarations
|
||
|
|
- Column sorting on all data columns, default sort by deadline ascending (most urgent first)
|
||
|
|
|
||
|
|
**3. Acting (Taking Action):**
|
||
|
|
- Inline status change: click status badge → dropdown → select new status → instant update with toast confirmation
|
||
|
|
- One-click nudge: click nudge icon → popover with assignee → click send → toast confirmation, no page navigation
|
||
|
|
- Bulk operations: select rows via checkboxes → floating action bar → choose action → confirmation → execute → toast with count
|
||
|
|
|
||
|
|
**4. Confirming (Knowing You're Done):**
|
||
|
|
- Summary cards update as statuses change ("3 En retard" → "2 En retard")
|
||
|
|
- Task list visually clears through the day -- urgent count decreases as work progresses
|
||
|
|
- End-of-day state: "0 En retard, 0 Actions en attente" -- the "nothing fell through" emotional payoff
|
||
|
|
|
||
|
|
## Visual Design Foundation
|
||
|
|
|
||
|
|
### Color System
|
||
|
|
|
||
|
|
**Base Theme (Existing -- Confirmed):**
|
||
|
|
The brownfield codebase uses shadcn-vue "new-york-v4" style with OKLCH color tokens. The existing palette serves as the foundation:
|
||
|
|
|
||
|
|
- **Primary:** Blue/purple (`oklch(0.488 0.243 264.376)`) -- main interactive elements, active states, sidebar highlights
|
||
|
|
- **Primary Foreground:** Near-white (`oklch(0.97 0.014 254.604)`) -- text on primary backgrounds
|
||
|
|
- **Destructive:** Red (`oklch(0.577 0.245 27.325)`) -- delete actions, critical errors
|
||
|
|
- **Background:** White (`oklch(1 0 0)`) -- page backgrounds
|
||
|
|
- **Foreground:** Near-black (`oklch(0.141 0.005 285.823)`) -- primary text
|
||
|
|
- **Muted:** Light gray (`oklch(0.967 0.001 286.375)`) -- secondary backgrounds
|
||
|
|
- **Muted Foreground:** Medium gray (`oklch(0.552 0.016 285.938)`) -- secondary text, labels
|
||
|
|
- **Border:** Light gray (`oklch(0.92 0.004 286.32)`) -- dividers, input borders
|
||
|
|
- **Dark mode:** Full dark theme variant with inverted tokens, togglable via system/user preference
|
||
|
|
|
||
|
|
**New Semantic Colors (To Add):**
|
||
|
|
|
||
|
|
Declaration status colors -- the universal visual language used across dashboards, tables, archive, and portal:
|
||
|
|
|
||
|
|
| Status | Color Token | OKLCH Value | Usage |
|
||
|
|
|---|---|---|---|
|
||
|
|
| **Overdue** (En retard) | `--status-overdue` | Red -- high chroma, clearly urgent | Declarations past deadline |
|
||
|
|
| **Urgent** (Urgent) | `--status-urgent` | Dark amber/orange -- approaching deadline | Declarations due within 3 days |
|
||
|
|
| **In Progress** (En cours) | `--status-in-progress` | Blue (primary) | Active work, normal state |
|
||
|
|
| **Waiting Client** (En attente client) | `--status-waiting` | Amber/yellow | Blocked on external action |
|
||
|
|
| **Completed** (Termine) | `--status-completed` | Green -- muted, not celebratory | Successfully closed |
|
||
|
|
| **Draft** (Brouillon) | `--status-draft` | Gray (muted foreground) | Not yet active |
|
||
|
|
| **Archived** (Archive) | `--status-archived` | Light gray, desaturated | Read-only historical |
|
||
|
|
|
||
|
|
Priority/deadline proximity gradient:
|
||
|
|
|
||
|
|
| Proximity | Color | Threshold |
|
||
|
|
|---|---|---|
|
||
|
|
| **Safe** | Green | > 7 days remaining |
|
||
|
|
| **Approaching** | Amber | 3-7 days remaining |
|
||
|
|
| **Urgent** | Orange-red | 1-3 days remaining |
|
||
|
|
| **Overdue** | Red | Past deadline |
|
||
|
|
|
||
|
|
Alert severity levels:
|
||
|
|
|
||
|
|
| Level | Color | Usage |
|
||
|
|
|---|---|---|
|
||
|
|
| **Critical** | Red (destructive) | Overdue declarations, system errors |
|
||
|
|
| **Warning** | Amber | Approaching deadlines, missing documents |
|
||
|
|
| **Info** | Blue (primary) | Nudge received, status update, new upload |
|
||
|
|
| **Neutral** | Gray (muted) | Activity log entries, completed items |
|
||
|
|
|
||
|
|
### Typography System
|
||
|
|
|
||
|
|
**Primary Typeface:** Instrument Sans (already configured)
|
||
|
|
- Clean, modern sans-serif with excellent readability at small sizes
|
||
|
|
- Appropriate for dense data tables and professional B2B context
|
||
|
|
- Full stack fallback: `Instrument Sans, ui-sans-serif, system-ui, sans-serif`
|
||
|
|
|
||
|
|
**Type Scale (optimized for density):**
|
||
|
|
|
||
|
|
| Level | Size | Weight | Line Height | Usage |
|
||
|
|
|---|---|---|---|---|
|
||
|
|
| **Page Title** | 1.5rem (24px) | 600 (semibold) | 1.33 | Page headings (Declarations, Clients, Archive) |
|
||
|
|
| **Section Title** | 1.125rem (18px) | 600 (semibold) | 1.33 | Dashboard section headers, card titles |
|
||
|
|
| **Card Metric** | 1.5rem (24px) | 700 (bold) | 1.2 | Summary card numbers ("12", "3", "45") |
|
||
|
|
| **Table Header** | 0.75rem (12px) | 500 (medium) | 1.5 | Column headers, uppercase tracking |
|
||
|
|
| **Table Body** | 0.8125rem (13px) | 400 (regular) | 1.5 | Table row content -- slightly smaller than default for density |
|
||
|
|
| **Body** | 0.875rem (14px) | 400 (regular) | 1.5 | General content, form labels |
|
||
|
|
| **Small/Caption** | 0.75rem (12px) | 400 (regular) | 1.5 | Timestamps, metadata, secondary info |
|
||
|
|
| **Badge** | 0.6875rem (11px) | 500 (medium) | 1.2 | Status badges, tags, counts |
|
||
|
|
|
||
|
|
**Density note:** Table body text at 13px (not the default 14px) allows approximately 20% more rows visible without scrolling, directly supporting our "density is clarity" principle. This small reduction is still readable on standard monitors.
|
||
|
|
|
||
|
|
### Spacing & Layout Foundation
|
||
|
|
|
||
|
|
**Base Spacing Unit:** 4px (Tailwind default)
|
||
|
|
**Density Strategy:** Use tighter spacing in data-heavy views, standard spacing in forms and settings.
|
||
|
|
|
||
|
|
| Context | Spacing Approach |
|
||
|
|
|---|---|
|
||
|
|
| **Dashboard summary cards** | Standard padding (p-4/p-6), comfortable spacing between cards |
|
||
|
|
| **Data tables (dense)** | Compact padding: py-2 px-3 per cell (not default py-4). Reduced row height to show 25-50 rows without scrolling |
|
||
|
|
| **Filter bar** | Compact: gap-2 between filter pills, py-1.5 px-3 per pill |
|
||
|
|
| **Forms** | Standard spacing: gap-4 between fields, comfortable padding |
|
||
|
|
| **Portal pages** | Generous spacing: p-6/p-8, large touch targets (min 44px), mobile-friendly |
|
||
|
|
| **Sidebar navigation** | Compact: py-1.5 px-3 per nav item, visually tight but clickable |
|
||
|
|
|
||
|
|
**Layout Grid:**
|
||
|
|
- **Dashboard:** CSS Grid -- 4-column layout for summary cards, full-width table below
|
||
|
|
- **List views (Clients, Declarations):** Full-width table with filter bar above
|
||
|
|
- **Detail pages:** Two-column layout (main content + sidebar with metadata/actions)
|
||
|
|
- **Portal pages:** Single-column, centered, max-width 480px (mobile-optimized)
|
||
|
|
- **Sidebar:** Fixed 240px collapsed to 64px (icon-only). Always visible on desktop.
|
||
|
|
|
||
|
|
**Border Radius (Existing):**
|
||
|
|
- Base: 0.65rem -- kept for buttons, cards, inputs
|
||
|
|
- Badges/pills: full rounded (rounded-full) for status indicators
|
||
|
|
- Tables: square corners (rounded-none) -- tables should feel sharp and data-like
|
||
|
|
|
||
|
|
### Accessibility Considerations
|
||
|
|
|
||
|
|
**Color Contrast:**
|
||
|
|
- All text meets WCAG 2.1 AA standard (4.5:1 for normal text, 3:1 for large text)
|
||
|
|
- Status colors must be distinguishable without relying solely on color -- pair with icons or text labels
|
||
|
|
- OKLCH color space (already used) provides perceptually uniform colors, improving accessibility
|
||
|
|
|
||
|
|
**Color Blindness:**
|
||
|
|
- Status system uses both color AND shape/icon: overdue = red + warning triangle, completed = green + checkmark, waiting = amber + clock
|
||
|
|
- Never use red/green distinction alone -- always paired with secondary visual cue
|
||
|
|
|
||
|
|
**Keyboard Navigation:**
|
||
|
|
- reka-ui (shadcn-vue foundation) provides keyboard navigation for all interactive components by default
|
||
|
|
- Focus rings visible (existing ring tokens configured)
|
||
|
|
- Tab order follows visual layout
|
||
|
|
|
||
|
|
**Text Readability:**
|
||
|
|
- Minimum body text size: 13px (table dense) / 14px (general)
|
||
|
|
- Line height minimum: 1.5 for body text, 1.33 for headings
|
||
|
|
- Instrument Sans has excellent x-height for readability at small sizes
|
||
|
|
|
||
|
|
**Dark Mode:**
|
||
|
|
- Full dark theme already configured with OKLCH tokens
|
||
|
|
- Status colors must maintain distinguishability and contrast in both light and dark modes
|
||
|
|
- New semantic color tokens will include both light and dark variants
|
||
|
|
|
||
|
|
## Design Direction Decision
|
||
|
|
|
||
|
|
### Design Directions Explored
|
||
|
|
|
||
|
|
Four distinct visual directions were generated and presented via an interactive HTML showcase (`ux-design-directions.html`):
|
||
|
|
|
||
|
|
1. **Linear Dense** — Ultra-compact, keyboard-first, minimal chrome, maximum data density
|
||
|
|
2. **Command Center Dashboard** — Bold KPI cards, full sidebar, activity/alerts panels, strong visual hierarchy
|
||
|
|
3. **Balanced Professional** — Standard-density tables, prominent filter bars, clean spacing, professional tone
|
||
|
|
4. **Split-View Action** — Master-detail layout, persistent context panel, action-oriented sidebar
|
||
|
|
|
||
|
|
Each direction applied the established visual foundation (OKLCH color tokens, Instrument Sans, shadcn-vue components) in different layout and density configurations.
|
||
|
|
|
||
|
|
### Chosen Direction
|
||
|
|
|
||
|
|
**Hybrid: "Command Professional"** — A combination of Direction 2 (Command Center Dashboard) and Direction 3 (Balanced Professional).
|
||
|
|
|
||
|
|
**Key elements from Command Center Dashboard:**
|
||
|
|
- Large KPI summary cards prominently displayed on dashboard views
|
||
|
|
- Full sidebar navigation with logically grouped sections (Clients, Declarations, Archive, Team, Settings)
|
||
|
|
- Activity feed and alerts panel for real-time operational awareness
|
||
|
|
- Bold visual hierarchy with distinct information zones
|
||
|
|
|
||
|
|
**Key elements from Balanced Professional:**
|
||
|
|
- Standard-density data tables with comfortable row height (~48px)
|
||
|
|
- Persistent filter bar above all list views for quick filtering
|
||
|
|
- Clean, balanced spacing (not ultra-dense, not airy) — professional middle ground
|
||
|
|
- Restrained color application — primary blue accents on interactive elements only
|
||
|
|
|
||
|
|
### Design Rationale
|
||
|
|
|
||
|
|
- **Dashboard pages** benefit from Command Center's bold KPI cards and activity panels — fiduciary managers (Chef de Mission) need at-a-glance operational status
|
||
|
|
- **List/table pages** benefit from Balanced Professional's readable density — workers processing many dossiers need comfortable scanning without fatigue
|
||
|
|
- **The full sidebar** supports the deep navigation structure (Clients, Declarations, Archive, Team, Settings) without hiding sections behind hamburger menus
|
||
|
|
- **Standard density tables** with persistent filters align with the "scan-decide-act" core experience — users scan filtered lists, decide on priority, and act inline
|
||
|
|
- The combination respects the Moroccan accounting context where precision and clarity are paramount, while keeping the interface modern and approachable
|
||
|
|
|
||
|
|
### Implementation Approach
|
||
|
|
|
||
|
|
- **Layout structure:** Fixed full sidebar (240px collapsed to icon-only on mobile) + main content area with top breadcrumb bar
|
||
|
|
- **Dashboard pattern:** CSS Grid for KPI card rows (auto-fill, minmax 280px) + two-column layout for activity feed + deadline alerts
|
||
|
|
- **Table pattern:** shadcn-vue DataTable with sticky header, persistent filter bar (Combobox + DateRangePicker + Search), inline row actions (dropdown menu)
|
||
|
|
- **Responsive strategy:** Sidebar collapses to overlay drawer on mobile; KPI cards stack single-column; tables switch to card-based list view below 768px
|
||
|
|
- **Component density:** Use shadcn-vue default sizing (not `size="sm"`) for comfortable touch targets and readability; compact mode available as user preference toggle
|
||
|
|
|
||
|
|
## User Journey Flows
|
||
|
|
|
||
|
|
### Journey 1: Owner/Manager Morning Dashboard (Scan-Decide-Act)
|
||
|
|
|
||
|
|
**Entry Point:** User logs in or opens the app → lands on role-appropriate dashboard
|
||
|
|
|
||
|
|
**Flow Summary:** The dashboard is the operational command center. Owners and Managers share the same view (all clients, all declarations). The flow follows the "scan-decide-act" pattern established as the core experience.
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
A[Login / Open App] --> B[Dashboard Loads]
|
||
|
|
B --> C[KPI Summary Cards]
|
||
|
|
C --> C1[Overdue Declarations - RED]
|
||
|
|
C --> C2[Due This Week - AMBER]
|
||
|
|
C --> C3[Waiting for Client - BLUE]
|
||
|
|
C --> C4[On Track - GREEN]
|
||
|
|
|
||
|
|
C1 --> D{Click KPI Card}
|
||
|
|
C2 --> D
|
||
|
|
C3 --> D
|
||
|
|
C4 --> D
|
||
|
|
|
||
|
|
D --> E[Filtered Declaration List]
|
||
|
|
E --> F{Scan & Decide}
|
||
|
|
|
||
|
|
F --> G[Nudge Worker]
|
||
|
|
F --> H[Reassign Declaration]
|
||
|
|
F --> I[View Declaration Detail]
|
||
|
|
F --> J[Bulk Select & Act]
|
||
|
|
|
||
|
|
G --> G1[One-Click Nudge Notification]
|
||
|
|
G1 --> K[Return to List]
|
||
|
|
|
||
|
|
H --> H1[Select New Assignee]
|
||
|
|
H1 --> H2[Confirm Reassignment]
|
||
|
|
H2 --> K
|
||
|
|
|
||
|
|
I --> I1[View Status & Documents]
|
||
|
|
I1 --> I2{Action Needed?}
|
||
|
|
I2 -->|Yes| I3[Take Action from Detail]
|
||
|
|
I2 -->|No| K
|
||
|
|
I3 --> K
|
||
|
|
|
||
|
|
J --> J1[Select Multiple Rows]
|
||
|
|
J1 --> J2[Bulk Action Menu]
|
||
|
|
J2 --> J3[Confirm Bulk Action]
|
||
|
|
J3 --> K
|
||
|
|
|
||
|
|
K --> F
|
||
|
|
|
||
|
|
B --> L[Activity Feed Panel]
|
||
|
|
L --> L1[Recent Changes Stream]
|
||
|
|
L1 --> L2{Requires Attention?}
|
||
|
|
L2 -->|Yes| I
|
||
|
|
L2 -->|No| M[Continue Scanning]
|
||
|
|
|
||
|
|
B --> N[Alerts Panel]
|
||
|
|
N --> N1[Deadline Alerts]
|
||
|
|
N --> N2[Missing Documents]
|
||
|
|
N --> N3[Unread Client Messages]
|
||
|
|
```
|
||
|
|
|
||
|
|
**Key Interaction Details:**
|
||
|
|
|
||
|
|
- **KPI cards as filters:** Clicking a KPI card filters the declaration table below — no page navigation needed
|
||
|
|
- **Inline row actions:** Hover a declaration row → action icons appear (nudge, reassign, view detail)
|
||
|
|
- **Nudge = one click:** No modal, no message composition — instant notification sent, toast confirms
|
||
|
|
- **Activity feed:** Right-side panel showing real-time changes (document uploads, status updates, reassignments)
|
||
|
|
- **Alerts panel:** Below KPI cards or in sidebar — sorted by urgency, each alert links directly to the relevant declaration
|
||
|
|
|
||
|
|
### Journey 2: Worker Daily Workflow (Filter-Process-Update)
|
||
|
|
|
||
|
|
**Entry Point:** Worker logs in → sees scoped dashboard (only their assigned clients/declarations)
|
||
|
|
|
||
|
|
**Flow Summary:** Workers focus on processing declarations efficiently. Their flow is a tight loop: filter by priority, check what's needed, notify clients for missing docs, process ready declarations, update statuses.
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
A[Login] --> B[Worker Dashboard]
|
||
|
|
B --> C[Scoped KPI Cards - My Declarations Only]
|
||
|
|
C --> D[Filtered Declaration List]
|
||
|
|
|
||
|
|
D --> E{Filter by Priority}
|
||
|
|
E --> E1[Overdue First]
|
||
|
|
E --> E2[Due This Week]
|
||
|
|
E --> E3[Waiting for Documents]
|
||
|
|
E --> E4[Ready to Process]
|
||
|
|
|
||
|
|
E1 --> F{For Each Declaration}
|
||
|
|
E2 --> F
|
||
|
|
E3 --> G[Select Missing-Docs Declarations]
|
||
|
|
E4 --> H[Open Declaration Detail]
|
||
|
|
|
||
|
|
F --> F1{Status?}
|
||
|
|
F1 -->|Missing Docs| G
|
||
|
|
F1 -->|Docs Ready| H
|
||
|
|
F1 -->|In Progress| H
|
||
|
|
|
||
|
|
G --> G1[Select Multiple Declarations]
|
||
|
|
G1 --> G2[Bulk Notify Clients]
|
||
|
|
G2 --> G3[Email Sent to Each Client with Token Link]
|
||
|
|
G3 --> G4[Status Auto-Updates to 'Client Notified']
|
||
|
|
G4 --> D
|
||
|
|
|
||
|
|
H --> H1[View Declaration Details]
|
||
|
|
H1 --> H2[Download Client Documents]
|
||
|
|
H2 --> H3[Process in Sage/JBS]
|
||
|
|
H3 --> H4[Return to L'Ami Fiduciaire]
|
||
|
|
H4 --> H5[Update Declaration Status]
|
||
|
|
H5 --> H6{New Status}
|
||
|
|
H6 -->|Completed| H7[Mark as Filed]
|
||
|
|
H6 -->|Blocked| H8[Add Note + Flag Issue]
|
||
|
|
H6 -->|In Progress| D
|
||
|
|
H7 --> D
|
||
|
|
H8 --> D
|
||
|
|
|
||
|
|
B --> I[Notification Badge]
|
||
|
|
I --> I1{Notification Type}
|
||
|
|
I1 -->|Nudge from Manager| I2[View Nudged Declaration]
|
||
|
|
I1 -->|Client Upload| I3[View New Document]
|
||
|
|
I1 -->|Reassignment| I4[New Declaration Added to List]
|
||
|
|
I2 --> H
|
||
|
|
I3 --> H
|
||
|
|
I4 --> D
|
||
|
|
```
|
||
|
|
|
||
|
|
**Key Interaction Details:**
|
||
|
|
|
||
|
|
- **Scoped view:** Workers only see their assigned declarations — no information overload
|
||
|
|
- **Bulk notify:** Select multiple "waiting for docs" declarations → one click sends personalized emails to each client
|
||
|
|
- **Status updates:** Dropdown or inline button to change status — no separate form or modal
|
||
|
|
- **Notification badge:** Sidebar icon shows count — clicking opens notification panel with direct links
|
||
|
|
- **Client upload awareness:** When a client uploads via portal, the worker's list updates in real-time (or on next refresh) with a visual indicator ("New document")
|
||
|
|
|
||
|
|
### Journey 3: Client Document Upload (Zero-Friction Portal)
|
||
|
|
|
||
|
|
**Entry Point:** Client receives email notification with "Voir la demande" button containing token link
|
||
|
|
|
||
|
|
**Flow Summary:** The client portal is intentionally minimal — no account, no login, no navigation. Single-purpose: see what's needed, upload it, done.
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
A[Client Receives Email] --> B[Clicks 'Voir la demande' Button]
|
||
|
|
B --> C[Token-Authenticated Portal Page Loads]
|
||
|
|
|
||
|
|
C --> D[Portal Shows:]
|
||
|
|
D --> D1[Firm Name & Logo]
|
||
|
|
D --> D2[Declaration Type & Period]
|
||
|
|
D --> D3[Documents Requested - Checklist]
|
||
|
|
D --> D4[Upload Zone]
|
||
|
|
D --> D5[Message Thread with Firm]
|
||
|
|
|
||
|
|
D4 --> E{Upload Document}
|
||
|
|
E --> E1[Drag & Drop or Tap to Browse]
|
||
|
|
E1 --> E2[File Selected]
|
||
|
|
E2 --> E3[Upload Progress Bar]
|
||
|
|
E3 --> E4{Upload Success?}
|
||
|
|
E4 -->|Yes| E5[Document reçu. Merci.]
|
||
|
|
E4 -->|No| E6[Error Message + Retry]
|
||
|
|
E6 --> E1
|
||
|
|
|
||
|
|
E5 --> F{More Documents Needed?}
|
||
|
|
F -->|Yes| D3
|
||
|
|
F -->|No| G[All Documents Submitted]
|
||
|
|
G --> G1[Thank You Message]
|
||
|
|
G1 --> G2[Page Can Be Closed]
|
||
|
|
|
||
|
|
D5 --> H[View Messages from Firm]
|
||
|
|
H --> H1[Reply to Message]
|
||
|
|
H1 --> H2[Message Sent Confirmation]
|
||
|
|
H2 --> D
|
||
|
|
|
||
|
|
C --> I[Token Expired or Invalid]
|
||
|
|
I --> I1[Friendly Error Page]
|
||
|
|
I1 --> I2[Contact Your Accountant Message]
|
||
|
|
```
|
||
|
|
|
||
|
|
**Key Interaction Details:**
|
||
|
|
|
||
|
|
- **No authentication wall:** Token in URL = instant access. No signup, no password, no friction
|
||
|
|
- **Mobile-first layout:** Large tap targets, single-column layout, camera-friendly upload (photo of documents)
|
||
|
|
- **Progress feedback:** Upload progress bar → success checkmark → remaining items count updates
|
||
|
|
- **Document checklist:** Each required document shown as a checklist item — green check when uploaded
|
||
|
|
- **Messaging:** Simple thread view — client can ask questions, firm can clarify requests
|
||
|
|
- **Token expiry:** Graceful error with clear "contact your accountant" message — no dead ends
|
||
|
|
|
||
|
|
### Journey 4: Declaration Lifecycle (Cross-Role Flow)
|
||
|
|
|
||
|
|
**Entry Point:** Owner/Manager creates declaration(s) → flows through assignment, client notification, document collection, processing, and filing
|
||
|
|
|
||
|
|
**Flow Summary:** This is the end-to-end lifecycle showing how a declaration moves through the system, touching all roles.
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
A[Owner/Manager: Create Declaration] --> A1{Creation Type}
|
||
|
|
A1 -->|Single| A2[Select Client + Type + Deadline]
|
||
|
|
A1 -->|Bulk| A3[Select Multiple Clients + Type + Deadline]
|
||
|
|
A2 --> B[Assign to Worker]
|
||
|
|
A3 --> B
|
||
|
|
|
||
|
|
B --> C[Status: created]
|
||
|
|
C --> D[Worker Sees in Dashboard]
|
||
|
|
|
||
|
|
D --> E{Documents Needed?}
|
||
|
|
E -->|Yes| F[Worker Triggers Client Notification]
|
||
|
|
E -->|No| K[Worker Begins Processing]
|
||
|
|
|
||
|
|
F --> F1[Status: en_attente_client]
|
||
|
|
F1 --> G[Client Receives Email]
|
||
|
|
G --> H[Client Uploads via Portal]
|
||
|
|
H --> I[Worker Notified of Upload]
|
||
|
|
I --> J[Worker Downloads & Reviews]
|
||
|
|
J --> J1{Documents OK?}
|
||
|
|
J1 -->|Yes| K
|
||
|
|
J1 -->|No| J2[Worker Messages Client via Portal]
|
||
|
|
J2 --> F1
|
||
|
|
|
||
|
|
K --> K1[Status: en_cours]
|
||
|
|
K1 --> L[Worker Processes in Sage/JBS]
|
||
|
|
L --> M[Worker Updates Status]
|
||
|
|
M --> M1[Status: termine]
|
||
|
|
M1 --> N[Declaration Complete]
|
||
|
|
|
||
|
|
N --> N1[Status: ferme]
|
||
|
|
N1 --> O[Auto-Archive]
|
||
|
|
O --> O1[Status: archive]
|
||
|
|
|
||
|
|
subgraph Edge Cases
|
||
|
|
EC1[Manager Nudges Worker] --> D
|
||
|
|
EC2[Manager Reassigns Declaration] --> B
|
||
|
|
EC3[Worker Edits Declaration Type] --> EC4[Activity Log Updated]
|
||
|
|
EC4 --> D
|
||
|
|
EC5[Deadline Approaching] --> EC6[System Alerts Owner/Manager]
|
||
|
|
EC6 --> EC1
|
||
|
|
end
|
||
|
|
```
|
||
|
|
|
||
|
|
**Declaration Status Flow:**
|
||
|
|
|
||
|
|
```
|
||
|
|
created → en_attente_client → en_cours → termine → ferme → archive
|
||
|
|
↑ |
|
||
|
|
└────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**Key Interaction Details:**
|
||
|
|
|
||
|
|
- **Bulk creation:** Select multiple clients from a filtered list → set shared type + deadline → create all at once
|
||
|
|
- **Status auto-transitions:** Some status changes happen automatically while others require worker action (mark as termine/ferme)
|
||
|
|
- **Nudge system:** Manager clicks nudge → worker gets notification with direct link to the declaration — no message composition, pure signal
|
||
|
|
- **Activity log:** Every status change, reassignment, edit, upload, and nudge is logged with timestamp and actor — visible in declaration detail
|
||
|
|
- **Deadline escalation:** System generates alerts as deadlines approach (7 days → amber, 3 days → red, overdue → critical alert to owner)
|
||
|
|
|
||
|
|
### Journey Patterns
|
||
|
|
|
||
|
|
**Common patterns extracted across all journeys:**
|
||
|
|
|
||
|
|
**Navigation Patterns:**
|
||
|
|
- **KPI-to-List filtering:** Click summary card → filtered table (used in Owner, Manager, and Worker dashboards)
|
||
|
|
- **Direct-link navigation:** Notifications, nudges, and alerts all deep-link directly to the relevant declaration — no hunting
|
||
|
|
- **Breadcrumb context:** Dashboard → Client → Declaration — always know where you are and how to go back
|
||
|
|
|
||
|
|
**Decision Patterns:**
|
||
|
|
- **Inline actions:** Most decisions happen without leaving the list view (nudge, reassign, status change)
|
||
|
|
- **Confirmation for destructive actions:** Reassignment and bulk operations show a confirmation step; simple status updates do not
|
||
|
|
- **Progressive disclosure:** List view shows summary → click for detail → expand sections for full history
|
||
|
|
|
||
|
|
**Feedback Patterns:**
|
||
|
|
- **Toast notifications:** Quick actions (nudge sent, status updated) confirmed with non-blocking toast
|
||
|
|
- **Real-time indicators:** New document uploads, status changes reflected with visual badges ("New", dot indicators)
|
||
|
|
- **Deadline color gradient:** Green (>7 days) → Amber (3-7 days) → Red (<3 days) → Critical pulse (overdue) — consistent across all views
|
||
|
|
|
||
|
|
### Flow Optimization Principles
|
||
|
|
|
||
|
|
1. **Minimize clicks to value:** Dashboard → filtered list → action = 2 clicks maximum for any priority task
|
||
|
|
2. **No dead ends:** Every screen has a clear next action; error states include recovery paths
|
||
|
|
3. **Batch over individual:** Bulk creation, bulk notification, multi-select actions — respect the user's time when dealing with 45+ clients
|
||
|
|
4. **Context preservation:** Opening a declaration detail doesn't lose the list context — use slide-over panels or maintain scroll position on return
|
||
|
|
5. **Role-appropriate density:** Owners/Managers see the full picture; Workers see only their scope — same components, different data filters
|
||
|
|
6. **Zero-friction client portal:** Every additional field, button, or step on the client portal is a potential drop-off — keep it brutally simple
|
||
|
|
|
||
|
|
## Component Strategy
|
||
|
|
|
||
|
|
### Design System Components
|
||
|
|
|
||
|
|
**shadcn-vue (reka-ui) — Installed (24 groups):**
|
||
|
|
alert, avatar, badge, breadcrumb, button, card, checkbox, collapsible, dialog, dropdown-menu, input, input-otp, item, label, navigation-menu, select, separator, sheet, sidebar, skeleton, spinner, tabs, timeline, tooltip
|
||
|
|
|
||
|
|
**shadcn-vue — Need to Install:**
|
||
|
|
- **table** — Foundation for DataTable (sortable headers, row selection)
|
||
|
|
- **calendar + popover** — Foundation for DateRangePicker
|
||
|
|
- **combobox** — Searchable select for client/worker/type filtering
|
||
|
|
- **toast / sonner** — Non-blocking feedback for quick actions (nudge sent, status updated)
|
||
|
|
- **progress** — Upload progress bars (client portal)
|
||
|
|
- **switch** — Toggle settings (compact mode, dark mode)
|
||
|
|
- **command** — Command palette for power users (optional Phase 3)
|
||
|
|
|
||
|
|
**Already Built Custom Components (30+):**
|
||
|
|
AppShell, AppSidebar, AppHeader, NavMain, NavFooter, NavUser, WorkspaceSwitcher, NotificationDropdown, Pagination, Breadcrumbs, ClientForm, FolderForm, UserForm, WorkspaceForm, FolderCalendar, MessageBubble, TwoFactorSetupModal, TwoFactorRecoveryCodes, InputError, TextLink, Heading, UserInfo, AppearanceTabs, DeleteUser, PlaceholderPattern
|
||
|
|
|
||
|
|
### Custom Components
|
||
|
|
|
||
|
|
**1. StatCard**
|
||
|
|
- **Purpose:** Display KPI metrics on dashboards (overdue count, due this week, waiting for client, on track)
|
||
|
|
- **Content:** Metric label, value (number), trend indicator (optional), status color
|
||
|
|
- **Actions:** Clickable — filters the declaration list below when clicked
|
||
|
|
- **States:** Default, active (selected as filter), loading (skeleton)
|
||
|
|
- **Variants:** `status="danger|warning|info|success"` maps to deadline proximity colors
|
||
|
|
- **Accessibility:** Role="button", aria-pressed for active state, keyboard focusable
|
||
|
|
- **Implementation:** Compose from shadcn-vue `card` + CVA variants for status colors
|
||
|
|
|
||
|
|
**2. DataTable**
|
||
|
|
- **Purpose:** Primary data display for declarations, clients, and dossiers lists
|
||
|
|
- **Content:** Sortable columns, row data, inline actions, selection checkboxes
|
||
|
|
- **Actions:** Sort by column, select rows (single/multi), inline row actions (dropdown), click row to navigate
|
||
|
|
- **States:** Default, loading (skeleton rows), empty (EmptyState), filtered (active filter indicators)
|
||
|
|
- **Variants:** Default density (~48px rows), compact density (~36px rows, user preference)
|
||
|
|
- **Accessibility:** Role="grid", aria-sort on headers, keyboard row navigation
|
||
|
|
- **Implementation:** shadcn-vue `table` + TanStack Table v8 for sorting/filtering/selection logic
|
||
|
|
|
||
|
|
**3. FilterBar**
|
||
|
|
- **Purpose:** Persistent filter controls above all list views
|
||
|
|
- **Content:** Search input, status filter (Combobox), date range (DateRangePicker), assignee filter (Combobox), type filter (Select)
|
||
|
|
- **Actions:** Apply filters (instant, no submit button), clear all, save filter presets (Phase 3)
|
||
|
|
- **States:** Default, active filters (count badge), collapsed on mobile (expandable)
|
||
|
|
- **Variants:** Full (dashboard lists), minimal (portal views)
|
||
|
|
- **Accessibility:** Role="search", aria-label for each filter, clear keyboard navigation between filters
|
||
|
|
- **Implementation:** Composite of shadcn-vue `input` + `combobox` + `select` + custom `DateRangePicker`
|
||
|
|
|
||
|
|
**4. DateRangePicker**
|
||
|
|
- **Purpose:** Select date ranges for filtering declarations by deadline period
|
||
|
|
- **Content:** Start date, end date, preset ranges (This week, This month, This quarter)
|
||
|
|
- **Actions:** Select range via calendar, select preset, clear selection
|
||
|
|
- **States:** Default (placeholder), selected (showing range), open (calendar visible)
|
||
|
|
- **Accessibility:** Keyboard date navigation, aria-label for date inputs
|
||
|
|
- **Implementation:** shadcn-vue `popover` + `calendar` (dual calendar view)
|
||
|
|
|
||
|
|
**5. ActivityFeed**
|
||
|
|
- **Purpose:** Real-time stream of workspace events on dashboard right panel
|
||
|
|
- **Content:** Event type icon, actor name, action description, target link, timestamp
|
||
|
|
- **Actions:** Click event to navigate to related entity, load more (infinite scroll)
|
||
|
|
- **States:** Default, loading, empty
|
||
|
|
- **Variants:** Dashboard panel (compact, last 20 events), full page (all events, filterable)
|
||
|
|
- **Accessibility:** Role="feed", aria-label for each entry, keyboard navigation
|
||
|
|
- **Implementation:** Custom component using existing `timeline` styling, Inertia polling or WebSocket for real-time
|
||
|
|
|
||
|
|
**6. BulkActionBar**
|
||
|
|
- **Purpose:** Contextual toolbar that appears when multiple table rows are selected
|
||
|
|
- **Content:** Selected count, available actions (notify clients, reassign, change status, archive)
|
||
|
|
- **Actions:** Execute bulk action with confirmation dialog
|
||
|
|
- **States:** Hidden (no selection), visible (with selection count), processing (loading state during action)
|
||
|
|
- **Accessibility:** Role="toolbar", announced via aria-live when appearing, keyboard operable
|
||
|
|
- **Implementation:** Fixed bottom bar or sticky top bar, appears on row selection, uses existing `button` + `dropdown-menu`
|
||
|
|
|
||
|
|
**7. StatusBadge**
|
||
|
|
- **Purpose:** Visual indicator for declaration status throughout the app
|
||
|
|
- **Content:** Status label text, optional icon
|
||
|
|
- **States/Variants:** Maps to declaration lifecycle — created (gray), en_attente_client (blue), en_cours (amber), termine (green), ferme (teal), archive (muted), overdue (red pulsing)
|
||
|
|
- **Accessibility:** Status text readable by screen readers, color not sole indicator (icon + text)
|
||
|
|
- **Implementation:** Extend existing `badge` with CVA status variants using OKLCH semantic tokens
|
||
|
|
|
||
|
|
**8. FileUploadZone**
|
||
|
|
- **Purpose:** Document upload area for client portal and internal document management
|
||
|
|
- **Content:** Drop zone area, file type/size constraints, upload progress, uploaded files list
|
||
|
|
- **Actions:** Drag & drop, click to browse, remove uploaded file, retry failed upload
|
||
|
|
- **States:** Default (empty), drag-over (highlighted), uploading (progress), success (file listed), error (retry option)
|
||
|
|
- **Variants:** Portal (large, single-purpose), inline (compact, within declaration detail)
|
||
|
|
- **Accessibility:** Role="button" for click-to-browse, keyboard operable, progress announced via aria-live
|
||
|
|
- **Implementation:** Custom component with native drag-and-drop API, chunked upload for large files
|
||
|
|
|
||
|
|
**9. EmptyState**
|
||
|
|
- **Purpose:** Placeholder for lists/pages with no data, guiding users toward action
|
||
|
|
- **Content:** Illustration (optional), title, description, primary action button
|
||
|
|
- **Variants:** Table empty (inline), page empty (centered), first-time (onboarding-oriented)
|
||
|
|
- **Accessibility:** Descriptive text, action button focusable
|
||
|
|
- **Implementation:** Simple layout component with slots for icon, text, and action
|
||
|
|
|
||
|
|
**10. DeclarationStatusStepper**
|
||
|
|
- **Purpose:** Visual progress indicator showing where a declaration is in its lifecycle
|
||
|
|
- **Content:** All status steps with current step highlighted, timestamps for completed steps
|
||
|
|
- **States:** Each step can be: completed, current, upcoming, or skipped
|
||
|
|
- **Accessibility:** Role="progressbar" or ordered list with aria-current
|
||
|
|
- **Implementation:** Horizontal stepper using existing `timeline` tokens, shown in declaration detail view
|
||
|
|
|
||
|
|
### Component Implementation Strategy
|
||
|
|
|
||
|
|
**Design Token Integration:**
|
||
|
|
- All custom components use OKLCH color tokens from `app.css` — no hardcoded colors
|
||
|
|
- CVA (Class Variance Authority) for all component variants — consistent with shadcn-vue patterns
|
||
|
|
- Tailwind CSS 4 utility classes for layout and spacing — no custom CSS unless necessary
|
||
|
|
- Dark mode support via existing `dark:` variants in all new components
|
||
|
|
|
||
|
|
**Composition Pattern:**
|
||
|
|
- Custom components are composed from shadcn-vue primitives where possible (StatCard wraps Card, StatusBadge extends Badge, FilterBar combines Input + Combobox + Select)
|
||
|
|
- Reuse reka-ui accessibility primitives (focus management, keyboard navigation, ARIA attributes)
|
||
|
|
- TypeScript strict mode with proper prop typing and emits
|
||
|
|
|
||
|
|
**State Management:**
|
||
|
|
- Component state managed locally (Vue 3 Composition API `ref`/`computed`)
|
||
|
|
- Server state via Inertia.js props — no client-side data fetching library needed
|
||
|
|
- Shared UI state (sidebar collapsed, compact mode) via composables or Pinia store
|
||
|
|
|
||
|
|
### Implementation Roadmap
|
||
|
|
|
||
|
|
**Phase 1 — Core (MVP Dashboard & Lists):**
|
||
|
|
- Install: `table`, `combobox`, `toast/sonner`, `calendar`, `popover`, `progress`
|
||
|
|
- Build: StatCard, DataTable, FilterBar, StatusBadge, EmptyState, BulkActionBar
|
||
|
|
- These components are required for Journey 1 (Dashboard) and Journey 2 (Worker Workflow)
|
||
|
|
|
||
|
|
**Phase 2 — Client Portal & Communication:**
|
||
|
|
- Build: FileUploadZone, DeclarationStatusStepper
|
||
|
|
- Enhance: ActivityFeed, DateRangePicker
|
||
|
|
- These components are required for Journey 3 (Client Upload) and Journey 4 (Declaration Lifecycle)
|
||
|
|
|
||
|
|
**Phase 3 — Power Features & Polish:**
|
||
|
|
- Install: `command` (command palette), `switch`
|
||
|
|
- Build: SavedFilterPresets, KeyboardShortcutHelper, CompactModeToggle
|
||
|
|
- Enhance: DataTable (column resizing, pinned columns), FilterBar (saved presets)
|
||
|
|
- These components optimize efficiency for power users processing high volumes
|
||
|
|
|
||
|
|
## UX Consistency Patterns
|
||
|
|
|
||
|
|
### Button Hierarchy
|
||
|
|
|
||
|
|
**Primary Action (one per screen section):**
|
||
|
|
- Solid fill with primary color (`bg-primary text-primary-foreground`)
|
||
|
|
- Used for: Create declaration, Save changes, Submit, Send notification
|
||
|
|
- Always positioned bottom-right of forms, or top-right of page headers for creation actions
|
||
|
|
|
||
|
|
**Secondary Action:**
|
||
|
|
- Outline variant (`border border-input bg-background`)
|
||
|
|
- Used for: Cancel, Back, Export, secondary options alongside a primary
|
||
|
|
- Positioned left of primary action in button groups
|
||
|
|
|
||
|
|
**Destructive Action:**
|
||
|
|
- Destructive variant (`bg-destructive text-destructive-foreground`)
|
||
|
|
- Used for: Delete, Archive (with confirmation), Remove team member
|
||
|
|
- Always requires confirmation dialog — never immediate
|
||
|
|
|
||
|
|
**Ghost/Inline Action:**
|
||
|
|
- Ghost variant (no border, no background, text only)
|
||
|
|
- Used for: Inline table row actions, "View all" links, tertiary options
|
||
|
|
- Appears on hover in table rows via dropdown-menu trigger
|
||
|
|
|
||
|
|
**Icon-Only Action:**
|
||
|
|
- Icon button with tooltip (mandatory for accessibility)
|
||
|
|
- Used for: Nudge (bell icon), Refresh, Toggle sidebar, Quick actions
|
||
|
|
- Always paired with `tooltip` for label — never icon-only without tooltip
|
||
|
|
|
||
|
|
**Button Sizing:**
|
||
|
|
- Default size for all primary UI actions
|
||
|
|
- `size="sm"` only inside table rows and compact toolbars
|
||
|
|
- `size="lg"` only for client portal CTA buttons (mobile touch targets)
|
||
|
|
|
||
|
|
### Feedback Patterns
|
||
|
|
|
||
|
|
**Toast Notifications (non-blocking):**
|
||
|
|
- **Success:** Green check icon + message — auto-dismiss after 4 seconds
|
||
|
|
- Used for: Status updated, Nudge sent, Declaration created, Document uploaded
|
||
|
|
- **Error:** Red X icon + message — persists until dismissed
|
||
|
|
- Used for: Save failed, Upload failed, Permission denied
|
||
|
|
- **Info:** Blue info icon + message — auto-dismiss after 5 seconds
|
||
|
|
- Used for: New document received, Declaration reassigned to you
|
||
|
|
- **Warning:** Amber warning icon + message — persists until dismissed
|
||
|
|
- Used for: Deadline approaching, Bulk action affects X items
|
||
|
|
- Position: Top-right, stacked, max 3 visible at once
|
||
|
|
|
||
|
|
**Inline Validation (forms):**
|
||
|
|
- Real-time validation on blur (not on keystroke)
|
||
|
|
- Error text appears below the field in `text-destructive` with shake animation
|
||
|
|
- Success state: Green check icon inside the input (not below)
|
||
|
|
- Server-side errors (from Laravel Form Request) displayed inline on the relevant field via Inertia error bags
|
||
|
|
|
||
|
|
**Confirmation Dialogs:**
|
||
|
|
- Required for: Delete, Archive, Bulk actions, Reassignment
|
||
|
|
- Not required for: Status updates, Nudges, Single notifications
|
||
|
|
- Dialog content: Clear description of what will happen, affected item count for bulk actions
|
||
|
|
- Two buttons: Cancel (secondary, left) + Confirm (primary or destructive, right)
|
||
|
|
- Destructive confirmations use red confirm button with action verb ("Delete 5 declarations" not "OK")
|
||
|
|
|
||
|
|
**Loading States:**
|
||
|
|
- **Initial page load:** Skeleton screens matching the layout structure (StatCard skeletons, table row skeletons)
|
||
|
|
- **Action processing:** Button shows spinner + disabled state, label changes to "Saving..." / "Sending..."
|
||
|
|
- **Table refresh:** Subtle opacity reduction (0.6) on table body while loading, no full skeleton replacement
|
||
|
|
- **File upload:** Progress bar with percentage inside FileUploadZone
|
||
|
|
|
||
|
|
**Empty States:**
|
||
|
|
- Every list/table has a designed empty state via `EmptyState` component
|
||
|
|
- Includes: Relevant illustration/icon, explanatory text, primary action button
|
||
|
|
- Examples: "No declarations yet — Create your first declaration", "No overdue items — You're on track!"
|
||
|
|
|
||
|
|
### Form Patterns
|
||
|
|
|
||
|
|
**Form Layout:**
|
||
|
|
- Single-column layout for all forms (max-width 640px centered)
|
||
|
|
- Labels above inputs (not inline/floating) — better for scanning and accessibility
|
||
|
|
- Required fields: No asterisk — all fields required by default; mark optional fields with "(optional)" suffix
|
||
|
|
- Field grouping: Use `separator` + section headings for logical groups (Client Info, Declaration Details, etc.)
|
||
|
|
|
||
|
|
**Input Patterns:**
|
||
|
|
- Text inputs: shadcn-vue `input` with `label` above
|
||
|
|
- Select/dropdown: shadcn-vue `select` for short lists (<10 items), `combobox` for searchable lists (>10 items)
|
||
|
|
- Date selection: `DateRangePicker` for ranges, single `calendar` popover for individual dates
|
||
|
|
- File upload: `FileUploadZone` component — drag-and-drop + click-to-browse
|
||
|
|
|
||
|
|
**Form Submission:**
|
||
|
|
- Inertia.js `useForm()` for all form handling — provides processing state, errors, and recentlySuccessful
|
||
|
|
- Submit button disables during processing with spinner
|
||
|
|
- On success: Toast notification + redirect (for create) or toast + stay on page (for edit)
|
||
|
|
- On error: Scroll to first error field, focus it, display inline error messages
|
||
|
|
|
||
|
|
**Inline Editing:**
|
||
|
|
- Status changes on declarations: Inline dropdown, no modal, immediate save
|
||
|
|
- Quick edits: Click to edit pattern only for simple fields (declaration type, deadline date)
|
||
|
|
- Complex edits: Always navigate to edit form (client details, user profiles)
|
||
|
|
|
||
|
|
### Navigation Patterns
|
||
|
|
|
||
|
|
**Sidebar Navigation:**
|
||
|
|
- Full sidebar (240px) with grouped sections: Dashboard, Clients, Declarations, Archive, Team, Settings
|
||
|
|
- Active section highlighted with primary color background
|
||
|
|
- Collapsible groups for sub-items (e.g., Settings → Profile, Team, Workspace, Appearance)
|
||
|
|
- Collapse to icon-only (64px) on smaller screens, overlay drawer on mobile (<768px)
|
||
|
|
- WorkspaceSwitcher at the top of sidebar
|
||
|
|
|
||
|
|
**Breadcrumbs:**
|
||
|
|
- Always visible below the page header: Dashboard / Clients / Client Name / Declaration
|
||
|
|
- Last item is the current page (non-clickable, muted text)
|
||
|
|
- All previous items are clickable links
|
||
|
|
- Mobile: Show only current + parent (collapse middle items with "...")
|
||
|
|
|
||
|
|
**Page Headers:**
|
||
|
|
- Every page has a consistent header: Page title (h1) + description (optional) + primary action button (top-right)
|
||
|
|
- Examples: "Declarations" + "Create Declaration" button, "Client: Benani SARL" + "Edit" button
|
||
|
|
|
||
|
|
**Back Navigation:**
|
||
|
|
- Browser back button works correctly (Inertia.js handles history)
|
||
|
|
- No explicit "Back" buttons in the UI — breadcrumbs serve this purpose
|
||
|
|
- Modals/sheets close with Escape key and clicking outside
|
||
|
|
|
||
|
|
**Deep Linking:**
|
||
|
|
- Every notification, nudge, and alert links directly to the relevant entity
|
||
|
|
- URL structure reflects navigation hierarchy: `/clients/123/declarations/456`
|
||
|
|
- Sharing a URL always works — no client-side routing state that breaks on refresh
|
||
|
|
|
||
|
|
### Additional Patterns
|
||
|
|
|
||
|
|
**Table Interaction Patterns:**
|
||
|
|
- **Row hover:** Subtle background highlight + inline action icons appear (right side)
|
||
|
|
- **Row click:** Navigates to detail page (entire row is clickable except action buttons)
|
||
|
|
- **Sort:** Click column header to sort — ascending → descending → unsorted. Active sort shown with arrow icon
|
||
|
|
- **Selection:** Checkbox column (first column) for multi-select. Header checkbox toggles all visible rows
|
||
|
|
- **Pagination:** Bottom of table — "Showing 1-25 of 142" + page navigation. Default 25 rows per page, configurable (25/50/100)
|
||
|
|
- **Sticky header:** Table header sticks when scrolling long lists
|
||
|
|
|
||
|
|
**Search & Filter Patterns:**
|
||
|
|
- **FilterBar** always visible above data tables (not hidden behind a toggle)
|
||
|
|
- Filters apply instantly on change (no "Apply" button needed)
|
||
|
|
- Active filters shown as removable chips/badges below the filter bar
|
||
|
|
- "Clear all filters" link when any filter is active
|
||
|
|
- URL query parameters reflect filter state — shareable filtered views
|
||
|
|
|
||
|
|
**Date & Time Patterns:**
|
||
|
|
- Dates displayed in Moroccan format: DD/MM/YYYY
|
||
|
|
- Relative time for recent events: "il y a 2 heures", "hier"
|
||
|
|
- Deadlines always show absolute date + relative countdown: "20/03/2026 (dans 5 jours)"
|
||
|
|
- Deadline color coding consistent everywhere: Green (>7d), Amber (3-7d), Red (<3d), Pulsing red (overdue)
|
||
|
|
|
||
|
|
**Notification Patterns:**
|
||
|
|
- **In-app:** Badge count on sidebar bell icon, dropdown panel with recent notifications, mark as read
|
||
|
|
- **Email:** Triggered by: client document requests, nudges (configurable), deadline warnings (configurable)
|
||
|
|
- **Notification grouping:** Multiple events for same entity grouped ("3 clients uploaded documents")
|
||
|
|
- **Quiet hours:** No email notifications outside business hours (configurable per workspace)
|
||
|
|
|
||
|
|
**Error & Recovery Patterns:**
|
||
|
|
- **Network error:** Toast with "Connection lost — changes will sync when reconnected" (Inertia handles gracefully)
|
||
|
|
- **Permission denied:** Redirect to dashboard with toast "You don't have permission to access this page"
|
||
|
|
- **404 Not Found:** Custom error page with "Go to Dashboard" link
|
||
|
|
- **Server error (500):** Custom error page with "Try again" + "Contact support" options
|
||
|
|
- **Session expired:** Redirect to login with "Your session expired — please log in again" message, preserving intended destination URL
|
||
|
|
|
||
|
|
## Responsive Design & Accessibility
|
||
|
|
|
||
|
|
### Responsive Strategy
|
||
|
|
|
||
|
|
**Desktop (Primary — Firm Staff):**
|
||
|
|
- Full "Command Professional" layout: 240px sidebar + main content area
|
||
|
|
- Two-column dashboard: KPI cards + table left, activity feed + alerts right
|
||
|
|
- Data tables at full width with all columns visible
|
||
|
|
- Inline row actions on hover, keyboard shortcuts for power users
|
||
|
|
- Multi-panel views where appropriate (e.g., declaration detail with document preview sidebar)
|
||
|
|
|
||
|
|
**Tablet (Secondary — Firm Staff on the Go):**
|
||
|
|
- Sidebar collapses to icon-only (64px) by default, expandable on tap
|
||
|
|
- Dashboard KPI cards reflow to 2-column grid
|
||
|
|
- Activity feed moves below the main table (single column)
|
||
|
|
- Tables maintain core columns, hide secondary columns behind a "More" expandable
|
||
|
|
- Touch-optimized: Larger tap targets on action buttons, swipe gestures for table row actions (optional)
|
||
|
|
|
||
|
|
**Mobile (Primary — Client Portal / Secondary — Firm Staff):**
|
||
|
|
- **Client portal:** Single-column, mobile-first layout — this is the primary device for Hassan-type users
|
||
|
|
- **Firm app:** Sidebar becomes overlay drawer (hamburger trigger in top-left)
|
||
|
|
- KPI cards stack single-column, full width
|
||
|
|
- Tables transform to card-based list view — each row becomes a card showing key fields
|
||
|
|
- Bottom sheet for actions instead of dropdown menus (better mobile UX)
|
||
|
|
- Large touch targets: minimum 44x44px for all interactive elements
|
||
|
|
- Camera integration for document upload (direct photo capture)
|
||
|
|
|
||
|
|
**Device Priority Matrix:**
|
||
|
|
|
||
|
|
| User Role | Primary Device | Secondary Device |
|
||
|
|
|---|---|---|
|
||
|
|
| Owner (Karim) | Desktop | Tablet/Mobile (checking dashboard) |
|
||
|
|
| Manager (Rachid) | Desktop | Mobile (nudges, quick reassignment) |
|
||
|
|
| Worker (Fatima) | Desktop | Rarely mobile |
|
||
|
|
| Client (Hassan) | **Mobile** | Desktop |
|
||
|
|
| Admin (Saad) | Desktop | — |
|
||
|
|
|
||
|
|
### Breakpoint Strategy
|
||
|
|
|
||
|
|
**Tailwind CSS 4 Breakpoints (standard):**
|
||
|
|
|
||
|
|
| Breakpoint | Width | Layout Behavior |
|
||
|
|
|---|---|---|
|
||
|
|
| `sm` | 640px+ | Client portal: content max-width, centered |
|
||
|
|
| `md` | 768px+ | Sidebar visible (icon-only), tables show core columns |
|
||
|
|
| `lg` | 1024px+ | Sidebar expanded (240px), full table columns, two-column dashboard |
|
||
|
|
| `xl` | 1280px+ | Extra breathing room, wider tables, optional third column |
|
||
|
|
| `2xl` | 1536px+ | Max content width (1400px centered), prevent ultra-wide line lengths |
|
||
|
|
|
||
|
|
**Mobile-First Approach:**
|
||
|
|
- Base styles target mobile (< 640px)
|
||
|
|
- Progressive enhancement via `sm:`, `md:`, `lg:` prefixes
|
||
|
|
- Client portal designed mobile-first — desktop is the enhanced version
|
||
|
|
- Firm app designed desktop-first conceptually, but implemented mobile-first in code
|
||
|
|
|
||
|
|
**Key Responsive Behaviors:**
|
||
|
|
|
||
|
|
| Component | Mobile (<768px) | Tablet (768-1023px) | Desktop (1024px+) |
|
||
|
|
|---|---|---|---|
|
||
|
|
| Sidebar | Overlay drawer | Icon-only (64px) | Full (240px) |
|
||
|
|
| KPI Cards | 1 column stack | 2 column grid | 4 column grid (auto-fill) |
|
||
|
|
| DataTable | Card list view | Table with fewer columns | Full table with all columns |
|
||
|
|
| FilterBar | Collapsed (expandable toggle) | Single row, scrollable | Full row, all filters visible |
|
||
|
|
| BulkActionBar | Fixed bottom sheet | Fixed bottom bar | Sticky top bar |
|
||
|
|
| Activity Feed | Hidden (accessible via tab) | Below main content | Right sidebar panel |
|
||
|
|
| Modals/Dialogs | Full-screen sheet (bottom-up) | Centered dialog | Centered dialog |
|
||
|
|
|
||
|
|
### Accessibility Strategy
|
||
|
|
|
||
|
|
**Target Compliance: WCAG 2.1 Level AA**
|
||
|
|
- This is the industry standard and appropriate for a B2B SaaS product
|
||
|
|
- Level AAA is not targeted but specific AAA criteria will be met where practical (e.g., enhanced contrast)
|
||
|
|
- Morocco does not have specific web accessibility legislation, but AA compliance ensures usability for all users and future-proofs against potential regulation
|
||
|
|
|
||
|
|
**Color & Contrast:**
|
||
|
|
- Minimum 4.5:1 contrast ratio for normal text (< 18px)
|
||
|
|
- Minimum 3:1 contrast ratio for large text (>= 18px bold or >= 24px)
|
||
|
|
- OKLCH color tokens already tested for contrast compliance in light and dark modes
|
||
|
|
- Color is never the sole indicator of status — always paired with icon and/or text label
|
||
|
|
- Deadline color gradient (green → amber → red) supplemented by text labels ("On track", "Due soon", "Overdue")
|
||
|
|
|
||
|
|
**Keyboard Navigation:**
|
||
|
|
- All interactive elements reachable via Tab key
|
||
|
|
- Logical tab order following visual layout (left-to-right, top-to-bottom)
|
||
|
|
- Skip-to-content link as first focusable element on every page
|
||
|
|
- Visible focus indicators: 2px ring using `ring-ring` token (already configured in shadcn-vue)
|
||
|
|
- Escape key closes modals, sheets, dropdowns, and popovers
|
||
|
|
- Table keyboard navigation: Arrow keys for row/cell navigation within DataTable
|
||
|
|
- Custom keyboard shortcuts documented and discoverable (Phase 3)
|
||
|
|
|
||
|
|
**Screen Reader Support:**
|
||
|
|
- Semantic HTML5 elements: `<nav>`, `<main>`, `<aside>`, `<header>`, `<footer>`, `<section>`
|
||
|
|
- ARIA landmarks: `role="navigation"`, `role="main"`, `role="complementary"` for sidebar
|
||
|
|
- Dynamic content updates: `aria-live="polite"` for toast notifications, activity feed updates, and filter result counts
|
||
|
|
- Form labels: Every input has an associated `<label>` — no placeholder-only fields
|
||
|
|
- Table headers: `<th scope="col">` for column headers, `aria-sort` for sortable columns
|
||
|
|
- reka-ui (shadcn-vue foundation) provides ARIA patterns for all primitives (dialog, combobox, tabs, etc.)
|
||
|
|
|
||
|
|
**Touch & Motor Accessibility:**
|
||
|
|
- Minimum touch target: 44x44px (WCAG 2.5.5 Target Size)
|
||
|
|
- Adequate spacing between interactive elements (minimum 8px gap)
|
||
|
|
- No time-dependent interactions — all actions wait for user input
|
||
|
|
- Drag-and-drop (file upload) always has click-to-browse alternative
|
||
|
|
- No complex gestures required — all functionality accessible via simple tap/click
|
||
|
|
|
||
|
|
### Testing Strategy
|
||
|
|
|
||
|
|
**Responsive Testing:**
|
||
|
|
- **Browser matrix:** Chrome (primary), Firefox, Safari (critical for iOS client portal), Edge
|
||
|
|
- **Device testing:** Test on actual Android and iOS devices for client portal — emulators are insufficient for touch/camera behavior
|
||
|
|
- **Key test scenarios:**
|
||
|
|
- Client portal upload flow on iPhone Safari and Android Chrome
|
||
|
|
- Dashboard KPI → filtered table flow on tablet
|
||
|
|
- Table-to-card transformation at mobile breakpoint
|
||
|
|
- Sidebar collapse/expand transitions
|
||
|
|
|
||
|
|
**Accessibility Testing:**
|
||
|
|
- **Automated (CI pipeline):** axe-core via Playwright for every PR — catches ~30% of accessibility issues automatically
|
||
|
|
- **Manual keyboard testing:** Tab through every page flow monthly — verify logical order and focus management
|
||
|
|
- **Screen reader testing:** VoiceOver (macOS/iOS) quarterly for critical flows (dashboard, declaration creation, client portal upload)
|
||
|
|
- **Color contrast:** Verified via OKLCH token definitions — re-verify when adding new semantic colors
|
||
|
|
- **Reduced motion:** Respect `prefers-reduced-motion` media query — disable animations and transitions for users who prefer it
|
||
|
|
|
||
|
|
**User Acceptance:**
|
||
|
|
- Include Moroccan fiduciary firm staff in usability testing (Karim/Rachid/Fatima personas)
|
||
|
|
- Test client portal with non-technical business owners (Hassan persona) on their actual devices
|
||
|
|
- Validate French/Arabic text rendering doesn't break layouts (text expansion for French, RTL considerations for future Arabic support)
|
||
|
|
|
||
|
|
### Implementation Guidelines
|
||
|
|
|
||
|
|
**Responsive Development:**
|
||
|
|
- Use Tailwind CSS 4 responsive prefixes (`sm:`, `md:`, `lg:`) — no custom media queries unless absolutely necessary
|
||
|
|
- CSS Grid for dashboard layouts (`grid-cols-1 md:grid-cols-2 lg:grid-cols-4`)
|
||
|
|
- Flexbox for component-level layout (button groups, filter bars, card content)
|
||
|
|
- `max-w-screen-xl mx-auto` on main content to prevent ultra-wide layouts
|
||
|
|
- Images: Use `<img>` with `srcset` for responsive images; SVG for icons (Lucide)
|
||
|
|
- Test all layouts with long French text content — French is ~20% longer than English equivalents
|
||
|
|
|
||
|
|
**Accessibility Development:**
|
||
|
|
- Semantic HTML first — ARIA only when native semantics are insufficient
|
||
|
|
- `import type` for TypeScript type-only imports (per project coding rules)
|
||
|
|
- Every custom component must pass axe-core automated checks before merge
|
||
|
|
- Focus trap for modals/dialogs (provided by reka-ui `Dialog` primitive)
|
||
|
|
- Skip link: `<a href="#main-content" class="sr-only focus:not-sr-only">Skip to content</a>` in AppLayout
|
||
|
|
- Announce dynamic changes: Use `aria-live` regions for toast notifications, filter result counts ("Showing 12 of 142 declarations"), and real-time updates
|
||
|
|
- `prefers-reduced-motion`: Wrap all CSS transitions/animations in `@media (prefers-reduced-motion: no-preference)` or use Tailwind's `motion-safe:` prefix
|
||
|
|
- `prefers-color-scheme`: Already handled by existing dark mode toggle — respect system preference as default
|