UX/UI Redesign, Dashboard & Accessibility
New Features
Dashboard
- Domain Health Row — three live status cards (Data Protection, Cybersecurity, Risk Management) appear above the dashboard tab switcher; clicking a card switches to the corresponding tab
- IAP KPI card — now shows the non-compliant member count, colour-coded (amber/red), with a direct link to IAP admin
- Needs Attention panel items deep-link directly to the individual task
- TIA “at risk” badge in the dashboard header — displays the count of non-authorised transfers or ”✓ All permitted”
Webhooks
- New Last delivery column in the webhooks table showing the most recent Svix attempt status and timestamp (success / pending / failed)
Enhancements
Design System
- Direction B design language applied across all modules — unified card shell, panel headers, table header typography, tab bar, and hover states (All Tasks, RPA, TIA, PIA, CSC, RM, IAP, Dashboard)
- Module Create buttons and empty-state CTAs migrated from DaisyUI to Shadcn
<Button> ModuleBadgerewritten as a pure Tailwind component; rendered inline in All Tasks and the Dashboard task matrix- Module page headings with record count pill added to RPA, TIA, PIA, RM, and IAP
- Comments redesign: single-column layout, hover-reveal edit/delete, Direction B typography
- IAP completion summary banner added above the course grid
Risk Management
- RM table header redesigned — replaced rotated
VerticalHeaderwith a two-row grouped header (Raw Risk / Treatment / Target Risk / Current Risk) for improved readability
Cybersecurity Controls
StatusesTableandSectionRailwrapped in a single Direction B card;SectionRailis hidden below thelg:breakpoint for better mobile usability
All Modules
- All table action columns standardised to icon-only buttons with
aria-label(Tasks, RPA, TIA, PIA, RM, Members, Invitations, IAP admin, Webhooks) - TIA country fields now display translated country names (previously rendered raw lowercase stored keys)
AuditTimelinegeneric component wired to all modules (RPA, TIA, PIA, CSC, RM)
Accessibility (WCAG 2.1 AA)
<html lang>attribute set from SSR locale on every page- All Chart.js canvases wrapped in
role="img"containers with descriptivearia-label - Mobile sidebar (
Drawer) rewritten as an accessible dialog:role="dialog",aria-modal, focus-on-open, Escape key, Tab focus trap,aria-hiddenbackdrop - Dashboard tab bar wired with full ARIA tab pattern (
tablist,tab,tabpanel) - Notification bell
aria-labelis dynamic with unread count; badge carriesaria-hidden - Webhook form: events fieldset wrapped in
<fieldset><legend>; inputs wired witharia-invalid,aria-describedby, androle="alert"error messages - All icon-only buttons and interactive cards carry
aria-label; active domain health cards carryaria-pressed - External navigation links include a visually-hidden “(opens in new tab)” label
- Content text colour raised to meet 4.5contrast ratio across KPI strip, task analysis, risk analysis, and webhooks table
Billing
- Monthly / Annual billing toggle with a 20% discount on annual plans
- Premium: €15.20/mo billed monthly · €182.40/yr billed annually
- Ultimate: €39.20/mo billed monthly · €470.40/yr billed annually
- Annual billing stored on the subscription (
isAnnualfield); next invoice date advances 12 months instead of 1 - Payment card reflects the annual discount, shows “/yr” billing cycle and “Annual” badge
- Pricing page redesigned — “Most Popular” badge on Premium, plan descriptions, colour-coded feature checkmarks
- Post-request confirmation toast now shown in all 7 supported languages
Mobile & Responsive
- Teams table:
overflow-x-autoinner wrapper added for horizontal scrolling on small screens - Risk matrix chart: wrapped in
overflow-x-autoto allow horizontal scrolling on mobile - All Tasks toolbar: stacks vertically on mobile, aligns inline on
lg:+ - Task filter dropdowns:
flex-1 min-w-[150px]applied so selectors share width evenly on narrow viewports - All remaining tables audited against the nested two-div overflow pattern
Translations & Internationalisation
- Italian, Japanese, and Portuguese added as fully supported locales — 880+ keys translated per language across all modules (Tasks, RPA, TIA, PIA, CSC, RM, IAP, Dashboard, Settings, Fleet, Auth)
- Language switcher added to Profile → Account settings; all 7 locales are now selectable in-app without touching the URL
iap.jsonnamespace created for all 7 locales; dashboard labels (“Your completion”, “Total”, “Completed”, “In progress”) now translate correctly- Hardcoded English labels replaced with
t()calls inCscStatusBadge,CompletionResultsChart, andStatusResultsChart - Dashboard task matrix column headers migrated to i18n keys
- Domain health card tab-switch
aria-labels fully translated across all 7 locales - CSC bulk-action toast messages split into distinct keys with proper
{{count}}/{{status}}interpolation
API
PUT /api/teams/{slug}/csc(single control status update) added to OpenAPI spec — previously undocumented;public/openapi.jsonregenerated
Testing
- 62 Jest unit and API handler tests added: status-key regression guard, CSC helper invariants, dashboard counting logic, full CRUD coverage for
/tasksand/tasks/[taskNumber], and both CSC endpoints - 3 Playwright E2E test suites added: dashboard task matrix + tab switching, task list / kanban usability, CSC bulk status change and task assignment
Fixes
- TIA: Legal Analysis column was rendering
DataExporterinstead ofLawImporterCountry - PIA: First column header labelled with the wrong translation key
- CSC: Dark mode inactive tabs appeared selected due to unconditional
dark:text-slate-200 - RM: Asset Owner column showed “Not found” due to invalid Map bracket access; fixed to
.get() - RM: Unstable row keys (
key={idx}) changed tokey={task.id} - CSC: Bulk status change was updating only the last selected control — root cause was
mutateStatuses()called after every individual write, causing SWR re-fetches to race with Prisma; fixed by writing all controls first, then mutating once - CSC: Task assignment required a full page refresh to appear; fixed by
await-ingmutateTasks - Dashboard: Task matrix status counters showed 0 for In Progress and In Review —
STATUS_COLSkeys mismatched DB-stored values; fixed across dashboard,TeamTasksAnalysis,GlobalSearch, andTaskKanbanBoard
Record of Processing Activities
Transfer Impact Assessment
Privacy Impact Assessment
Cybersecurity Controls
Cybersecurity Risk Management
Interactive Awareness Program