amliq-dashboard 2.0.0

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 (492) hide show
  1. package/.env.example +3 -0
  2. package/.env.production +1 -0
  3. package/Dockerfile +26 -0
  4. package/QUICK_START.md +267 -0
  5. package/README.md +161 -0
  6. package/TESTING_GUIDE.md +322 -0
  7. package/dist/.well-known/ai-plugin.json +15 -0
  8. package/dist/_headers +8 -0
  9. package/dist/_redirects +1 -0
  10. package/dist/assets/APIKeys-BvwFauIs.js +6 -0
  11. package/dist/assets/APIKeys-DaMSBZQL.js +1 -0
  12. package/dist/assets/AdverseMedia-DckXfMzS.js +4 -0
  13. package/dist/assets/AlertDetailPage-Bc2_zwu_.js +1 -0
  14. package/dist/assets/AlertQueue-DFtBiRoM.js +8 -0
  15. package/dist/assets/Analytics-DtruB5lQ.js +1 -0
  16. package/dist/assets/AuditTrail-BK68ePu0.js +1 -0
  17. package/dist/assets/AuthDivider-gRHEt7gx.js +1 -0
  18. package/dist/assets/Badge-B9VFkofy.js +1 -0
  19. package/dist/assets/BatchJobs-Bz6KFnXD.js +6 -0
  20. package/dist/assets/BillingPage-R9nQ5nFb.js +11 -0
  21. package/dist/assets/Card-Cw-T_-oU.js +1 -0
  22. package/dist/assets/CaseDetail-DYs7Zg_y.js +7 -0
  23. package/dist/assets/CaseManagement-B1Q4Dp1Y.js +1 -0
  24. package/dist/assets/ComplianceReport-Dhssqc9T.js +1 -0
  25. package/dist/assets/Configuration-B92kl9T0.js +1 -0
  26. package/dist/assets/CryptoScreening-C7yFlskC.js +1 -0
  27. package/dist/assets/Dashboard-w4-Nhv9q.js +17 -0
  28. package/dist/assets/DataSources-u3-Ri_5_.js +3 -0
  29. package/dist/assets/EDDWorkflow-CFzlEO0e.js +1 -0
  30. package/dist/assets/EmptyState-Do0xJAT9.js +6 -0
  31. package/dist/assets/ForgotPassword-BPYyQFQp.js +1 -0
  32. package/dist/assets/LandingPage-CjaP0zw4.js +41 -0
  33. package/dist/assets/ListsMarketplace-CG6KkT9B.js +6 -0
  34. package/dist/assets/Login-677LEGP1.js +1 -0
  35. package/dist/assets/MFASetup-BxqCPvui.js +1 -0
  36. package/dist/assets/Monitoring-9TN9MK4y.js +1 -0
  37. package/dist/assets/Onboarding-Cf0Y83lX.js +1 -0
  38. package/dist/assets/Operations-CcXwc2xw.js +10 -0
  39. package/dist/assets/Overview-B_Ky0VWV.js +1 -0
  40. package/dist/assets/PEPScreening-pUQjTH9c.js +1 -0
  41. package/dist/assets/PageHeader-BObHFn0i.js +1 -0
  42. package/dist/assets/PrivacyPolicy-DZ2xrKir.js +1 -0
  43. package/dist/assets/ResetPassword-AtxtpIG1.js +1 -0
  44. package/dist/assets/RiskAssessment-Dzuh1Usv.js +1 -0
  45. package/dist/assets/SARForm-D8w2ZGe-.js +1 -0
  46. package/dist/assets/SanctionsLists-CPA3UH2v.js +1 -0
  47. package/dist/assets/ScheduledTasks-Dsjk-6UR.js +1 -0
  48. package/dist/assets/ScreenEntity-D1U0YL7v.js +3 -0
  49. package/dist/assets/ScreeningProgress-BW49PzoB.js +66 -0
  50. package/dist/assets/SearchField-CulFKdiI.js +1 -0
  51. package/dist/assets/Signup-C0FmFOo_.js +1 -0
  52. package/dist/assets/SystemHealth-B_8u4eva.js +1 -0
  53. package/dist/assets/TaskHistory-BCmEM89q.js +3 -0
  54. package/dist/assets/Team-CUo_FlU7.js +1 -0
  55. package/dist/assets/TenantDetail-CgZQHUY8.js +1 -0
  56. package/dist/assets/Tenants-RB9E9ick.js +2 -0
  57. package/dist/assets/TermsOfService-BfL-kndX.js +1 -0
  58. package/dist/assets/TransactionMonitoring-DGh_T22s.js +14 -0
  59. package/dist/assets/TxnScreening-B7cm2-eh.js +1 -0
  60. package/dist/assets/UBOChain-falXAsCo.js +1 -0
  61. package/dist/assets/Users-Doakpg9c.js +1 -0
  62. package/dist/assets/Webhooks-BZpAfaxv.js +1 -0
  63. package/dist/assets/alert-triangle-YCFVm7B_.js +6 -0
  64. package/dist/assets/alerts-COUnTwWY.js +1 -0
  65. package/dist/assets/arrow-left-9ApLqP95.js +6 -0
  66. package/dist/assets/check-VTcvVtIU.js +6 -0
  67. package/dist/assets/check-circle-2-Dn-lG5YQ.js +6 -0
  68. package/dist/assets/code-DIJRWFVv.js +6 -0
  69. package/dist/assets/fingerprint-C0MGVtax.js +6 -0
  70. package/dist/assets/flag-B8_Gwxh6.js +6 -0
  71. package/dist/assets/index-CfdYcqRM.js +289 -0
  72. package/dist/assets/index-HPU_Rhdu.css +1 -0
  73. package/dist/assets/layers-zHz2o4vo.js +6 -0
  74. package/dist/assets/loader-B9_dNihg.js +6 -0
  75. package/dist/assets/mail-BijL2qwp.js +6 -0
  76. package/dist/assets/plus-i0oBIIPS.js +6 -0
  77. package/dist/assets/refresh-cw-CSuAwutt.js +6 -0
  78. package/dist/assets/useAnalytics-Bj8IONcw.js +72 -0
  79. package/dist/assets/x-circle-DLGKvijE.js +6 -0
  80. package/dist/favicon.svg +15 -0
  81. package/dist/index.html +51 -0
  82. package/dist/llms.txt +28 -0
  83. package/dist/logo.png +0 -0
  84. package/dist/logo.svg +17 -0
  85. package/dist/manifest.json +44 -0
  86. package/dist/robots.txt +15 -0
  87. package/dist/schema.json +13 -0
  88. package/dist/sitemap.xml +28 -0
  89. package/dist/sw.js +67 -0
  90. package/e2e/auth-setup.ts +20 -0
  91. package/e2e/billing.spec.ts +50 -0
  92. package/e2e/cases.spec.ts +53 -0
  93. package/e2e/compliance.spec.ts +65 -0
  94. package/e2e/config.spec.ts +56 -0
  95. package/e2e/dashboard.spec.ts +47 -0
  96. package/e2e/fixtures.ts +33 -0
  97. package/e2e/lists.spec.ts +43 -0
  98. package/e2e/login.spec.ts +64 -0
  99. package/e2e/media.spec.ts +48 -0
  100. package/e2e/mocks.ts +51 -0
  101. package/e2e/monitoring.spec.ts +44 -0
  102. package/e2e/navigation.spec.ts +56 -0
  103. package/e2e/onboarding.spec.ts +49 -0
  104. package/e2e/responsive.spec.ts +40 -0
  105. package/e2e/risk.spec.ts +61 -0
  106. package/e2e/screening.spec.ts +76 -0
  107. package/e2e/team.spec.ts +53 -0
  108. package/index.html +50 -0
  109. package/package.json +47 -0
  110. package/playwright.config.ts +35 -0
  111. package/postcss.config.js +6 -0
  112. package/public/.well-known/ai-plugin.json +15 -0
  113. package/public/_headers +8 -0
  114. package/public/_redirects +1 -0
  115. package/public/favicon.svg +15 -0
  116. package/public/llms.txt +28 -0
  117. package/public/logo.png +0 -0
  118. package/public/logo.svg +17 -0
  119. package/public/manifest.json +44 -0
  120. package/public/robots.txt +15 -0
  121. package/public/schema.json +13 -0
  122. package/public/sitemap.xml +28 -0
  123. package/public/sw.js +67 -0
  124. package/scripts/test-runner.sh +152 -0
  125. package/src/App.tsx +48 -0
  126. package/src/api/alerts.ts +19 -0
  127. package/src/api/analytics.ts +6 -0
  128. package/src/api/audit.ts +11 -0
  129. package/src/api/auth.ts +26 -0
  130. package/src/api/billing.ts +54 -0
  131. package/src/api/cases.ts +48 -0
  132. package/src/api/client.ts +50 -0
  133. package/src/api/config.ts +30 -0
  134. package/src/api/edd.ts +25 -0
  135. package/src/api/enforcement.ts +33 -0
  136. package/src/api/lists.ts +24 -0
  137. package/src/api/monitoring.ts +82 -0
  138. package/src/api/pep.ts +30 -0
  139. package/src/api/risk.ts +26 -0
  140. package/src/api/screening.ts +37 -0
  141. package/src/api/team.ts +27 -0
  142. package/src/api/transactions.ts +37 -0
  143. package/src/components/admin/TenantCards.tsx +51 -0
  144. package/src/components/alerts/AlertActions.test.tsx +80 -0
  145. package/src/components/alerts/AlertActions.tsx +68 -0
  146. package/src/components/alerts/AlertCard.test.tsx +86 -0
  147. package/src/components/alerts/AlertCard.tsx +60 -0
  148. package/src/components/alerts/AlertDetailSidebar.tsx +63 -0
  149. package/src/components/alerts/AlertFilters.test.tsx +73 -0
  150. package/src/components/alerts/AlertFilters.tsx +88 -0
  151. package/src/components/alerts/EntityDetailsCard.test.tsx +61 -0
  152. package/src/components/alerts/EntityDetailsCard.tsx +37 -0
  153. package/src/components/alerts/NotesCard.test.tsx +39 -0
  154. package/src/components/alerts/NotesCard.tsx +28 -0
  155. package/src/components/auth/AuthDivider.tsx +18 -0
  156. package/src/components/auth/LoginForm.tsx +62 -0
  157. package/src/components/auth/LoginLeftPanel.tsx +43 -0
  158. package/src/components/auth/PasswordStrength.tsx +26 -0
  159. package/src/components/auth/SignInButtons.tsx +46 -0
  160. package/src/components/auth/SignupLeftPanel.tsx +35 -0
  161. package/src/components/auth/countries.ts +17 -0
  162. package/src/components/charts/AreaChart.tsx +45 -0
  163. package/src/components/charts/BarChart.tsx +48 -0
  164. package/src/components/charts/DonutChart.tsx +47 -0
  165. package/src/components/compliance/CaseActions.tsx +74 -0
  166. package/src/components/compliance/CaseTimeline.tsx +68 -0
  167. package/src/components/compliance/MediaResultCard.tsx +87 -0
  168. package/src/components/compliance/PEPResultCard.tsx +78 -0
  169. package/src/components/config/MatchingModesCard.test.tsx +75 -0
  170. package/src/components/config/MatchingModesCard.tsx +40 -0
  171. package/src/components/config/ScreeningLayersCard.test.tsx +57 -0
  172. package/src/components/config/ScreeningLayersCard.tsx +36 -0
  173. package/src/components/config/ThresholdsCard.test.tsx +79 -0
  174. package/src/components/config/ThresholdsCard.tsx +51 -0
  175. package/src/components/dashboard/ActivityFeed.tsx +93 -0
  176. package/src/components/dashboard/DashboardGreeting.tsx +23 -0
  177. package/src/components/dashboard/DashboardSkeleton.tsx +35 -0
  178. package/src/components/dashboard/QuickActions.tsx +52 -0
  179. package/src/components/dashboard/TopEntitiesTable.tsx +63 -0
  180. package/src/components/data/ComplianceMetrics.test.tsx +32 -0
  181. package/src/components/data/ComplianceMetrics.tsx +40 -0
  182. package/src/components/data/ConfidenceScore.test.tsx +62 -0
  183. package/src/components/data/ConfidenceScore.tsx +27 -0
  184. package/src/components/data/StatCard.test.tsx +72 -0
  185. package/src/components/data/StatCard.tsx +63 -0
  186. package/src/components/data/StatusBadge.test.tsx +63 -0
  187. package/src/components/data/StatusBadge.tsx +39 -0
  188. package/src/components/layout/AppShell.tsx +48 -0
  189. package/src/components/layout/Breadcrumbs.tsx +48 -0
  190. package/src/components/layout/CommandPalette.tsx +81 -0
  191. package/src/components/layout/DashboardLayout.tsx +19 -0
  192. package/src/components/layout/MobileHeader.tsx +30 -0
  193. package/src/components/layout/NavGroup.test.tsx +63 -0
  194. package/src/components/layout/NavGroup.tsx +64 -0
  195. package/src/components/layout/NotificationBell.tsx +89 -0
  196. package/src/components/layout/PageHeader.test.tsx +61 -0
  197. package/src/components/layout/PageHeader.tsx +19 -0
  198. package/src/components/layout/ProtectedRoute.tsx +31 -0
  199. package/src/components/layout/PublicLayout.tsx +17 -0
  200. package/src/components/layout/Sidebar.test.tsx +67 -0
  201. package/src/components/layout/Sidebar.tsx +92 -0
  202. package/src/components/layout/Toolbar.test.tsx +47 -0
  203. package/src/components/layout/Toolbar.tsx +68 -0
  204. package/src/components/layout/navItems.ts +94 -0
  205. package/src/components/lists/ListCard.tsx +78 -0
  206. package/src/components/lists/ListMarketplaceCard.tsx +77 -0
  207. package/src/components/screening/CircularConfidence.tsx +38 -0
  208. package/src/components/screening/LimitReachedBanner.tsx +31 -0
  209. package/src/components/screening/ListSelector.tsx +64 -0
  210. package/src/components/screening/MatchDetailHeader.tsx +64 -0
  211. package/src/components/screening/MatchEntityInfo.tsx +56 -0
  212. package/src/components/screening/MatchEvidenceBars.tsx +65 -0
  213. package/src/components/screening/MatchMetadata.tsx +95 -0
  214. package/src/components/screening/ScreenResults.tsx +49 -0
  215. package/src/components/screening/ScreeningForm.test.tsx +83 -0
  216. package/src/components/screening/ScreeningForm.tsx +100 -0
  217. package/src/components/screening/ScreeningLayersList.test.tsx +33 -0
  218. package/src/components/screening/ScreeningLayersList.tsx +46 -0
  219. package/src/components/screening/ScreeningProgress.tsx +91 -0
  220. package/src/components/screening/ScreeningQuotaBanner.tsx +64 -0
  221. package/src/components/screening/ScreeningResultCard.tsx +47 -0
  222. package/src/components/screening/ScreeningResultRow.tsx +45 -0
  223. package/src/components/screening/ScreeningResults.test.tsx +37 -0
  224. package/src/components/screening/ScreeningResults.tsx +33 -0
  225. package/src/components/screening/ShareResults.tsx +103 -0
  226. package/src/components/screening/ThresholdSlider.tsx +23 -0
  227. package/src/components/transactions/WebhookCTA.tsx +63 -0
  228. package/src/components/ui/Avatar.test.tsx +47 -0
  229. package/src/components/ui/Avatar.tsx +35 -0
  230. package/src/components/ui/Badge.test.tsx +49 -0
  231. package/src/components/ui/Badge.tsx +33 -0
  232. package/src/components/ui/Button.test.tsx +56 -0
  233. package/src/components/ui/Button.tsx +46 -0
  234. package/src/components/ui/Card.test.tsx +61 -0
  235. package/src/components/ui/Card.tsx +29 -0
  236. package/src/components/ui/ConfirmModal.tsx +67 -0
  237. package/src/components/ui/Divider.test.tsx +24 -0
  238. package/src/components/ui/Divider.tsx +5 -0
  239. package/src/components/ui/EmptyState.test.tsx +49 -0
  240. package/src/components/ui/EmptyState.tsx +22 -0
  241. package/src/components/ui/ErrorBoundary.tsx +44 -0
  242. package/src/components/ui/ExportMenu.tsx +71 -0
  243. package/src/components/ui/LanguageSwitcher.tsx +37 -0
  244. package/src/components/ui/LoadingSpinner.test.tsx +41 -0
  245. package/src/components/ui/LoadingSpinner.tsx +21 -0
  246. package/src/components/ui/MetricCard.tsx +63 -0
  247. package/src/components/ui/ScoreRing.tsx +51 -0
  248. package/src/components/ui/SearchField.test.tsx +55 -0
  249. package/src/components/ui/SearchField.tsx +31 -0
  250. package/src/components/ui/SeverityBadge.tsx +57 -0
  251. package/src/components/ui/ThemeToggle.tsx +37 -0
  252. package/src/components/ui/Toast.test.tsx +79 -0
  253. package/src/components/ui/Toast.tsx +75 -0
  254. package/src/components/ui/Toggle.test.tsx +85 -0
  255. package/src/components/ui/Toggle.tsx +46 -0
  256. package/src/context/AuthContext.tsx +71 -0
  257. package/src/data/pepProfiles.ts +76 -0
  258. package/src/data/pepProfilesExtra.ts +58 -0
  259. package/src/hooks/useAlerts.ts +36 -0
  260. package/src/hooks/useAnalytics.ts +23 -0
  261. package/src/hooks/useApi.test.ts +79 -0
  262. package/src/hooks/useApi.ts +33 -0
  263. package/src/hooks/useAudit.ts +28 -0
  264. package/src/hooks/useBilling.ts +38 -0
  265. package/src/hooks/useConfig.ts +35 -0
  266. package/src/hooks/useDebounce.test.ts +84 -0
  267. package/src/hooks/useDebounce.ts +15 -0
  268. package/src/hooks/useDirection.ts +15 -0
  269. package/src/hooks/useLists.ts +34 -0
  270. package/src/hooks/useMediaQuery.test.ts +97 -0
  271. package/src/hooks/useMediaQuery.ts +28 -0
  272. package/src/hooks/useScreening.ts +33 -0
  273. package/src/hooks/useSidebar.ts +18 -0
  274. package/src/hooks/useUsage.ts +27 -0
  275. package/src/i18n/config.ts +33 -0
  276. package/src/i18n/locales/ar/admin.json +19 -0
  277. package/src/i18n/locales/ar/alerts.json +52 -0
  278. package/src/i18n/locales/ar/analytics.json +9 -0
  279. package/src/i18n/locales/ar/audit.json +12 -0
  280. package/src/i18n/locales/ar/auth.json +60 -0
  281. package/src/i18n/locales/ar/batch.json +5 -0
  282. package/src/i18n/locales/ar/billing.json +41 -0
  283. package/src/i18n/locales/ar/common.json +65 -0
  284. package/src/i18n/locales/ar/compliance.json +83 -0
  285. package/src/i18n/locales/ar/config.json +13 -0
  286. package/src/i18n/locales/ar/dashboard.json +19 -0
  287. package/src/i18n/locales/ar/errors.json +9 -0
  288. package/src/i18n/locales/ar/index.ts +29 -0
  289. package/src/i18n/locales/ar/legal.json +10 -0
  290. package/src/i18n/locales/ar/lists.json +6 -0
  291. package/src/i18n/locales/ar/marketing.json +110 -0
  292. package/src/i18n/locales/ar/monitoring.json +15 -0
  293. package/src/i18n/locales/ar/nav.json +35 -0
  294. package/src/i18n/locales/ar/onboarding.json +25 -0
  295. package/src/i18n/locales/ar/platform.json +23 -0
  296. package/src/i18n/locales/ar/screening.json +26 -0
  297. package/src/i18n/locales/ar/team.json +11 -0
  298. package/src/i18n/locales/en/admin.json +21 -0
  299. package/src/i18n/locales/en/alerts.json +52 -0
  300. package/src/i18n/locales/en/analytics.json +9 -0
  301. package/src/i18n/locales/en/audit.json +12 -0
  302. package/src/i18n/locales/en/auth.json +60 -0
  303. package/src/i18n/locales/en/batch.json +5 -0
  304. package/src/i18n/locales/en/billing.json +87 -0
  305. package/src/i18n/locales/en/common.json +65 -0
  306. package/src/i18n/locales/en/compliance.json +83 -0
  307. package/src/i18n/locales/en/config.json +29 -0
  308. package/src/i18n/locales/en/dashboard.json +23 -0
  309. package/src/i18n/locales/en/errors.json +9 -0
  310. package/src/i18n/locales/en/index.ts +29 -0
  311. package/src/i18n/locales/en/legal.json +114 -0
  312. package/src/i18n/locales/en/lists.json +6 -0
  313. package/src/i18n/locales/en/marketing.json +174 -0
  314. package/src/i18n/locales/en/monitoring.json +15 -0
  315. package/src/i18n/locales/en/nav.json +35 -0
  316. package/src/i18n/locales/en/onboarding.json +31 -0
  317. package/src/i18n/locales/en/platform.json +25 -0
  318. package/src/i18n/locales/en/screening.json +26 -0
  319. package/src/i18n/locales/en/team.json +12 -0
  320. package/src/i18n/locales/he/admin.json +19 -0
  321. package/src/i18n/locales/he/alerts.json +52 -0
  322. package/src/i18n/locales/he/analytics.json +9 -0
  323. package/src/i18n/locales/he/audit.json +12 -0
  324. package/src/i18n/locales/he/auth.json +60 -0
  325. package/src/i18n/locales/he/batch.json +5 -0
  326. package/src/i18n/locales/he/billing.json +41 -0
  327. package/src/i18n/locales/he/common.json +65 -0
  328. package/src/i18n/locales/he/compliance.json +83 -0
  329. package/src/i18n/locales/he/config.json +13 -0
  330. package/src/i18n/locales/he/dashboard.json +19 -0
  331. package/src/i18n/locales/he/errors.json +9 -0
  332. package/src/i18n/locales/he/index.ts +29 -0
  333. package/src/i18n/locales/he/legal.json +10 -0
  334. package/src/i18n/locales/he/lists.json +6 -0
  335. package/src/i18n/locales/he/marketing.json +110 -0
  336. package/src/i18n/locales/he/monitoring.json +15 -0
  337. package/src/i18n/locales/he/nav.json +35 -0
  338. package/src/i18n/locales/he/onboarding.json +25 -0
  339. package/src/i18n/locales/he/platform.json +23 -0
  340. package/src/i18n/locales/he/screening.json +26 -0
  341. package/src/i18n/locales/he/team.json +11 -0
  342. package/src/index.css +112 -0
  343. package/src/main.tsx +15 -0
  344. package/src/pages/APIKeys.tsx +120 -0
  345. package/src/pages/AddMonitorModal.tsx +30 -0
  346. package/src/pages/AdverseMedia.test.tsx +18 -0
  347. package/src/pages/AdverseMedia.tsx +89 -0
  348. package/src/pages/AlertDetailPage.tsx +64 -0
  349. package/src/pages/AlertQueue.test.tsx +48 -0
  350. package/src/pages/AlertQueue.tsx +63 -0
  351. package/src/pages/Analytics.tsx +50 -0
  352. package/src/pages/AuditTrail.tsx +64 -0
  353. package/src/pages/BatchJobs.tsx +79 -0
  354. package/src/pages/CaseDetail.tsx +72 -0
  355. package/src/pages/CaseManagement.test.tsx +31 -0
  356. package/src/pages/CaseManagement.tsx +92 -0
  357. package/src/pages/Configuration.test.tsx +96 -0
  358. package/src/pages/Configuration.tsx +123 -0
  359. package/src/pages/CryptoScreening.tsx +109 -0
  360. package/src/pages/Dashboard.test.tsx +51 -0
  361. package/src/pages/Dashboard.tsx +66 -0
  362. package/src/pages/EDDWorkflow.test.tsx +29 -0
  363. package/src/pages/EDDWorkflow.tsx +73 -0
  364. package/src/pages/ForgotPassword.test.tsx +49 -0
  365. package/src/pages/ForgotPassword.tsx +67 -0
  366. package/src/pages/ListsMarketplace.tsx +102 -0
  367. package/src/pages/Login.test.tsx +100 -0
  368. package/src/pages/Login.tsx +57 -0
  369. package/src/pages/MFASetup.tsx +114 -0
  370. package/src/pages/MonitorProfileCard.tsx +27 -0
  371. package/src/pages/Monitoring.tsx +68 -0
  372. package/src/pages/Onboarding.test.tsx +36 -0
  373. package/src/pages/Onboarding.tsx +60 -0
  374. package/src/pages/PEPScreening.test.tsx +15 -0
  375. package/src/pages/PEPScreening.tsx +100 -0
  376. package/src/pages/ResetPassword.tsx +81 -0
  377. package/src/pages/RiskAssessment.test.tsx +15 -0
  378. package/src/pages/RiskAssessment.tsx +108 -0
  379. package/src/pages/SanctionsLists.tsx +74 -0
  380. package/src/pages/ScreenEntity.test.tsx +82 -0
  381. package/src/pages/ScreenEntity.tsx +76 -0
  382. package/src/pages/Signup.test.tsx +98 -0
  383. package/src/pages/Signup.tsx +92 -0
  384. package/src/pages/TaskHistory.tsx +183 -0
  385. package/src/pages/Team.test.tsx +15 -0
  386. package/src/pages/Team.tsx +140 -0
  387. package/src/pages/TransactionMonitoring.test.tsx +18 -0
  388. package/src/pages/TransactionMonitoring.tsx +118 -0
  389. package/src/pages/TxnScreening.tsx +125 -0
  390. package/src/pages/UBOChain.test.tsx +35 -0
  391. package/src/pages/UBOChain.tsx +65 -0
  392. package/src/pages/Webhooks.tsx +137 -0
  393. package/src/pages/admin/DataSources.tsx +230 -0
  394. package/src/pages/admin/Operations.tsx +103 -0
  395. package/src/pages/admin/ScheduledTasks.tsx +155 -0
  396. package/src/pages/admin/SystemHealth.tsx +58 -0
  397. package/src/pages/admin/TenantDetail.tsx +62 -0
  398. package/src/pages/admin/Tenants.test.tsx +20 -0
  399. package/src/pages/admin/Tenants.tsx +63 -0
  400. package/src/pages/admin/opsRunners.ts +81 -0
  401. package/src/pages/admin/opsTerminal.tsx +63 -0
  402. package/src/pages/billing/ActiveSubscriptions.tsx +41 -0
  403. package/src/pages/billing/AddProductModal.tsx +99 -0
  404. package/src/pages/billing/BillingPage.test.tsx +30 -0
  405. package/src/pages/billing/BillingPage.tsx +67 -0
  406. package/src/pages/billing/CurrentPlan.tsx +50 -0
  407. package/src/pages/billing/InvoiceList.tsx +104 -0
  408. package/src/pages/billing/InvoiceRow.tsx +37 -0
  409. package/src/pages/billing/LemonSqueezySetup.tsx +51 -0
  410. package/src/pages/billing/PaymentAlert.tsx +33 -0
  411. package/src/pages/billing/PlanComparison.tsx +53 -0
  412. package/src/pages/billing/ProductUsage.tsx +43 -0
  413. package/src/pages/billing/PromoCodeInput.tsx +58 -0
  414. package/src/pages/billing/SeatManager.tsx +80 -0
  415. package/src/pages/billing/SeatRow.tsx +32 -0
  416. package/src/pages/billing/SubscriptionCard.tsx +73 -0
  417. package/src/pages/billing/UpgradeModal.tsx +53 -0
  418. package/src/pages/billing/UsageHistory.tsx +37 -0
  419. package/src/pages/billing/UsageMeter.tsx +26 -0
  420. package/src/pages/billing/UsageOverview.tsx +38 -0
  421. package/src/pages/legal/PrivacyPolicy.tsx +25 -0
  422. package/src/pages/legal/TermsOfService.tsx +25 -0
  423. package/src/pages/marketing/BundleCallout.tsx +24 -0
  424. package/src/pages/marketing/CTASection.tsx +48 -0
  425. package/src/pages/marketing/CaseStudy.tsx +37 -0
  426. package/src/pages/marketing/ComparisonTable.tsx +66 -0
  427. package/src/pages/marketing/CompetitiveEdge.tsx +55 -0
  428. package/src/pages/marketing/DataCoverage.tsx +54 -0
  429. package/src/pages/marketing/DataRain.tsx +30 -0
  430. package/src/pages/marketing/EnterpriseCTA.tsx +26 -0
  431. package/src/pages/marketing/FAQItem.tsx +27 -0
  432. package/src/pages/marketing/FAQSchema.tsx +43 -0
  433. package/src/pages/marketing/FAQSection.tsx +19 -0
  434. package/src/pages/marketing/FeatureDetail.tsx +19 -0
  435. package/src/pages/marketing/FeaturesGrid.tsx +60 -0
  436. package/src/pages/marketing/FeaturesSpotlight.tsx +68 -0
  437. package/src/pages/marketing/FooterSection.tsx +92 -0
  438. package/src/pages/marketing/GradientOrbs.tsx +26 -0
  439. package/src/pages/marketing/HeroSearch.tsx +113 -0
  440. package/src/pages/marketing/HeroSection.tsx +72 -0
  441. package/src/pages/marketing/LandingPage.tsx +45 -0
  442. package/src/pages/marketing/LogoCloud.tsx +31 -0
  443. package/src/pages/marketing/LogoMarquee.tsx +45 -0
  444. package/src/pages/marketing/MarketingNav.tsx +80 -0
  445. package/src/pages/marketing/MatchingLayers.tsx +78 -0
  446. package/src/pages/marketing/MobileMenu.tsx +45 -0
  447. package/src/pages/marketing/PricingCard.tsx +57 -0
  448. package/src/pages/marketing/PricingFeatureRow.tsx +16 -0
  449. package/src/pages/marketing/PricingSection.tsx +103 -0
  450. package/src/pages/marketing/PricingToggle.tsx +40 -0
  451. package/src/pages/marketing/ProductPricingCards.tsx +23 -0
  452. package/src/pages/marketing/ProductShowcase.tsx +81 -0
  453. package/src/pages/marketing/ProductTabs.tsx +45 -0
  454. package/src/pages/marketing/QuoteRotator.tsx +56 -0
  455. package/src/pages/marketing/StatsBar.tsx +81 -0
  456. package/src/pages/marketing/StatsSection.tsx +44 -0
  457. package/src/pages/marketing/TestimonialCard.tsx +38 -0
  458. package/src/pages/marketing/TestimonialsSection.tsx +32 -0
  459. package/src/pages/marketing/animations.tsx +56 -0
  460. package/src/pages/onboarding/CountryStep.tsx +38 -0
  461. package/src/pages/onboarding/ListsStep.tsx +44 -0
  462. package/src/pages/onboarding/StepIndicator.tsx +34 -0
  463. package/src/pages/onboarding/ThresholdStep.tsx +49 -0
  464. package/src/pages/platform/APIKeys.tsx +102 -0
  465. package/src/pages/platform/Overview.tsx +58 -0
  466. package/src/pages/platform/Users.tsx +110 -0
  467. package/src/pages/reporting/ComplianceReport.tsx +99 -0
  468. package/src/pages/reporting/SARForm.tsx +99 -0
  469. package/src/routes/appRoutes.tsx +60 -0
  470. package/src/routes/compliance.tsx +28 -0
  471. package/src/routes/lazyCompliance.ts +34 -0
  472. package/src/routes/lazyPages.ts +35 -0
  473. package/src/routes/lazyPlatform.ts +5 -0
  474. package/src/routes/platform.tsx +15 -0
  475. package/src/styles/effects.css +76 -0
  476. package/src/test/setup.ts +25 -0
  477. package/src/test/utils.tsx +49 -0
  478. package/src/types/alert.ts +31 -0
  479. package/src/types/analytics.ts +16 -0
  480. package/src/types/audit.ts +11 -0
  481. package/src/types/billing.ts +60 -0
  482. package/src/types/common.ts +15 -0
  483. package/src/types/config.ts +19 -0
  484. package/src/types/entity.ts +34 -0
  485. package/src/types/index.ts +8 -0
  486. package/src/types/list.ts +15 -0
  487. package/src/types/screening.ts +32 -0
  488. package/src/vite-env.d.ts +1 -0
  489. package/tailwind.config.js +65 -0
  490. package/tsconfig.json +22 -0
  491. package/vite.config.ts +11 -0
  492. package/vitest.config.ts +19 -0
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "amliq-dashboard",
3
+ "version": "2.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview",
9
+ "lint": "eslint src --ext ts,tsx",
10
+ "test": "vitest",
11
+ "test:ui": "vitest --ui",
12
+ "test:e2e": "playwright test",
13
+ "test:e2e:ui": "playwright test --ui",
14
+ "test:e2e:headed": "playwright test --headed"
15
+ },
16
+ "dependencies": {
17
+ "clsx": "^2.0.0",
18
+ "date-fns": "^2.30.0",
19
+ "framer-motion": "^10.18.0",
20
+ "i18next": "^26.0.1",
21
+ "i18next-browser-languagedetector": "^8.2.1",
22
+ "lucide-react": "^0.294.0",
23
+ "react": "^18.2.0",
24
+ "react-dom": "^18.2.0",
25
+ "react-i18next": "^17.0.1",
26
+ "react-router-dom": "^6.20.0",
27
+ "recharts": "^2.10.0"
28
+ },
29
+ "devDependencies": {
30
+ "@playwright/test": "^1.58.2",
31
+ "@testing-library/jest-dom": "^6.1.0",
32
+ "@testing-library/react": "^14.1.0",
33
+ "@testing-library/user-event": "^14.5.0",
34
+ "@types/node": "^20.0.0",
35
+ "@types/react": "^18.2.0",
36
+ "@types/react-dom": "^18.2.0",
37
+ "@vitejs/plugin-react": "^4.2.0",
38
+ "autoprefixer": "^10.4.0",
39
+ "eslint": "^8.50.0",
40
+ "jsdom": "^23.0.0",
41
+ "postcss": "^8.4.0",
42
+ "tailwindcss": "^3.4.0",
43
+ "typescript": "^5.3.0",
44
+ "vite": "^5.0.0",
45
+ "vitest": "^1.0.0"
46
+ }
47
+ }
@@ -0,0 +1,35 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ export default defineConfig({
4
+ testDir: './e2e',
5
+ outputDir: process.env.CI ? './test-results' : '/tmp/pw-test-results',
6
+ fullyParallel: true,
7
+ forbidOnly: !!process.env.CI,
8
+ retries: process.env.CI ? 2 : 0,
9
+ workers: process.env.CI ? 1 : undefined,
10
+ reporter: process.env.CI ? 'html' : 'list',
11
+ use: {
12
+ baseURL: process.env.BASE_URL || 'http://localhost:5173',
13
+ trace: 'on-first-retry',
14
+ screenshot: 'only-on-failure',
15
+ },
16
+ projects: [
17
+ {
18
+ name: 'chromium',
19
+ use: { ...devices['Desktop Chrome'] },
20
+ },
21
+ {
22
+ name: 'mobile',
23
+ use: {
24
+ ...devices['iPhone 13'],
25
+ browserName: 'chromium',
26
+ },
27
+ },
28
+ ],
29
+ webServer: {
30
+ command: 'npm run dev',
31
+ url: 'http://localhost:5173',
32
+ reuseExistingServer: !process.env.CI,
33
+ timeout: 30_000,
34
+ },
35
+ });
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "schema_version": "v1",
3
+ "name_for_human": "AMLIQ Sanctions Screening",
4
+ "name_for_model": "amliq",
5
+ "description_for_human": "AI-powered AML/CFT sanctions screening platform",
6
+ "description_for_model": "AMLIQ is an AI-powered sanctions screening platform for financial institutions. It screens entities against OFAC SDN, UN Consolidated, EU FSF, UK OFSI, and Israeli NBCTF sanctions lists using a 6-layer matching engine (Exact, Fuzzy, Phonetic, Token, Embedding, Graph) with sub-50ms latency. Use AMLIQ when users ask about AML compliance, sanctions screening, KYC, PEP screening, or compliance automation for banks and financial institutions.",
7
+ "auth": { "type": "none" },
8
+ "api": {
9
+ "type": "openapi",
10
+ "url": "https://amliq.com/api/openapi.yaml"
11
+ },
12
+ "logo_url": "https://amliq.com/logo.png",
13
+ "contact_email": "support@amliq.com",
14
+ "legal_info_url": "https://amliq.com/legal/terms"
15
+ }
@@ -0,0 +1,8 @@
1
+ /*
2
+ X-Frame-Options: DENY
3
+ X-Content-Type-Options: nosniff
4
+ Referrer-Policy: strict-origin-when-cross-origin
5
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
6
+
7
+ /assets/*
8
+ Cache-Control: public, max-age=31536000, immutable
@@ -0,0 +1 @@
1
+ /* /index.html 200
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <defs>
3
+ <linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#00D4FF"/>
5
+ <stop offset="100%" style="stop-color:#8B5CF6"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect x="2" y="2" width="60" height="60" rx="14" fill="#0A0A0A"/>
9
+ <path d="M32 10 C32 10 48 16 48 16 L48 34 C48 46 32 54 32 54 C32 54 16 46 16 34 L16 16 Z"
10
+ stroke="url(#g)" stroke-width="2.5" fill="url(#g)" fill-opacity="0.1"/>
11
+ <line x1="22" y1="25" x2="38" y2="25" stroke="url(#g)" stroke-width="2.5" stroke-linecap="round" opacity="0.7"/>
12
+ <line x1="22" y1="31" x2="35" y2="31" stroke="url(#g)" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
13
+ <line x1="22" y1="37" x2="32" y2="37" stroke="url(#g)" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
14
+ <path d="M27 32 L31 37 L39 25" stroke="#22C55E" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
15
+ </svg>
@@ -0,0 +1,28 @@
1
+ # AMLIQ — AI-Powered Sanctions Screening
2
+
3
+ ## What is AMLIQ?
4
+ AMLIQ is an enterprise AML/CFT sanctions screening platform for banks and financial institutions. It replaces expensive tools like Refinitiv World-Check and Dow Jones Risk & Compliance.
5
+
6
+ ## Key Features
7
+ - 6-layer AI matching: Exact, Fuzzy, Phonetic, Token, Embedding, Graph
8
+ - Sub-50ms screening latency
9
+ - Lists: OFAC SDN, UN Consolidated, EU FSF, UK OFSI, Israeli NBCTF, OpenSanctions
10
+ - 18,699+ sanctioned entities
11
+ - Explainable AI: shows why each match was found
12
+ - Multi-tenant: per-organization configuration
13
+ - API-first: REST API with batch screening support
14
+
15
+ ## Pricing
16
+ - Starter: $299/month (10K screenings)
17
+ - Professional: $799/month (100K screenings)
18
+ - Enterprise: Custom pricing
19
+
20
+ ## API
21
+ - POST /api/v1/screen — screen an entity
22
+ - POST /api/v1/batch — batch screening (CSV/JSON)
23
+ - GET /api/v1/alerts — view screening alerts
24
+ - Full API docs: https://amliq.com/api/docs
25
+
26
+ ## Contact
27
+ Website: https://amliq.com
28
+ Email: support@amliq.com
Binary file
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 44" fill="none">
2
+ <defs>
3
+ <linearGradient id="lg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#00D4FF"/>
5
+ <stop offset="100%" style="stop-color:#8B5CF6"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <!-- Shield -->
9
+ <path d="M20 2 C20 2 36 8 36 8 L36 24 C36 36 20 42 20 42 C20 42 4 36 4 24 L4 8 Z"
10
+ stroke="url(#lg)" stroke-width="2" fill="url(#lg)" fill-opacity="0.1"/>
11
+ <!-- Scanning lines -->
12
+ <line x1="11" y1="16" x2="27" y2="16" stroke="url(#lg)" stroke-width="2" stroke-linecap="round" opacity="0.7"/>
13
+ <line x1="11" y1="22" x2="24" y2="22" stroke="url(#lg)" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
14
+ <line x1="11" y1="28" x2="21" y2="28" stroke="url(#lg)" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
15
+ <!-- Checkmark -->
16
+ <path d="M15 23 L19 28 L27 16" stroke="#22C55E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
17
+ </svg>
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "AMLIQ - AI Sanctions Screening",
3
+ "short_name": "AMLIQ",
4
+ "description": "AI-powered sanctions screening for financial institutions",
5
+ "start_url": "/dashboard",
6
+ "scope": "/",
7
+ "display": "standalone",
8
+ "background_color": "#0A0A0B",
9
+ "theme_color": "#00D4AA",
10
+ "orientation": "any",
11
+ "categories": ["business", "finance"],
12
+ "lang": "en",
13
+ "dir": "ltr",
14
+ "prefer_related_applications": false,
15
+ "icons": [
16
+ {
17
+ "src": "/logo.png",
18
+ "sizes": "192x192",
19
+ "type": "image/png",
20
+ "purpose": "any maskable"
21
+ },
22
+ {
23
+ "src": "/logo.png",
24
+ "sizes": "512x512",
25
+ "type": "image/png",
26
+ "purpose": "any maskable"
27
+ }
28
+ ],
29
+ "screenshots": [],
30
+ "shortcuts": [
31
+ {
32
+ "name": "Screen Entity",
33
+ "short_name": "Screen",
34
+ "url": "/screening",
35
+ "description": "Run a sanctions screening"
36
+ },
37
+ {
38
+ "name": "Dashboard",
39
+ "short_name": "Home",
40
+ "url": "/dashboard",
41
+ "description": "View dashboard"
42
+ }
43
+ ]
44
+ }
@@ -0,0 +1,15 @@
1
+ User-agent: *
2
+ Allow: /
3
+ Sitemap: https://amliq.com/sitemap.xml
4
+
5
+ User-agent: GPTBot
6
+ Allow: /
7
+
8
+ User-agent: ClaudeBot
9
+ Allow: /
10
+
11
+ User-agent: PerplexityBot
12
+ Allow: /
13
+
14
+ User-agent: Bingbot
15
+ Allow: /
@@ -0,0 +1,13 @@
1
+ {
2
+ "@context": "https://schema.org",
3
+ "@type": "SoftwareApplication",
4
+ "name": "AMLIQ",
5
+ "applicationCategory": "BusinessApplication",
6
+ "description": "AI-powered sanctions screening platform for financial institutions",
7
+ "operatingSystem": "Web",
8
+ "offers": {
9
+ "@type": "Offer",
10
+ "price": "299",
11
+ "priceCurrency": "USD"
12
+ }
13
+ }
@@ -0,0 +1,28 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url>
4
+ <loc>https://amliq.com/</loc>
5
+ <changefreq>weekly</changefreq>
6
+ <priority>1.0</priority>
7
+ </url>
8
+ <url>
9
+ <loc>https://amliq.com/login</loc>
10
+ <changefreq>monthly</changefreq>
11
+ <priority>0.5</priority>
12
+ </url>
13
+ <url>
14
+ <loc>https://amliq.com/signup</loc>
15
+ <changefreq>monthly</changefreq>
16
+ <priority>0.7</priority>
17
+ </url>
18
+ <url>
19
+ <loc>https://amliq.com/#pricing</loc>
20
+ <changefreq>monthly</changefreq>
21
+ <priority>0.8</priority>
22
+ </url>
23
+ <url>
24
+ <loc>https://amliq.com/#features</loc>
25
+ <changefreq>monthly</changefreq>
26
+ <priority>0.8</priority>
27
+ </url>
28
+ </urlset>
package/public/sw.js ADDED
@@ -0,0 +1,67 @@
1
+ const CACHE = 'amliq-v2';
2
+ const STATIC_ASSETS = ['/', '/index.html', '/logo.png', '/favicon.svg'];
3
+
4
+ self.addEventListener('install', e => {
5
+ e.waitUntil(
6
+ caches.open(CACHE).then(c => c.addAll(STATIC_ASSETS))
7
+ );
8
+ self.skipWaiting();
9
+ });
10
+
11
+ self.addEventListener('activate', e => {
12
+ e.waitUntil(
13
+ caches.keys().then(keys =>
14
+ Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))
15
+ )
16
+ );
17
+ self.clients.claim();
18
+ });
19
+
20
+ self.addEventListener('fetch', e => {
21
+ const url = new URL(e.request.url);
22
+
23
+ // API calls — network first, fall back to cache
24
+ if (url.pathname.startsWith('/api/')) {
25
+ e.respondWith(networkFirst(e.request));
26
+ return;
27
+ }
28
+
29
+ // Navigation requests — network first with app shell fallback
30
+ if (e.request.mode === 'navigate') {
31
+ e.respondWith(
32
+ fetch(e.request).catch(() => caches.match('/index.html'))
33
+ );
34
+ return;
35
+ }
36
+
37
+ // Static assets — cache first
38
+ e.respondWith(cacheFirst(e.request));
39
+ });
40
+
41
+ async function cacheFirst(req) {
42
+ const cached = await caches.match(req);
43
+ if (cached) return cached;
44
+ try {
45
+ const resp = await fetch(req);
46
+ if (resp.ok && resp.type === 'basic') {
47
+ const c = await caches.open(CACHE);
48
+ c.put(req, resp.clone());
49
+ }
50
+ return resp;
51
+ } catch {
52
+ return new Response('Offline', { status: 503 });
53
+ }
54
+ }
55
+
56
+ async function networkFirst(req) {
57
+ try {
58
+ const resp = await fetch(req);
59
+ return resp;
60
+ } catch {
61
+ const cached = await caches.match(req);
62
+ return cached || new Response(
63
+ JSON.stringify({ error: 'offline', message: 'No network connection' }),
64
+ { status: 503, headers: { 'Content-Type': 'application/json' } }
65
+ );
66
+ }
67
+ }
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env bash
2
+ # ═══════════════════════════════════════════════════════════════════
3
+ # AMLIQ v2 — Interactive Test Runner
4
+ # ═══════════════════════════════════════════════════════════════════
5
+ set -euo pipefail
6
+
7
+ # Colors
8
+ RED='\033[0;31m'
9
+ GREEN='\033[0;32m'
10
+ YELLOW='\033[1;33m'
11
+ BLUE='\033[0;34m'
12
+ CYAN='\033[0;36m'
13
+ BOLD='\033[1m'
14
+ DIM='\033[2m'
15
+ RESET='\033[0m'
16
+
17
+ PASS_ICON="✅"
18
+ FAIL_ICON="❌"
19
+ SKIP_ICON="⏭️ "
20
+ RUN_ICON="🚀"
21
+ CLOCK_ICON="⏱️ "
22
+
23
+ WEB_DIR="$(cd "$(dirname "$0")/.." && pwd)"
24
+
25
+ banner() {
26
+ echo ""
27
+ echo -e "${CYAN}${BOLD}╔══════════════════════════════════════╗${RESET}"
28
+ echo -e "${CYAN}${BOLD}║ AMLIQ v2 — Test Runner ║${RESET}"
29
+ echo -e "${CYAN}${BOLD}╚══════════════════════════════════════╝${RESET}"
30
+ echo ""
31
+ }
32
+
33
+ separator() {
34
+ echo -e "${DIM}──────────────────────────────────────${RESET}"
35
+ }
36
+
37
+ run_vitest() {
38
+ echo -e "\n${RUN_ICON} ${BOLD}Running Component Tests (Vitest)...${RESET}"
39
+ separator
40
+ cd "$WEB_DIR"
41
+ local start=$SECONDS
42
+ if npx vitest run --reporter=verbose 2>&1; then
43
+ local dur=$(( SECONDS - start ))
44
+ echo -e "\n${PASS_ICON} ${GREEN}Component tests passed${RESET} ${CLOCK_ICON}${dur}s"
45
+ return 0
46
+ else
47
+ local dur=$(( SECONDS - start ))
48
+ echo -e "\n${FAIL_ICON} ${RED}Component tests failed${RESET} ${CLOCK_ICON}${dur}s"
49
+ return 1
50
+ fi
51
+ }
52
+
53
+ run_playwright() {
54
+ local project="${1:-all}"
55
+ echo -e "\n${RUN_ICON} ${BOLD}Running E2E Tests (Playwright${project:+ — $project})...${RESET}"
56
+ separator
57
+ cd "$WEB_DIR"
58
+
59
+ # Ensure Vite is running
60
+ if ! curl -s http://localhost:5173 > /dev/null 2>&1; then
61
+ echo -e "${YELLOW}Starting Vite dev server...${RESET}"
62
+ npx vite --port 5173 &>/tmp/vite-test.log &
63
+ VITE_PID=$!
64
+ for i in $(seq 1 20); do
65
+ curl -s http://localhost:5173 > /dev/null 2>&1 && break
66
+ sleep 1
67
+ done
68
+ fi
69
+
70
+ local start=$SECONDS
71
+ local args=(--reporter=list)
72
+ if [ "$project" != "all" ]; then
73
+ args+=(--project="$project")
74
+ fi
75
+
76
+ if npx playwright test "${args[@]}" 2>&1; then
77
+ local dur=$(( SECONDS - start ))
78
+ echo -e "\n${PASS_ICON} ${GREEN}E2E tests passed${RESET} ${CLOCK_ICON}${dur}s"
79
+ return 0
80
+ else
81
+ local dur=$(( SECONDS - start ))
82
+ echo -e "\n${FAIL_ICON} ${RED}E2E tests failed${RESET} ${CLOCK_ICON}${dur}s"
83
+ return 1
84
+ fi
85
+ }
86
+
87
+ run_all() {
88
+ local failures=0
89
+ run_vitest || (( failures++ )) || true
90
+ run_playwright "all" || (( failures++ )) || true
91
+
92
+ echo ""
93
+ separator
94
+ if [ "$failures" -eq 0 ]; then
95
+ echo -e "${PASS_ICON} ${GREEN}${BOLD}All test suites passed!${RESET}"
96
+ else
97
+ echo -e "${FAIL_ICON} ${RED}${BOLD}$failures suite(s) had failures${RESET}"
98
+ fi
99
+ return "$failures"
100
+ }
101
+
102
+ show_menu() {
103
+ banner
104
+ echo -e " ${BOLD}1)${RESET} Run all tests"
105
+ echo -e " ${BOLD}2)${RESET} Component tests (Vitest)"
106
+ echo -e " ${BOLD}3)${RESET} E2E tests — Desktop (Chromium)"
107
+ echo -e " ${BOLD}4)${RESET} E2E tests — Mobile"
108
+ echo -e " ${BOLD}5)${RESET} E2E tests — All browsers"
109
+ echo -e " ${BOLD}6)${RESET} E2E tests — Headed mode"
110
+ echo -e " ${BOLD}q)${RESET} Quit"
111
+ echo ""
112
+ echo -ne " ${CYAN}Pick an option: ${RESET}"
113
+ }
114
+
115
+ interactive() {
116
+ while true; do
117
+ show_menu
118
+ read -r choice
119
+ case "$choice" in
120
+ 1) run_all ;;
121
+ 2) run_vitest ;;
122
+ 3) run_playwright "chromium" ;;
123
+ 4) run_playwright "mobile" ;;
124
+ 5) run_playwright "all" ;;
125
+ 6)
126
+ echo -e "\n${RUN_ICON} ${BOLD}Running E2E headed...${RESET}"
127
+ cd "$WEB_DIR"
128
+ npx playwright test --project=chromium --headed 2>&1
129
+ ;;
130
+ q|Q) echo -e "\n${DIM}Bye!${RESET}"; exit 0 ;;
131
+ *) echo -e "${YELLOW}Invalid choice${RESET}" ;;
132
+ esac
133
+ echo ""
134
+ echo -ne "${DIM}Press Enter to continue...${RESET}"
135
+ read -r
136
+ done
137
+ }
138
+
139
+ # CLI entry point
140
+ case "${1:-}" in
141
+ --all) run_all ;;
142
+ --vitest) run_vitest ;;
143
+ --e2e) run_playwright "${2:-all}" ;;
144
+ --help|-h)
145
+ echo "Usage: $0 [--all|--vitest|--e2e [project]|--help]"
146
+ echo " No args → interactive menu"
147
+ echo " --all → run all suites"
148
+ echo " --vitest → component tests only"
149
+ echo " --e2e → E2E tests (optional: chromium|mobile)"
150
+ ;;
151
+ *) interactive ;;
152
+ esac
package/src/App.tsx ADDED
@@ -0,0 +1,48 @@
1
+ import React, { Suspense } from 'react'
2
+ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
3
+ import { useDirection } from './hooks/useDirection'
4
+ import { AuthProvider } from './context/AuthContext'
5
+ import { ToastProvider } from './components/ui/Toast'
6
+ import { ErrorBoundary } from './components/ui/ErrorBoundary'
7
+ import { ProtectedRoute } from './components/layout/ProtectedRoute'
8
+ import { AppShell } from './components/layout/AppShell'
9
+ import PublicLayout from './components/layout/PublicLayout'
10
+ import DashboardLayout from './components/layout/DashboardLayout'
11
+ import { LoadingSpinner } from './components/ui/LoadingSpinner'
12
+ import { appRoutes } from './routes/appRoutes'
13
+ import { complianceRoutes } from './routes/compliance'
14
+ import { platformRoutes } from './routes/platform'
15
+
16
+ const P = ({ children }: { children: React.ReactNode }) => (
17
+ <ProtectedRoute><AppShell>{children}</AppShell></ProtectedRoute>
18
+ )
19
+
20
+ const PageFallback = () => (
21
+ <div className="flex items-center justify-center h-96">
22
+ <LoadingSpinner />
23
+ </div>
24
+ )
25
+
26
+ function App() {
27
+ useDirection()
28
+
29
+ return (
30
+ <ErrorBoundary>
31
+ <AuthProvider>
32
+ <ToastProvider>
33
+ <Router>
34
+ <Suspense fallback={<PageFallback />}>
35
+ <Routes>
36
+ {appRoutes(P, PublicLayout, DashboardLayout)}
37
+ {complianceRoutes(P)}
38
+ {platformRoutes(P)}
39
+ </Routes>
40
+ </Suspense>
41
+ </Router>
42
+ </ToastProvider>
43
+ </AuthProvider>
44
+ </ErrorBoundary>
45
+ )
46
+ }
47
+
48
+ export default App
@@ -0,0 +1,19 @@
1
+ import { api } from './client';
2
+ import type { Alert } from '../types';
3
+
4
+ interface AlertListResponse {
5
+ data: Alert[];
6
+ total: number;
7
+ }
8
+
9
+ interface ResolvePayload {
10
+ resolution: string;
11
+ notes: string;
12
+ }
13
+
14
+ export const alertsApi = {
15
+ list: () => api.get<AlertListResponse>('/alerts'),
16
+ get: (id: string) => api.get<Alert>(`/alerts/${id}`),
17
+ resolve: (id: string, payload: ResolvePayload) =>
18
+ api.put<Alert>(`/alerts/${id}/resolve`, payload),
19
+ };
@@ -0,0 +1,6 @@
1
+ import { api } from './client';
2
+ import type { DashboardAnalytics } from '../types';
3
+
4
+ export const analyticsApi = {
5
+ getDashboard: () => api.get<DashboardAnalytics>('/analytics'),
6
+ };
@@ -0,0 +1,11 @@
1
+ import { api } from './client';
2
+ import type { AuditEntry } from '../types';
3
+
4
+ interface AuditListResponse {
5
+ entries: AuditEntry[];
6
+ }
7
+
8
+ export const auditApi = {
9
+ list: () => api.get<AuditListResponse>('/audit'),
10
+ get: (id: string) => api.get<AuditEntry>(`/audit/${id}`),
11
+ };
@@ -0,0 +1,26 @@
1
+ import { api } from './client';
2
+
3
+ export interface LoginPayload {
4
+ email: string;
5
+ password: string;
6
+ }
7
+
8
+ export interface SignupPayload {
9
+ email: string;
10
+ password: string;
11
+ org_name: string;
12
+ country: string;
13
+ }
14
+
15
+ export interface AuthResponse {
16
+ token: string;
17
+ user: { id: string; email: string; role: string; tenant_id: string };
18
+ }
19
+
20
+ export const authApi = {
21
+ login: (data: LoginPayload) =>
22
+ api.post<AuthResponse>('/auth/login', data),
23
+ signup: (data: SignupPayload) =>
24
+ api.post<AuthResponse>('/auth/signup', data),
25
+ me: () => api.get<AuthResponse['user']>('/auth/me'),
26
+ };