NDPRDashboard

Read-only compliance dashboard. Visualises a ComplianceReport from getComplianceScore() with an overall ring, per-module cards, and a prioritised recommendations list.

Overview

NDPRDashboardis a presentational component for the toolkit's compliance scoring engine. Pass it a ComplianceReport — the typed object produced by getComplianceScore(input) — and it renders:

  • An overall score ring (0–100) with a coloured rating badge (excellent / good / needs-work / critical).
  • A 2×4 grid of per-module cards (consent, DSR, DPIA, breach, policy, lawful basis, cross-border, ROPA) each with a score and gap count.
  • A prioritised recommendations list, capped at maxRecommendations (default 5).

Quickstart

import { NDPRDashboard, getComplianceScore } from '@tantainnovative/ndpr-toolkit';
import type { ComplianceInput } from '@tantainnovative/ndpr-toolkit';

const input: ComplianceInput = {
  consent: {
    hasConsentMechanism: true,
    hasPurposeSpecification: true,
    hasWithdrawalMechanism: true,
    hasMinorProtection: false,
    consentRecordsRetained: true,
  },
  dsr: {
    hasRequestMechanism: true,
    supportsAccess: true,
    supportsRectification: true,
    supportsErasure: true,
    supportsPortability: false,
    supportsObjection: true,
    responseTimelineDays: 30,
  },
  dpia: {
    conductedForHighRisk: true,
    documentedRisks: true,
    mitigationMeasures: false,
  },
  breach: {
    hasNotificationProcess: true,
    notifiesWithin72Hours: true,
    hasRiskAssessment: true,
    hasRecordKeeping: false,
  },
  policy: {
    hasPrivacyPolicy: true,
    isPubliclyAccessible: true,
    lastUpdated: '2025-01-15',
    coversAllSections: true,
  },
  lawfulBasis: {
    documentedForAllProcessing: true,
    hasLegitimateInterestAssessment: false,
  },
  crossBorder: {
    hasTransferMechanisms: true,
    adequacyAssessed: false,
    ndpcApprovalObtained: false,
  },
  ropa: {
    maintained: true,
    includesAllProcessing: true,
    lastReviewed: '2025-03-01',
  },
};

const report = getComplianceScore(input);

export default function CompliancePage() {
  return (
    <NDPRDashboard
      report={report}
      title="Acme Compliance Overview"
      showRecommendations
      maxRecommendations={5}
    />
  );
}

Preset wrapper: NDPRComplianceDashboard

If you don't want to call getComplianceScore() yourself, use the preset wrapper from /presets. It accepts the raw ComplianceInput, computes the report internally, and delegates rendering to NDPRDashboard:

import { NDPRComplianceDashboard } from '@tantainnovative/ndpr-toolkit/presets';

<NDPRComplianceDashboard
  input={{
    consent: {
      hasConsentMechanism: true,
      hasPurposeSpecification: true,
      hasWithdrawalMechanism: true,
      hasMinorProtection: false,
      consentRecordsRetained: true,
    },
    dsr: {
      hasRequestMechanism: true,
      supportsAccess: true,
      supportsRectification: true,
      supportsErasure: true,
      supportsPortability: false,
      supportsObjection: true,
      responseTimelineDays: 30,
    },
    // …dpia, breach, policy, lawfulBasis, crossBorder, ropa
  }}
  title="Compliance overview"
/>

Same visual surface; the only difference is whether the score computation lives in the preset or in your code.

Props

PropTypeDescription
reportComplianceReportRequired. The report object from getComplianceScore().
titlestringDashboard heading. Defaults to "NDPA Compliance Dashboard".
showRecommendationsbooleanToggle the recommendations section. Defaults to true.
maxRecommendationsnumberCap on the rendered recommendations. Defaults to 5.
classNamesNDPRDashboardClassNamesPer-slot class overrides (root, header, scoreCircle, moduleCard, etc.).
unstyledbooleanStrip all default classes for a true blank slate.

Recommendation shape

Each Recommendation carries enough context to drive a follow-up action: the NDPA section it traces back to, a priority bucket, and an effort estimate.

interface Recommendation {
  module: string;                  // 'consent' | 'dsr' | ...
  key: string;
  label: string;                   // short title
  recommendation: string;          // body
  priority: 'critical' | 'high' | 'medium' | 'low';
  effort: EffortLevel;
  ndpaSection: string;             // e.g. 'Section 25'
}