@tantainnovative/ndpr-toolkit 1.0.10 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -136
  3. package/dist/breach-6z0r-KuE.d.mts +17 -0
  4. package/dist/breach-BFfnvtRk.d.ts +17 -0
  5. package/dist/breach-BtFbDOmV.d.mts +185 -0
  6. package/dist/breach-BtFbDOmV.d.ts +185 -0
  7. package/dist/breach.d.mts +275 -0
  8. package/dist/breach.d.ts +275 -0
  9. package/dist/breach.js +2 -0
  10. package/dist/breach.js.map +1 -0
  11. package/dist/breach.mjs +2 -0
  12. package/dist/breach.mjs.map +1 -0
  13. package/dist/chunk-2SYNHRP6.mjs +2 -0
  14. package/dist/chunk-2SYNHRP6.mjs.map +1 -0
  15. package/dist/chunk-2XHD22J7.mjs +7 -0
  16. package/dist/chunk-2XHD22J7.mjs.map +1 -0
  17. package/dist/chunk-3YCV2BA6.js +2 -0
  18. package/dist/chunk-3YCV2BA6.js.map +1 -0
  19. package/dist/chunk-4A354HL3.js +2 -0
  20. package/dist/chunk-4A354HL3.js.map +1 -0
  21. package/dist/chunk-4DKT6IB6.js +94 -0
  22. package/dist/chunk-4DKT6IB6.js.map +1 -0
  23. package/dist/chunk-5ZBO2UPH.js +2 -0
  24. package/dist/chunk-5ZBO2UPH.js.map +1 -0
  25. package/dist/chunk-6GGGTRDZ.mjs +2 -0
  26. package/dist/chunk-6GGGTRDZ.mjs.map +1 -0
  27. package/dist/chunk-6JFTAYXV.mjs +2 -0
  28. package/dist/chunk-6JFTAYXV.mjs.map +1 -0
  29. package/dist/chunk-6JVYYLS7.js +2 -0
  30. package/dist/chunk-6JVYYLS7.js.map +1 -0
  31. package/dist/chunk-6SGG6WPA.mjs +2 -0
  32. package/dist/chunk-6SGG6WPA.mjs.map +1 -0
  33. package/dist/chunk-AQEGDEQM.js +7 -0
  34. package/dist/chunk-AQEGDEQM.js.map +1 -0
  35. package/dist/chunk-C2IJWCZQ.mjs +2 -0
  36. package/dist/chunk-C2IJWCZQ.mjs.map +1 -0
  37. package/dist/chunk-CMZTI7SG.js +2 -0
  38. package/dist/chunk-CMZTI7SG.js.map +1 -0
  39. package/dist/chunk-DB3JH4DS.mjs +2 -0
  40. package/dist/chunk-DB3JH4DS.mjs.map +1 -0
  41. package/dist/chunk-FFW7RUAG.mjs +94 -0
  42. package/dist/chunk-FFW7RUAG.mjs.map +1 -0
  43. package/dist/chunk-FK3CSFLJ.js +2 -0
  44. package/dist/chunk-FK3CSFLJ.js.map +1 -0
  45. package/dist/chunk-GIV2OHE6.mjs +2 -0
  46. package/dist/chunk-GIV2OHE6.mjs.map +1 -0
  47. package/dist/chunk-GMLNWS2N.mjs +2 -0
  48. package/dist/chunk-GMLNWS2N.mjs.map +1 -0
  49. package/dist/chunk-IQF726GS.js +2 -0
  50. package/dist/chunk-IQF726GS.js.map +1 -0
  51. package/dist/chunk-IWUUVRLJ.js +2 -0
  52. package/dist/chunk-IWUUVRLJ.js.map +1 -0
  53. package/dist/chunk-JUN6YPLL.mjs +72 -0
  54. package/dist/chunk-JUN6YPLL.mjs.map +1 -0
  55. package/dist/chunk-L3FKTBGV.js +72 -0
  56. package/dist/chunk-L3FKTBGV.js.map +1 -0
  57. package/dist/chunk-L52PDW6O.mjs +2 -0
  58. package/dist/chunk-L52PDW6O.mjs.map +1 -0
  59. package/dist/chunk-LI6WJ3LZ.js +2 -0
  60. package/dist/chunk-LI6WJ3LZ.js.map +1 -0
  61. package/dist/chunk-LXRXDTPI.js +2 -0
  62. package/dist/chunk-LXRXDTPI.js.map +1 -0
  63. package/dist/chunk-MQFZHA2D.js +2 -0
  64. package/dist/chunk-MQFZHA2D.js.map +1 -0
  65. package/dist/chunk-OITITR6K.mjs +2 -0
  66. package/dist/chunk-OITITR6K.mjs.map +1 -0
  67. package/dist/chunk-PDJGTQMY.mjs +2 -0
  68. package/dist/chunk-PDJGTQMY.mjs.map +1 -0
  69. package/dist/chunk-PGSA2O5P.mjs +2 -0
  70. package/dist/chunk-PGSA2O5P.mjs.map +1 -0
  71. package/dist/chunk-PM7CMTMB.js +4 -0
  72. package/dist/chunk-PM7CMTMB.js.map +1 -0
  73. package/dist/chunk-PYEX7DFR.mjs +4 -0
  74. package/dist/chunk-PYEX7DFR.mjs.map +1 -0
  75. package/dist/chunk-QKK5S54L.mjs +2 -0
  76. package/dist/chunk-QKK5S54L.mjs.map +1 -0
  77. package/dist/chunk-RB26MIRI.js +2 -0
  78. package/dist/chunk-RB26MIRI.js.map +1 -0
  79. package/dist/chunk-RGYK4VAY.mjs +2 -0
  80. package/dist/chunk-RGYK4VAY.mjs.map +1 -0
  81. package/dist/chunk-RHWW5FDP.js +16 -0
  82. package/dist/chunk-RHWW5FDP.js.map +1 -0
  83. package/dist/chunk-RYZEIDNR.js +2 -0
  84. package/dist/chunk-RYZEIDNR.js.map +1 -0
  85. package/dist/chunk-SLNMKGQ2.mjs +2 -0
  86. package/dist/chunk-SLNMKGQ2.mjs.map +1 -0
  87. package/dist/chunk-SSGJREE3.js +2 -0
  88. package/dist/chunk-SSGJREE3.js.map +1 -0
  89. package/dist/chunk-SWF3YVE5.js +4 -0
  90. package/dist/chunk-SWF3YVE5.js.map +1 -0
  91. package/dist/chunk-T44JQT2O.mjs +2 -0
  92. package/dist/chunk-T44JQT2O.mjs.map +1 -0
  93. package/dist/chunk-TDDAYVKK.js +2 -0
  94. package/dist/chunk-TDDAYVKK.js.map +1 -0
  95. package/dist/chunk-TXBZPCGF.mjs +2 -0
  96. package/dist/chunk-TXBZPCGF.mjs.map +1 -0
  97. package/dist/chunk-UUWVBENC.js +2 -0
  98. package/dist/chunk-UUWVBENC.js.map +1 -0
  99. package/dist/chunk-UYP64PV7.mjs +4 -0
  100. package/dist/chunk-UYP64PV7.mjs.map +1 -0
  101. package/dist/chunk-VMJBW3EF.mjs +2 -0
  102. package/dist/chunk-VMJBW3EF.mjs.map +1 -0
  103. package/dist/chunk-WW3X3ELF.js +2 -0
  104. package/dist/chunk-WW3X3ELF.js.map +1 -0
  105. package/dist/chunk-WWT2ZSNU.mjs +2 -0
  106. package/dist/chunk-WWT2ZSNU.mjs.map +1 -0
  107. package/dist/chunk-XMKA6GVK.mjs +16 -0
  108. package/dist/chunk-XMKA6GVK.mjs.map +1 -0
  109. package/dist/chunk-Y34DQYS7.js +2 -0
  110. package/dist/chunk-Y34DQYS7.js.map +1 -0
  111. package/dist/chunk-ZU73VG3X.js +2 -0
  112. package/dist/chunk-ZU73VG3X.js.map +1 -0
  113. package/dist/consent-CmVzqZUk.d.mts +99 -0
  114. package/dist/consent-CmVzqZUk.d.ts +99 -0
  115. package/dist/consent-DCc5zjXI.d.mts +24 -0
  116. package/dist/consent-DLWb5ota.d.ts +24 -0
  117. package/dist/consent.d.mts +197 -0
  118. package/dist/consent.d.ts +197 -0
  119. package/dist/consent.js +2 -0
  120. package/dist/consent.js.map +1 -0
  121. package/dist/consent.mjs +2 -0
  122. package/dist/consent.mjs.map +1 -0
  123. package/dist/core.d.mts +14 -0
  124. package/dist/core.d.ts +14 -0
  125. package/dist/core.js +2 -0
  126. package/dist/core.js.map +1 -0
  127. package/dist/core.mjs +2 -0
  128. package/dist/core.mjs.map +1 -0
  129. package/dist/cross-border-BrIy1ieh.d.mts +192 -0
  130. package/dist/cross-border-BrIy1ieh.d.ts +192 -0
  131. package/dist/cross-border.d.mts +58 -0
  132. package/dist/cross-border.d.ts +58 -0
  133. package/dist/cross-border.js +2 -0
  134. package/dist/cross-border.js.map +1 -0
  135. package/dist/cross-border.mjs +2 -0
  136. package/dist/cross-border.mjs.map +1 -0
  137. package/dist/dpia-B9ZZJG5a.d.mts +15 -0
  138. package/dist/dpia-fdtTd2DI.d.ts +15 -0
  139. package/dist/dpia-vWfE_9bO.d.mts +137 -0
  140. package/dist/dpia-vWfE_9bO.d.ts +137 -0
  141. package/dist/dpia.d.mts +179 -0
  142. package/dist/dpia.d.ts +179 -0
  143. package/dist/dpia.js +2 -0
  144. package/dist/dpia.js.map +1 -0
  145. package/dist/dpia.mjs +2 -0
  146. package/dist/dpia.mjs.map +1 -0
  147. package/dist/dsr-jq5NUEdz.d.ts +14 -0
  148. package/dist/dsr-pQzQ3H1O.d.mts +128 -0
  149. package/dist/dsr-pQzQ3H1O.d.ts +128 -0
  150. package/dist/dsr-whPkiI0_.d.mts +14 -0
  151. package/dist/dsr.d.mts +192 -0
  152. package/dist/dsr.d.ts +192 -0
  153. package/dist/dsr.js +2 -0
  154. package/dist/dsr.js.map +1 -0
  155. package/dist/dsr.mjs +2 -0
  156. package/dist/dsr.mjs.map +1 -0
  157. package/dist/hooks.d.mts +17 -0
  158. package/dist/hooks.d.ts +17 -0
  159. package/dist/hooks.js +2 -0
  160. package/dist/hooks.js.map +1 -0
  161. package/dist/hooks.mjs +2 -0
  162. package/dist/hooks.mjs.map +1 -0
  163. package/dist/index.d.mts +31 -448
  164. package/dist/index.d.ts +31 -448
  165. package/dist/index.js +1 -190
  166. package/dist/index.js.map +1 -1
  167. package/dist/index.mjs +1 -190
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/lawful-basis-CWtvDG1x.d.mts +112 -0
  170. package/dist/lawful-basis-CWtvDG1x.d.ts +112 -0
  171. package/dist/lawful-basis-D-oXFizg.d.mts +57 -0
  172. package/dist/lawful-basis-v04AhbK2.d.ts +57 -0
  173. package/dist/lawful-basis.d.mts +55 -0
  174. package/dist/lawful-basis.d.ts +55 -0
  175. package/dist/lawful-basis.js +2 -0
  176. package/dist/lawful-basis.js.map +1 -0
  177. package/dist/lawful-basis.mjs +2 -0
  178. package/dist/lawful-basis.mjs.map +1 -0
  179. package/dist/policy.d.mts +195 -0
  180. package/dist/policy.d.ts +195 -0
  181. package/dist/policy.js +2 -0
  182. package/dist/policy.js.map +1 -0
  183. package/dist/policy.mjs +2 -0
  184. package/dist/policy.mjs.map +1 -0
  185. package/dist/privacy-9FcJceMr.d.mts +15 -0
  186. package/dist/privacy-BXz7O2ej.d.ts +15 -0
  187. package/dist/privacy-Ca6te9Ir.d.mts +138 -0
  188. package/dist/privacy-Ca6te9Ir.d.ts +138 -0
  189. package/dist/ropa-BebGfqKQ.d.ts +200 -0
  190. package/dist/ropa-Rb4dsFSz.d.mts +200 -0
  191. package/dist/ropa.d.mts +45 -0
  192. package/dist/ropa.d.ts +45 -0
  193. package/dist/ropa.js +2 -0
  194. package/dist/ropa.js.map +1 -0
  195. package/dist/ropa.mjs +2 -0
  196. package/dist/ropa.mjs.map +1 -0
  197. package/dist/unstyled.d.mts +4 -4
  198. package/dist/unstyled.d.ts +4 -4
  199. package/dist/unstyled.js +1 -1
  200. package/dist/unstyled.js.map +1 -1
  201. package/dist/unstyled.mjs +1 -1
  202. package/dist/unstyled.mjs.map +1 -1
  203. package/dist/useBreach-WrZzJilM.d.mts +99 -0
  204. package/dist/useBreach-vrh_XMpI.d.ts +99 -0
  205. package/dist/useConsent-D0pAfTlb.d.ts +65 -0
  206. package/dist/useConsent-DOt2Njst.d.mts +65 -0
  207. package/dist/useCrossBorderTransfer-D4FQYfFt.d.ts +66 -0
  208. package/dist/useCrossBorderTransfer-TVnY8_UX.d.mts +66 -0
  209. package/dist/useDPIA-DFDHBLSa.d.ts +94 -0
  210. package/dist/useDPIA-FqPofFaV.d.mts +94 -0
  211. package/dist/useDSR-DAqqOBXb.d.ts +74 -0
  212. package/dist/useDSR-OXM5Q9rf.d.mts +74 -0
  213. package/dist/useLawfulBasis-DNQ8YszQ.d.mts +68 -0
  214. package/dist/useLawfulBasis-RILM_xsx.d.ts +68 -0
  215. package/dist/usePrivacyPolicy-CfySfBLS.d.ts +89 -0
  216. package/dist/usePrivacyPolicy-Dit2sFuV.d.mts +89 -0
  217. package/dist/useROPA-Bcs6cRdi.d.ts +64 -0
  218. package/dist/useROPA-nmcSiUYv.d.mts +64 -0
  219. package/package.json +146 -20
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/utils/dpia.ts"],"names":["assessDPIARisk","dpiaResult","riskCounts","highestRiskScore","unmitigatedHighRisks","risk","overallRiskLevel","requiresConsultation","canProceed","recommendations"],"mappings":"aAOO,SAASA,CAAAA,CAAeC,CAAAA,CAK7B,CAEA,IAAMC,EAAa,CACjB,GAAA,CAAK,CAAA,CACL,MAAA,CAAQ,CAAA,CACR,IAAA,CAAM,CAAA,CACN,QAAA,CAAU,CACZ,CAAA,CAGIC,CAAAA,CAAmB,CAAA,CAGjBC,CAAAA,CAAmC,EAAC,CAG1CH,CAAAA,CAAW,KAAA,CAAM,QAAQI,CAAAA,EAAQ,CAE/BH,CAAAA,CAAWG,CAAAA,CAAK,KAAK,CAAA,EAAA,CAGjBA,CAAAA,CAAK,KAAA,CAAQF,IACfA,CAAAA,CAAmBE,CAAAA,CAAK,KAAA,CAAA,CAAA,CAIrBA,CAAAA,CAAK,KAAA,GAAU,MAAA,EAAUA,CAAAA,CAAK,KAAA,GAAU,aAAe,CAACA,CAAAA,CAAK,SAAA,EAChED,CAAAA,CAAqB,IAAA,CAAKC,CAAI,EAElC,CAAC,EAGD,IAAIC,CAAAA,CAEAJ,CAAAA,CAAW,QAAA,CAAW,CAAA,CACxBI,CAAAA,CAAmB,UAAA,CACVJ,CAAAA,CAAW,KAAO,CAAA,EAAMA,CAAAA,CAAW,IAAA,CAAO,CAAA,EAAKA,CAAAA,CAAW,MAAA,CAAS,CAAA,CAC5EI,CAAAA,CAAmB,OACVJ,CAAAA,CAAW,IAAA,CAAO,CAAA,EAAKA,CAAAA,CAAW,MAAA,CAAS,CAAA,CACpDI,CAAAA,CAAmB,QAAA,CAEnBA,EAAmB,KAAA,CAKrB,IAAMC,CAAAA,CAAuBD,CAAAA,GAAqB,MAAA,EAAUA,CAAAA,GAAqB,UAAA,CAI3EE,CAAAA,CAAaJ,EAAqB,MAAA,GAAW,CAAA,CAG7CK,CAAAA,CAA4B,EAAC,CAEnC,OAAIL,CAAAA,CAAqB,MAAA,CAAS,GAChCK,CAAAA,CAAgB,IAAA,CACd,CAAA,8DAAA,EACEL,CAAAA,CAAqB,GAAA,CAAIC,CAAAA,EAAQA,CAAAA,CAAK,WAAW,EAAE,IAAA,CAAK,IAAI,CAC9D,CAAA,CACF,CAAA,CAGEE,CAAAA,EACFE,CAAAA,CAAgB,IAAA,CACd,6IACF,CAAA,CAGEP,CAAAA,CAAW,MAAA,CAAS,CAAA,EACtBO,CAAAA,CAAgB,IAAA,CACd,8EACF,CAAA,CAGEH,IAAqB,KAAA,CACvBG,CAAAA,CAAgB,IAAA,CACd,wGACF,CAAA,CAEAA,CAAAA,CAAgB,IAAA,CACd,uFACF,EAGK,CACL,gBAAA,CAAAH,CAAAA,CACA,oBAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,eAAA,CAAAC,CACF,CACF","file":"chunk-SSGJREE3.js","sourcesContent":["import { DPIAResult, DPIARisk } from '../types/dpia';\n\n/**\n * Assesses the risk level of a DPIA based on the identified risks\n * @param dpiaResult The DPIA result containing risks to assess\n * @returns Assessment result with overall risk level and recommendations\n */\nexport function assessDPIARisk(dpiaResult: DPIAResult): {\n overallRiskLevel: 'low' | 'medium' | 'high' | 'critical';\n requiresConsultation: boolean;\n canProceed: boolean;\n recommendations: string[];\n} {\n // Count risks by level\n const riskCounts = {\n low: 0,\n medium: 0,\n high: 0,\n critical: 0\n };\n \n // Calculate the highest risk score\n let highestRiskScore = 0;\n \n // Track unmitigated high/critical risks\n const unmitigatedHighRisks: DPIARisk[] = [];\n \n // Analyze each risk\n dpiaResult.risks.forEach(risk => {\n // Count by level\n riskCounts[risk.level]++;\n \n // Track highest score\n if (risk.score > highestRiskScore) {\n highestRiskScore = risk.score;\n }\n \n // Track unmitigated high/critical risks\n if ((risk.level === 'high' || risk.level === 'critical') && !risk.mitigated) {\n unmitigatedHighRisks.push(risk);\n }\n });\n \n // Determine overall risk level\n let overallRiskLevel: 'low' | 'medium' | 'high' | 'critical';\n \n if (riskCounts.critical > 0) {\n overallRiskLevel = 'critical';\n } else if (riskCounts.high > 2 || (riskCounts.high > 0 && riskCounts.medium > 3)) {\n overallRiskLevel = 'high';\n } else if (riskCounts.high > 0 || riskCounts.medium > 1) {\n overallRiskLevel = 'medium';\n } else {\n overallRiskLevel = 'low';\n }\n \n // Determine if NDPC consultation is required\n // Under NDPA Section 39, prior consultation with the NDPC is required when residual risk is high\n const requiresConsultation = overallRiskLevel === 'high' || overallRiskLevel === 'critical';\n \n // Determine if processing can proceed\n // Processing can proceed if all high/critical risks are mitigated\n const canProceed = unmitigatedHighRisks.length === 0;\n \n // Generate recommendations\n const recommendations: string[] = [];\n \n if (unmitigatedHighRisks.length > 0) {\n recommendations.push(\n `Mitigate the following high/critical risks before proceeding: ${\n unmitigatedHighRisks.map(risk => risk.description).join(', ')\n }`\n );\n }\n \n if (requiresConsultation) {\n recommendations.push(\n 'Consult with the NDPC (Nigeria Data Protection Commission) before proceeding with this processing activity, as required by NDPA Section 39.'\n );\n }\n \n if (riskCounts.medium > 0) {\n recommendations.push(\n 'Implement additional safeguards to reduce medium-level risks where possible.'\n );\n }\n \n if (overallRiskLevel !== 'low') {\n recommendations.push(\n 'Schedule a review of this DPIA in 6 months to reassess risks and effectiveness of mitigation measures.'\n );\n } else {\n recommendations.push(\n 'Schedule a review of this DPIA in 12 months as part of regular compliance activities.'\n );\n }\n \n return {\n overallRiskLevel,\n requiresConsultation,\n canProceed,\n recommendations\n };\n}\n"]}
@@ -0,0 +1,4 @@
1
+ 'use strict';var l=["consent","contract","legal_obligation","vital_interests","public_interest","legitimate_interests"];function h(e){let s=[];return (!e.id||e.id.trim()==="")&&s.push("Record ID is required."),(!e.name||e.name.trim()==="")&&s.push("Processing activity name is required."),(!e.description||e.description.trim()==="")&&s.push("Processing description is required."),e.controllerDetails?((!e.controllerDetails.name||e.controllerDetails.name.trim()==="")&&s.push("Controller name is required."),(!e.controllerDetails.contact||e.controllerDetails.contact.trim()==="")&&s.push("Controller contact is required."),(!e.controllerDetails.address||e.controllerDetails.address.trim()==="")&&s.push("Controller address is required.")):s.push("Controller details are required."),(!e.lawfulBasis||!l.includes(e.lawfulBasis))&&s.push("A valid lawful basis must be specified (NDPA Section 25)."),(!e.lawfulBasisJustification||e.lawfulBasisJustification.trim()==="")&&s.push("Lawful basis justification is required to demonstrate compliance."),(!e.purposes||e.purposes.length===0)&&s.push("At least one processing purpose must be specified."),(!e.dataCategories||e.dataCategories.length===0)&&s.push("At least one data category must be specified."),(!e.dataSubjectCategories||e.dataSubjectCategories.length===0)&&s.push("At least one data subject category must be specified."),(!e.recipients||e.recipients.length===0)&&s.push("At least one recipient or category of recipients must be specified."),(!e.retentionPeriod||e.retentionPeriod.trim()==="")&&s.push("Retention period must be specified."),(!e.securityMeasures||e.securityMeasures.length===0)&&s.push("At least one security measure must be documented."),e.dataSource||s.push("Data source must be specified."),e.dataSource==="third_party"&&(!e.thirdPartySourceDetails||e.thirdPartySourceDetails.trim()==="")&&s.push('Third-party source details are required when data source is "third_party".'),e.automatedDecisionMaking&&(!e.automatedDecisionMakingDetails||e.automatedDecisionMakingDetails.trim()==="")&&s.push("Automated decision-making details are required when automated decision-making is involved."),e.dpiaRequired&&(!e.dpiaReference||e.dpiaReference.trim()==="")&&s.push("DPIA reference is required when DPIA is marked as required."),{valid:s.length===0,errors:s}}function D(e){let s=l.reduce((a,u)=>(a[u]=0,a),{}),o=0,t=0,i=0,n=0,r=0,p=[],d={},m=Date.now();for(let a of e.records)a.lawfulBasis&&l.includes(a.lawfulBasis)&&s[a.lawfulBasis]++,a.status==="active"&&o++,a.sensitiveDataCategories&&a.sensitiveDataCategories.length>0&&t++,a.crossBorderTransfers&&a.crossBorderTransfers.length>0&&i++,a.dpiaRequired&&n++,a.automatedDecisionMaking&&r++,a.nextReviewDate&&a.nextReviewDate<=m&&p.push(a),a.department&&(d[a.department]=(d[a.department]||0)+1);let g=Object.entries(d).map(([a,u])=>({department:a,count:u})).sort((a,u)=>u.count-a.count).slice(0,10);return {totalRecords:e.records.length,activeRecords:o,byLawfulBasis:s,sensitiveDataRecords:t,crossBorderRecords:i,dpiaRequiredRecords:n,automatedDecisionRecords:r,recordsDueForReview:p,topDepartments:g,lastUpdated:e.lastUpdated}}function f(e){return e.includes(",")||e.includes('"')||e.includes(`
2
+ `)||e.includes("\r")?`"${e.replace(/"/g,'""')}"`:e}function c(e){return e?new Date(e).toISOString():""}function R(e){let s=["ID","Name","Description","Controller Name","Controller Contact","Lawful Basis","Lawful Basis Justification","Purposes","Data Categories","Sensitive Data Categories","Data Subject Categories","Recipients","Cross-Border Transfers","Retention Period","Security Measures","Data Source","DPIA Required","DPIA Reference","Automated Decision-Making","Status","Department","Systems Used","Created At","Updated At","Last Reviewed At","Next Review Date"],o=e.records.map(i=>{let n=i.crossBorderTransfers?i.crossBorderTransfers.map(r=>`${r.destinationCountry} (${r.transferMechanism}: ${r.safeguards})`).join("; "):"";return [i.id,i.name,i.description,i.controllerDetails.name,i.controllerDetails.contact,i.lawfulBasis,i.lawfulBasisJustification,i.purposes.join("; "),i.dataCategories.join("; "),(i.sensitiveDataCategories||[]).join("; "),i.dataSubjectCategories.join("; "),i.recipients.join("; "),n,i.retentionPeriod,i.securityMeasures.join("; "),i.dataSource,i.dpiaRequired?"Yes":"No",i.dpiaReference||"",i.automatedDecisionMaking?"Yes":"No",i.status,i.department||"",(i.systemsUsed||[]).join("; "),c(i.createdAt),c(i.updatedAt),c(i.lastReviewedAt),c(i.nextReviewDate)].map(r=>f(String(r)))});return [s.map(i=>f(i)).join(","),...o.map(i=>i.join(","))].join(`
3
+ `)}function w(e){let s=[],o=Date.now();for(let t of e.records){let i=[];if((!t.lawfulBasisJustification||t.lawfulBasisJustification.trim()==="")&&i.push("Missing lawful basis justification (NDPA Section 25 requires documented justification)."),(!t.retentionPeriod||t.retentionPeriod.trim()==="")&&i.push("Missing retention period (data must not be kept longer than necessary)."),(!t.securityMeasures||t.securityMeasures.length===0)&&i.push("No security measures documented (NDPA requires appropriate technical and organizational measures)."),t.nextReviewDate&&t.nextReviewDate<=o){let n=Math.ceil((o-t.nextReviewDate)/864e5);i.push(`Review is overdue by ${n} day${n!==1?"s":""}.`);}if(t.dpiaRequired&&(!t.dpiaReference||t.dpiaReference.trim()==="")&&i.push("DPIA is required but no reference to a completed DPIA was provided."),t.automatedDecisionMaking&&(!t.automatedDecisionMakingDetails||t.automatedDecisionMakingDetails.trim()==="")&&i.push("Automated decision-making is flagged but no details are documented."),t.crossBorderTransfers)for(let n of t.crossBorderTransfers)(!n.safeguards||n.safeguards.trim()==="")&&i.push(`Cross-border transfer to ${n.destinationCountry} is missing safeguard documentation.`),(!n.transferMechanism||n.transferMechanism.trim()==="")&&i.push(`Cross-border transfer to ${n.destinationCountry} is missing transfer mechanism.`);t.dataSource==="third_party"&&(!t.thirdPartySourceDetails||t.thirdPartySourceDetails.trim()==="")&&i.push('Data source is "third_party" but no source details are provided.'),(!t.purposes||t.purposes.length===0)&&i.push("No processing purposes specified."),(!t.recipients||t.recipients.length===0)&&i.push("No recipients or categories of recipients specified."),i.length>0&&s.push({recordId:t.id,recordName:t.name,gaps:i});}return s}exports.a=h;exports.b=D;exports.c=R;exports.d=w;//# sourceMappingURL=chunk-SWF3YVE5.js.map
4
+ //# sourceMappingURL=chunk-SWF3YVE5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/utils/ropa.ts"],"names":["ALL_LAWFUL_BASES","validateProcessingRecord","record","errors","generateROPASummary","ropa","byLawfulBasis","acc","basis","activeRecords","sensitiveDataRecords","crossBorderRecords","dpiaRequiredRecords","automatedDecisionRecords","recordsDueForReview","departmentCounts","now","topDepartments","department","count","b","escapeCSVField","value","formatTimestamp","timestamp","exportROPAToCSV","headers","rows","crossBorderSummary","t","field","h","row","identifyComplianceGaps","gaps","recordGaps","overdueBy","transfer"],"mappings":"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","file":"chunk-SWF3YVE5.js","sourcesContent":["import type { LawfulBasis } from '../types/lawful-basis';\nimport type {\n ProcessingRecord,\n RecordOfProcessingActivities,\n ROPASummary,\n} from '../types/ropa';\n\n/**\n * Compliance gap found in a processing record\n */\nexport interface ROPAComplianceGap {\n recordId: string;\n recordName: string;\n gaps: string[];\n}\n\n/**\n * Validation result for a processing record\n */\nexport interface ROPAValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nconst ALL_LAWFUL_BASES: LawfulBasis[] = [\n 'consent',\n 'contract',\n 'legal_obligation',\n 'vital_interests',\n 'public_interest',\n 'legitimate_interests',\n];\n\n/**\n * Validates a processing record to ensure all required fields are present\n * and properly filled per NDPA 2023 requirements.\n *\n * @param record - The processing record to validate\n * @returns Validation result with any errors found\n */\nexport function validateProcessingRecord(\n record: ProcessingRecord\n): ROPAValidationResult {\n const errors: string[] = [];\n\n if (!record.id || record.id.trim() === '') {\n errors.push('Record ID is required.');\n }\n\n if (!record.name || record.name.trim() === '') {\n errors.push('Processing activity name is required.');\n }\n\n if (!record.description || record.description.trim() === '') {\n errors.push('Processing description is required.');\n }\n\n if (!record.controllerDetails) {\n errors.push('Controller details are required.');\n } else {\n if (!record.controllerDetails.name || record.controllerDetails.name.trim() === '') {\n errors.push('Controller name is required.');\n }\n if (!record.controllerDetails.contact || record.controllerDetails.contact.trim() === '') {\n errors.push('Controller contact is required.');\n }\n if (!record.controllerDetails.address || record.controllerDetails.address.trim() === '') {\n errors.push('Controller address is required.');\n }\n }\n\n if (!record.lawfulBasis || !ALL_LAWFUL_BASES.includes(record.lawfulBasis)) {\n errors.push('A valid lawful basis must be specified (NDPA Section 25).');\n }\n\n if (!record.lawfulBasisJustification || record.lawfulBasisJustification.trim() === '') {\n errors.push('Lawful basis justification is required to demonstrate compliance.');\n }\n\n if (!record.purposes || record.purposes.length === 0) {\n errors.push('At least one processing purpose must be specified.');\n }\n\n if (!record.dataCategories || record.dataCategories.length === 0) {\n errors.push('At least one data category must be specified.');\n }\n\n if (!record.dataSubjectCategories || record.dataSubjectCategories.length === 0) {\n errors.push('At least one data subject category must be specified.');\n }\n\n if (!record.recipients || record.recipients.length === 0) {\n errors.push('At least one recipient or category of recipients must be specified.');\n }\n\n if (!record.retentionPeriod || record.retentionPeriod.trim() === '') {\n errors.push('Retention period must be specified.');\n }\n\n if (!record.securityMeasures || record.securityMeasures.length === 0) {\n errors.push('At least one security measure must be documented.');\n }\n\n if (!record.dataSource) {\n errors.push('Data source must be specified.');\n }\n\n if (\n record.dataSource === 'third_party' &&\n (!record.thirdPartySourceDetails || record.thirdPartySourceDetails.trim() === '')\n ) {\n errors.push('Third-party source details are required when data source is \"third_party\".');\n }\n\n if (\n record.automatedDecisionMaking &&\n (!record.automatedDecisionMakingDetails || record.automatedDecisionMakingDetails.trim() === '')\n ) {\n errors.push(\n 'Automated decision-making details are required when automated decision-making is involved.'\n );\n }\n\n if (\n record.dpiaRequired &&\n (!record.dpiaReference || record.dpiaReference.trim() === '')\n ) {\n errors.push('DPIA reference is required when DPIA is marked as required.');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Generates a summary of the Record of Processing Activities.\n * Provides statistics and identifies records that are due for review.\n *\n * @param ropa - The full Record of Processing Activities\n * @returns Summary statistics for the ROPA\n */\nexport function generateROPASummary(\n ropa: RecordOfProcessingActivities\n): ROPASummary {\n const byLawfulBasis = ALL_LAWFUL_BASES.reduce(\n (acc, basis) => {\n acc[basis] = 0;\n return acc;\n },\n {} as Record<LawfulBasis, number>\n );\n\n let activeRecords = 0;\n let sensitiveDataRecords = 0;\n let crossBorderRecords = 0;\n let dpiaRequiredRecords = 0;\n let automatedDecisionRecords = 0;\n const recordsDueForReview: ProcessingRecord[] = [];\n const departmentCounts: Record<string, number> = {};\n\n const now = Date.now();\n\n for (const record of ropa.records) {\n // Count by lawful basis\n if (record.lawfulBasis && ALL_LAWFUL_BASES.includes(record.lawfulBasis)) {\n byLawfulBasis[record.lawfulBasis]++;\n }\n\n // Count active records\n if (record.status === 'active') {\n activeRecords++;\n }\n\n // Count sensitive data records\n if (\n record.sensitiveDataCategories &&\n record.sensitiveDataCategories.length > 0\n ) {\n sensitiveDataRecords++;\n }\n\n // Count cross-border transfer records\n if (record.crossBorderTransfers && record.crossBorderTransfers.length > 0) {\n crossBorderRecords++;\n }\n\n // Count DPIA-required records\n if (record.dpiaRequired) {\n dpiaRequiredRecords++;\n }\n\n // Count automated decision-making records\n if (record.automatedDecisionMaking) {\n automatedDecisionRecords++;\n }\n\n // Identify records due for review\n if (record.nextReviewDate && record.nextReviewDate <= now) {\n recordsDueForReview.push(record);\n }\n\n // Track department counts\n if (record.department) {\n departmentCounts[record.department] =\n (departmentCounts[record.department] || 0) + 1;\n }\n }\n\n // Sort departments by count and take the top ones\n const topDepartments = Object.entries(departmentCounts)\n .map(([department, count]) => ({ department, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n\n return {\n totalRecords: ropa.records.length,\n activeRecords,\n byLawfulBasis,\n sensitiveDataRecords,\n crossBorderRecords,\n dpiaRequiredRecords,\n automatedDecisionRecords,\n recordsDueForReview,\n topDepartments,\n lastUpdated: ropa.lastUpdated,\n };\n}\n\n/**\n * Escapes a string value for safe inclusion in CSV output\n */\nfunction escapeCSVField(value: string): string {\n if (\n value.includes(',') ||\n value.includes('\"') ||\n value.includes('\\n') ||\n value.includes('\\r')\n ) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n/**\n * Formats a timestamp as an ISO date string for CSV export\n */\nfunction formatTimestamp(timestamp: number | undefined): string {\n if (!timestamp) return '';\n return new Date(timestamp).toISOString();\n}\n\n/**\n * Exports the Record of Processing Activities to a CSV string.\n * The CSV includes all key fields from each processing record.\n *\n * @param ropa - The full Record of Processing Activities\n * @returns CSV-formatted string\n */\nexport function exportROPAToCSV(ropa: RecordOfProcessingActivities): string {\n const headers = [\n 'ID',\n 'Name',\n 'Description',\n 'Controller Name',\n 'Controller Contact',\n 'Lawful Basis',\n 'Lawful Basis Justification',\n 'Purposes',\n 'Data Categories',\n 'Sensitive Data Categories',\n 'Data Subject Categories',\n 'Recipients',\n 'Cross-Border Transfers',\n 'Retention Period',\n 'Security Measures',\n 'Data Source',\n 'DPIA Required',\n 'DPIA Reference',\n 'Automated Decision-Making',\n 'Status',\n 'Department',\n 'Systems Used',\n 'Created At',\n 'Updated At',\n 'Last Reviewed At',\n 'Next Review Date',\n ];\n\n const rows = ropa.records.map((record) => {\n const crossBorderSummary = record.crossBorderTransfers\n ? record.crossBorderTransfers\n .map(\n (t) =>\n `${t.destinationCountry} (${t.transferMechanism}: ${t.safeguards})`\n )\n .join('; ')\n : '';\n\n return [\n record.id,\n record.name,\n record.description,\n record.controllerDetails.name,\n record.controllerDetails.contact,\n record.lawfulBasis,\n record.lawfulBasisJustification,\n record.purposes.join('; '),\n record.dataCategories.join('; '),\n (record.sensitiveDataCategories || []).join('; '),\n record.dataSubjectCategories.join('; '),\n record.recipients.join('; '),\n crossBorderSummary,\n record.retentionPeriod,\n record.securityMeasures.join('; '),\n record.dataSource,\n record.dpiaRequired ? 'Yes' : 'No',\n record.dpiaReference || '',\n record.automatedDecisionMaking ? 'Yes' : 'No',\n record.status,\n record.department || '',\n (record.systemsUsed || []).join('; '),\n formatTimestamp(record.createdAt),\n formatTimestamp(record.updatedAt),\n formatTimestamp(record.lastReviewedAt),\n formatTimestamp(record.nextReviewDate),\n ].map((field) => escapeCSVField(String(field)));\n });\n\n const csvLines = [\n headers.map((h) => escapeCSVField(h)).join(','),\n ...rows.map((row) => row.join(',')),\n ];\n\n return csvLines.join('\\n');\n}\n\n/**\n * Identifies compliance gaps in the Record of Processing Activities.\n * Finds records that are missing required information per NDPA 2023.\n *\n * @param ropa - The full Record of Processing Activities\n * @returns Array of compliance gaps grouped by record\n */\nexport function identifyComplianceGaps(\n ropa: RecordOfProcessingActivities\n): ROPAComplianceGap[] {\n const gaps: ROPAComplianceGap[] = [];\n const now = Date.now();\n\n for (const record of ropa.records) {\n const recordGaps: string[] = [];\n\n // Check lawful basis justification\n if (\n !record.lawfulBasisJustification ||\n record.lawfulBasisJustification.trim() === ''\n ) {\n recordGaps.push(\n 'Missing lawful basis justification (NDPA Section 25 requires documented justification).'\n );\n }\n\n // Check retention period\n if (!record.retentionPeriod || record.retentionPeriod.trim() === '') {\n recordGaps.push(\n 'Missing retention period (data must not be kept longer than necessary).'\n );\n }\n\n // Check security measures\n if (!record.securityMeasures || record.securityMeasures.length === 0) {\n recordGaps.push(\n 'No security measures documented (NDPA requires appropriate technical and organizational measures).'\n );\n }\n\n // Check for overdue review\n if (record.nextReviewDate && record.nextReviewDate <= now) {\n const overdueBy = Math.ceil(\n (now - record.nextReviewDate) / (24 * 60 * 60 * 1000)\n );\n recordGaps.push(\n `Review is overdue by ${overdueBy} day${overdueBy !== 1 ? 's' : ''}.`\n );\n }\n\n // Check DPIA reference when required\n if (\n record.dpiaRequired &&\n (!record.dpiaReference || record.dpiaReference.trim() === '')\n ) {\n recordGaps.push(\n 'DPIA is required but no reference to a completed DPIA was provided.'\n );\n }\n\n // Check automated decision-making documentation\n if (\n record.automatedDecisionMaking &&\n (!record.automatedDecisionMakingDetails ||\n record.automatedDecisionMakingDetails.trim() === '')\n ) {\n recordGaps.push(\n 'Automated decision-making is flagged but no details are documented.'\n );\n }\n\n // Check cross-border transfer safeguards\n if (record.crossBorderTransfers) {\n for (const transfer of record.crossBorderTransfers) {\n if (!transfer.safeguards || transfer.safeguards.trim() === '') {\n recordGaps.push(\n `Cross-border transfer to ${transfer.destinationCountry} is missing safeguard documentation.`\n );\n }\n if (\n !transfer.transferMechanism ||\n transfer.transferMechanism.trim() === ''\n ) {\n recordGaps.push(\n `Cross-border transfer to ${transfer.destinationCountry} is missing transfer mechanism.`\n );\n }\n }\n }\n\n // Check third-party source details\n if (\n record.dataSource === 'third_party' &&\n (!record.thirdPartySourceDetails ||\n record.thirdPartySourceDetails.trim() === '')\n ) {\n recordGaps.push(\n 'Data source is \"third_party\" but no source details are provided.'\n );\n }\n\n // Check missing purposes\n if (!record.purposes || record.purposes.length === 0) {\n recordGaps.push('No processing purposes specified.');\n }\n\n // Check missing recipients\n if (!record.recipients || record.recipients.length === 0) {\n recordGaps.push('No recipients or categories of recipients specified.');\n }\n\n if (recordGaps.length > 0) {\n gaps.push({\n recordId: record.id,\n recordName: record.name,\n gaps: recordGaps,\n });\n }\n }\n\n return gaps;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import {b as b$1,c,d}from'./chunk-PYEX7DFR.mjs';import {b,a}from'./chunk-WWT2ZSNU.mjs';import {useState,useCallback}from'react';function w({initialData:R,onRecordAdd:n,onRecordUpdate:c$1,onRecordArchive:d$1}){let[s,p]=useState(R),O=useCallback(e=>{p(t=>b(a({},t),{records:[...t.records,e],lastUpdated:Date.now()})),n==null||n(e);},[n]),l=useCallback((e,t)=>{p(o=>b(a({},o),{records:o.records.map(g=>g.id===e?b(a(a({},g),t),{updatedAt:Date.now()}):g),lastUpdated:Date.now()})),c$1==null||c$1(e,t);},[c$1]),f=useCallback(e=>{p(t=>b(a({},t),{records:t.records.map(o=>o.id===e?b(a({},o),{status:"archived",updatedAt:Date.now()}):o),lastUpdated:Date.now()})),d$1==null||d$1(e);},[d$1]),A=useCallback(e=>s.records.find(t=>t.id===e),[s.records]),y=useCallback(()=>b$1(s),[s]),C=useCallback(()=>c(s),[s]),S=useCallback(()=>d(s),[s]);return {ropa:s,addRecord:O,updateRecord:l,archiveRecord:f,getRecord:A,getSummary:y,exportCSV:C,getComplianceGaps:S}}export{w as a};//# sourceMappingURL=chunk-T44JQT2O.mjs.map
2
+ //# sourceMappingURL=chunk-T44JQT2O.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/hooks/useROPA.ts"],"names":["useROPA","initialData","onRecordAdd","onRecordUpdate","onRecordArchive","ropa","setROPA","useState","addRecord","useCallback","record","prev","__spreadProps","__spreadValues","updateRecord","id","updates","archiveRecord","getRecord","getSummary","generateROPASummary","exportCSV","exportROPAToCSV","getComplianceGaps","identifyComplianceGaps"],"mappings":"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","file":"chunk-T44JQT2O.mjs","sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport type {\n ProcessingRecord,\n RecordOfProcessingActivities,\n ROPASummary,\n} from '../types/ropa';\nimport {\n generateROPASummary,\n exportROPAToCSV,\n identifyComplianceGaps,\n type ROPAComplianceGap,\n} from '../utils/ropa';\n\nexport interface UseROPAOptions {\n /**\n * Initial ROPA state\n */\n initialData: RecordOfProcessingActivities;\n\n /**\n * Callback when a record is added\n */\n onRecordAdd?: (record: ProcessingRecord) => void;\n\n /**\n * Callback when a record is updated\n */\n onRecordUpdate?: (id: string, updates: Partial<ProcessingRecord>) => void;\n\n /**\n * Callback when a record is archived\n */\n onRecordArchive?: (id: string) => void;\n}\n\nexport interface UseROPAReturn {\n /**\n * Current state of the Record of Processing Activities\n */\n ropa: RecordOfProcessingActivities;\n\n /**\n * Add a new processing record\n */\n addRecord: (record: ProcessingRecord) => void;\n\n /**\n * Update an existing processing record\n */\n updateRecord: (id: string, updates: Partial<ProcessingRecord>) => void;\n\n /**\n * Archive a processing record by setting its status to 'archived'\n */\n archiveRecord: (id: string) => void;\n\n /**\n * Get a single processing record by ID\n */\n getRecord: (id: string) => ProcessingRecord | undefined;\n\n /**\n * Get a summary of the ROPA including statistics\n */\n getSummary: () => ROPASummary;\n\n /**\n * Export the ROPA as a CSV string\n */\n exportCSV: () => string;\n\n /**\n * Identify compliance gaps across all records\n */\n getComplianceGaps: () => ROPAComplianceGap[];\n}\n\n/**\n * Hook for managing a Record of Processing Activities (ROPA)\n * in compliance with NDPA 2023 requirements.\n *\n * Provides state management and utility functions for maintaining\n * a comprehensive register of all data processing activities.\n */\nexport function useROPA({\n initialData,\n onRecordAdd,\n onRecordUpdate,\n onRecordArchive,\n}: UseROPAOptions): UseROPAReturn {\n const [ropa, setROPA] = useState<RecordOfProcessingActivities>(initialData);\n\n const addRecord = useCallback(\n (record: ProcessingRecord) => {\n setROPA((prev) => ({\n ...prev,\n records: [...prev.records, record],\n lastUpdated: Date.now(),\n }));\n onRecordAdd?.(record);\n },\n [onRecordAdd]\n );\n\n const updateRecord = useCallback(\n (id: string, updates: Partial<ProcessingRecord>) => {\n setROPA((prev) => ({\n ...prev,\n records: prev.records.map((record) =>\n record.id === id\n ? { ...record, ...updates, updatedAt: Date.now() }\n : record\n ),\n lastUpdated: Date.now(),\n }));\n onRecordUpdate?.(id, updates);\n },\n [onRecordUpdate]\n );\n\n const archiveRecord = useCallback(\n (id: string) => {\n setROPA((prev) => ({\n ...prev,\n records: prev.records.map((record) =>\n record.id === id\n ? { ...record, status: 'archived' as const, updatedAt: Date.now() }\n : record\n ),\n lastUpdated: Date.now(),\n }));\n onRecordArchive?.(id);\n },\n [onRecordArchive]\n );\n\n const getRecord = useCallback(\n (id: string): ProcessingRecord | undefined => {\n return ropa.records.find((record) => record.id === id);\n },\n [ropa.records]\n );\n\n const getSummary = useCallback((): ROPASummary => {\n return generateROPASummary(ropa);\n }, [ropa]);\n\n const exportCSV = useCallback((): string => {\n return exportROPAToCSV(ropa);\n }, [ropa]);\n\n const getComplianceGaps = useCallback((): ROPAComplianceGap[] => {\n return identifyComplianceGaps(ropa);\n }, [ropa]);\n\n return {\n ropa,\n addRecord,\n updateRecord,\n archiveRecord,\n getRecord,\n getSummary,\n exportCSV,\n getComplianceGaps,\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';function o(i){let t=[],e=[];return i.id||t.push("Activity ID is required."),(!i.name||i.name.trim()==="")&&t.push("Activity name is required."),(!i.description||i.description.trim()==="")&&t.push("Activity description is required."),i.lawfulBasis||t.push("Lawful basis is required per NDPA Section 25."),(!i.lawfulBasisJustification||i.lawfulBasisJustification.trim()==="")&&t.push("Justification for the lawful basis is required."),(!i.dataCategories||i.dataCategories.length===0)&&t.push("At least one data category must be specified."),(!i.dataSubjectCategories||i.dataSubjectCategories.length===0)&&t.push("At least one data subject category must be specified."),(!i.purposes||i.purposes.length===0)&&t.push("At least one processing purpose must be specified."),(!i.retentionPeriod||i.retentionPeriod.trim()==="")&&t.push("Data retention period is required."),i.lawfulBasis==="legitimate_interests"&&(!i.lawfulBasisJustification||i.lawfulBasisJustification.trim().length<20)&&t.push("Legitimate interests requires a detailed Legitimate Interest Assessment (LIA) justification (NDPA Section 25(1)(f))."),i.involvesSensitiveData&&!i.sensitiveDataCondition&&t.push("Processing sensitive personal data requires specifying a condition under NDPA Section 27."),i.dpoApproval?i.dpoApproval.approved||e.push("Activity has a DPO review but has not been approved."):e.push("Activity has not been approved by the DPO."),i.reviewDate?i.reviewDate<Date.now()&&e.push("Activity is overdue for review."):e.push("No review date has been set. Regular reviews are recommended."),i.retentionJustification||e.push("Consider documenting the justification for the retention period."),i.crossBorderTransfer&&(!i.recipients||i.recipients.length===0)&&e.push("Cross-border transfer is indicated but no recipients are listed. Document the recipients or categories of recipients."),{isValid:t.length===0,errors:t,warnings:e}}function c(i){return {consent:"Consent (NDPA Section 25(1)(a)) - The data subject has given consent to the processing of their personal data for one or more specific purposes.",contract:"Contract (NDPA Section 25(1)(b)) - Processing is necessary for the performance of a contract to which the data subject is a party, or in order to take steps at the request of the data subject prior to entering into a contract.",legal_obligation:"Legal Obligation (NDPA Section 25(1)(c)) - Processing is necessary for compliance with a legal obligation to which the data controller is subject.",vital_interests:"Vital Interests (NDPA Section 25(1)(d)) - Processing is necessary to protect the vital interests of the data subject or another natural person.",public_interest:"Public Interest (NDPA Section 25(1)(e)) - Processing is necessary for the performance of a task carried out in the public interest or in the exercise of official authority vested in the data controller.",legitimate_interests:"Legitimate Interests (NDPA Section 25(1)(f)) - Processing is necessary for the purposes of the legitimate interests pursued by the data controller or a third party, except where such interests are overridden by the interests, rights, or freedoms of the data subject."}[i]}function p(i){let t=[];for(let e of i)e.status!=="archived"&&((!e.dpoApproval||!e.dpoApproval.approved)&&t.push({activityId:e.id,activityName:e.name,type:"missing_approval",severity:"high",description:`Processing activity "${e.name}" has not been approved by the DPO.`}),e.reviewDate&&e.reviewDate<Date.now()&&t.push({activityId:e.id,activityName:e.name,type:"overdue_review",severity:"medium",description:`Processing activity "${e.name}" was due for review on ${new Date(e.reviewDate).toLocaleDateString()}.`}),(!e.lawfulBasisJustification||e.lawfulBasisJustification.trim()==="")&&t.push({activityId:e.id,activityName:e.name,type:"missing_justification",severity:"high",description:`Processing activity "${e.name}" is missing the lawful basis justification.`}),e.lawfulBasis==="legitimate_interests"&&(!e.lawfulBasisJustification||e.lawfulBasisJustification.trim().length<20)&&t.push({activityId:e.id,activityName:e.name,type:"missing_lia",severity:"high",description:`Processing activity "${e.name}" relies on legitimate interests but lacks a detailed Legitimate Interest Assessment (NDPA Section 25(1)(f)).`}),e.involvesSensitiveData&&!e.sensitiveDataCondition&&t.push({activityId:e.id,activityName:e.name,type:"missing_sensitive_condition",severity:"high",description:`Processing activity "${e.name}" involves sensitive data but no condition under NDPA Section 27 has been specified.`}),(!e.retentionPeriod||e.retentionPeriod.trim()==="")&&t.push({activityId:e.id,activityName:e.name,type:"missing_retention",severity:"medium",description:`Processing activity "${e.name}" is missing a documented retention period.`}),(!e.dataCategories||e.dataCategories.length===0)&&t.push({activityId:e.id,activityName:e.name,type:"missing_data_categories",severity:"medium",description:`Processing activity "${e.name}" has no documented data categories.`}),(!e.purposes||e.purposes.length===0)&&t.push({activityId:e.id,activityName:e.name,type:"missing_purposes",severity:"medium",description:`Processing activity "${e.name}" has no documented processing purposes.`}));return t}function u(i){let t={consent:0,contract:0,legal_obligation:0,vital_interests:0,public_interest:0,legitimate_interests:0},e=0,a=0,n=[],r=[];for(let s of i)s.status!=="archived"&&(s.lawfulBasis in t&&t[s.lawfulBasis]++,s.involvesSensitiveData&&e++,s.crossBorderTransfer&&a++,s.reviewDate&&s.reviewDate<Date.now()&&n.push(s),(!s.dpoApproval||!s.dpoApproval.approved)&&r.push(s));return {totalActivities:i.filter(s=>s.status!=="archived").length,byBasis:t,sensitiveDataActivities:e,crossBorderActivities:a,activitiesDueForReview:n,activitiesWithoutApproval:r,lastUpdated:Date.now()}}exports.a=o;exports.b=c;exports.c=p;exports.d=u;//# sourceMappingURL=chunk-TDDAYVKK.js.map
2
+ //# sourceMappingURL=chunk-TDDAYVKK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/utils/lawful-basis.ts"],"names":["validateProcessingActivity","activity","errors","warnings","getLawfulBasisDescription","basis","assessComplianceGaps","activities","gaps","generateLawfulBasisSummary","byBasis","sensitiveDataActivities","crossBorderActivities","activitiesDueForReview","activitiesWithoutApproval","a"],"mappings":"aAoCO,SAASA,CAAAA,CAA2BC,CAAAA,CAA2D,CACpG,IAAMC,CAAAA,CAAmB,EAAC,CACpBC,CAAAA,CAAqB,EAAC,CAG5B,OAAKF,CAAAA,CAAS,IACZC,CAAAA,CAAO,IAAA,CAAK,0BAA0B,CAAA,CAAA,CAGpC,CAACD,CAAAA,CAAS,IAAA,EAAQA,CAAAA,CAAS,IAAA,CAAK,IAAA,EAAK,GAAM,EAAA,GAC7CC,CAAAA,CAAO,IAAA,CAAK,4BAA4B,CAAA,CAAA,CAGtC,CAACD,CAAAA,CAAS,WAAA,EAAeA,CAAAA,CAAS,WAAA,CAAY,IAAA,EAAK,GAAM,EAAA,GAC3DC,CAAAA,CAAO,IAAA,CAAK,mCAAmC,CAAA,CAG5CD,CAAAA,CAAS,WAAA,EACZC,CAAAA,CAAO,IAAA,CAAK,+CAA+C,GAGzD,CAACD,CAAAA,CAAS,wBAAA,EAA4BA,CAAAA,CAAS,wBAAA,CAAyB,IAAA,EAAK,GAAM,EAAA,GACrFC,EAAO,IAAA,CAAK,iDAAiD,CAAA,CAAA,CAG3D,CAACD,CAAAA,CAAS,cAAA,EAAkBA,CAAAA,CAAS,cAAA,CAAe,SAAW,CAAA,GACjEC,CAAAA,CAAO,IAAA,CAAK,+CAA+C,CAAA,CAAA,CAGzD,CAACD,CAAAA,CAAS,qBAAA,EAAyBA,CAAAA,CAAS,qBAAA,CAAsB,MAAA,GAAW,CAAA,GAC/EC,CAAAA,CAAO,IAAA,CAAK,uDAAuD,CAAA,CAAA,CAGjE,CAACD,CAAAA,CAAS,QAAA,EAAYA,CAAAA,CAAS,QAAA,CAAS,MAAA,GAAW,CAAA,GACrDC,CAAAA,CAAO,IAAA,CAAK,oDAAoD,CAAA,CAAA,CAG9D,CAACD,CAAAA,CAAS,eAAA,EAAmBA,CAAAA,CAAS,eAAA,CAAgB,IAAA,KAAW,EAAA,GACnEC,CAAAA,CAAO,IAAA,CAAK,oCAAoC,CAAA,CAI9CD,CAAAA,CAAS,WAAA,GAAgB,sBAAA,GACvB,CAACA,CAAAA,CAAS,wBAAA,EAA4BA,CAAAA,CAAS,wBAAA,CAAyB,IAAA,EAAK,CAAE,MAAA,CAAS,KAC1FC,CAAAA,CAAO,IAAA,CACL,sHACF,CAAA,CAKAD,CAAAA,CAAS,qBAAA,EAAyB,CAACA,CAAAA,CAAS,wBAC9CC,CAAAA,CAAO,IAAA,CACL,2FACF,CAAA,CAIGD,CAAAA,CAAS,WAAA,CAEFA,CAAAA,CAAS,WAAA,CAAY,UAC/BE,CAAAA,CAAS,IAAA,CAAK,sDAAsD,CAAA,CAFpEA,CAAAA,CAAS,IAAA,CAAK,4CAA4C,CAAA,CAKvDF,CAAAA,CAAS,UAAA,CAEHA,CAAAA,CAAS,UAAA,CAAa,IAAA,CAAK,GAAA,EAAI,EACxCE,CAAAA,CAAS,KAAK,iCAAiC,CAAA,CAF/CA,CAAAA,CAAS,IAAA,CAAK,+DAA+D,CAAA,CAK1EF,CAAAA,CAAS,sBAAA,EACZE,CAAAA,CAAS,IAAA,CAAK,kEAAkE,CAAA,CAG9EF,CAAAA,CAAS,mBAAA,GAAwB,CAACA,CAAAA,CAAS,YAAcA,CAAAA,CAAS,UAAA,CAAW,MAAA,GAAW,CAAA,CAAA,EAC1FE,CAAAA,CAAS,IAAA,CACP,uHACF,CAAA,CAGK,CACL,OAAA,CAASD,CAAAA,CAAO,MAAA,GAAW,CAAA,CAC3B,MAAA,CAAAA,CAAAA,CACA,QAAA,CAAAC,CACF,CACF,CASO,SAASC,CAAAA,CAA0BC,CAAAA,CAA4B,CAgBpE,OAfkD,CAChD,QACE,kJAAA,CACF,QAAA,CACE,oOAAA,CACF,gBAAA,CACE,oJAAA,CACF,eAAA,CACE,iJAAA,CACF,eAAA,CACE,6MACF,oBAAA,CACE,4QACJ,CAAA,CAEoBA,CAAK,CAC3B,CAUO,SAASC,CAAAA,CAAqBC,CAAAA,CAA8D,CACjG,IAAMC,CAAAA,CAAmC,EAAC,CAE1C,IAAA,IAAWP,CAAAA,IAAYM,EAEjBN,CAAAA,CAAS,MAAA,GAAW,UAAA,GAAA,CAKpB,CAACA,CAAAA,CAAS,WAAA,EAAe,CAACA,CAAAA,CAAS,YAAY,QAAA,GACjDO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,YAAA,CAAcA,EAAS,IAAA,CACvB,IAAA,CAAM,kBAAA,CACN,QAAA,CAAU,MAAA,CACV,WAAA,CAAa,CAAA,qBAAA,EAAwBA,CAAAA,CAAS,IAAI,CAAA,mCAAA,CACpD,CAAC,CAAA,CAICA,CAAAA,CAAS,UAAA,EAAcA,CAAAA,CAAS,UAAA,CAAa,KAAK,GAAA,EAAI,EACxDO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,aAAcA,CAAAA,CAAS,IAAA,CACvB,IAAA,CAAM,gBAAA,CACN,QAAA,CAAU,QAAA,CACV,WAAA,CAAa,CAAA,qBAAA,EAAwBA,EAAS,IAAI,CAAA,wBAAA,EAA2B,IAAI,IAAA,CAAKA,CAAAA,CAAS,UAAU,CAAA,CAAE,kBAAA,EAAoB,CAAA,CAAA,CACjI,CAAC,CAAA,CAAA,CAIC,CAACA,CAAAA,CAAS,wBAAA,EAA4BA,CAAAA,CAAS,yBAAyB,IAAA,EAAK,GAAM,EAAA,GACrFO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,YAAA,CAAcA,CAAAA,CAAS,IAAA,CACvB,IAAA,CAAM,uBAAA,CACN,QAAA,CAAU,MAAA,CACV,YAAa,CAAA,qBAAA,EAAwBA,CAAAA,CAAS,IAAI,CAAA,4CAAA,CACpD,CAAC,CAAA,CAKDA,CAAAA,CAAS,WAAA,GAAgB,sBAAA,GACxB,CAACA,CAAAA,CAAS,wBAAA,EAA4BA,CAAAA,CAAS,wBAAA,CAAyB,IAAA,EAAK,CAAE,OAAS,EAAA,CAAA,EAEzFO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,YAAA,CAAcA,EAAS,IAAA,CACvB,IAAA,CAAM,aAAA,CACN,QAAA,CAAU,MAAA,CACV,WAAA,CAAa,CAAA,qBAAA,EAAwBA,CAAAA,CAAS,IAAI,CAAA,6GAAA,CACpD,CAAC,CAAA,CAICA,CAAAA,CAAS,qBAAA,EAAyB,CAACA,CAAAA,CAAS,sBAAA,EAC9CO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,YAAA,CAAcA,CAAAA,CAAS,KACvB,IAAA,CAAM,6BAAA,CACN,QAAA,CAAU,MAAA,CACV,WAAA,CAAa,CAAA,qBAAA,EAAwBA,CAAAA,CAAS,IAAI,sFACpD,CAAC,CAAA,CAAA,CAIC,CAACA,CAAAA,CAAS,eAAA,EAAmBA,CAAAA,CAAS,eAAA,CAAgB,IAAA,KAAW,EAAA,GACnEO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,YAAA,CAAcA,CAAAA,CAAS,IAAA,CACvB,IAAA,CAAM,mBAAA,CACN,QAAA,CAAU,QAAA,CACV,WAAA,CAAa,CAAA,qBAAA,EAAwBA,EAAS,IAAI,CAAA,2CAAA,CACpD,CAAC,CAAA,CAAA,CAIC,CAACA,CAAAA,CAAS,cAAA,EAAkBA,CAAAA,CAAS,eAAe,MAAA,GAAW,CAAA,GACjEO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,aAAcA,CAAAA,CAAS,IAAA,CACvB,IAAA,CAAM,yBAAA,CACN,QAAA,CAAU,QAAA,CACV,WAAA,CAAa,CAAA,qBAAA,EAAwBA,CAAAA,CAAS,IAAI,CAAA,oCAAA,CACpD,CAAC,CAAA,CAAA,CAIC,CAACA,CAAAA,CAAS,QAAA,EAAYA,EAAS,QAAA,CAAS,MAAA,GAAW,CAAA,GACrDO,CAAAA,CAAK,IAAA,CAAK,CACR,UAAA,CAAYP,CAAAA,CAAS,EAAA,CACrB,YAAA,CAAcA,CAAAA,CAAS,IAAA,CACvB,IAAA,CAAM,kBAAA,CACN,QAAA,CAAU,QAAA,CACV,YAAa,CAAA,qBAAA,EAAwBA,CAAAA,CAAS,IAAI,CAAA,wCAAA,CACpD,CAAC,CAAA,CAAA,CAIL,OAAOO,CACT,CAQO,SAASC,CAAAA,CAA2BF,CAAAA,CAAsD,CAC/F,IAAMG,CAAAA,CAAuC,CAC3C,QAAS,CAAA,CACT,QAAA,CAAU,CAAA,CACV,gBAAA,CAAkB,CAAA,CAClB,eAAA,CAAiB,CAAA,CACjB,eAAA,CAAiB,EACjB,oBAAA,CAAsB,CACxB,CAAA,CAEIC,CAAAA,CAA0B,CAAA,CAC1BC,CAAAA,CAAwB,CAAA,CACtBC,CAAAA,CAA+C,EAAC,CAChDC,CAAAA,CAAkD,EAAC,CAEzD,IAAA,IAAWb,CAAAA,IAAYM,CAAAA,CACjBN,CAAAA,CAAS,MAAA,GAAW,UAAA,GAKpBA,CAAAA,CAAS,WAAA,IAAeS,CAAAA,EAC1BA,CAAAA,CAAQT,CAAAA,CAAS,WAAW,IAI1BA,CAAAA,CAAS,qBAAA,EACXU,CAAAA,EAAAA,CAIEV,CAAAA,CAAS,mBAAA,EACXW,CAAAA,EAAAA,CAIEX,CAAAA,CAAS,UAAA,EAAcA,EAAS,UAAA,CAAa,IAAA,CAAK,GAAA,EAAI,EACxDY,CAAAA,CAAuB,IAAA,CAAKZ,CAAQ,CAAA,CAAA,CAIlC,CAACA,CAAAA,CAAS,WAAA,EAAe,CAACA,CAAAA,CAAS,WAAA,CAAY,QAAA,GACjDa,CAAAA,CAA0B,IAAA,CAAKb,CAAQ,CAAA,CAAA,CAI3C,OAAO,CACL,eAAA,CAAiBM,CAAAA,CAAW,MAAA,CAAOQ,CAAAA,EAAKA,EAAE,MAAA,GAAW,UAAU,CAAA,CAAE,MAAA,CACjE,OAAA,CAAAL,CAAAA,CACA,uBAAA,CAAAC,CAAAA,CACA,sBAAAC,CAAAA,CACA,sBAAA,CAAAC,CAAAA,CACA,yBAAA,CAAAC,CAAAA,CACA,WAAA,CAAa,IAAA,CAAK,GAAA,EACpB,CACF","file":"chunk-TDDAYVKK.js","sourcesContent":["import {\n LawfulBasis,\n ProcessingActivity,\n LawfulBasisSummary,\n} from '../types/lawful-basis';\n\n/**\n * Validation result for a processing activity\n */\nexport interface LawfulBasisValidationResult {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/**\n * Compliance gap identified across processing activities\n */\nexport interface LawfulBasisComplianceGap {\n activityId: string;\n activityName: string;\n type: 'missing_approval' | 'overdue_review' | 'missing_justification' | 'missing_lia' | 'missing_sensitive_condition' | 'missing_retention' | 'missing_data_categories' | 'missing_purposes';\n severity: 'high' | 'medium' | 'low';\n description: string;\n}\n\n/**\n * Validates that all required fields are present on a processing activity\n * and that the lawful basis is properly documented.\n *\n * If lawfulBasis is 'legitimate_interests', ensures a LIA justification exists.\n * If involvesSensitiveData is true, ensures sensitiveDataCondition is set.\n *\n * @param activity The processing activity to validate\n * @returns Validation result with errors and warnings\n */\nexport function validateProcessingActivity(activity: ProcessingActivity): LawfulBasisValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Required fields\n if (!activity.id) {\n errors.push('Activity ID is required.');\n }\n\n if (!activity.name || activity.name.trim() === '') {\n errors.push('Activity name is required.');\n }\n\n if (!activity.description || activity.description.trim() === '') {\n errors.push('Activity description is required.');\n }\n\n if (!activity.lawfulBasis) {\n errors.push('Lawful basis is required per NDPA Section 25.');\n }\n\n if (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim() === '') {\n errors.push('Justification for the lawful basis is required.');\n }\n\n if (!activity.dataCategories || activity.dataCategories.length === 0) {\n errors.push('At least one data category must be specified.');\n }\n\n if (!activity.dataSubjectCategories || activity.dataSubjectCategories.length === 0) {\n errors.push('At least one data subject category must be specified.');\n }\n\n if (!activity.purposes || activity.purposes.length === 0) {\n errors.push('At least one processing purpose must be specified.');\n }\n\n if (!activity.retentionPeriod || activity.retentionPeriod.trim() === '') {\n errors.push('Data retention period is required.');\n }\n\n // Legitimate interests requires additional justification (LIA)\n if (activity.lawfulBasis === 'legitimate_interests') {\n if (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim().length < 20) {\n errors.push(\n 'Legitimate interests requires a detailed Legitimate Interest Assessment (LIA) justification (NDPA Section 25(1)(f)).'\n );\n }\n }\n\n // Sensitive data requires a specific condition per NDPA Section 27\n if (activity.involvesSensitiveData && !activity.sensitiveDataCondition) {\n errors.push(\n 'Processing sensitive personal data requires specifying a condition under NDPA Section 27.'\n );\n }\n\n // Warnings for best practices\n if (!activity.dpoApproval) {\n warnings.push('Activity has not been approved by the DPO.');\n } else if (!activity.dpoApproval.approved) {\n warnings.push('Activity has a DPO review but has not been approved.');\n }\n\n if (!activity.reviewDate) {\n warnings.push('No review date has been set. Regular reviews are recommended.');\n } else if (activity.reviewDate < Date.now()) {\n warnings.push('Activity is overdue for review.');\n }\n\n if (!activity.retentionJustification) {\n warnings.push('Consider documenting the justification for the retention period.');\n }\n\n if (activity.crossBorderTransfer && (!activity.recipients || activity.recipients.length === 0)) {\n warnings.push(\n 'Cross-border transfer is indicated but no recipients are listed. Document the recipients or categories of recipients.'\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Returns a human-readable description of a lawful basis with the relevant\n * NDPA section reference.\n *\n * @param basis The lawful basis to describe\n * @returns Description string including NDPA section reference\n */\nexport function getLawfulBasisDescription(basis: LawfulBasis): string {\n const descriptions: Record<LawfulBasis, string> = {\n consent:\n 'Consent (NDPA Section 25(1)(a)) - The data subject has given consent to the processing of their personal data for one or more specific purposes.',\n contract:\n 'Contract (NDPA Section 25(1)(b)) - Processing is necessary for the performance of a contract to which the data subject is a party, or in order to take steps at the request of the data subject prior to entering into a contract.',\n legal_obligation:\n 'Legal Obligation (NDPA Section 25(1)(c)) - Processing is necessary for compliance with a legal obligation to which the data controller is subject.',\n vital_interests:\n 'Vital Interests (NDPA Section 25(1)(d)) - Processing is necessary to protect the vital interests of the data subject or another natural person.',\n public_interest:\n 'Public Interest (NDPA Section 25(1)(e)) - Processing is necessary for the performance of a task carried out in the public interest or in the exercise of official authority vested in the data controller.',\n legitimate_interests:\n 'Legitimate Interests (NDPA Section 25(1)(f)) - Processing is necessary for the purposes of the legitimate interests pursued by the data controller or a third party, except where such interests are overridden by the interests, rights, or freedoms of the data subject.',\n };\n\n return descriptions[basis];\n}\n\n/**\n * Analyzes all processing activities and returns compliance gaps including\n * missing DPO approval, overdue reviews, undocumented justifications,\n * missing LIA for legitimate interests, and other documentation issues.\n *\n * @param activities Array of processing activities to analyze\n * @returns Array of identified compliance gaps\n */\nexport function assessComplianceGaps(activities: ProcessingActivity[]): LawfulBasisComplianceGap[] {\n const gaps: LawfulBasisComplianceGap[] = [];\n\n for (const activity of activities) {\n // Skip archived activities\n if (activity.status === 'archived') {\n continue;\n }\n\n // Missing DPO approval\n if (!activity.dpoApproval || !activity.dpoApproval.approved) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_approval',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" has not been approved by the DPO.`,\n });\n }\n\n // Overdue review\n if (activity.reviewDate && activity.reviewDate < Date.now()) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'overdue_review',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" was due for review on ${new Date(activity.reviewDate).toLocaleDateString()}.`,\n });\n }\n\n // Missing justification\n if (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim() === '') {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_justification',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" is missing the lawful basis justification.`,\n });\n }\n\n // Missing LIA for legitimate interests\n if (\n activity.lawfulBasis === 'legitimate_interests' &&\n (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim().length < 20)\n ) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_lia',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" relies on legitimate interests but lacks a detailed Legitimate Interest Assessment (NDPA Section 25(1)(f)).`,\n });\n }\n\n // Missing sensitive data condition\n if (activity.involvesSensitiveData && !activity.sensitiveDataCondition) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_sensitive_condition',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" involves sensitive data but no condition under NDPA Section 27 has been specified.`,\n });\n }\n\n // Missing retention period\n if (!activity.retentionPeriod || activity.retentionPeriod.trim() === '') {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_retention',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" is missing a documented retention period.`,\n });\n }\n\n // Missing data categories\n if (!activity.dataCategories || activity.dataCategories.length === 0) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_data_categories',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" has no documented data categories.`,\n });\n }\n\n // Missing purposes\n if (!activity.purposes || activity.purposes.length === 0) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_purposes',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" has no documented processing purposes.`,\n });\n }\n }\n\n return gaps;\n}\n\n/**\n * Generates a summary of all lawful basis documentation across processing activities.\n *\n * @param activities Array of processing activities to summarize\n * @returns LawfulBasisSummary with counts, breakdowns, and flagged activities\n */\nexport function generateLawfulBasisSummary(activities: ProcessingActivity[]): LawfulBasisSummary {\n const byBasis: Record<LawfulBasis, number> = {\n consent: 0,\n contract: 0,\n legal_obligation: 0,\n vital_interests: 0,\n public_interest: 0,\n legitimate_interests: 0,\n };\n\n let sensitiveDataActivities = 0;\n let crossBorderActivities = 0;\n const activitiesDueForReview: ProcessingActivity[] = [];\n const activitiesWithoutApproval: ProcessingActivity[] = [];\n\n for (const activity of activities) {\n if (activity.status === 'archived') {\n continue;\n }\n\n // Count by lawful basis\n if (activity.lawfulBasis in byBasis) {\n byBasis[activity.lawfulBasis]++;\n }\n\n // Count sensitive data activities\n if (activity.involvesSensitiveData) {\n sensitiveDataActivities++;\n }\n\n // Count cross-border transfers\n if (activity.crossBorderTransfer) {\n crossBorderActivities++;\n }\n\n // Check for overdue reviews\n if (activity.reviewDate && activity.reviewDate < Date.now()) {\n activitiesDueForReview.push(activity);\n }\n\n // Check for missing DPO approval\n if (!activity.dpoApproval || !activity.dpoApproval.approved) {\n activitiesWithoutApproval.push(activity);\n }\n }\n\n return {\n totalActivities: activities.filter(a => a.status !== 'archived').length,\n byBasis,\n sensitiveDataActivities,\n crossBorderActivities,\n activitiesDueForReview,\n activitiesWithoutApproval,\n lastUpdated: Date.now(),\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ function o(i){let t=[],e=[];return i.id||t.push("Activity ID is required."),(!i.name||i.name.trim()==="")&&t.push("Activity name is required."),(!i.description||i.description.trim()==="")&&t.push("Activity description is required."),i.lawfulBasis||t.push("Lawful basis is required per NDPA Section 25."),(!i.lawfulBasisJustification||i.lawfulBasisJustification.trim()==="")&&t.push("Justification for the lawful basis is required."),(!i.dataCategories||i.dataCategories.length===0)&&t.push("At least one data category must be specified."),(!i.dataSubjectCategories||i.dataSubjectCategories.length===0)&&t.push("At least one data subject category must be specified."),(!i.purposes||i.purposes.length===0)&&t.push("At least one processing purpose must be specified."),(!i.retentionPeriod||i.retentionPeriod.trim()==="")&&t.push("Data retention period is required."),i.lawfulBasis==="legitimate_interests"&&(!i.lawfulBasisJustification||i.lawfulBasisJustification.trim().length<20)&&t.push("Legitimate interests requires a detailed Legitimate Interest Assessment (LIA) justification (NDPA Section 25(1)(f))."),i.involvesSensitiveData&&!i.sensitiveDataCondition&&t.push("Processing sensitive personal data requires specifying a condition under NDPA Section 27."),i.dpoApproval?i.dpoApproval.approved||e.push("Activity has a DPO review but has not been approved."):e.push("Activity has not been approved by the DPO."),i.reviewDate?i.reviewDate<Date.now()&&e.push("Activity is overdue for review."):e.push("No review date has been set. Regular reviews are recommended."),i.retentionJustification||e.push("Consider documenting the justification for the retention period."),i.crossBorderTransfer&&(!i.recipients||i.recipients.length===0)&&e.push("Cross-border transfer is indicated but no recipients are listed. Document the recipients or categories of recipients."),{isValid:t.length===0,errors:t,warnings:e}}function c(i){return {consent:"Consent (NDPA Section 25(1)(a)) - The data subject has given consent to the processing of their personal data for one or more specific purposes.",contract:"Contract (NDPA Section 25(1)(b)) - Processing is necessary for the performance of a contract to which the data subject is a party, or in order to take steps at the request of the data subject prior to entering into a contract.",legal_obligation:"Legal Obligation (NDPA Section 25(1)(c)) - Processing is necessary for compliance with a legal obligation to which the data controller is subject.",vital_interests:"Vital Interests (NDPA Section 25(1)(d)) - Processing is necessary to protect the vital interests of the data subject or another natural person.",public_interest:"Public Interest (NDPA Section 25(1)(e)) - Processing is necessary for the performance of a task carried out in the public interest or in the exercise of official authority vested in the data controller.",legitimate_interests:"Legitimate Interests (NDPA Section 25(1)(f)) - Processing is necessary for the purposes of the legitimate interests pursued by the data controller or a third party, except where such interests are overridden by the interests, rights, or freedoms of the data subject."}[i]}function p(i){let t=[];for(let e of i)e.status!=="archived"&&((!e.dpoApproval||!e.dpoApproval.approved)&&t.push({activityId:e.id,activityName:e.name,type:"missing_approval",severity:"high",description:`Processing activity "${e.name}" has not been approved by the DPO.`}),e.reviewDate&&e.reviewDate<Date.now()&&t.push({activityId:e.id,activityName:e.name,type:"overdue_review",severity:"medium",description:`Processing activity "${e.name}" was due for review on ${new Date(e.reviewDate).toLocaleDateString()}.`}),(!e.lawfulBasisJustification||e.lawfulBasisJustification.trim()==="")&&t.push({activityId:e.id,activityName:e.name,type:"missing_justification",severity:"high",description:`Processing activity "${e.name}" is missing the lawful basis justification.`}),e.lawfulBasis==="legitimate_interests"&&(!e.lawfulBasisJustification||e.lawfulBasisJustification.trim().length<20)&&t.push({activityId:e.id,activityName:e.name,type:"missing_lia",severity:"high",description:`Processing activity "${e.name}" relies on legitimate interests but lacks a detailed Legitimate Interest Assessment (NDPA Section 25(1)(f)).`}),e.involvesSensitiveData&&!e.sensitiveDataCondition&&t.push({activityId:e.id,activityName:e.name,type:"missing_sensitive_condition",severity:"high",description:`Processing activity "${e.name}" involves sensitive data but no condition under NDPA Section 27 has been specified.`}),(!e.retentionPeriod||e.retentionPeriod.trim()==="")&&t.push({activityId:e.id,activityName:e.name,type:"missing_retention",severity:"medium",description:`Processing activity "${e.name}" is missing a documented retention period.`}),(!e.dataCategories||e.dataCategories.length===0)&&t.push({activityId:e.id,activityName:e.name,type:"missing_data_categories",severity:"medium",description:`Processing activity "${e.name}" has no documented data categories.`}),(!e.purposes||e.purposes.length===0)&&t.push({activityId:e.id,activityName:e.name,type:"missing_purposes",severity:"medium",description:`Processing activity "${e.name}" has no documented processing purposes.`}));return t}function u(i){let t={consent:0,contract:0,legal_obligation:0,vital_interests:0,public_interest:0,legitimate_interests:0},e=0,a=0,n=[],r=[];for(let s of i)s.status!=="archived"&&(s.lawfulBasis in t&&t[s.lawfulBasis]++,s.involvesSensitiveData&&e++,s.crossBorderTransfer&&a++,s.reviewDate&&s.reviewDate<Date.now()&&n.push(s),(!s.dpoApproval||!s.dpoApproval.approved)&&r.push(s));return {totalActivities:i.filter(s=>s.status!=="archived").length,byBasis:t,sensitiveDataActivities:e,crossBorderActivities:a,activitiesDueForReview:n,activitiesWithoutApproval:r,lastUpdated:Date.now()}}export{o as a,c as b,p as c,u as d};//# sourceMappingURL=chunk-TXBZPCGF.mjs.map
2
+ //# sourceMappingURL=chunk-TXBZPCGF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/utils/lawful-basis.ts"],"names":["validateProcessingActivity","activity","errors","warnings","getLawfulBasisDescription","basis","assessComplianceGaps","activities","gaps","generateLawfulBasisSummary","byBasis","sensitiveDataActivities","crossBorderActivities","activitiesDueForReview","activitiesWithoutApproval","a"],"mappings":"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","file":"chunk-TXBZPCGF.mjs","sourcesContent":["import {\n LawfulBasis,\n ProcessingActivity,\n LawfulBasisSummary,\n} from '../types/lawful-basis';\n\n/**\n * Validation result for a processing activity\n */\nexport interface LawfulBasisValidationResult {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/**\n * Compliance gap identified across processing activities\n */\nexport interface LawfulBasisComplianceGap {\n activityId: string;\n activityName: string;\n type: 'missing_approval' | 'overdue_review' | 'missing_justification' | 'missing_lia' | 'missing_sensitive_condition' | 'missing_retention' | 'missing_data_categories' | 'missing_purposes';\n severity: 'high' | 'medium' | 'low';\n description: string;\n}\n\n/**\n * Validates that all required fields are present on a processing activity\n * and that the lawful basis is properly documented.\n *\n * If lawfulBasis is 'legitimate_interests', ensures a LIA justification exists.\n * If involvesSensitiveData is true, ensures sensitiveDataCondition is set.\n *\n * @param activity The processing activity to validate\n * @returns Validation result with errors and warnings\n */\nexport function validateProcessingActivity(activity: ProcessingActivity): LawfulBasisValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Required fields\n if (!activity.id) {\n errors.push('Activity ID is required.');\n }\n\n if (!activity.name || activity.name.trim() === '') {\n errors.push('Activity name is required.');\n }\n\n if (!activity.description || activity.description.trim() === '') {\n errors.push('Activity description is required.');\n }\n\n if (!activity.lawfulBasis) {\n errors.push('Lawful basis is required per NDPA Section 25.');\n }\n\n if (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim() === '') {\n errors.push('Justification for the lawful basis is required.');\n }\n\n if (!activity.dataCategories || activity.dataCategories.length === 0) {\n errors.push('At least one data category must be specified.');\n }\n\n if (!activity.dataSubjectCategories || activity.dataSubjectCategories.length === 0) {\n errors.push('At least one data subject category must be specified.');\n }\n\n if (!activity.purposes || activity.purposes.length === 0) {\n errors.push('At least one processing purpose must be specified.');\n }\n\n if (!activity.retentionPeriod || activity.retentionPeriod.trim() === '') {\n errors.push('Data retention period is required.');\n }\n\n // Legitimate interests requires additional justification (LIA)\n if (activity.lawfulBasis === 'legitimate_interests') {\n if (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim().length < 20) {\n errors.push(\n 'Legitimate interests requires a detailed Legitimate Interest Assessment (LIA) justification (NDPA Section 25(1)(f)).'\n );\n }\n }\n\n // Sensitive data requires a specific condition per NDPA Section 27\n if (activity.involvesSensitiveData && !activity.sensitiveDataCondition) {\n errors.push(\n 'Processing sensitive personal data requires specifying a condition under NDPA Section 27.'\n );\n }\n\n // Warnings for best practices\n if (!activity.dpoApproval) {\n warnings.push('Activity has not been approved by the DPO.');\n } else if (!activity.dpoApproval.approved) {\n warnings.push('Activity has a DPO review but has not been approved.');\n }\n\n if (!activity.reviewDate) {\n warnings.push('No review date has been set. Regular reviews are recommended.');\n } else if (activity.reviewDate < Date.now()) {\n warnings.push('Activity is overdue for review.');\n }\n\n if (!activity.retentionJustification) {\n warnings.push('Consider documenting the justification for the retention period.');\n }\n\n if (activity.crossBorderTransfer && (!activity.recipients || activity.recipients.length === 0)) {\n warnings.push(\n 'Cross-border transfer is indicated but no recipients are listed. Document the recipients or categories of recipients.'\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Returns a human-readable description of a lawful basis with the relevant\n * NDPA section reference.\n *\n * @param basis The lawful basis to describe\n * @returns Description string including NDPA section reference\n */\nexport function getLawfulBasisDescription(basis: LawfulBasis): string {\n const descriptions: Record<LawfulBasis, string> = {\n consent:\n 'Consent (NDPA Section 25(1)(a)) - The data subject has given consent to the processing of their personal data for one or more specific purposes.',\n contract:\n 'Contract (NDPA Section 25(1)(b)) - Processing is necessary for the performance of a contract to which the data subject is a party, or in order to take steps at the request of the data subject prior to entering into a contract.',\n legal_obligation:\n 'Legal Obligation (NDPA Section 25(1)(c)) - Processing is necessary for compliance with a legal obligation to which the data controller is subject.',\n vital_interests:\n 'Vital Interests (NDPA Section 25(1)(d)) - Processing is necessary to protect the vital interests of the data subject or another natural person.',\n public_interest:\n 'Public Interest (NDPA Section 25(1)(e)) - Processing is necessary for the performance of a task carried out in the public interest or in the exercise of official authority vested in the data controller.',\n legitimate_interests:\n 'Legitimate Interests (NDPA Section 25(1)(f)) - Processing is necessary for the purposes of the legitimate interests pursued by the data controller or a third party, except where such interests are overridden by the interests, rights, or freedoms of the data subject.',\n };\n\n return descriptions[basis];\n}\n\n/**\n * Analyzes all processing activities and returns compliance gaps including\n * missing DPO approval, overdue reviews, undocumented justifications,\n * missing LIA for legitimate interests, and other documentation issues.\n *\n * @param activities Array of processing activities to analyze\n * @returns Array of identified compliance gaps\n */\nexport function assessComplianceGaps(activities: ProcessingActivity[]): LawfulBasisComplianceGap[] {\n const gaps: LawfulBasisComplianceGap[] = [];\n\n for (const activity of activities) {\n // Skip archived activities\n if (activity.status === 'archived') {\n continue;\n }\n\n // Missing DPO approval\n if (!activity.dpoApproval || !activity.dpoApproval.approved) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_approval',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" has not been approved by the DPO.`,\n });\n }\n\n // Overdue review\n if (activity.reviewDate && activity.reviewDate < Date.now()) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'overdue_review',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" was due for review on ${new Date(activity.reviewDate).toLocaleDateString()}.`,\n });\n }\n\n // Missing justification\n if (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim() === '') {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_justification',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" is missing the lawful basis justification.`,\n });\n }\n\n // Missing LIA for legitimate interests\n if (\n activity.lawfulBasis === 'legitimate_interests' &&\n (!activity.lawfulBasisJustification || activity.lawfulBasisJustification.trim().length < 20)\n ) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_lia',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" relies on legitimate interests but lacks a detailed Legitimate Interest Assessment (NDPA Section 25(1)(f)).`,\n });\n }\n\n // Missing sensitive data condition\n if (activity.involvesSensitiveData && !activity.sensitiveDataCondition) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_sensitive_condition',\n severity: 'high',\n description: `Processing activity \"${activity.name}\" involves sensitive data but no condition under NDPA Section 27 has been specified.`,\n });\n }\n\n // Missing retention period\n if (!activity.retentionPeriod || activity.retentionPeriod.trim() === '') {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_retention',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" is missing a documented retention period.`,\n });\n }\n\n // Missing data categories\n if (!activity.dataCategories || activity.dataCategories.length === 0) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_data_categories',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" has no documented data categories.`,\n });\n }\n\n // Missing purposes\n if (!activity.purposes || activity.purposes.length === 0) {\n gaps.push({\n activityId: activity.id,\n activityName: activity.name,\n type: 'missing_purposes',\n severity: 'medium',\n description: `Processing activity \"${activity.name}\" has no documented processing purposes.`,\n });\n }\n }\n\n return gaps;\n}\n\n/**\n * Generates a summary of all lawful basis documentation across processing activities.\n *\n * @param activities Array of processing activities to summarize\n * @returns LawfulBasisSummary with counts, breakdowns, and flagged activities\n */\nexport function generateLawfulBasisSummary(activities: ProcessingActivity[]): LawfulBasisSummary {\n const byBasis: Record<LawfulBasis, number> = {\n consent: 0,\n contract: 0,\n legal_obligation: 0,\n vital_interests: 0,\n public_interest: 0,\n legitimate_interests: 0,\n };\n\n let sensitiveDataActivities = 0;\n let crossBorderActivities = 0;\n const activitiesDueForReview: ProcessingActivity[] = [];\n const activitiesWithoutApproval: ProcessingActivity[] = [];\n\n for (const activity of activities) {\n if (activity.status === 'archived') {\n continue;\n }\n\n // Count by lawful basis\n if (activity.lawfulBasis in byBasis) {\n byBasis[activity.lawfulBasis]++;\n }\n\n // Count sensitive data activities\n if (activity.involvesSensitiveData) {\n sensitiveDataActivities++;\n }\n\n // Count cross-border transfers\n if (activity.crossBorderTransfer) {\n crossBorderActivities++;\n }\n\n // Check for overdue reviews\n if (activity.reviewDate && activity.reviewDate < Date.now()) {\n activitiesDueForReview.push(activity);\n }\n\n // Check for missing DPO approval\n if (!activity.dpoApproval || !activity.dpoApproval.approved) {\n activitiesWithoutApproval.push(activity);\n }\n }\n\n return {\n totalActivities: activities.filter(a => a.status !== 'archived').length,\n byBasis,\n sensitiveDataActivities,\n crossBorderActivities,\n activitiesDueForReview,\n activitiesWithoutApproval,\n lastUpdated: Date.now(),\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkSWF3YVE5_js=require('./chunk-SWF3YVE5.js'),chunkMQFZHA2D_js=require('./chunk-MQFZHA2D.js'),e=require('react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var e__default=/*#__PURE__*/_interopDefault(e);var P=[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_interest",label:"Public Interest (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}],Q=[{value:"active",label:"Active"},{value:"inactive",label:"Inactive"},{value:"archived",label:"Archived"}],ve=[{value:"data_subject",label:"Directly from Data Subject"},{value:"third_party",label:"Third Party"},{value:"public_source",label:"Public Source"},{value:"other",label:"Other"}];function fe(){let s=Date.now();return {id:`proc_${s}_${Math.random().toString(36).substring(2,11)}`,name:"",description:"",controllerDetails:{name:"",contact:"",address:""},lawfulBasis:"consent",lawfulBasisJustification:"",purposes:[],dataCategories:[],dataSubjectCategories:[],recipients:[],retentionPeriod:"",securityMeasures:[],dataSource:"data_subject",dpiaRequired:false,automatedDecisionMaking:false,status:"active",createdAt:s,updatedAt:s}}function X(s){return s?new Date(s).toLocaleDateString():"N/A"}var he=({ropa:s,onAddRecord:h,onUpdateRecord:k,onArchiveRecord:w,title:Y="Record of Processing Activities (ROPA)",description:Z="Maintain a comprehensive record of all data processing activities as required by the NDPA 2023.",className:R="",buttonClassName:D=""})=>{let[m,c]=e.useState("list"),[f,ee]=e.useState(""),[y,te]=e.useState("all"),[N,re]=e.useState("all"),[a,g]=e.useState(null),[A,x]=e.useState([]),[F,B]=e.useState(""),[I,M]=e.useState(""),[L,j]=e.useState(""),[O,_]=e.useState(""),[E,T]=e.useState(""),[U,$]=e.useState(""),[J,q]=e.useState(""),i=e.useMemo(()=>chunkSWF3YVE5_js.b(s),[s]),b=e.useMemo(()=>chunkSWF3YVE5_js.d(s),[s]),V=e.useMemo(()=>{let r=[...s.records];if(y!=="all"&&(r=r.filter(t=>t.status===y)),N!=="all"&&(r=r.filter(t=>t.lawfulBasis===N)),f){let t=f.toLowerCase();r=r.filter(l=>l.name.toLowerCase().includes(t)||l.description.toLowerCase().includes(t)||l.dataCategories.some(n=>n.toLowerCase().includes(t))||l.department&&l.department.toLowerCase().includes(t));}return r},[s.records,y,N,f]);e.useEffect(()=>{a&&(B(a.purposes.join(", ")),M(a.dataCategories.join(", ")),j((a.sensitiveDataCategories||[]).join(", ")),_(a.dataSubjectCategories.join(", ")),T(a.recipients.join(", ")),$(a.securityMeasures.join(", ")),q((a.systemsUsed||[]).join(", ")));},[a==null?void 0:a.id]);let ae=()=>{let r=fe();r.controllerDetails.name=s.organizationName,r.controllerDetails.contact=s.organizationContact,r.controllerDetails.address=s.organizationAddress,s.ndpcRegistrationNumber&&(r.controllerDetails.registrationNumber=s.ndpcRegistrationNumber),s.dpoDetails&&(r.controllerDetails.dpoContact=s.dpoDetails.email),g(r),x([]),c("form");},se=r=>{g(chunkMQFZHA2D_js.a({},r)),x([]),c("form");},u=r=>r.split(",").map(t=>t.trim()).filter(t=>t.length>0),le=()=>{if(!a)return;let r=chunkMQFZHA2D_js.b(chunkMQFZHA2D_js.a({},a),{purposes:u(F),dataCategories:u(I),sensitiveDataCategories:u(L),dataSubjectCategories:u(O),recipients:u(E),securityMeasures:u(U),systemsUsed:u(J),updatedAt:Date.now()});r.sensitiveDataCategories&&r.sensitiveDataCategories.length===0&&(r.sensitiveDataCategories=void 0),r.systemsUsed&&r.systemsUsed.length===0&&(r.systemsUsed=void 0);let t=chunkSWF3YVE5_js.a(r);if(!t.valid){x(t.errors);return}s.records.find(n=>n.id===r.id)?k==null||k(r.id,r):h==null||h(r),g(null),x([]),c("list");},oe=r=>{w==null||w(r);},de=()=>{let r=chunkSWF3YVE5_js.c(s),t=new Blob([r],{type:"text/csv;charset=utf-8;"}),l=URL.createObjectURL(t),n=document.createElement("a");n.href=l,n.download=`ropa_${s.organizationName.replace(/\s+/g,"_").toLowerCase()}_${new Date().toISOString().slice(0,10)}.csv`,n.click(),setTimeout(()=>URL.revokeObjectURL(l),100);},z=()=>{g(null),x([]),c("list");},o=(r,t)=>{a&&g(l=>l&&chunkMQFZHA2D_js.b(chunkMQFZHA2D_js.a({},l),{[r]:t}));},C=(r,t)=>{a&&g(l=>l&&chunkMQFZHA2D_js.b(chunkMQFZHA2D_js.a({},l),{controllerDetails:chunkMQFZHA2D_js.b(chunkMQFZHA2D_js.a({},l.controllerDetails),{[r]:t})}));},ie=r=>!!r.nextReviewDate&&r.nextReviewDate<=Date.now(),ne=r=>{let t={active:"bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200",inactive:"bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200",archived:"bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300"},l={active:"Active",inactive:"Inactive",archived:"Archived"};return e__default.default.createElement("span",{className:`px-2 py-1 rounded text-xs font-medium ${t[r]}`},l[r])},ue=r=>e__default.default.createElement("span",{className:"px-2 py-1 rounded text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200"},{consent:"Consent",contract:"Contract",legal_obligation:"Legal Obligation",vital_interests:"Vital Interests",public_interest:"Public Interest",legitimate_interests:"Legitimate Interests"}[r]),me=()=>e__default.default.createElement("div",{className:"mb-6 p-4 bg-gray-50 dark:bg-gray-700 rounded-md"},e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("p",{className:"text-sm font-medium text-gray-500 dark:text-gray-400"},"Organization"),e__default.default.createElement("p",{className:"text-sm font-semibold"},s.organizationName)),s.dpoDetails&&e__default.default.createElement("div",null,e__default.default.createElement("p",{className:"text-sm font-medium text-gray-500 dark:text-gray-400"},"Data Protection Officer"),e__default.default.createElement("p",{className:"text-sm font-semibold"},s.dpoDetails.name),e__default.default.createElement("p",{className:"text-xs text-gray-500 dark:text-gray-400"},s.dpoDetails.email)),s.ndpcRegistrationNumber&&e__default.default.createElement("div",null,e__default.default.createElement("p",{className:"text-sm font-medium text-gray-500 dark:text-gray-400"},"NDPC Registration No."),e__default.default.createElement("p",{className:"text-sm font-semibold"},s.ndpcRegistrationNumber))),e__default.default.createElement("div",{className:"mt-2 text-xs text-gray-500 dark:text-gray-400"},"Version ",s.version," | Last Updated: ",X(s.lastUpdated))),ce=()=>e__default.default.createElement("div",{className:"mb-6"},e__default.default.createElement("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 mb-4"},e__default.default.createElement("div",{className:"p-4 bg-blue-50 dark:bg-blue-900/20 rounded-md text-center"},e__default.default.createElement("p",{className:"text-2xl font-bold text-blue-700 dark:text-blue-300"},i.totalRecords),e__default.default.createElement("p",{className:"text-xs text-blue-600 dark:text-blue-400"},"Total Records")),e__default.default.createElement("div",{className:"p-4 bg-green-50 dark:bg-green-900/20 rounded-md text-center"},e__default.default.createElement("p",{className:"text-2xl font-bold text-green-700 dark:text-green-300"},i.activeRecords),e__default.default.createElement("p",{className:"text-xs text-green-600 dark:text-green-400"},"Active")),e__default.default.createElement("div",{className:"p-4 bg-purple-50 dark:bg-purple-900/20 rounded-md text-center"},e__default.default.createElement("p",{className:"text-2xl font-bold text-purple-700 dark:text-purple-300"},i.crossBorderRecords),e__default.default.createElement("p",{className:"text-xs text-purple-600 dark:text-purple-400"},"Cross-Border")),e__default.default.createElement("div",{className:"p-4 bg-orange-50 dark:bg-orange-900/20 rounded-md text-center"},e__default.default.createElement("p",{className:"text-2xl font-bold text-orange-700 dark:text-orange-300"},b.length),e__default.default.createElement("p",{className:"text-xs text-orange-600 dark:text-orange-400"},"Records with Gaps"))),e__default.default.createElement("div",{className:"grid grid-cols-2 md:grid-cols-3 gap-4 mb-4"},e__default.default.createElement("div",{className:"p-3 bg-gray-50 dark:bg-gray-700 rounded-md"},e__default.default.createElement("p",{className:"text-sm font-medium mb-2"},"By Lawful Basis"),P.map(r=>e__default.default.createElement("div",{key:r.value,className:"flex justify-between text-xs mb-1"},e__default.default.createElement("span",{className:"text-gray-600 dark:text-gray-400"},r.label.split(" (")[0]),e__default.default.createElement("span",{className:"font-medium"},i.byLawfulBasis[r.value]||0)))),e__default.default.createElement("div",{className:"p-3 bg-gray-50 dark:bg-gray-700 rounded-md"},e__default.default.createElement("p",{className:"text-sm font-medium mb-2"},"Risk Indicators"),e__default.default.createElement("div",{className:"flex justify-between text-xs mb-1"},e__default.default.createElement("span",{className:"text-gray-600 dark:text-gray-400"},"Sensitive Data"),e__default.default.createElement("span",{className:"font-medium"},i.sensitiveDataRecords)),e__default.default.createElement("div",{className:"flex justify-between text-xs mb-1"},e__default.default.createElement("span",{className:"text-gray-600 dark:text-gray-400"},"DPIA Required"),e__default.default.createElement("span",{className:"font-medium"},i.dpiaRequiredRecords)),e__default.default.createElement("div",{className:"flex justify-between text-xs mb-1"},e__default.default.createElement("span",{className:"text-gray-600 dark:text-gray-400"},"Automated Decisions"),e__default.default.createElement("span",{className:"font-medium"},i.automatedDecisionRecords)),e__default.default.createElement("div",{className:"flex justify-between text-xs mb-1"},e__default.default.createElement("span",{className:"text-gray-600 dark:text-gray-400"},"Due for Review"),e__default.default.createElement("span",{className:`font-medium ${i.recordsDueForReview.length>0?"text-red-600 dark:text-red-400":""}`},i.recordsDueForReview.length))),i.topDepartments.length>0&&e__default.default.createElement("div",{className:"p-3 bg-gray-50 dark:bg-gray-700 rounded-md"},e__default.default.createElement("p",{className:"text-sm font-medium mb-2"},"Top Departments"),i.topDepartments.slice(0,5).map(r=>e__default.default.createElement("div",{key:r.department,className:"flex justify-between text-xs mb-1"},e__default.default.createElement("span",{className:"text-gray-600 dark:text-gray-400"},r.department),e__default.default.createElement("span",{className:"font-medium"},r.count))))),b.length>0&&e__default.default.createElement("div",{className:"p-3 bg-red-50 dark:bg-red-900/20 rounded-md"},e__default.default.createElement("p",{className:"text-sm font-medium text-red-800 dark:text-red-200 mb-2"},"Compliance Gaps Detected"),b.slice(0,5).map(r=>e__default.default.createElement("div",{key:r.recordId,className:"mb-2"},e__default.default.createElement("p",{className:"text-xs font-medium text-red-700 dark:text-red-300"},r.recordName),e__default.default.createElement("ul",{className:"list-disc list-inside"},r.gaps.map((t,l)=>e__default.default.createElement("li",{key:l,className:"text-xs text-red-600 dark:text-red-400"},t))))),b.length>5&&e__default.default.createElement("p",{className:"text-xs text-red-600 dark:text-red-400 mt-1"},"...and ",b.length-5," more record(s) with gaps."))),ge=()=>e__default.default.createElement("div",null,e__default.default.createElement("div",{className:"mb-4 grid grid-cols-1 md:grid-cols-4 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"ropaSearch",className:"block text-sm font-medium mb-1"},"Search"),e__default.default.createElement("input",{type:"text",id:"ropaSearch",value:f,onChange:r=>ee(r.target.value),placeholder:"Search records...",className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"ropaStatusFilter",className:"block text-sm font-medium mb-1"},"Status"),e__default.default.createElement("select",{id:"ropaStatusFilter",value:y,onChange:r=>te(r.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"},e__default.default.createElement("option",{value:"all"},"All Statuses"),Q.map(r=>e__default.default.createElement("option",{key:r.value,value:r.value},r.label)))),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"ropaBasisFilter",className:"block text-sm font-medium mb-1"},"Lawful Basis"),e__default.default.createElement("select",{id:"ropaBasisFilter",value:N,onChange:r=>re(r.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"},e__default.default.createElement("option",{value:"all"},"All Bases"),P.map(r=>e__default.default.createElement("option",{key:r.value,value:r.value},r.label.split(" (")[0])))),e__default.default.createElement("div",{className:"flex items-end space-x-2"},e__default.default.createElement("button",{onClick:ae,className:`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm ${D}`},"Add Record"),e__default.default.createElement("button",{onClick:de,className:`px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 text-sm ${D}`},"Export CSV"))),V.length===0?e__default.default.createElement("p",{className:"text-gray-500 dark:text-gray-400 text-sm text-center py-8"},"No processing records found."):e__default.default.createElement("div",{className:"overflow-x-auto"},e__default.default.createElement("table",{className:"w-full text-sm text-left"},e__default.default.createElement("thead",{className:"text-xs uppercase bg-gray-50 dark:bg-gray-700"},e__default.default.createElement("tr",null,e__default.default.createElement("th",{className:"px-4 py-3"},"Name"),e__default.default.createElement("th",{className:"px-4 py-3"},"Lawful Basis"),e__default.default.createElement("th",{className:"px-4 py-3"},"Data Categories"),e__default.default.createElement("th",{className:"px-4 py-3"},"Status"),e__default.default.createElement("th",{className:"px-4 py-3"},"Last Reviewed"),e__default.default.createElement("th",{className:"px-4 py-3"},"Actions"))),e__default.default.createElement("tbody",null,V.map(r=>{let t=ie(r),l=b.some(n=>n.recordId===r.id);return e__default.default.createElement("tr",{key:r.id,className:`border-b dark:border-gray-600 ${t?"bg-red-50 dark:bg-red-900/10":l?"bg-yellow-50 dark:bg-yellow-900/10":"bg-white dark:bg-gray-800"} hover:bg-gray-50 dark:hover:bg-gray-700`},e__default.default.createElement("td",{className:"px-4 py-3"},e__default.default.createElement("div",null,e__default.default.createElement("p",{className:"font-medium"},r.name),r.department&&e__default.default.createElement("p",{className:"text-xs text-gray-500 dark:text-gray-400"},r.department),t&&e__default.default.createElement("span",{className:"text-xs text-red-600 dark:text-red-400 font-medium"},"Review Overdue"))),e__default.default.createElement("td",{className:"px-4 py-3"},ue(r.lawfulBasis)),e__default.default.createElement("td",{className:"px-4 py-3"},e__default.default.createElement("p",{className:"text-xs text-gray-600 dark:text-gray-300 max-w-xs truncate"},r.dataCategories.join(", "))),e__default.default.createElement("td",{className:"px-4 py-3"},ne(r.status)),e__default.default.createElement("td",{className:"px-4 py-3 text-xs text-gray-500 dark:text-gray-400"},X(r.lastReviewedAt)),e__default.default.createElement("td",{className:"px-4 py-3"},e__default.default.createElement("div",{className:"flex space-x-2"},e__default.default.createElement("button",{onClick:()=>se(r),className:"text-blue-600 dark:text-blue-400 hover:underline text-xs"},"Edit"),r.status!=="archived"&&e__default.default.createElement("button",{onClick:()=>oe(r.id),className:"text-gray-600 dark:text-gray-400 hover:underline text-xs"},"Archive"))))}))))),be=()=>{if(!a)return null;let r=!s.records.find(t=>t.id===a.id);return e__default.default.createElement("div",null,e__default.default.createElement("div",{className:"flex justify-between items-center mb-4"},e__default.default.createElement("h3",{className:"text-lg font-medium"},r?"Add Processing Record":"Edit Processing Record"),e__default.default.createElement("button",{onClick:z,className:"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 text-sm"},"Cancel")),A.length>0&&e__default.default.createElement("div",{className:"mb-4 p-3 bg-red-50 dark:bg-red-900/20 rounded-md"},e__default.default.createElement("p",{className:"text-sm font-medium text-red-800 dark:text-red-200 mb-1"},"Please fix the following errors:"),e__default.default.createElement("ul",{className:"list-disc list-inside"},A.map((t,l)=>e__default.default.createElement("li",{key:l,className:"text-xs text-red-600 dark:text-red-400"},t)))),e__default.default.createElement("div",{className:"space-y-6"},e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Basic Information"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"recordName",className:"block text-sm font-medium mb-1"},"Activity Name *"),e__default.default.createElement("input",{type:"text",id:"recordName",value:a.name,onChange:t=>o("name",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Customer Account Management"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"recordDepartment",className:"block text-sm font-medium mb-1"},"Department"),e__default.default.createElement("input",{type:"text",id:"recordDepartment",value:a.department||"",onChange:t=>o("department",t.target.value||void 0),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Marketing"})),e__default.default.createElement("div",{className:"md:col-span-2"},e__default.default.createElement("label",{htmlFor:"recordDescription",className:"block text-sm font-medium mb-1"},"Description *"),e__default.default.createElement("textarea",{id:"recordDescription",value:a.description,onChange:t=>o("description",t.target.value),rows:3,className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"Describe what personal data processing is performed..."})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"recordStatus",className:"block text-sm font-medium mb-1"},"Status *"),e__default.default.createElement("select",{id:"recordStatus",value:a.status,onChange:t=>o("status",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"},Q.map(t=>e__default.default.createElement("option",{key:t.value,value:t.value},t.label)))))),e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Controller Details"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"controllerName",className:"block text-sm font-medium mb-1"},"Controller Name *"),e__default.default.createElement("input",{type:"text",id:"controllerName",value:a.controllerDetails.name,onChange:t=>C("name",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"controllerContact",className:"block text-sm font-medium mb-1"},"Controller Contact *"),e__default.default.createElement("input",{type:"text",id:"controllerContact",value:a.controllerDetails.contact,onChange:t=>C("contact",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"})),e__default.default.createElement("div",{className:"md:col-span-2"},e__default.default.createElement("label",{htmlFor:"controllerAddress",className:"block text-sm font-medium mb-1"},"Controller Address *"),e__default.default.createElement("input",{type:"text",id:"controllerAddress",value:a.controllerDetails.address,onChange:t=>C("address",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"})))),e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Lawful Basis (NDPA Section 25)"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"lawfulBasis",className:"block text-sm font-medium mb-1"},"Lawful Basis *"),e__default.default.createElement("select",{id:"lawfulBasis",value:a.lawfulBasis,onChange:t=>o("lawfulBasis",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"},P.map(t=>e__default.default.createElement("option",{key:t.value,value:t.value},t.label)))),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"lawfulBasisJustification",className:"block text-sm font-medium mb-1"},"Justification *"),e__default.default.createElement("textarea",{id:"lawfulBasisJustification",value:a.lawfulBasisJustification,onChange:t=>o("lawfulBasisJustification",t.target.value),rows:2,className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"Explain why this lawful basis applies..."})))),e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Data Details"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"purposes",className:"block text-sm font-medium mb-1"},"Purposes * (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"purposes",value:F,onChange:t=>B(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Account management, Service delivery"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"dataCategories",className:"block text-sm font-medium mb-1"},"Data Categories * (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"dataCategories",value:I,onChange:t=>M(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Name, Email, Phone number"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"sensitiveData",className:"block text-sm font-medium mb-1"},"Sensitive Data Categories (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"sensitiveData",value:L,onChange:t=>j(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Health data, Biometric data"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"subjectCategories",className:"block text-sm font-medium mb-1"},"Data Subject Categories * (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"subjectCategories",value:O,onChange:t=>_(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Customers, Employees"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"recipients",className:"block text-sm font-medium mb-1"},"Recipients * (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"recipients",value:E,onChange:t=>T(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Payment processors, Cloud service providers"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"dataSource",className:"block text-sm font-medium mb-1"},"Data Source *"),e__default.default.createElement("select",{id:"dataSource",value:a.dataSource,onChange:t=>o("dataSource",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"},ve.map(t=>e__default.default.createElement("option",{key:t.value,value:t.value},t.label)))),a.dataSource==="third_party"&&e__default.default.createElement("div",{className:"md:col-span-2"},e__default.default.createElement("label",{htmlFor:"thirdPartyDetails",className:"block text-sm font-medium mb-1"},"Third-Party Source Details *"),e__default.default.createElement("input",{type:"text",id:"thirdPartyDetails",value:a.thirdPartySourceDetails||"",onChange:t=>o("thirdPartySourceDetails",t.target.value||void 0),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"Describe the third-party data source..."})))),e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Retention and Security"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"retentionPeriod",className:"block text-sm font-medium mb-1"},"Retention Period *"),e__default.default.createElement("input",{type:"text",id:"retentionPeriod",value:a.retentionPeriod,onChange:t=>o("retentionPeriod",t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., 5 years after account closure"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"retentionJustification",className:"block text-sm font-medium mb-1"},"Retention Justification"),e__default.default.createElement("input",{type:"text",id:"retentionJustification",value:a.retentionJustification||"",onChange:t=>o("retentionJustification",t.target.value||void 0),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"Why this retention period is necessary..."})),e__default.default.createElement("div",{className:"md:col-span-2"},e__default.default.createElement("label",{htmlFor:"securityMeasures",className:"block text-sm font-medium mb-1"},"Security Measures * (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"securityMeasures",value:U,onChange:t=>$(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., Encryption at rest, Access controls, Audit logging"})),e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"systemsUsed",className:"block text-sm font-medium mb-1"},"Systems Used (comma-separated)"),e__default.default.createElement("input",{type:"text",id:"systemsUsed",value:J,onChange:t=>q(t.target.value),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"e.g., CRM, ERP, Cloud Storage"})))),e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Risk Indicators"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",{className:"flex items-center space-x-2"},e__default.default.createElement("input",{type:"checkbox",id:"dpiaRequired",checked:a.dpiaRequired,onChange:t=>o("dpiaRequired",t.target.checked),className:"rounded border-gray-300 dark:border-gray-600"}),e__default.default.createElement("label",{htmlFor:"dpiaRequired",className:"text-sm font-medium"},"DPIA Required")),a.dpiaRequired&&e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"dpiaReference",className:"block text-sm font-medium mb-1"},"DPIA Reference *"),e__default.default.createElement("input",{type:"text",id:"dpiaReference",value:a.dpiaReference||"",onChange:t=>o("dpiaReference",t.target.value||void 0),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"Reference to the completed DPIA"})),e__default.default.createElement("div",{className:"flex items-center space-x-2"},e__default.default.createElement("input",{type:"checkbox",id:"automatedDecisionMaking",checked:a.automatedDecisionMaking,onChange:t=>o("automatedDecisionMaking",t.target.checked),className:"rounded border-gray-300 dark:border-gray-600"}),e__default.default.createElement("label",{htmlFor:"automatedDecisionMaking",className:"text-sm font-medium"},"Automated Decision-Making")),a.automatedDecisionMaking&&e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"automatedDecisionMakingDetails",className:"block text-sm font-medium mb-1"},"Automated Decision-Making Details *"),e__default.default.createElement("textarea",{id:"automatedDecisionMakingDetails",value:a.automatedDecisionMakingDetails||"",onChange:t=>o("automatedDecisionMakingDetails",t.target.value||void 0),rows:2,className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:"Describe the automated decision-making process..."})))),e__default.default.createElement("fieldset",{className:"border border-gray-200 dark:border-gray-600 rounded-md p-4"},e__default.default.createElement("legend",{className:"text-sm font-medium px-2"},"Review Schedule"),e__default.default.createElement("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4"},e__default.default.createElement("div",null,e__default.default.createElement("label",{htmlFor:"nextReviewDate",className:"block text-sm font-medium mb-1"},"Next Review Date"),e__default.default.createElement("input",{type:"date",id:"nextReviewDate",value:a.nextReviewDate?new Date(a.nextReviewDate).toISOString().slice(0,10):"",onChange:t=>o("nextReviewDate",t.target.value?new Date(t.target.value).getTime():void 0),className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"})))),e__default.default.createElement("div",{className:"flex justify-end space-x-3"},e__default.default.createElement("button",{onClick:z,className:"px-4 py-2 border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-sm"},"Cancel"),e__default.default.createElement("button",{onClick:le,className:`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm ${D}`},r?"Add Record":"Save Changes"))))},pe=()=>e__default.default.createElement("div",{className:"flex space-x-4 mb-6 border-b border-gray-200 dark:border-gray-600"},e__default.default.createElement("button",{onClick:()=>c("list"),className:`pb-2 text-sm font-medium ${m==="list"?"border-b-2 border-blue-500 text-blue-600 dark:text-blue-400":"text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"}`},"Processing Records"),e__default.default.createElement("button",{onClick:()=>c("summary"),className:`pb-2 text-sm font-medium ${m==="summary"?"border-b-2 border-blue-500 text-blue-600 dark:text-blue-400":"text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"}`},"Compliance Summary"));return e__default.default.createElement("div",{className:`bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md ${R}`},e__default.default.createElement("h2",{className:"text-xl font-bold mb-2"},Y),e__default.default.createElement("p",{className:"mb-6 text-gray-600 dark:text-gray-300"},Z),me(),m!=="form"&&pe(),m==="list"&&ge(),m==="summary"&&ce(),m==="form"&&be())};exports.a=he;//# sourceMappingURL=chunk-UUWVBENC.js.map
2
+ //# sourceMappingURL=chunk-UUWVBENC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/components/ropa/ROPAManager.tsx"],"names":["LAWFUL_BASIS_OPTIONS","STATUS_OPTIONS","DATA_SOURCE_OPTIONS","createEmptyRecord","now","formatDate","timestamp","ROPAManager","ropa","onAddRecord","onUpdateRecord","onArchiveRecord","title","description","className","buttonClassName","viewMode","setViewMode","useState","searchTerm","setSearchTerm","statusFilter","setStatusFilter","basisFilter","setBasisFilter","editingRecord","setEditingRecord","formErrors","setFormErrors","purposesInput","setPurposesInput","dataCategoriesInput","setDataCategoriesInput","sensitiveDataInput","setSensitiveDataInput","subjectCategoriesInput","setSubjectCategoriesInput","recipientsInput","setRecipientsInput","securityMeasuresInput","setSecurityMeasuresInput","systemsUsedInput","setSystemsUsedInput","summary","useMemo","generateROPASummary","complianceGaps","identifyComplianceGaps","filteredRecords","filtered","r","term","c","useEffect","handleNewRecord","newRecord","handleEditRecord","record","__spreadValues","parseCommaSeparated","value","s","handleSaveRecord","recordToSave","__spreadProps","validation","validateProcessingRecord","handleArchiveRecord","id","handleExportCSV","csv","exportROPAToCSV","blob","url","link","handleCancelForm","updateEditingField","field","prev","updateControllerField","isReviewOverdue","renderStatusBadge","status","colorClasses","labels","React","renderBasisBadge","basis","renderOrganizationHeader","renderSummaryDashboard","option","dept","gap","g","i","renderRecordsTable","e","opt","overdue","hasGaps","renderForm","isNew","error","renderViewTabs"],"mappings":"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","file":"chunk-UUWVBENC.js","sourcesContent":["import React, { useState, useEffect, useMemo } from 'react';\nimport type { LawfulBasis } from '../../types/lawful-basis';\nimport type {\n ProcessingRecord,\n RecordOfProcessingActivities,\n ROPASummary,\n} from '../../types/ropa';\nimport type { ROPAComplianceGap } from '../../utils/ropa';\nimport {\n validateProcessingRecord,\n generateROPASummary,\n exportROPAToCSV,\n identifyComplianceGaps,\n} from '../../utils/ropa';\n\nexport interface ROPAManagerProps {\n /**\n * The full Record of Processing Activities\n */\n ropa: RecordOfProcessingActivities;\n\n /**\n * Callback when a new record is added\n */\n onAddRecord?: (record: ProcessingRecord) => void;\n\n /**\n * Callback when a record is updated\n */\n onUpdateRecord?: (id: string, updates: Partial<ProcessingRecord>) => void;\n\n /**\n * Callback when a record is archived\n */\n onArchiveRecord?: (id: string) => void;\n\n /**\n * Title displayed on the manager\n * @default \"Record of Processing Activities (ROPA)\"\n */\n title?: string;\n\n /**\n * Description text\n * @default \"Maintain a comprehensive record of all data processing activities as required by the NDPA 2023.\"\n */\n description?: string;\n\n /**\n * Custom CSS class\n */\n className?: string;\n\n /**\n * Custom CSS class for buttons\n */\n buttonClassName?: string;\n}\n\nconst LAWFUL_BASIS_OPTIONS: Array<{ value: LawfulBasis; label: string }> = [\n { value: 'consent', label: 'Consent (Section 25(1)(a))' },\n { value: 'contract', label: 'Contract (Section 25(1)(b))' },\n { value: 'legal_obligation', label: 'Legal Obligation (Section 25(1)(c))' },\n { value: 'vital_interests', label: 'Vital Interests (Section 25(1)(d))' },\n { value: 'public_interest', label: 'Public Interest (Section 25(1)(e))' },\n { value: 'legitimate_interests', label: 'Legitimate Interests (Section 25(1)(f))' },\n];\n\nconst STATUS_OPTIONS: Array<{ value: ProcessingRecord['status']; label: string }> = [\n { value: 'active', label: 'Active' },\n { value: 'inactive', label: 'Inactive' },\n { value: 'archived', label: 'Archived' },\n];\n\nconst DATA_SOURCE_OPTIONS: Array<{ value: ProcessingRecord['dataSource']; label: string }> = [\n { value: 'data_subject', label: 'Directly from Data Subject' },\n { value: 'third_party', label: 'Third Party' },\n { value: 'public_source', label: 'Public Source' },\n { value: 'other', label: 'Other' },\n];\n\ntype ViewMode = 'list' | 'form' | 'summary';\n\nfunction createEmptyRecord(): ProcessingRecord {\n const now = Date.now();\n return {\n id: `proc_${now}_${Math.random().toString(36).substring(2, 11)}`,\n name: '',\n description: '',\n controllerDetails: { name: '', contact: '', address: '' },\n lawfulBasis: 'consent',\n lawfulBasisJustification: '',\n purposes: [],\n dataCategories: [],\n dataSubjectCategories: [],\n recipients: [],\n retentionPeriod: '',\n securityMeasures: [],\n dataSource: 'data_subject',\n dpiaRequired: false,\n automatedDecisionMaking: false,\n status: 'active',\n createdAt: now,\n updatedAt: now,\n };\n}\n\nfunction formatDate(timestamp: number | undefined): string {\n if (!timestamp) return 'N/A';\n return new Date(timestamp).toLocaleDateString();\n}\n\nexport const ROPAManager: React.FC<ROPAManagerProps> = ({\n ropa,\n onAddRecord,\n onUpdateRecord,\n onArchiveRecord,\n title = 'Record of Processing Activities (ROPA)',\n description = 'Maintain a comprehensive record of all data processing activities as required by the NDPA 2023.',\n className = '',\n buttonClassName = '',\n}) => {\n const [viewMode, setViewMode] = useState<ViewMode>('list');\n const [searchTerm, setSearchTerm] = useState('');\n const [statusFilter, setStatusFilter] = useState<string>('all');\n const [basisFilter, setBasisFilter] = useState<string>('all');\n const [editingRecord, setEditingRecord] = useState<ProcessingRecord | null>(null);\n const [formErrors, setFormErrors] = useState<string[]>([]);\n\n // Temporary field values for comma-separated list inputs\n const [purposesInput, setPurposesInput] = useState('');\n const [dataCategoriesInput, setDataCategoriesInput] = useState('');\n const [sensitiveDataInput, setSensitiveDataInput] = useState('');\n const [subjectCategoriesInput, setSubjectCategoriesInput] = useState('');\n const [recipientsInput, setRecipientsInput] = useState('');\n const [securityMeasuresInput, setSecurityMeasuresInput] = useState('');\n const [systemsUsedInput, setSystemsUsedInput] = useState('');\n\n const summary = useMemo(() => generateROPASummary(ropa), [ropa]);\n const complianceGaps = useMemo(() => identifyComplianceGaps(ropa), [ropa]);\n\n // Filter records\n const filteredRecords = useMemo(() => {\n let filtered = [...ropa.records];\n\n if (statusFilter !== 'all') {\n filtered = filtered.filter((r) => r.status === statusFilter);\n }\n\n if (basisFilter !== 'all') {\n filtered = filtered.filter((r) => r.lawfulBasis === basisFilter);\n }\n\n if (searchTerm) {\n const term = searchTerm.toLowerCase();\n filtered = filtered.filter(\n (r) =>\n r.name.toLowerCase().includes(term) ||\n r.description.toLowerCase().includes(term) ||\n r.dataCategories.some((c) => c.toLowerCase().includes(term)) ||\n (r.department && r.department.toLowerCase().includes(term))\n );\n }\n\n return filtered;\n }, [ropa.records, statusFilter, basisFilter, searchTerm]);\n\n // Sync form inputs when editing record changes\n useEffect(() => {\n if (editingRecord) {\n setPurposesInput(editingRecord.purposes.join(', '));\n setDataCategoriesInput(editingRecord.dataCategories.join(', '));\n setSensitiveDataInput((editingRecord.sensitiveDataCategories || []).join(', '));\n setSubjectCategoriesInput(editingRecord.dataSubjectCategories.join(', '));\n setRecipientsInput(editingRecord.recipients.join(', '));\n setSecurityMeasuresInput(editingRecord.securityMeasures.join(', '));\n setSystemsUsedInput((editingRecord.systemsUsed || []).join(', '));\n }\n }, [editingRecord?.id]);\n\n const handleNewRecord = () => {\n const newRecord = createEmptyRecord();\n // Prefill controller details from the organization\n newRecord.controllerDetails.name = ropa.organizationName;\n newRecord.controllerDetails.contact = ropa.organizationContact;\n newRecord.controllerDetails.address = ropa.organizationAddress;\n if (ropa.ndpcRegistrationNumber) {\n newRecord.controllerDetails.registrationNumber = ropa.ndpcRegistrationNumber;\n }\n if (ropa.dpoDetails) {\n newRecord.controllerDetails.dpoContact = ropa.dpoDetails.email;\n }\n setEditingRecord(newRecord);\n setFormErrors([]);\n setViewMode('form');\n };\n\n const handleEditRecord = (record: ProcessingRecord) => {\n setEditingRecord({ ...record });\n setFormErrors([]);\n setViewMode('form');\n };\n\n const parseCommaSeparated = (value: string): string[] => {\n return value\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n };\n\n const handleSaveRecord = () => {\n if (!editingRecord) return;\n\n // Apply comma-separated inputs to the record\n const recordToSave: ProcessingRecord = {\n ...editingRecord,\n purposes: parseCommaSeparated(purposesInput),\n dataCategories: parseCommaSeparated(dataCategoriesInput),\n sensitiveDataCategories: parseCommaSeparated(sensitiveDataInput),\n dataSubjectCategories: parseCommaSeparated(subjectCategoriesInput),\n recipients: parseCommaSeparated(recipientsInput),\n securityMeasures: parseCommaSeparated(securityMeasuresInput),\n systemsUsed: parseCommaSeparated(systemsUsedInput),\n updatedAt: Date.now(),\n };\n\n // Remove empty sensitive data categories\n if (\n recordToSave.sensitiveDataCategories &&\n recordToSave.sensitiveDataCategories.length === 0\n ) {\n recordToSave.sensitiveDataCategories = undefined;\n }\n\n // Remove empty systems used\n if (recordToSave.systemsUsed && recordToSave.systemsUsed.length === 0) {\n recordToSave.systemsUsed = undefined;\n }\n\n const validation = validateProcessingRecord(recordToSave);\n if (!validation.valid) {\n setFormErrors(validation.errors);\n return;\n }\n\n // Check if this is a new record or an update\n const existingRecord = ropa.records.find((r) => r.id === recordToSave.id);\n if (existingRecord) {\n onUpdateRecord?.(recordToSave.id, recordToSave);\n } else {\n onAddRecord?.(recordToSave);\n }\n\n setEditingRecord(null);\n setFormErrors([]);\n setViewMode('list');\n };\n\n const handleArchiveRecord = (id: string) => {\n onArchiveRecord?.(id);\n };\n\n const handleExportCSV = () => {\n const csv = exportROPAToCSV(ropa);\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `ropa_${ropa.organizationName.replace(/\\s+/g, '_').toLowerCase()}_${new Date().toISOString().slice(0, 10)}.csv`;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 100);\n };\n\n const handleCancelForm = () => {\n setEditingRecord(null);\n setFormErrors([]);\n setViewMode('list');\n };\n\n const updateEditingField = (field: string, value: any) => {\n if (!editingRecord) return;\n setEditingRecord((prev) => (prev ? { ...prev, [field]: value } : prev));\n };\n\n const updateControllerField = (field: string, value: string) => {\n if (!editingRecord) return;\n setEditingRecord((prev) =>\n prev\n ? {\n ...prev,\n controllerDetails: { ...prev.controllerDetails, [field]: value },\n }\n : prev\n );\n };\n\n const isReviewOverdue = (record: ProcessingRecord): boolean => {\n return !!record.nextReviewDate && record.nextReviewDate <= Date.now();\n };\n\n // Status badge rendering\n const renderStatusBadge = (status: ProcessingRecord['status']) => {\n const colorClasses: Record<ProcessingRecord['status'], string> = {\n active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',\n inactive: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',\n archived: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',\n };\n\n const labels: Record<ProcessingRecord['status'], string> = {\n active: 'Active',\n inactive: 'Inactive',\n archived: 'Archived',\n };\n\n return (\n <span className={`px-2 py-1 rounded text-xs font-medium ${colorClasses[status]}`}>\n {labels[status]}\n </span>\n );\n };\n\n // Lawful basis badge rendering\n const renderBasisBadge = (basis: LawfulBasis) => {\n const labels: Record<LawfulBasis, string> = {\n consent: 'Consent',\n contract: 'Contract',\n legal_obligation: 'Legal Obligation',\n vital_interests: 'Vital Interests',\n public_interest: 'Public Interest',\n legitimate_interests: 'Legitimate Interests',\n };\n\n return (\n <span className=\"px-2 py-1 rounded text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200\">\n {labels[basis]}\n </span>\n );\n };\n\n // Render organization header\n const renderOrganizationHeader = () => (\n <div className=\"mb-6 p-4 bg-gray-50 dark:bg-gray-700 rounded-md\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div>\n <p className=\"text-sm font-medium text-gray-500 dark:text-gray-400\">Organization</p>\n <p className=\"text-sm font-semibold\">{ropa.organizationName}</p>\n </div>\n {ropa.dpoDetails && (\n <div>\n <p className=\"text-sm font-medium text-gray-500 dark:text-gray-400\">\n Data Protection Officer\n </p>\n <p className=\"text-sm font-semibold\">{ropa.dpoDetails.name}</p>\n <p className=\"text-xs text-gray-500 dark:text-gray-400\">{ropa.dpoDetails.email}</p>\n </div>\n )}\n {ropa.ndpcRegistrationNumber && (\n <div>\n <p className=\"text-sm font-medium text-gray-500 dark:text-gray-400\">\n NDPC Registration No.\n </p>\n <p className=\"text-sm font-semibold\">{ropa.ndpcRegistrationNumber}</p>\n </div>\n )}\n </div>\n <div className=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">\n Version {ropa.version} | Last Updated: {formatDate(ropa.lastUpdated)}\n </div>\n </div>\n );\n\n // Render compliance summary dashboard\n const renderSummaryDashboard = () => (\n <div className=\"mb-6\">\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-4\">\n <div className=\"p-4 bg-blue-50 dark:bg-blue-900/20 rounded-md text-center\">\n <p className=\"text-2xl font-bold text-blue-700 dark:text-blue-300\">\n {summary.totalRecords}\n </p>\n <p className=\"text-xs text-blue-600 dark:text-blue-400\">Total Records</p>\n </div>\n <div className=\"p-4 bg-green-50 dark:bg-green-900/20 rounded-md text-center\">\n <p className=\"text-2xl font-bold text-green-700 dark:text-green-300\">\n {summary.activeRecords}\n </p>\n <p className=\"text-xs text-green-600 dark:text-green-400\">Active</p>\n </div>\n <div className=\"p-4 bg-purple-50 dark:bg-purple-900/20 rounded-md text-center\">\n <p className=\"text-2xl font-bold text-purple-700 dark:text-purple-300\">\n {summary.crossBorderRecords}\n </p>\n <p className=\"text-xs text-purple-600 dark:text-purple-400\">Cross-Border</p>\n </div>\n <div className=\"p-4 bg-orange-50 dark:bg-orange-900/20 rounded-md text-center\">\n <p className=\"text-2xl font-bold text-orange-700 dark:text-orange-300\">\n {complianceGaps.length}\n </p>\n <p className=\"text-xs text-orange-600 dark:text-orange-400\">Records with Gaps</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-3 gap-4 mb-4\">\n <div className=\"p-3 bg-gray-50 dark:bg-gray-700 rounded-md\">\n <p className=\"text-sm font-medium mb-2\">By Lawful Basis</p>\n {LAWFUL_BASIS_OPTIONS.map((option) => (\n <div key={option.value} className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-gray-600 dark:text-gray-400\">{option.label.split(' (')[0]}</span>\n <span className=\"font-medium\">{summary.byLawfulBasis[option.value] || 0}</span>\n </div>\n ))}\n </div>\n <div className=\"p-3 bg-gray-50 dark:bg-gray-700 rounded-md\">\n <p className=\"text-sm font-medium mb-2\">Risk Indicators</p>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-gray-600 dark:text-gray-400\">Sensitive Data</span>\n <span className=\"font-medium\">{summary.sensitiveDataRecords}</span>\n </div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-gray-600 dark:text-gray-400\">DPIA Required</span>\n <span className=\"font-medium\">{summary.dpiaRequiredRecords}</span>\n </div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-gray-600 dark:text-gray-400\">Automated Decisions</span>\n <span className=\"font-medium\">{summary.automatedDecisionRecords}</span>\n </div>\n <div className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-gray-600 dark:text-gray-400\">Due for Review</span>\n <span className={`font-medium ${summary.recordsDueForReview.length > 0 ? 'text-red-600 dark:text-red-400' : ''}`}>\n {summary.recordsDueForReview.length}\n </span>\n </div>\n </div>\n {summary.topDepartments.length > 0 && (\n <div className=\"p-3 bg-gray-50 dark:bg-gray-700 rounded-md\">\n <p className=\"text-sm font-medium mb-2\">Top Departments</p>\n {summary.topDepartments.slice(0, 5).map((dept) => (\n <div key={dept.department} className=\"flex justify-between text-xs mb-1\">\n <span className=\"text-gray-600 dark:text-gray-400\">{dept.department}</span>\n <span className=\"font-medium\">{dept.count}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {complianceGaps.length > 0 && (\n <div className=\"p-3 bg-red-50 dark:bg-red-900/20 rounded-md\">\n <p className=\"text-sm font-medium text-red-800 dark:text-red-200 mb-2\">\n Compliance Gaps Detected\n </p>\n {complianceGaps.slice(0, 5).map((gap) => (\n <div key={gap.recordId} className=\"mb-2\">\n <p className=\"text-xs font-medium text-red-700 dark:text-red-300\">{gap.recordName}</p>\n <ul className=\"list-disc list-inside\">\n {gap.gaps.map((g, i) => (\n <li key={i} className=\"text-xs text-red-600 dark:text-red-400\">\n {g}\n </li>\n ))}\n </ul>\n </div>\n ))}\n {complianceGaps.length > 5 && (\n <p className=\"text-xs text-red-600 dark:text-red-400 mt-1\">\n ...and {complianceGaps.length - 5} more record(s) with gaps.\n </p>\n )}\n </div>\n )}\n </div>\n );\n\n // Render the records table\n const renderRecordsTable = () => (\n <div>\n {/* Filters */}\n <div className=\"mb-4 grid grid-cols-1 md:grid-cols-4 gap-4\">\n <div>\n <label htmlFor=\"ropaSearch\" className=\"block text-sm font-medium mb-1\">\n Search\n </label>\n <input\n type=\"text\"\n id=\"ropaSearch\"\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n placeholder=\"Search records...\"\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n <div>\n <label htmlFor=\"ropaStatusFilter\" className=\"block text-sm font-medium mb-1\">\n Status\n </label>\n <select\n id=\"ropaStatusFilter\"\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"all\">All Statuses</option>\n {STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"ropaBasisFilter\" className=\"block text-sm font-medium mb-1\">\n Lawful Basis\n </label>\n <select\n id=\"ropaBasisFilter\"\n value={basisFilter}\n onChange={(e) => setBasisFilter(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"all\">All Bases</option>\n {LAWFUL_BASIS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label.split(' (')[0]}\n </option>\n ))}\n </select>\n </div>\n <div className=\"flex items-end space-x-2\">\n <button\n onClick={handleNewRecord}\n className={`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm ${buttonClassName}`}\n >\n Add Record\n </button>\n <button\n onClick={handleExportCSV}\n className={`px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 text-sm ${buttonClassName}`}\n >\n Export CSV\n </button>\n </div>\n </div>\n\n {/* Table */}\n {filteredRecords.length === 0 ? (\n <p className=\"text-gray-500 dark:text-gray-400 text-sm text-center py-8\">\n No processing records found.\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full text-sm text-left\">\n <thead className=\"text-xs uppercase bg-gray-50 dark:bg-gray-700\">\n <tr>\n <th className=\"px-4 py-3\">Name</th>\n <th className=\"px-4 py-3\">Lawful Basis</th>\n <th className=\"px-4 py-3\">Data Categories</th>\n <th className=\"px-4 py-3\">Status</th>\n <th className=\"px-4 py-3\">Last Reviewed</th>\n <th className=\"px-4 py-3\">Actions</th>\n </tr>\n </thead>\n <tbody>\n {filteredRecords.map((record) => {\n const overdue = isReviewOverdue(record);\n const hasGaps = complianceGaps.some((g) => g.recordId === record.id);\n\n return (\n <tr\n key={record.id}\n className={`border-b dark:border-gray-600 ${\n overdue\n ? 'bg-red-50 dark:bg-red-900/10'\n : hasGaps\n ? 'bg-yellow-50 dark:bg-yellow-900/10'\n : 'bg-white dark:bg-gray-800'\n } hover:bg-gray-50 dark:hover:bg-gray-700`}\n >\n <td className=\"px-4 py-3\">\n <div>\n <p className=\"font-medium\">{record.name}</p>\n {record.department && (\n <p className=\"text-xs text-gray-500 dark:text-gray-400\">\n {record.department}\n </p>\n )}\n {overdue && (\n <span className=\"text-xs text-red-600 dark:text-red-400 font-medium\">\n Review Overdue\n </span>\n )}\n </div>\n </td>\n <td className=\"px-4 py-3\">{renderBasisBadge(record.lawfulBasis)}</td>\n <td className=\"px-4 py-3\">\n <p className=\"text-xs text-gray-600 dark:text-gray-300 max-w-xs truncate\">\n {record.dataCategories.join(', ')}\n </p>\n </td>\n <td className=\"px-4 py-3\">{renderStatusBadge(record.status)}</td>\n <td className=\"px-4 py-3 text-xs text-gray-500 dark:text-gray-400\">\n {formatDate(record.lastReviewedAt)}\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"flex space-x-2\">\n <button\n onClick={() => handleEditRecord(record)}\n className=\"text-blue-600 dark:text-blue-400 hover:underline text-xs\"\n >\n Edit\n </button>\n {record.status !== 'archived' && (\n <button\n onClick={() => handleArchiveRecord(record.id)}\n className=\"text-gray-600 dark:text-gray-400 hover:underline text-xs\"\n >\n Archive\n </button>\n )}\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n )}\n </div>\n );\n\n // Render the add/edit form\n const renderForm = () => {\n if (!editingRecord) return null;\n\n const isNew = !ropa.records.find((r) => r.id === editingRecord.id);\n\n return (\n <div>\n <div className=\"flex justify-between items-center mb-4\">\n <h3 className=\"text-lg font-medium\">\n {isNew ? 'Add Processing Record' : 'Edit Processing Record'}\n </h3>\n <button\n onClick={handleCancelForm}\n className=\"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 text-sm\"\n >\n Cancel\n </button>\n </div>\n\n {formErrors.length > 0 && (\n <div className=\"mb-4 p-3 bg-red-50 dark:bg-red-900/20 rounded-md\">\n <p className=\"text-sm font-medium text-red-800 dark:text-red-200 mb-1\">\n Please fix the following errors:\n </p>\n <ul className=\"list-disc list-inside\">\n {formErrors.map((error, i) => (\n <li key={i} className=\"text-xs text-red-600 dark:text-red-400\">\n {error}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div className=\"space-y-6\">\n {/* Basic Information */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Basic Information</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label htmlFor=\"recordName\" className=\"block text-sm font-medium mb-1\">\n Activity Name *\n </label>\n <input\n type=\"text\"\n id=\"recordName\"\n value={editingRecord.name}\n onChange={(e) => updateEditingField('name', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Customer Account Management\"\n />\n </div>\n <div>\n <label htmlFor=\"recordDepartment\" className=\"block text-sm font-medium mb-1\">\n Department\n </label>\n <input\n type=\"text\"\n id=\"recordDepartment\"\n value={editingRecord.department || ''}\n onChange={(e) => updateEditingField('department', e.target.value || undefined)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Marketing\"\n />\n </div>\n <div className=\"md:col-span-2\">\n <label htmlFor=\"recordDescription\" className=\"block text-sm font-medium mb-1\">\n Description *\n </label>\n <textarea\n id=\"recordDescription\"\n value={editingRecord.description}\n onChange={(e) => updateEditingField('description', e.target.value)}\n rows={3}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Describe what personal data processing is performed...\"\n />\n </div>\n <div>\n <label htmlFor=\"recordStatus\" className=\"block text-sm font-medium mb-1\">\n Status *\n </label>\n <select\n id=\"recordStatus\"\n value={editingRecord.status}\n onChange={(e) =>\n updateEditingField('status', e.target.value as ProcessingRecord['status'])\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n </fieldset>\n\n {/* Controller Details */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Controller Details</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label htmlFor=\"controllerName\" className=\"block text-sm font-medium mb-1\">\n Controller Name *\n </label>\n <input\n type=\"text\"\n id=\"controllerName\"\n value={editingRecord.controllerDetails.name}\n onChange={(e) => updateControllerField('name', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n <div>\n <label htmlFor=\"controllerContact\" className=\"block text-sm font-medium mb-1\">\n Controller Contact *\n </label>\n <input\n type=\"text\"\n id=\"controllerContact\"\n value={editingRecord.controllerDetails.contact}\n onChange={(e) => updateControllerField('contact', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n <div className=\"md:col-span-2\">\n <label htmlFor=\"controllerAddress\" className=\"block text-sm font-medium mb-1\">\n Controller Address *\n </label>\n <input\n type=\"text\"\n id=\"controllerAddress\"\n value={editingRecord.controllerDetails.address}\n onChange={(e) => updateControllerField('address', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n </div>\n </fieldset>\n\n {/* Lawful Basis */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Lawful Basis (NDPA Section 25)</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label htmlFor=\"lawfulBasis\" className=\"block text-sm font-medium mb-1\">\n Lawful Basis *\n </label>\n <select\n id=\"lawfulBasis\"\n value={editingRecord.lawfulBasis}\n onChange={(e) =>\n updateEditingField('lawfulBasis', e.target.value as LawfulBasis)\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {LAWFUL_BASIS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"lawfulBasisJustification\" className=\"block text-sm font-medium mb-1\">\n Justification *\n </label>\n <textarea\n id=\"lawfulBasisJustification\"\n value={editingRecord.lawfulBasisJustification}\n onChange={(e) =>\n updateEditingField('lawfulBasisJustification', e.target.value)\n }\n rows={2}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Explain why this lawful basis applies...\"\n />\n </div>\n </div>\n </fieldset>\n\n {/* Data Details */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Data Details</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label htmlFor=\"purposes\" className=\"block text-sm font-medium mb-1\">\n Purposes * (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"purposes\"\n value={purposesInput}\n onChange={(e) => setPurposesInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Account management, Service delivery\"\n />\n </div>\n <div>\n <label htmlFor=\"dataCategories\" className=\"block text-sm font-medium mb-1\">\n Data Categories * (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"dataCategories\"\n value={dataCategoriesInput}\n onChange={(e) => setDataCategoriesInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Name, Email, Phone number\"\n />\n </div>\n <div>\n <label htmlFor=\"sensitiveData\" className=\"block text-sm font-medium mb-1\">\n Sensitive Data Categories (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"sensitiveData\"\n value={sensitiveDataInput}\n onChange={(e) => setSensitiveDataInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Health data, Biometric data\"\n />\n </div>\n <div>\n <label htmlFor=\"subjectCategories\" className=\"block text-sm font-medium mb-1\">\n Data Subject Categories * (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"subjectCategories\"\n value={subjectCategoriesInput}\n onChange={(e) => setSubjectCategoriesInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Customers, Employees\"\n />\n </div>\n <div>\n <label htmlFor=\"recipients\" className=\"block text-sm font-medium mb-1\">\n Recipients * (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"recipients\"\n value={recipientsInput}\n onChange={(e) => setRecipientsInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Payment processors, Cloud service providers\"\n />\n </div>\n <div>\n <label htmlFor=\"dataSource\" className=\"block text-sm font-medium mb-1\">\n Data Source *\n </label>\n <select\n id=\"dataSource\"\n value={editingRecord.dataSource}\n onChange={(e) =>\n updateEditingField(\n 'dataSource',\n e.target.value as ProcessingRecord['dataSource']\n )\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {DATA_SOURCE_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n {editingRecord.dataSource === 'third_party' && (\n <div className=\"md:col-span-2\">\n <label\n htmlFor=\"thirdPartyDetails\"\n className=\"block text-sm font-medium mb-1\"\n >\n Third-Party Source Details *\n </label>\n <input\n type=\"text\"\n id=\"thirdPartyDetails\"\n value={editingRecord.thirdPartySourceDetails || ''}\n onChange={(e) =>\n updateEditingField('thirdPartySourceDetails', e.target.value || undefined)\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Describe the third-party data source...\"\n />\n </div>\n )}\n </div>\n </fieldset>\n\n {/* Retention and Security */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Retention and Security</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label htmlFor=\"retentionPeriod\" className=\"block text-sm font-medium mb-1\">\n Retention Period *\n </label>\n <input\n type=\"text\"\n id=\"retentionPeriod\"\n value={editingRecord.retentionPeriod}\n onChange={(e) => updateEditingField('retentionPeriod', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., 5 years after account closure\"\n />\n </div>\n <div>\n <label htmlFor=\"retentionJustification\" className=\"block text-sm font-medium mb-1\">\n Retention Justification\n </label>\n <input\n type=\"text\"\n id=\"retentionJustification\"\n value={editingRecord.retentionJustification || ''}\n onChange={(e) =>\n updateEditingField('retentionJustification', e.target.value || undefined)\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Why this retention period is necessary...\"\n />\n </div>\n <div className=\"md:col-span-2\">\n <label htmlFor=\"securityMeasures\" className=\"block text-sm font-medium mb-1\">\n Security Measures * (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"securityMeasures\"\n value={securityMeasuresInput}\n onChange={(e) => setSecurityMeasuresInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., Encryption at rest, Access controls, Audit logging\"\n />\n </div>\n <div>\n <label htmlFor=\"systemsUsed\" className=\"block text-sm font-medium mb-1\">\n Systems Used (comma-separated)\n </label>\n <input\n type=\"text\"\n id=\"systemsUsed\"\n value={systemsUsedInput}\n onChange={(e) => setSystemsUsedInput(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"e.g., CRM, ERP, Cloud Storage\"\n />\n </div>\n </div>\n </fieldset>\n\n {/* Risk Indicators */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Risk Indicators</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n id=\"dpiaRequired\"\n checked={editingRecord.dpiaRequired}\n onChange={(e) => updateEditingField('dpiaRequired', e.target.checked)}\n className=\"rounded border-gray-300 dark:border-gray-600\"\n />\n <label htmlFor=\"dpiaRequired\" className=\"text-sm font-medium\">\n DPIA Required\n </label>\n </div>\n {editingRecord.dpiaRequired && (\n <div>\n <label htmlFor=\"dpiaReference\" className=\"block text-sm font-medium mb-1\">\n DPIA Reference *\n </label>\n <input\n type=\"text\"\n id=\"dpiaReference\"\n value={editingRecord.dpiaReference || ''}\n onChange={(e) =>\n updateEditingField('dpiaReference', e.target.value || undefined)\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Reference to the completed DPIA\"\n />\n </div>\n )}\n <div className=\"flex items-center space-x-2\">\n <input\n type=\"checkbox\"\n id=\"automatedDecisionMaking\"\n checked={editingRecord.automatedDecisionMaking}\n onChange={(e) =>\n updateEditingField('automatedDecisionMaking', e.target.checked)\n }\n className=\"rounded border-gray-300 dark:border-gray-600\"\n />\n <label htmlFor=\"automatedDecisionMaking\" className=\"text-sm font-medium\">\n Automated Decision-Making\n </label>\n </div>\n {editingRecord.automatedDecisionMaking && (\n <div>\n <label\n htmlFor=\"automatedDecisionMakingDetails\"\n className=\"block text-sm font-medium mb-1\"\n >\n Automated Decision-Making Details *\n </label>\n <textarea\n id=\"automatedDecisionMakingDetails\"\n value={editingRecord.automatedDecisionMakingDetails || ''}\n onChange={(e) =>\n updateEditingField(\n 'automatedDecisionMakingDetails',\n e.target.value || undefined\n )\n }\n rows={2}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder=\"Describe the automated decision-making process...\"\n />\n </div>\n )}\n </div>\n </fieldset>\n\n {/* Review Schedule */}\n <fieldset className=\"border border-gray-200 dark:border-gray-600 rounded-md p-4\">\n <legend className=\"text-sm font-medium px-2\">Review Schedule</legend>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <label htmlFor=\"nextReviewDate\" className=\"block text-sm font-medium mb-1\">\n Next Review Date\n </label>\n <input\n type=\"date\"\n id=\"nextReviewDate\"\n value={\n editingRecord.nextReviewDate\n ? new Date(editingRecord.nextReviewDate).toISOString().slice(0, 10)\n : ''\n }\n onChange={(e) =>\n updateEditingField(\n 'nextReviewDate',\n e.target.value ? new Date(e.target.value).getTime() : undefined\n )\n }\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n </div>\n </fieldset>\n\n {/* Save / Cancel */}\n <div className=\"flex justify-end space-x-3\">\n <button\n onClick={handleCancelForm}\n className=\"px-4 py-2 border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-sm\"\n >\n Cancel\n </button>\n <button\n onClick={handleSaveRecord}\n className={`px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm ${buttonClassName}`}\n >\n {isNew ? 'Add Record' : 'Save Changes'}\n </button>\n </div>\n </div>\n </div>\n );\n };\n\n // View mode tabs\n const renderViewTabs = () => (\n <div className=\"flex space-x-4 mb-6 border-b border-gray-200 dark:border-gray-600\">\n <button\n onClick={() => setViewMode('list')}\n className={`pb-2 text-sm font-medium ${\n viewMode === 'list'\n ? 'border-b-2 border-blue-500 text-blue-600 dark:text-blue-400'\n : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'\n }`}\n >\n Processing Records\n </button>\n <button\n onClick={() => setViewMode('summary')}\n className={`pb-2 text-sm font-medium ${\n viewMode === 'summary'\n ? 'border-b-2 border-blue-500 text-blue-600 dark:text-blue-400'\n : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'\n }`}\n >\n Compliance Summary\n </button>\n </div>\n );\n\n return (\n <div className={`bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md ${className}`}>\n <h2 className=\"text-xl font-bold mb-2\">{title}</h2>\n <p className=\"mb-6 text-gray-600 dark:text-gray-300\">{description}</p>\n\n {renderOrganizationHeader()}\n\n {viewMode !== 'form' && renderViewTabs()}\n\n {viewMode === 'list' && renderRecordsTable()}\n {viewMode === 'summary' && renderSummaryDashboard()}\n {viewMode === 'form' && renderForm()}\n </div>\n );\n};\n"]}
@@ -0,0 +1,4 @@
1
+ function x(c,g){if(typeof c=="string"){let i=c,r=g,n=i,s=/\{\{([^}]+)\}\}/g,l;for(;(l=s.exec(i))!==null;){let t=l[1].trim(),e=r[t]||"";n=n.replace(new RegExp(`\\{\\{\\s*${t}\\s*\\}\\}`,"g"),e);}return n}else {let i=c,r=g,n={},s=[];return i.filter(t=>t.included).sort((t,e)=>(t.order||0)-(e.order||0)).forEach(t=>{let e=t.template||t.customContent||t.defaultContent||"",m=/\{\{([^}]+)\}\}/g,f,u=[];for(;(f=m.exec(e))!==null;)u.push(f[1].trim());u.forEach(o=>{let a="";o in r&&(a=r[o]||""),a||s.push(o),e=e.replace(new RegExp(`\\{\\{\\s*${o}\\s*\\}\\}`,"g"),a);}),n[t.id]=e;}),{fullText:Object.values(n).join(`
2
+
3
+ `),sectionTexts:n,missingVariables:Array.from(new Set(s))}}}export{x as a};//# sourceMappingURL=chunk-UYP64PV7.mjs.map
4
+ //# sourceMappingURL=chunk-UYP64PV7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/ndpr-toolkit/src/utils/privacy.ts"],"names":["generatePolicyText","sectionsOrTemplate","organizationInfoOrVariables","template","variableMap","result","variableRegex","match","variable","replacement","sections","organizationInfo","sectionTexts","missingVariables","section","a","b","content","contentVariables"],"mappings":"AAQO,SAASA,EACdC,CAAAA,CACAC,CAAAA,CAKA,CAEA,GAAI,OAAOD,CAAAA,EAAuB,QAAA,CAAU,CAC1C,IAAME,EAAWF,CAAAA,CACXG,CAAAA,CAAcF,EAGhBG,CAAAA,CAASF,CAAAA,CACPG,EAAgB,kBAAA,CAClBC,CAAAA,CAGJ,KAAA,CAAQA,CAAAA,CAAQD,EAAc,IAAA,CAAKH,CAAQ,CAAA,IAAO,IAAA,EAAM,CACtD,IAAMK,CAAAA,CAAWD,CAAAA,CAAM,CAAC,EAAE,IAAA,EAAK,CACzBE,EAAcL,CAAAA,CAAYI,CAAQ,GAAK,EAAA,CAG7CH,CAAAA,CAASA,CAAAA,CAAO,OAAA,CACd,IAAI,MAAA,CAAO,CAAA,UAAA,EAAaG,CAAQ,CAAA,UAAA,CAAA,CAAc,GAAG,CAAA,CACjDC,CACF,EACF,CAEA,OAAOJ,CACT,CAAA,KAEK,CACH,IAAMK,CAAAA,CAAWT,EACXU,CAAAA,CAAmBT,CAAAA,CACnBU,CAAAA,CAAuC,GACvCC,CAAAA,CAA6B,EAAC,CAGpC,OAAAH,EACG,MAAA,CAAOI,CAAAA,EAAWA,CAAAA,CAAQ,QAAQ,EAClC,IAAA,CAAK,CAACC,EAAGC,CAAAA,GAAAA,CAAOD,CAAAA,CAAE,OAAS,CAAA,GAAMC,CAAAA,CAAE,KAAA,EAAS,CAAA,CAAE,EAC9C,OAAA,CAAQF,CAAAA,EAAW,CAElB,IAAIG,EAAUH,CAAAA,CAAQ,QAAA,EAAYA,CAAAA,CAAQ,aAAA,EAAiBA,EAAQ,cAAA,EAAkB,EAAA,CAG/ER,EAAgB,kBAAA,CAClBC,CAAAA,CAGEW,EAA6B,EAAC,CACpC,KAAA,CAAQX,CAAAA,CAAQD,EAAc,IAAA,CAAKW,CAAO,CAAA,IAAO,IAAA,EAC/CC,EAAiB,IAAA,CAAKX,CAAAA,CAAM,CAAC,CAAA,CAAE,MAAM,CAAA,CAIvCW,EAAiB,OAAA,CAAQV,CAAAA,EAAY,CACnC,IAAIC,CAAAA,CAAc,EAAA,CAGdD,CAAAA,IAAYG,IACdF,CAAAA,CAAcE,CAAAA,CAAiBH,CAAkC,CAAA,EAAe,IAI7EC,CAAAA,EACHI,CAAAA,CAAiB,IAAA,CAAKL,CAAQ,EAIhCS,CAAAA,CAAUA,CAAAA,CAAQ,QAChB,IAAI,MAAA,CAAO,aAAaT,CAAQ,CAAA,UAAA,CAAA,CAAc,GAAG,CAAA,CACjDC,CACF,EACF,CAAC,CAAA,CAGDG,CAAAA,CAAaE,EAAQ,EAAE,CAAA,CAAIG,EAC7B,CAAC,EAKI,CACL,QAAA,CAHe,OAAO,MAAA,CAAOL,CAAY,EAAE,IAAA,CAAK;;AAAA,CAAM,CAAA,CAItD,YAAA,CAAAA,CAAAA,CACA,gBAAA,CAAkB,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAIC,CAAgB,CAAC,CACxD,CACF,CACF","file":"chunk-UYP64PV7.mjs","sourcesContent":["import { PolicySection, OrganizationInfo, PolicyVariable } from '../types/privacy';\n\n/**\n * Generates policy text by replacing variables in a template with organization-specific values\n * @param sectionsOrTemplate The policy sections or template string to generate text for\n * @param organizationInfoOrVariables The organization information or variable map to use for replacement\n * @returns The generated policy text or an object with the generated text and metadata\n */\nexport function generatePolicyText(\n sectionsOrTemplate: PolicySection[] | string,\n organizationInfoOrVariables: OrganizationInfo | Record<string, string>\n): string | {\n fullText: string;\n sectionTexts: Record<string, string>;\n missingVariables: string[];\n} {\n // Check if we're using the new API (template string and variable map)\n if (typeof sectionsOrTemplate === 'string') {\n const template = sectionsOrTemplate;\n const variableMap = organizationInfoOrVariables as Record<string, string>;\n \n // Replace variables in the template\n let result = template;\n const variableRegex = /\\{\\{([^}]+)\\}\\}/g;\n let match;\n \n // Find and replace all variables in the content\n while ((match = variableRegex.exec(template)) !== null) {\n const variable = match[1].trim();\n const replacement = variableMap[variable] || '';\n \n // Replace the variable in the content\n result = result.replace(\n new RegExp(`\\\\{\\\\{\\\\s*${variable}\\\\s*\\\\}\\\\}`, 'g'), \n replacement\n );\n }\n \n return result;\n } \n // Otherwise use the original API (sections array and organization info)\n else {\n const sections = sectionsOrTemplate;\n const organizationInfo = organizationInfoOrVariables as OrganizationInfo;\n const sectionTexts: Record<string, string> = {};\n const missingVariables: string[] = [];\n \n // Process each section\n sections\n .filter(section => section.included)\n .sort((a, b) => (a.order || 0) - (b.order || 0))\n .forEach(section => {\n // Use template if available, otherwise fall back to custom/default content\n let content = section.template || section.customContent || section.defaultContent || '';\n \n // Replace variables in the content\n const variableRegex = /\\{\\{([^}]+)\\}\\}/g;\n let match;\n \n // Find all variables in the content\n const contentVariables: string[] = [];\n while ((match = variableRegex.exec(content)) !== null) {\n contentVariables.push(match[1].trim());\n }\n \n // Replace each variable with its value\n contentVariables.forEach(variable => {\n let replacement = '';\n \n // Check if the variable exists in organizationInfo\n if (variable in organizationInfo) {\n replacement = organizationInfo[variable as keyof OrganizationInfo] as string || '';\n }\n \n // If replacement is empty, add to missing variables\n if (!replacement) {\n missingVariables.push(variable);\n }\n \n // Replace the variable in the content\n content = content.replace(\n new RegExp(`\\\\{\\\\{\\\\s*${variable}\\\\s*\\\\}\\\\}`, 'g'), \n replacement\n );\n });\n \n // Store the processed section text\n sectionTexts[section.id] = content;\n });\n \n // Combine all sections into full text\n const fullText = Object.values(sectionTexts).join('\\n\\n');\n \n return {\n fullText,\n sectionTexts,\n missingVariables: Array.from(new Set(missingVariables)) // Remove duplicates\n };\n }\n}\n"]}