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
@@ -0,0 +1,45 @@
1
+ import HeroSection from './HeroSection'
2
+ import ProductShowcase from './ProductShowcase'
3
+ import MatchingLayers from './MatchingLayers'
4
+ import LogoMarquee from './LogoMarquee'
5
+ import FeaturesSpotlight from './FeaturesSpotlight'
6
+ import StatsBar from './StatsBar'
7
+ import CompetitiveEdge from './CompetitiveEdge'
8
+ import DataCoverage from './DataCoverage'
9
+ import QuoteRotator from './QuoteRotator'
10
+ import CaseStudy from './CaseStudy'
11
+ import PricingSection from './PricingSection'
12
+ import CTASection from './CTASection'
13
+ import FAQSchema from './FAQSchema'
14
+
15
+ export default function LandingPage() {
16
+ return (
17
+ <div
18
+ className="text-[#1A1A2E] scroll-smooth"
19
+ style={{
20
+ background: '#FFFFFF',
21
+ fontFamily: "'Inter', -apple-system, sans-serif",
22
+ }}
23
+ >
24
+ <header>
25
+ <HeroSection />
26
+ <ProductShowcase />
27
+ </header>
28
+ <LogoMarquee />
29
+ <StatsBar />
30
+ <MatchingLayers />
31
+ <section aria-label="Features">
32
+ <FeaturesSpotlight />
33
+ </section>
34
+ <CompetitiveEdge />
35
+ <DataCoverage />
36
+ <QuoteRotator />
37
+ <CaseStudy />
38
+ <section aria-label="Pricing">
39
+ <PricingSection />
40
+ </section>
41
+ <CTASection />
42
+ <FAQSchema />
43
+ </div>
44
+ )
45
+ }
@@ -0,0 +1,31 @@
1
+ import React from 'react'
2
+ import { useTranslation } from 'react-i18next'
3
+ import { Building2, Landmark, Shield, Globe, Scale, Wallet } from 'lucide-react'
4
+
5
+ export default function LogoCloud() {
6
+ const { t } = useTranslation('marketing')
7
+ const segments = [
8
+ { icon: <Landmark size={20} />, label: t('logo_cloud.banks') },
9
+ { icon: <Shield size={20} />, label: t('logo_cloud.fintechs') },
10
+ { icon: <Building2 size={20} />, label: t('logo_cloud.msbs') },
11
+ { icon: <Globe size={20} />, label: t('logo_cloud.neobanks') },
12
+ { icon: <Scale size={20} />, label: t('logo_cloud.regulators') },
13
+ { icon: <Wallet size={20} />, label: t('logo_cloud.payments') },
14
+ ]
15
+
16
+ return (
17
+ <section className="py-16 border-y border-white/[0.04]">
18
+ <div className="max-w-7xl mx-auto px-4">
19
+ <p className="text-center text-sm text-zinc-400 mb-12">{t('logo_cloud.subtitle')}</p>
20
+ <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
21
+ {segments.map(s => (
22
+ <div key={s.label} className="flex items-center justify-center gap-2 p-4 border border-white/[0.06] rounded-xl hover:border-white/[0.12] transition-colors">
23
+ <span className="text-zinc-400">{s.icon}</span>
24
+ <span className="text-sm text-zinc-400">{s.label}</span>
25
+ </div>
26
+ ))}
27
+ </div>
28
+ </div>
29
+ </section>
30
+ )
31
+ }
@@ -0,0 +1,45 @@
1
+ import { Shield, Globe, Database, Lock, Zap, FileCheck } from 'lucide-react'
2
+
3
+ const dataSources = [
4
+ { name: 'OFAC SDN', icon: Shield },
5
+ { name: 'UN Sanctions', icon: Globe },
6
+ { name: 'EU Consolidated', icon: Database },
7
+ { name: 'UK OFSI', icon: Lock },
8
+ { name: 'IL NBCTF', icon: Shield },
9
+ { name: 'OpenSanctions', icon: Database },
10
+ { name: 'PEP Lists', icon: FileCheck },
11
+ { name: '3M+ Entities', icon: Zap },
12
+ ]
13
+
14
+ function SourceBadge({ name, icon: Icon }: { name: string; icon: typeof Shield }) {
15
+ return (
16
+ <div className="flex items-center gap-2 px-8 shrink-0 opacity-60 hover:opacity-100 transition-opacity">
17
+ <div className="w-8 h-8 rounded-md bg-[#F1F5F9] flex items-center justify-center">
18
+ <Icon size={14} className="text-[#00B894]" />
19
+ </div>
20
+ <span className="text-sm text-[#64748B] whitespace-nowrap font-medium">{name}</span>
21
+ </div>
22
+ )
23
+ }
24
+
25
+ export default function LogoMarquee() {
26
+ return (
27
+ <section className="py-16 overflow-hidden"
28
+ style={{ borderTop: '1px solid rgba(0,0,0,0.06)', borderBottom: '1px solid rgba(0,0,0,0.06)' }}>
29
+ <p className="text-center text-xs uppercase tracking-[0.05em] text-[#64748B] font-medium mb-8">
30
+ Screening against global sanctions and watchlists
31
+ </p>
32
+ <div className="relative">
33
+ <div className="absolute left-0 top-0 bottom-0 w-24 z-10"
34
+ style={{ background: 'linear-gradient(90deg, #FFFFFF, transparent)' }} />
35
+ <div className="absolute right-0 top-0 bottom-0 w-24 z-10"
36
+ style={{ background: 'linear-gradient(270deg, #FFFFFF, transparent)' }} />
37
+ <div className="flex items-center marquee-track">
38
+ {[...dataSources, ...dataSources].map((src, i) => (
39
+ <SourceBadge key={`${src.name}-${i}`} name={src.name} icon={src.icon} />
40
+ ))}
41
+ </div>
42
+ </div>
43
+ </section>
44
+ )
45
+ }
@@ -0,0 +1,80 @@
1
+ import { useState, useEffect } from 'react'
2
+ import { useNavigate } from 'react-router-dom'
3
+ import { Menu, X } from 'lucide-react'
4
+ import { motion, AnimatePresence } from 'framer-motion'
5
+ import MobileMenu from './MobileMenu'
6
+
7
+ const navLinks = [
8
+ { label: 'Features', href: '#features' },
9
+ { label: 'Pricing', href: '#pricing' },
10
+ ]
11
+
12
+ export default function MarketingNav() {
13
+ const [mobileOpen, setMobileOpen] = useState(false)
14
+ const [scrolled, setScrolled] = useState(false)
15
+ const navigate = useNavigate()
16
+
17
+ useEffect(() => {
18
+ const onScroll = () => setScrolled(window.scrollY > 20)
19
+ window.addEventListener('scroll', onScroll, { passive: true })
20
+ return () => window.removeEventListener('scroll', onScroll)
21
+ }, [])
22
+
23
+ return (
24
+ <>
25
+ <motion.nav
26
+ className="sticky top-0 z-50 transition-all duration-300"
27
+ style={{
28
+ background: scrolled ? 'rgba(255,255,255,0.9)' : 'rgba(255,255,255,0.6)',
29
+ backdropFilter: 'blur(20px) saturate(180%)',
30
+ borderBottom: scrolled ? '1px solid rgba(0,0,0,0.06)' : '1px solid transparent',
31
+ boxShadow: scrolled ? '0 1px 3px rgba(0,0,0,0.04)' : 'none',
32
+ }}>
33
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
34
+ <a href="/" className="flex items-center gap-1 group">
35
+ <span className="text-xl font-extrabold text-[#0F172A] tracking-tight">AMLIQ</span>
36
+ <motion.span className="w-1.5 h-1.5 rounded-full bg-[#00B894] -mt-3"
37
+ animate={{ scale: [1, 1.3, 1] }}
38
+ transition={{ duration: 2, repeat: Infinity }} />
39
+ </a>
40
+ <div className="hidden md:flex items-center gap-8">
41
+ {navLinks.map(l => (
42
+ <a key={l.label} href={l.href}
43
+ className="text-sm text-[#64748B] hover:text-[#0F172A] transition-colors font-medium">
44
+ {l.label}
45
+ </a>
46
+ ))}
47
+ </div>
48
+ <div className="hidden md:flex items-center gap-4">
49
+ <button type="button" onClick={() => navigate('/login')}
50
+ className="text-sm text-[#64748B] hover:text-[#0F172A] transition-colors cursor-pointer font-medium">
51
+ Login
52
+ </button>
53
+ <motion.button type="button"
54
+ onClick={() => window.open('https://calendly.com/amliq', '_blank')}
55
+ className="px-5 py-2 bg-[#00B894] text-white text-sm font-semibold rounded-xl cursor-pointer"
56
+ whileHover={{ scale: 1.04, boxShadow: '0 4px 16px rgba(0,184,148,0.3)' }}
57
+ whileTap={{ scale: 0.97 }}>
58
+ Book a Demo
59
+ </motion.button>
60
+ </div>
61
+ <button type="button" onClick={() => setMobileOpen(!mobileOpen)}
62
+ className="md:hidden text-[#0F172A] p-2 -mr-2">
63
+ {mobileOpen ? <X size={24} /> : <Menu size={24} />}
64
+ </button>
65
+ </div>
66
+ </motion.nav>
67
+ <AnimatePresence>
68
+ {mobileOpen && (
69
+ <motion.div
70
+ initial={{ opacity: 0, height: 0 }}
71
+ animate={{ opacity: 1, height: 'auto' }}
72
+ exit={{ opacity: 0, height: 0 }}
73
+ transition={{ duration: 0.25 }}>
74
+ <MobileMenu onClose={() => setMobileOpen(false)} />
75
+ </motion.div>
76
+ )}
77
+ </AnimatePresence>
78
+ </>
79
+ )
80
+ }
@@ -0,0 +1,78 @@
1
+ import { useEffect, useRef, useState } from 'react'
2
+ import { motion } from 'framer-motion'
3
+ import { FadeUp, ScaleIn } from './animations'
4
+
5
+ const layers = [
6
+ { name: 'Exact', score: 100, color: '#00B894' },
7
+ { name: 'Fuzzy', score: 92, color: '#22C55E' },
8
+ { name: 'Phonetic', score: 88, color: '#6366F1' },
9
+ { name: 'Token', score: 85, color: '#8B5CF6' },
10
+ { name: 'Embedding', score: 79, color: '#EC4899' },
11
+ { name: 'Graph', score: 71, color: '#F59E0B' },
12
+ ]
13
+
14
+ function LayerBar({ name, score, color, delay }: {
15
+ name: string; score: number; color: string; delay: number
16
+ }) {
17
+ const [width, setWidth] = useState(0)
18
+ const ref = useRef<HTMLDivElement>(null)
19
+ useEffect(() => {
20
+ const el = ref.current
21
+ if (!el) return
22
+ const obs = new IntersectionObserver(([e]) => {
23
+ if (e.isIntersecting) { setTimeout(() => setWidth(score), delay); obs.disconnect() }
24
+ }, { threshold: 0.3 })
25
+ obs.observe(el)
26
+ return () => obs.disconnect()
27
+ }, [score, delay])
28
+
29
+ return (
30
+ <motion.div ref={ref} className="flex items-center gap-4"
31
+ whileHover={{ x: 2 }} transition={{ type: 'spring', stiffness: 400 }}>
32
+ <span className="w-24 text-right text-sm font-semibold text-[#64748B] shrink-0">{name}</span>
33
+ <div className="flex-1 h-9 rounded-lg bg-[#F1F5F9] overflow-hidden relative">
34
+ <motion.div
35
+ className="h-full rounded-lg flex items-center justify-end pr-3"
36
+ style={{ width: `${width}%`, background: `linear-gradient(90deg, ${color}, ${color}CC)` }}
37
+ initial={{ width: 0 }}
38
+ animate={{ width: `${width}%` }}
39
+ transition={{ duration: 1.2, ease: [0.25, 0.4, 0, 1], delay: delay / 1000 }}>
40
+ {width > 0 && <span className="text-xs font-bold text-white">{score}%</span>}
41
+ </motion.div>
42
+ </div>
43
+ </motion.div>
44
+ )
45
+ }
46
+
47
+ export default function MatchingLayers() {
48
+ return (
49
+ <section className="py-28 px-4">
50
+ <div className="max-w-3xl mx-auto">
51
+ <FadeUp>
52
+ <p className="text-xs uppercase tracking-[0.2em] text-[#00B894] font-semibold text-center mb-3">
53
+ Matching Engine
54
+ </p>
55
+ <h2 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-center mb-4 text-[#0F172A]"
56
+ style={{ letterSpacing: '-0.03em' }}>
57
+ 6-layer AI pipeline
58
+ </h2>
59
+ <p className="text-[#64748B] text-center mb-14 max-w-lg mx-auto">
60
+ Every entity flows through six independent matching layers.
61
+ Each score is weighted and explained.
62
+ </p>
63
+ </FadeUp>
64
+ <ScaleIn>
65
+ <div className="space-y-4 p-8 rounded-2xl" style={{
66
+ background: '#FAFBFC', border: '1px solid rgba(0,0,0,0.06)',
67
+ boxShadow: '0 8px 30px rgba(0,0,0,0.04)',
68
+ }}>
69
+ <p className="text-xs text-[#94A3B8] mb-3" style={{ fontFamily: "'JetBrains Mono', monospace" }}>
70
+ screening &quot;Mohammad Ali Hassan&quot;
71
+ </p>
72
+ {layers.map((l, i) => <LayerBar key={l.name} {...l} delay={i * 200} />)}
73
+ </div>
74
+ </ScaleIn>
75
+ </div>
76
+ </section>
77
+ )
78
+ }
@@ -0,0 +1,45 @@
1
+ import { useNavigate } from 'react-router-dom'
2
+
3
+ interface MobileMenuProps {
4
+ onClose: () => void
5
+ }
6
+
7
+ const links = [
8
+ { label: 'Features', href: '#features' },
9
+ { label: 'Pricing', href: '#pricing' },
10
+ { label: 'Solutions', href: '#screening' },
11
+ { label: 'Contact', href: 'mailto:info@amliq.finance' },
12
+ ]
13
+
14
+ export default function MobileMenu({ onClose }: MobileMenuProps) {
15
+ const navigate = useNavigate()
16
+
17
+ const go = (path: string) => {
18
+ navigate(path)
19
+ onClose()
20
+ }
21
+
22
+ return (
23
+ <div
24
+ className="md:hidden px-4 py-6 space-y-4"
25
+ style={{ background: '#FAFBFC', borderBottom: '1px solid rgba(0,0,0,0.08)' }}
26
+ >
27
+ {links.map(l => (
28
+ <a key={l.label} href={l.href} onClick={onClose}
29
+ className="block text-[#64748B] hover:text-[#1A1A2E] transition-colors">
30
+ {l.label}
31
+ </a>
32
+ ))}
33
+ <div className="pt-4 space-y-3" style={{ borderTop: '1px solid rgba(0,0,0,0.08)' }}>
34
+ <button type="button" onClick={() => go('/login')}
35
+ className="w-full text-left text-[#64748B] hover:text-[#1A1A2E] transition-colors">
36
+ Login
37
+ </button>
38
+ <button type="button" onClick={() => go('/signup')}
39
+ className="w-full px-4 py-2.5 bg-[#00B894] hover:bg-[#00A383] text-white font-semibold rounded-lg transition-colors">
40
+ Book a Demo
41
+ </button>
42
+ </div>
43
+ </div>
44
+ )
45
+ }
@@ -0,0 +1,57 @@
1
+ import React from 'react'
2
+ import { useTranslation } from 'react-i18next'
3
+ import { Check } from 'lucide-react'
4
+ import { Plan } from '../../types/billing'
5
+
6
+ interface PricingCardProps {
7
+ plan: Plan
8
+ annual?: boolean
9
+ productType?: string
10
+ }
11
+
12
+ export default function PricingCard({ plan, annual = false }: PricingCardProps) {
13
+ const { t } = useTranslation('marketing')
14
+ const price = annual ? plan.annualPrice : plan.monthlyPrice
15
+ const displayPrice = annual ? (price / 12).toFixed(0) : price.toFixed(0)
16
+ const isEnterprise = price === 0 || plan.name === 'Enterprise'
17
+ const popular = plan.highlighted
18
+
19
+ return (
20
+ <div className={`relative card-vibrancy p-lg transition-all ${popular ? 'border-apple-blue shadow-[0_0_24px_rgba(10,132,255,0.15)]' : ''} hover:border-white/20`}>
21
+ {popular && (
22
+ <div className="absolute -top-3 left-4 bg-apple-blue text-white sf-caption font-bold px-md py-xs rounded-apple-md">
23
+ {t('pricing.most_popular')}
24
+ </div>
25
+ )}
26
+
27
+ <h3 className="sf-headline text-white mb-lg">{plan.name}</h3>
28
+
29
+ {!isEnterprise ? (
30
+ <div className="mb-lg">
31
+ <span className="text-5xl font-bold text-white">${displayPrice}</span>
32
+ <span className="sf-caption text-apple-label-tertiary ml-xs">{t('pricing.per_month')}</span>
33
+ {annual && (
34
+ <div className="sf-caption text-apple-label-secondary mt-sm">
35
+ {t('pricing.billed_yearly', { price: price.toFixed(0) })}
36
+ </div>
37
+ )}
38
+ </div>
39
+ ) : (
40
+ <div className="mb-lg text-3xl font-bold text-white">{t('pricing.custom')}</div>
41
+ )}
42
+
43
+ <button type="button" className={`w-full py-md rounded-apple-md font-semibold transition-colors cursor-pointer mb-lg ${popular ? 'bg-apple-blue hover:bg-blue-600 text-white' : 'border border-white/20 text-white hover:border-white/40'}`}>
44
+ {isEnterprise ? t('pricing.contact_sales') : t('pricing.get_started')}
45
+ </button>
46
+
47
+ <div className="space-y-sm">
48
+ {plan.features.map((f, i) => (
49
+ <div key={i} className="flex items-start gap-sm">
50
+ <Check size={14} className="text-apple-green mt-0.5 shrink-0" />
51
+ <span className="sf-caption text-apple-label-secondary">{f}</span>
52
+ </div>
53
+ ))}
54
+ </div>
55
+ </div>
56
+ )
57
+ }
@@ -0,0 +1,16 @@
1
+ import React from 'react'
2
+ import { Check } from 'lucide-react'
3
+
4
+ interface PricingFeatureRowProps {
5
+ label: string
6
+ included: boolean
7
+ }
8
+
9
+ export default function PricingFeatureRow({ label, included }: PricingFeatureRowProps) {
10
+ return (
11
+ <div className={`flex items-center gap-3 py-2 text-sm ${included ? 'text-zinc-400' : 'text-zinc-400 line-through'}`}>
12
+ {included ? <Check size={16} className="text-green-500 flex-shrink-0" /> : <div className="w-4 h-4 flex-shrink-0" />}
13
+ {label}
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,103 @@
1
+ import { useState } from 'react'
2
+ import { Check } from 'lucide-react'
3
+ import { motion } from 'framer-motion'
4
+ import { FadeUp } from './animations'
5
+ import PricingToggle from './PricingToggle'
6
+
7
+ interface Plan {
8
+ name: string; monthly: number; features: string[]
9
+ highlighted?: boolean; enterprise?: boolean
10
+ }
11
+
12
+ const plans: Plan[] = [
13
+ { name: 'Free', monthly: 0, features: [
14
+ '100 screenings/mo', 'OFAC + UN + EU lists', 'REST API', '6-layer matching',
15
+ 'Community support', '7-day retention',
16
+ ]},
17
+ { name: 'Pro', monthly: 299, highlighted: true, features: [
18
+ '50,000 screenings/mo', 'All 86 sanctions lists', '3M+ entity database',
19
+ 'AI cascade (Claude)', 'Freetext screening', 'Batch screening',
20
+ 'Webhooks & MFA', 'Priority support', '90-day retention',
21
+ ]},
22
+ { name: 'Enterprise', monthly: 0, enterprise: true, features: [
23
+ 'Unlimited screenings', 'Custom list uploads', 'On-premise agent',
24
+ 'SAML SSO', 'Dedicated CSM + SLA', 'Self-hosted option',
25
+ 'Crypto wallet screening', 'Transaction orchestration',
26
+ ]},
27
+ ]
28
+
29
+ function PlanCard({ plan, annual }: { plan: Plan; annual: boolean }) {
30
+ const price = annual ? Math.round(plan.monthly * 0.8) : plan.monthly
31
+ const hl = plan.highlighted
32
+ return (
33
+ <motion.div
34
+ className={`relative rounded-2xl p-6 ${hl ? '-translate-y-2' : ''}`}
35
+ style={{
36
+ background: hl ? '#FAFBFC' : '#FFFFFF',
37
+ border: `1px solid ${hl ? '#00B894' : 'rgba(0,0,0,0.06)'}`,
38
+ boxShadow: hl ? '0 8px 40px rgba(0,184,148,0.12)' : '0 2px 8px rgba(0,0,0,0.04)',
39
+ }}
40
+ whileHover={{ y: hl ? -12 : -6, boxShadow: '0 16px 50px rgba(0,0,0,0.1)' }}
41
+ transition={{ type: 'spring', stiffness: 300, damping: 20 }}>
42
+ {hl && (
43
+ <div className="absolute -top-3 left-6 px-3 py-0.5 text-[11px] font-bold rounded-full text-white
44
+ bg-gradient-to-r from-[#00B894] to-[#059669] uppercase tracking-wider">
45
+ Most Popular
46
+ </div>
47
+ )}
48
+ <h3 className="text-lg font-bold text-[#0F172A] mb-4">{plan.name}</h3>
49
+ {plan.enterprise ? (
50
+ <p className="text-3xl font-extrabold text-[#0F172A] mb-6">Custom</p>
51
+ ) : price === 0 ? (
52
+ <p className="text-4xl font-extrabold text-[#0F172A] mb-6">Free</p>
53
+ ) : (
54
+ <div className="mb-6">
55
+ <span className="text-4xl font-extrabold text-[#0F172A]">${price}</span>
56
+ <span className="text-sm text-[#94A3B8] ml-1">/mo</span>
57
+ </div>
58
+ )}
59
+ <motion.button type="button"
60
+ className={`w-full py-3 rounded-xl font-semibold text-sm mb-6 cursor-pointer ${hl
61
+ ? 'bg-[#00B894] text-white' : 'text-[#0F172A] border border-[#E2E8F0]'}`}
62
+ whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }}>
63
+ {plan.enterprise ? 'Contact Sales' : price === 0 ? 'Get Started Free' : 'Start Free Trial'}
64
+ </motion.button>
65
+ <ul className="space-y-3">
66
+ {plan.features.map(f => (
67
+ <li key={f} className="flex items-start gap-2.5">
68
+ <Check size={14} className="text-[#00B894] mt-0.5 shrink-0" />
69
+ <span className="text-sm text-[#64748B]">{f}</span>
70
+ </li>
71
+ ))}
72
+ </ul>
73
+ </motion.div>
74
+ )
75
+ }
76
+
77
+ export default function PricingSection() {
78
+ const [annual, setAnnual] = useState(false)
79
+ return (
80
+ <section id="pricing" className="py-28 px-4">
81
+ <div className="max-w-5xl mx-auto">
82
+ <FadeUp>
83
+ <p className="text-xs uppercase tracking-[0.2em] text-[#00B894] font-semibold text-center mb-3">Pricing</p>
84
+ <h2 className="text-3xl sm:text-4xl lg:text-5xl font-bold text-[#0F172A] text-center mb-4"
85
+ style={{ letterSpacing: '-0.03em' }}>
86
+ Simple, transparent pricing
87
+ </h2>
88
+ <p className="text-[#64748B] text-center mb-10 max-w-xl mx-auto">
89
+ Start free. Scale as you grow. No hidden fees.
90
+ </p>
91
+ <PricingToggle annual={annual} onChange={setAnnual} />
92
+ </FadeUp>
93
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-12">
94
+ {plans.map((p, i) => (
95
+ <FadeUp key={p.name} delay={i * 0.1}>
96
+ <PlanCard plan={p} annual={annual} />
97
+ </FadeUp>
98
+ ))}
99
+ </div>
100
+ </div>
101
+ </section>
102
+ )
103
+ }
@@ -0,0 +1,40 @@
1
+ interface PricingToggleProps {
2
+ annual: boolean
3
+ onChange: (annual: boolean) => void
4
+ }
5
+
6
+ export default function PricingToggle({ annual, onChange }: PricingToggleProps) {
7
+ return (
8
+ <div className="flex items-center justify-center gap-3">
9
+ <button
10
+ type="button"
11
+ onClick={() => onChange(false)}
12
+ className={`px-4 py-2 rounded-lg text-sm font-medium transition-all ${
13
+ !annual
14
+ ? 'bg-[#00B894]/10 text-[#00B894]'
15
+ : 'text-[#64748B] hover:text-[#0F172A]'
16
+ }`}
17
+ style={!annual ? { border: '1px solid rgba(0,184,148,0.2)' } : {}}
18
+ >
19
+ Monthly
20
+ </button>
21
+ <button
22
+ type="button"
23
+ onClick={() => onChange(true)}
24
+ className={`px-4 py-2 rounded-lg text-sm font-medium transition-all ${
25
+ annual
26
+ ? 'bg-[#00B894]/10 text-[#00B894]'
27
+ : 'text-[#64748B] hover:text-[#0F172A]'
28
+ }`}
29
+ style={annual ? { border: '1px solid rgba(0,184,148,0.2)' } : {}}
30
+ >
31
+ Annual
32
+ </button>
33
+ {annual && (
34
+ <span className="text-xs font-semibold text-[#22C55E] bg-[#22C55E]/10 px-2.5 py-1 rounded">
35
+ Save 20%
36
+ </span>
37
+ )}
38
+ </div>
39
+ )
40
+ }
@@ -0,0 +1,23 @@
1
+ import React from 'react'
2
+ import { Product } from '../../types/billing'
3
+ import PricingCard from './PricingCard'
4
+
5
+ interface ProductPricingCardsProps {
6
+ product: Product
7
+ annual?: boolean
8
+ }
9
+
10
+ export function ProductPricingCards({ product, annual = false }: ProductPricingCardsProps) {
11
+ return (
12
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-lg">
13
+ {product.plans.map(plan => (
14
+ <PricingCard
15
+ key={plan.id}
16
+ plan={plan}
17
+ annual={annual}
18
+ productType={product.type}
19
+ />
20
+ ))}
21
+ </div>
22
+ )
23
+ }
@@ -0,0 +1,81 @@
1
+ import { useNavigate } from 'react-router-dom'
2
+ import { Shield, Zap, Globe, Brain, Layers, BarChart3 } from 'lucide-react'
3
+ import { motion } from 'framer-motion'
4
+ import { FadeUp, ScaleIn } from './animations'
5
+
6
+ const features = [
7
+ { icon: Layers, label: '6-Layer AI Matching', detail: 'Exact, Fuzzy, Phonetic, Token, Embedding, Graph' },
8
+ { icon: Zap, label: 'Sub-50ms Screening', detail: '18,699+ entities screened in real-time' },
9
+ { icon: Globe, label: 'Global List Coverage', detail: 'OFAC, UN, EU, UK OFSI, IL NBCTF, OpenSanctions' },
10
+ { icon: Shield, label: 'PEP + RCA Screening', detail: 'Politicians, relatives, close associates' },
11
+ { icon: Brain, label: 'Explainable Results', detail: 'Every match shows why it matched and how' },
12
+ { icon: BarChart3, label: 'Ongoing Monitoring', detail: 'Continuous re-screening when lists update' },
13
+ ]
14
+
15
+ export default function ProductShowcase() {
16
+ const navigate = useNavigate()
17
+
18
+ return (
19
+ <section className="px-4 pb-24 pt-8">
20
+ <div className="max-w-5xl mx-auto">
21
+ <ScaleIn>
22
+ <div className="relative rounded-2xl overflow-hidden"
23
+ style={{ border: '1px solid rgba(0,0,0,0.06)', background: '#FAFBFC',
24
+ boxShadow: '0 20px 60px rgba(0,0,0,0.06)' }}>
25
+
26
+ <div className="flex items-center gap-2 px-4 py-3 bg-[#F1F5F9]">
27
+ <span className="w-3 h-3 rounded-full bg-[#EF4444]" />
28
+ <span className="w-3 h-3 rounded-full bg-[#F59E0B]" />
29
+ <span className="w-3 h-3 rounded-full bg-[#22C55E]" />
30
+ <span className="ml-4 text-xs text-[#94A3B8]">AMLIQ Dashboard — Sanctions Screening</span>
31
+ </div>
32
+
33
+ <div className="p-8 md:p-12">
34
+ <div className="grid md:grid-cols-2 gap-8 mb-10">
35
+ {features.map((f, i) => (
36
+ <FadeUp key={f.label} delay={i * 0.08}>
37
+ <motion.div className="flex gap-4 items-start group"
38
+ whileHover={{ x: 4 }} transition={{ type: 'spring', stiffness: 300 }}>
39
+ <div className="w-10 h-10 rounded-xl flex items-center justify-center shrink-0
40
+ bg-gradient-to-br from-[#00B894]/10 to-[#00B894]/5 border border-[#00B894]/15">
41
+ <f.icon size={18} color="#00B894" />
42
+ </div>
43
+ <div>
44
+ <p className="text-[#0F172A] font-semibold text-sm">{f.label}</p>
45
+ <p className="text-[#64748B] text-xs mt-1 leading-relaxed">{f.detail}</p>
46
+ </div>
47
+ </motion.div>
48
+ </FadeUp>
49
+ ))}
50
+ </div>
51
+
52
+ <div className="border-t border-[#E2E8F0] pt-8 flex flex-col sm:flex-row items-center justify-between gap-6">
53
+ <div>
54
+ <p className="text-[#0F172A] font-semibold">See it screening real sanctions data</p>
55
+ <p className="text-[#64748B] text-sm mt-1">
56
+ 18,699+ OFAC entities · PEP databases · IL NBCTF · Hebrew + English
57
+ </p>
58
+ </div>
59
+ <div className="flex gap-3">
60
+ <motion.button type="button" onClick={() => navigate('/signup')}
61
+ className="px-6 py-3 bg-[#00B894] text-white font-semibold text-sm rounded-xl cursor-pointer"
62
+ whileHover={{ scale: 1.03, boxShadow: '0 6px 24px rgba(0,184,148,0.25)' }}
63
+ whileTap={{ scale: 0.97 }}>
64
+ Start Free Trial
65
+ </motion.button>
66
+ <motion.button type="button"
67
+ onClick={() => window.open('https://calendly.com/amliq', '_blank')}
68
+ className="px-6 py-3 text-[#1A1A2E] text-sm rounded-xl cursor-pointer border border-[#E2E8F0]"
69
+ whileHover={{ scale: 1.03, backgroundColor: '#F8FAFC' }}
70
+ whileTap={{ scale: 0.97 }}>
71
+ Book a Demo
72
+ </motion.button>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </ScaleIn>
78
+ </div>
79
+ </section>
80
+ )
81
+ }