moonhead 1.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 (631) hide show
  1. package/README.md +32 -0
  2. package/dist/components/layout/app-header.d.ts +1 -0
  3. package/dist/components/layout/app-header.js +1 -0
  4. package/dist/components/layout/app-sidebar.d.ts +9 -0
  5. package/dist/components/layout/app-sidebar.js +1 -0
  6. package/dist/components/layout/brand-logo.d.ts +2 -0
  7. package/dist/components/layout/brand-logo.js +1 -0
  8. package/dist/components/layout/user-menu.d.ts +6 -0
  9. package/dist/components/layout/user-menu.js +1 -0
  10. package/dist/components/ui/action-form.d.ts +10 -0
  11. package/dist/components/ui/action-form.js +1 -0
  12. package/dist/components/ui/alert-dialog.d.ts +14 -0
  13. package/dist/components/ui/alert-dialog.js +1 -0
  14. package/dist/components/ui/alert.d.ts +12 -0
  15. package/dist/components/ui/alert.js +1 -0
  16. package/dist/components/ui/avatar.d.ts +12 -0
  17. package/dist/components/ui/avatar.js +1 -0
  18. package/dist/components/ui/badge.d.ts +2 -0
  19. package/dist/components/ui/badge.js +1 -0
  20. package/dist/components/ui/button.d.ts +12 -0
  21. package/dist/components/ui/button.js +1 -0
  22. package/dist/components/ui/card.d.ts +2 -0
  23. package/dist/components/ui/card.js +1 -0
  24. package/dist/components/ui/checkbox.d.ts +5 -0
  25. package/dist/components/ui/checkbox.js +1 -0
  26. package/dist/components/ui/combobox.d.ts +18 -0
  27. package/dist/components/ui/combobox.js +1 -0
  28. package/dist/components/ui/copy-button.d.ts +8 -0
  29. package/dist/components/ui/copy-button.js +1 -0
  30. package/dist/components/ui/country-select.d.ts +12 -0
  31. package/dist/components/ui/country-select.js +1 -0
  32. package/dist/components/ui/data-table.d.ts +11 -0
  33. package/dist/components/ui/data-table.js +1 -0
  34. package/dist/components/ui/date-range-picker.d.ts +25 -0
  35. package/dist/components/ui/date-range-picker.js +1 -0
  36. package/dist/components/ui/dialog.d.ts +19 -0
  37. package/dist/components/ui/dialog.js +1 -0
  38. package/dist/components/ui/drawer.d.ts +24 -0
  39. package/dist/components/ui/drawer.js +1 -0
  40. package/dist/components/ui/dropdown-menu.d.ts +17 -0
  41. package/dist/components/ui/dropdown-menu.js +1 -0
  42. package/dist/components/ui/field.d.ts +7 -0
  43. package/dist/components/ui/field.js +1 -0
  44. package/dist/components/ui/fieldset.d.ts +4 -0
  45. package/dist/components/ui/fieldset.js +1 -0
  46. package/dist/components/ui/form-field.d.ts +17 -0
  47. package/dist/components/ui/form-field.js +1 -0
  48. package/dist/components/ui/form.d.ts +3 -0
  49. package/dist/components/ui/form.js +1 -0
  50. package/dist/components/ui/icon-tile.d.ts +5 -0
  51. package/dist/components/ui/icon-tile.js +1 -0
  52. package/dist/components/ui/identity.d.ts +6 -0
  53. package/dist/components/ui/identity.js +1 -0
  54. package/dist/components/ui/input.d.ts +4 -0
  55. package/dist/components/ui/input.js +1 -0
  56. package/dist/components/ui/number-input.d.ts +19 -0
  57. package/dist/components/ui/number-input.js +1 -0
  58. package/dist/components/ui/otp-field.d.ts +6 -0
  59. package/dist/components/ui/otp-field.js +1 -0
  60. package/dist/components/ui/page-toolbar.d.ts +9 -0
  61. package/dist/components/ui/page-toolbar.js +1 -0
  62. package/dist/components/ui/password-input.d.ts +7 -0
  63. package/dist/components/ui/password-input.js +1 -0
  64. package/dist/components/ui/radio-group.d.ts +5 -0
  65. package/dist/components/ui/radio-group.js +1 -0
  66. package/dist/components/ui/search-input.d.ts +4 -0
  67. package/dist/components/ui/search-input.js +1 -0
  68. package/dist/components/ui/section-card.d.ts +7 -0
  69. package/dist/components/ui/section-card.js +1 -0
  70. package/dist/components/ui/select-field.d.ts +19 -0
  71. package/dist/components/ui/select-field.js +1 -0
  72. package/dist/components/ui/select.d.ts +17 -0
  73. package/dist/components/ui/select.js +1 -0
  74. package/dist/components/ui/sidebar.d.ts +27 -0
  75. package/dist/components/ui/sidebar.js +1 -0
  76. package/dist/components/ui/slider.d.ts +10 -0
  77. package/dist/components/ui/slider.js +1 -0
  78. package/dist/components/ui/sort-button.d.ts +5 -0
  79. package/dist/components/ui/sort-button.js +1 -0
  80. package/dist/components/ui/spinner.d.ts +4 -0
  81. package/dist/components/ui/spinner.js +1 -0
  82. package/dist/components/ui/status-badge.d.ts +11 -0
  83. package/dist/components/ui/status-badge.js +1 -0
  84. package/dist/components/ui/switch-field.d.ts +18 -0
  85. package/dist/components/ui/switch-field.js +1 -0
  86. package/dist/components/ui/switch.d.ts +3 -0
  87. package/dist/components/ui/switch.js +1 -0
  88. package/dist/components/ui/table-pagination.d.ts +9 -0
  89. package/dist/components/ui/table-pagination.js +1 -0
  90. package/dist/components/ui/table.d.ts +18 -0
  91. package/dist/components/ui/table.js +1 -0
  92. package/dist/components/ui/tabs.d.ts +8 -0
  93. package/dist/components/ui/tabs.js +1 -0
  94. package/dist/components/ui/tag-input.d.ts +9 -0
  95. package/dist/components/ui/tag-input.js +1 -0
  96. package/dist/components/ui/text-link.d.ts +10 -0
  97. package/dist/components/ui/text-link.js +1 -0
  98. package/dist/components/ui/textarea.d.ts +2 -0
  99. package/dist/components/ui/textarea.js +1 -0
  100. package/dist/components/ui/toast.d.ts +1 -0
  101. package/dist/components/ui/toast.js +1 -0
  102. package/dist/components/ui/tree.d.ts +32 -0
  103. package/dist/components/ui/tree.js +1 -0
  104. package/dist/db/client.d.ts +8 -0
  105. package/dist/db/client.js +1 -0
  106. package/dist/db/index.d.ts +3 -0
  107. package/dist/db/index.js +1 -0
  108. package/dist/db/logger.d.ts +2 -0
  109. package/dist/db/logger.js +1 -0
  110. package/dist/db/migrations/20260628182304_wonderful_groot/migration.sql +289 -0
  111. package/dist/db/migrations/20260628182304_wonderful_groot/snapshot.json +3750 -0
  112. package/dist/db/migrations/20260630082829_wet_robin_chapel/migration.sql +2 -0
  113. package/dist/db/migrations/20260630082829_wet_robin_chapel/snapshot.json +3791 -0
  114. package/dist/db/migrations/20260702132335_wooden_iron_monger/migration.sql +48 -0
  115. package/dist/db/migrations/20260702132335_wooden_iron_monger/snapshot.json +4407 -0
  116. package/dist/db/migrations/20260702142948_vengeful_rhino/migration.sql +1 -0
  117. package/dist/db/migrations/20260702142948_vengeful_rhino/snapshot.json +4420 -0
  118. package/dist/db/migrations/20260702185813_curved_pyro/migration.sql +16 -0
  119. package/dist/db/migrations/20260702185813_curved_pyro/snapshot.json +4646 -0
  120. package/dist/db/migrations/20260702192041_shiny_franklin_storm/migration.sql +16 -0
  121. package/dist/db/migrations/20260702192041_shiny_franklin_storm/snapshot.json +4872 -0
  122. package/dist/db/migrations/20260704101548_bizarre_namorita/migration.sql +1 -0
  123. package/dist/db/migrations/20260704101548_bizarre_namorita/snapshot.json +4885 -0
  124. package/dist/db/migrations/20260704105911_sleepy_juggernaut/migration.sql +1 -0
  125. package/dist/db/migrations/20260704105911_sleepy_juggernaut/snapshot.json +4898 -0
  126. package/dist/db/migrations/20260704115959_lean_sandman/migration.sql +1 -0
  127. package/dist/db/migrations/20260704115959_lean_sandman/snapshot.json +4885 -0
  128. package/dist/db/migrations/20260707231532_daffy_captain_stacy/migration.sql +10 -0
  129. package/dist/db/migrations/20260707231532_daffy_captain_stacy/snapshot.json +4919 -0
  130. package/dist/db/migrations/20260708190355_spooky_jimmy_woo/migration.sql +3 -0
  131. package/dist/db/migrations/20260708190355_spooky_jimmy_woo/snapshot.json +4970 -0
  132. package/dist/db/migrations/20260711145212_drop_legacy_earning_status/migration.sql +7 -0
  133. package/dist/db/migrations/20260711145212_drop_legacy_earning_status/snapshot.json +4968 -0
  134. package/dist/db/migrations/20260712161249_dashboard_stat_indexes/migration.sql +3 -0
  135. package/dist/db/migrations/20260712161249_dashboard_stat_indexes/snapshot.json +5038 -0
  136. package/dist/db/migrations/20260713013911_add_payout_paid_at/migration.sql +2 -0
  137. package/dist/db/migrations/20260713013911_add_payout_paid_at/snapshot.json +5072 -0
  138. package/dist/db/schema/analytics-outbox.d.ts +145 -0
  139. package/dist/db/schema/analytics-outbox.js +1 -0
  140. package/dist/db/schema/audit-logs.d.ts +204 -0
  141. package/dist/db/schema/audit-logs.js +1 -0
  142. package/dist/db/schema/campaigns.d.ts +180 -0
  143. package/dist/db/schema/campaigns.js +1 -0
  144. package/dist/db/schema/casinos.d.ts +129 -0
  145. package/dist/db/schema/casinos.js +1 -0
  146. package/dist/db/schema/commission-rule-groups.d.ts +84 -0
  147. package/dist/db/schema/commission-rule-groups.js +1 -0
  148. package/dist/db/schema/commission-rules.d.ts +145 -0
  149. package/dist/db/schema/commission-rules.js +1 -0
  150. package/dist/db/schema/commissions.d.ts +242 -0
  151. package/dist/db/schema/commissions.js +1 -0
  152. package/dist/db/schema/conversions.d.ts +302 -0
  153. package/dist/db/schema/conversions.js +1 -0
  154. package/dist/db/schema/deals.d.ts +180 -0
  155. package/dist/db/schema/deals.js +1 -0
  156. package/dist/db/schema/earnings.d.ts +262 -0
  157. package/dist/db/schema/earnings.js +1 -0
  158. package/dist/db/schema/groups.d.ts +214 -0
  159. package/dist/db/schema/groups.js +1 -0
  160. package/dist/db/schema/index.d.ts +18 -0
  161. package/dist/db/schema/index.js +1 -0
  162. package/dist/db/schema/payouts.d.ts +182 -0
  163. package/dist/db/schema/payouts.js +1 -0
  164. package/dist/db/schema/platform-settings.d.ts +84 -0
  165. package/dist/db/schema/platform-settings.js +1 -0
  166. package/dist/db/schema/player-activity.d.ts +159 -0
  167. package/dist/db/schema/player-activity.js +1 -0
  168. package/dist/db/schema/revshare-carryover.d.ts +129 -0
  169. package/dist/db/schema/revshare-carryover.js +1 -0
  170. package/dist/db/schema/sessions.d.ts +213 -0
  171. package/dist/db/schema/sessions.js +1 -0
  172. package/dist/db/schema/table.d.ts +1 -0
  173. package/dist/db/schema/table.js +1 -0
  174. package/dist/db/schema/users.d.ts +609 -0
  175. package/dist/db/schema/users.js +1 -0
  176. package/dist/db/schema/verification-tokens.d.ts +106 -0
  177. package/dist/db/schema/verification-tokens.js +1 -0
  178. package/dist/db/types/branded.d.ts +3 -0
  179. package/dist/db/types/branded.js +0 -0
  180. package/dist/db/types/commission-rules.d.ts +70 -0
  181. package/dist/db/types/commission-rules.js +1 -0
  182. package/dist/db/types/index.d.ts +2 -0
  183. package/dist/db/types/index.js +1 -0
  184. package/dist/emails/admin/support-message.d.ts +39 -0
  185. package/dist/emails/admin/support-message.js +5 -0
  186. package/dist/emails/affiliate/activated.d.ts +33 -0
  187. package/dist/emails/affiliate/activated.js +1 -0
  188. package/dist/emails/affiliate/deal-notice.d.ts +35 -0
  189. package/dist/emails/affiliate/deal-notice.js +1 -0
  190. package/dist/emails/affiliate/invite.d.ts +35 -0
  191. package/dist/emails/affiliate/invite.js +1 -0
  192. package/dist/emails/affiliate/signup-verify.d.ts +35 -0
  193. package/dist/emails/affiliate/signup-verify.js +1 -0
  194. package/dist/emails/auth/password-reset.d.ts +37 -0
  195. package/dist/emails/auth/password-reset.js +1 -0
  196. package/dist/emails/layout.d.ts +10 -0
  197. package/dist/emails/layout.js +1 -0
  198. package/dist/emails/manager/affiliate-activated.d.ts +33 -0
  199. package/dist/emails/manager/affiliate-activated.js +1 -0
  200. package/dist/emails/manager/bulk-affiliates-activated.d.ts +33 -0
  201. package/dist/emails/manager/bulk-affiliates-activated.js +1 -0
  202. package/dist/emails/manager/invite.d.ts +35 -0
  203. package/dist/emails/manager/invite.js +1 -0
  204. package/dist/emails/manager/pending-approval.d.ts +33 -0
  205. package/dist/emails/manager/pending-approval.js +1 -0
  206. package/dist/emails/preview-env.d.ts +2 -0
  207. package/dist/emails/preview-env.js +1 -0
  208. package/dist/features/affiliates/actions.d.ts +60 -0
  209. package/dist/features/affiliates/actions.js +1 -0
  210. package/dist/features/affiliates/activation-email.d.ts +8 -0
  211. package/dist/features/affiliates/activation-email.js +1 -0
  212. package/dist/features/affiliates/bulk-approve.d.ts +2 -0
  213. package/dist/features/affiliates/bulk-approve.js +1 -0
  214. package/dist/features/affiliates/components/affiliate-actions-menu.d.ts +6 -0
  215. package/dist/features/affiliates/components/affiliate-actions-menu.js +1 -0
  216. package/dist/features/affiliates/components/affiliate-create-button.d.ts +1 -0
  217. package/dist/features/affiliates/components/affiliate-create-button.js +1 -0
  218. package/dist/features/affiliates/components/affiliate-detail-tabs.d.ts +6 -0
  219. package/dist/features/affiliates/components/affiliate-detail-tabs.js +1 -0
  220. package/dist/features/affiliates/components/affiliate-dialog.d.ts +11 -0
  221. package/dist/features/affiliates/components/affiliate-dialog.js +1 -0
  222. package/dist/features/affiliates/components/affiliate-profile-fields.d.ts +6 -0
  223. package/dist/features/affiliates/components/affiliate-profile-fields.js +1 -0
  224. package/dist/features/affiliates/components/affiliate-status-badge.d.ts +4 -0
  225. package/dist/features/affiliates/components/affiliate-status-badge.js +1 -0
  226. package/dist/features/affiliates/components/affiliate-status-tabs.d.ts +4 -0
  227. package/dist/features/affiliates/components/affiliate-status-tabs.js +1 -0
  228. package/dist/features/affiliates/components/affiliates-table.d.ts +10 -0
  229. package/dist/features/affiliates/components/affiliates-table.js +1 -0
  230. package/dist/features/affiliates/components/assign-parent-dialog.d.ts +5 -0
  231. package/dist/features/affiliates/components/assign-parent-dialog.js +1 -0
  232. package/dist/features/affiliates/components/detach-affiliate-confirm.d.ts +5 -0
  233. package/dist/features/affiliates/components/detach-affiliate-confirm.js +1 -0
  234. package/dist/features/affiliates/components/reject-affiliate-confirm.d.ts +5 -0
  235. package/dist/features/affiliates/components/reject-affiliate-confirm.js +1 -0
  236. package/dist/features/affiliates/components/sub-affiliate-invite-button.d.ts +3 -0
  237. package/dist/features/affiliates/components/sub-affiliate-invite-button.js +1 -0
  238. package/dist/features/affiliates/invite.d.ts +6 -0
  239. package/dist/features/affiliates/invite.js +1 -0
  240. package/dist/features/affiliates/list-params.d.ts +27 -0
  241. package/dist/features/affiliates/list-params.js +1 -0
  242. package/dist/features/affiliates/pending-notification.d.ts +18 -0
  243. package/dist/features/affiliates/pending-notification.js +1 -0
  244. package/dist/features/affiliates/sub-invite.d.ts +7 -0
  245. package/dist/features/affiliates/sub-invite.js +1 -0
  246. package/dist/features/audit/action-labels.d.ts +15 -0
  247. package/dist/features/audit/action-labels.js +1 -0
  248. package/dist/features/audit/components/audit-log-table.d.ts +5 -0
  249. package/dist/features/audit/components/audit-log-table.js +1 -0
  250. package/dist/features/audit/list-params.d.ts +2 -0
  251. package/dist/features/audit/list-params.js +1 -0
  252. package/dist/features/audit/read.d.ts +27 -0
  253. package/dist/features/audit/read.js +1 -0
  254. package/dist/features/auth/actions.d.ts +33 -0
  255. package/dist/features/auth/actions.js +1 -0
  256. package/dist/features/auth/authorization.d.ts +14 -0
  257. package/dist/features/auth/authorization.js +1 -0
  258. package/dist/features/auth/components/accept-invite-form.d.ts +3 -0
  259. package/dist/features/auth/components/accept-invite-form.js +1 -0
  260. package/dist/features/auth/components/forgot-password-form.d.ts +1 -0
  261. package/dist/features/auth/components/forgot-password-form.js +1 -0
  262. package/dist/features/auth/components/permissions-form.d.ts +5 -0
  263. package/dist/features/auth/components/permissions-form.js +1 -0
  264. package/dist/features/auth/components/reset-password-form.d.ts +3 -0
  265. package/dist/features/auth/components/reset-password-form.js +1 -0
  266. package/dist/features/auth/components/signin-form.d.ts +5 -0
  267. package/dist/features/auth/components/signin-form.js +1 -0
  268. package/dist/features/auth/components/signup-form.d.ts +1 -0
  269. package/dist/features/auth/components/signup-form.js +1 -0
  270. package/dist/features/auth/components/verify-email-form.d.ts +3 -0
  271. package/dist/features/auth/components/verify-email-form.js +1 -0
  272. package/dist/features/auth/password-reset.d.ts +6 -0
  273. package/dist/features/auth/password-reset.js +1 -0
  274. package/dist/features/auth/permissions.d.ts +49 -0
  275. package/dist/features/auth/permissions.js +1 -0
  276. package/dist/features/auth/require.d.ts +3 -0
  277. package/dist/features/auth/require.js +1 -0
  278. package/dist/features/auth/signup-email.d.ts +6 -0
  279. package/dist/features/auth/signup-email.js +1 -0
  280. package/dist/features/campaigns/actions.d.ts +53 -0
  281. package/dist/features/campaigns/actions.js +1 -0
  282. package/dist/features/campaigns/components/campaign-dialog.d.ts +7 -0
  283. package/dist/features/campaigns/components/campaign-dialog.js +1 -0
  284. package/dist/features/campaigns/components/campaign-row-actions.d.ts +8 -0
  285. package/dist/features/campaigns/components/campaign-row-actions.js +1 -0
  286. package/dist/features/campaigns/components/campaign-status-badge.d.ts +6 -0
  287. package/dist/features/campaigns/components/campaign-status-badge.js +1 -0
  288. package/dist/features/campaigns/components/campaign-status-tabs.d.ts +1 -0
  289. package/dist/features/campaigns/components/campaign-status-tabs.js +1 -0
  290. package/dist/features/campaigns/components/campaigns-table.d.ts +7 -0
  291. package/dist/features/campaigns/components/campaigns-table.js +1 -0
  292. package/dist/features/campaigns/components/create-campaign-button.d.ts +5 -0
  293. package/dist/features/campaigns/components/create-campaign-button.js +1 -0
  294. package/dist/features/campaigns/components/sub-id-builder.d.ts +4 -0
  295. package/dist/features/campaigns/components/sub-id-builder.js +1 -0
  296. package/dist/features/campaigns/components/tracking-link-box.d.ts +3 -0
  297. package/dist/features/campaigns/components/tracking-link-box.js +1 -0
  298. package/dist/features/campaigns/components/tracking-link-cell.d.ts +4 -0
  299. package/dist/features/campaigns/components/tracking-link-cell.js +1 -0
  300. package/dist/features/campaigns/components/tracking-link-dialog.d.ts +6 -0
  301. package/dist/features/campaigns/components/tracking-link-dialog.js +1 -0
  302. package/dist/features/campaigns/list-params.d.ts +14 -0
  303. package/dist/features/campaigns/list-params.js +1 -0
  304. package/dist/features/campaigns/tracking-url.d.ts +8 -0
  305. package/dist/features/campaigns/tracking-url.js +1 -0
  306. package/dist/features/casinos/actions.d.ts +39 -0
  307. package/dist/features/casinos/actions.js +1 -0
  308. package/dist/features/casinos/components/casino-create-button.d.ts +1 -0
  309. package/dist/features/casinos/components/casino-create-button.js +1 -0
  310. package/dist/features/casinos/components/casino-dialog.d.ts +11 -0
  311. package/dist/features/casinos/components/casino-dialog.js +1 -0
  312. package/dist/features/casinos/components/casino-form-fields.d.ts +7 -0
  313. package/dist/features/casinos/components/casino-form-fields.js +1 -0
  314. package/dist/features/casinos/components/casino-status-tabs.d.ts +1 -0
  315. package/dist/features/casinos/components/casino-status-tabs.js +1 -0
  316. package/dist/features/casinos/components/casinos-table.d.ts +6 -0
  317. package/dist/features/casinos/components/casinos-table.js +1 -0
  318. package/dist/features/casinos/components/delete-casino-confirm.d.ts +5 -0
  319. package/dist/features/casinos/components/delete-casino-confirm.js +1 -0
  320. package/dist/features/casinos/list-params.d.ts +14 -0
  321. package/dist/features/casinos/list-params.js +1 -0
  322. package/dist/features/commissions/actions.d.ts +76 -0
  323. package/dist/features/commissions/actions.js +1 -0
  324. package/dist/features/commissions/components/casino-bindings-field.d.ts +10 -0
  325. package/dist/features/commissions/components/casino-bindings-field.js +1 -0
  326. package/dist/features/commissions/components/commission-create-button.d.ts +1 -0
  327. package/dist/features/commissions/components/commission-create-button.js +1 -0
  328. package/dist/features/commissions/components/commission-detail-dialog.d.ts +5 -0
  329. package/dist/features/commissions/components/commission-detail-dialog.js +1 -0
  330. package/dist/features/commissions/components/commission-editor.d.ts +8 -0
  331. package/dist/features/commissions/components/commission-editor.js +1 -0
  332. package/dist/features/commissions/components/commission-read-view.d.ts +5 -0
  333. package/dist/features/commissions/components/commission-read-view.js +1 -0
  334. package/dist/features/commissions/components/commission-status-badge.d.ts +4 -0
  335. package/dist/features/commissions/components/commission-status-badge.js +1 -0
  336. package/dist/features/commissions/components/commission-status-tabs.d.ts +1 -0
  337. package/dist/features/commissions/components/commission-status-tabs.js +1 -0
  338. package/dist/features/commissions/components/commissions-table.d.ts +14 -0
  339. package/dist/features/commissions/components/commissions-table.js +1 -0
  340. package/dist/features/commissions/components/delete-commission-confirm.d.ts +5 -0
  341. package/dist/features/commissions/components/delete-commission-confirm.js +1 -0
  342. package/dist/features/commissions/components/duplicate-commission-dialog.d.ts +6 -0
  343. package/dist/features/commissions/components/duplicate-commission-dialog.js +1 -0
  344. package/dist/features/commissions/components/rule-editor/conditions-block.d.ts +9 -0
  345. package/dist/features/commissions/components/rule-editor/conditions-block.js +1 -0
  346. package/dist/features/commissions/components/rule-editor/modifiers-block.d.ts +9 -0
  347. package/dist/features/commissions/components/rule-editor/modifiers-block.js +1 -0
  348. package/dist/features/commissions/components/rule-editor/qualifiers-block.d.ts +9 -0
  349. package/dist/features/commissions/components/rule-editor/qualifiers-block.js +1 -0
  350. package/dist/features/commissions/components/rule-editor/reducer.d.ts +102 -0
  351. package/dist/features/commissions/components/rule-editor/reducer.js +1 -0
  352. package/dist/features/commissions/components/rule-editor/rewards-block.d.ts +9 -0
  353. package/dist/features/commissions/components/rule-editor/rewards-block.js +1 -0
  354. package/dist/features/commissions/components/rule-editor/rule-card.d.ts +10 -0
  355. package/dist/features/commissions/components/rule-editor/rule-card.js +1 -0
  356. package/dist/features/commissions/components/rule-editor/rule-editor.d.ts +7 -0
  357. package/dist/features/commissions/components/rule-editor/rule-editor.js +1 -0
  358. package/dist/features/commissions/components/rule-editor/rule-group-card.d.ts +9 -0
  359. package/dist/features/commissions/components/rule-editor/rule-group-card.js +1 -0
  360. package/dist/features/commissions/components/rule-editor/state.d.ts +21 -0
  361. package/dist/features/commissions/components/rule-editor/state.js +1 -0
  362. package/dist/features/commissions/components/rule-groups-read-view.d.ts +4 -0
  363. package/dist/features/commissions/components/rule-groups-read-view.js +1 -0
  364. package/dist/features/commissions/list-params.d.ts +14 -0
  365. package/dist/features/commissions/list-params.js +1 -0
  366. package/dist/features/commissions/rule-validation.d.ts +173 -0
  367. package/dist/features/commissions/rule-validation.js +1 -0
  368. package/dist/features/dashboard/affiliate-queries.d.ts +14 -0
  369. package/dist/features/dashboard/affiliate-queries.js +1 -0
  370. package/dist/features/dashboard/clickhouse.d.ts +3 -0
  371. package/dist/features/dashboard/clickhouse.js +2 -0
  372. package/dist/features/dashboard/components/affiliate-charts.d.ts +5 -0
  373. package/dist/features/dashboard/components/affiliate-charts.js +1 -0
  374. package/dist/features/dashboard/components/affiliate-stats.d.ts +5 -0
  375. package/dist/features/dashboard/components/affiliate-stats.js +1 -0
  376. package/dist/features/dashboard/components/charts/funnel-chart.d.ts +11 -0
  377. package/dist/features/dashboard/components/charts/funnel-chart.js +1 -0
  378. package/dist/features/dashboard/components/charts/rank-bar-chart.d.ts +10 -0
  379. package/dist/features/dashboard/components/charts/rank-bar-chart.js +1 -0
  380. package/dist/features/dashboard/components/charts/time-series-chart.d.ts +12 -0
  381. package/dist/features/dashboard/components/charts/time-series-chart.js +1 -0
  382. package/dist/features/dashboard/components/charts-grid.d.ts +8 -0
  383. package/dist/features/dashboard/components/charts-grid.js +1 -0
  384. package/dist/features/dashboard/components/dashboard-charts.d.ts +4 -0
  385. package/dist/features/dashboard/components/dashboard-charts.js +1 -0
  386. package/dist/features/dashboard/components/dashboard-period-tabs.d.ts +1 -0
  387. package/dist/features/dashboard/components/dashboard-period-tabs.js +1 -0
  388. package/dist/features/dashboard/components/money-stat-card.d.ts +6 -0
  389. package/dist/features/dashboard/components/money-stat-card.js +1 -0
  390. package/dist/features/dashboard/components/stat-card.d.ts +6 -0
  391. package/dist/features/dashboard/components/stat-card.js +1 -0
  392. package/dist/features/dashboard/components/top-affiliates.d.ts +4 -0
  393. package/dist/features/dashboard/components/top-affiliates.js +1 -0
  394. package/dist/features/dashboard/list-params.d.ts +24 -0
  395. package/dist/features/dashboard/list-params.js +1 -0
  396. package/dist/features/dashboard/queries.d.ts +63 -0
  397. package/dist/features/dashboard/queries.js +1 -0
  398. package/dist/features/dashboard/series.d.ts +32 -0
  399. package/dist/features/dashboard/series.js +1 -0
  400. package/dist/features/deals/actions.d.ts +60 -0
  401. package/dist/features/deals/actions.js +1 -0
  402. package/dist/features/deals/components/affiliate-deals.d.ts +10 -0
  403. package/dist/features/deals/components/affiliate-deals.js +1 -0
  404. package/dist/features/deals/components/assign-deal-button.d.ts +9 -0
  405. package/dist/features/deals/components/assign-deal-button.js +1 -0
  406. package/dist/features/deals/components/deal-dialog.d.ts +19 -0
  407. package/dist/features/deals/components/deal-dialog.js +1 -0
  408. package/dist/features/deals/components/deal-row-actions.d.ts +6 -0
  409. package/dist/features/deals/components/deal-row-actions.js +1 -0
  410. package/dist/features/deals/components/deal-status-badge.d.ts +10 -0
  411. package/dist/features/deals/components/deal-status-badge.js +1 -0
  412. package/dist/features/deals/components/deal-status-tabs.d.ts +1 -0
  413. package/dist/features/deals/components/deal-status-tabs.js +1 -0
  414. package/dist/features/deals/components/delegate-deal-button.d.ts +8 -0
  415. package/dist/features/deals/components/delegate-deal-button.js +1 -0
  416. package/dist/features/deals/deal-assigned-email.d.ts +11 -0
  417. package/dist/features/deals/deal-assigned-email.js +1 -0
  418. package/dist/features/deals/deal-delegated-email.d.ts +13 -0
  419. package/dist/features/deals/deal-delegated-email.js +1 -0
  420. package/dist/features/deals/list-params.d.ts +14 -0
  421. package/dist/features/deals/list-params.js +1 -0
  422. package/dist/features/earnings/components/earnings-balances.d.ts +4 -0
  423. package/dist/features/earnings/components/earnings-balances.js +1 -0
  424. package/dist/features/earnings/components/earnings-ledger.d.ts +5 -0
  425. package/dist/features/earnings/components/earnings-ledger.js +1 -0
  426. package/dist/features/earnings/components/earnings-status-badge.d.ts +4 -0
  427. package/dist/features/earnings/components/earnings-status-badge.js +1 -0
  428. package/dist/features/earnings/components/earnings-status-tabs.d.ts +1 -0
  429. package/dist/features/earnings/components/earnings-status-tabs.js +1 -0
  430. package/dist/features/earnings/components/sub-affiliate-earnings.d.ts +4 -0
  431. package/dist/features/earnings/components/sub-affiliate-earnings.js +1 -0
  432. package/dist/features/earnings/list-params.d.ts +14 -0
  433. package/dist/features/earnings/list-params.js +1 -0
  434. package/dist/features/earnings/queries.d.ts +30 -0
  435. package/dist/features/earnings/queries.js +1 -0
  436. package/dist/features/groups/actions.d.ts +36 -0
  437. package/dist/features/groups/actions.js +1 -0
  438. package/dist/features/groups/components/delete-group-confirm.d.ts +5 -0
  439. package/dist/features/groups/components/delete-group-confirm.js +1 -0
  440. package/dist/features/groups/components/group-create-button.d.ts +1 -0
  441. package/dist/features/groups/components/group-create-button.js +1 -0
  442. package/dist/features/groups/components/group-dialog.d.ts +11 -0
  443. package/dist/features/groups/components/group-dialog.js +1 -0
  444. package/dist/features/groups/components/group-form-fields.d.ts +10 -0
  445. package/dist/features/groups/components/group-form-fields.js +1 -0
  446. package/dist/features/groups/components/group-status-tabs.d.ts +1 -0
  447. package/dist/features/groups/components/group-status-tabs.js +1 -0
  448. package/dist/features/groups/components/groups-table.d.ts +9 -0
  449. package/dist/features/groups/components/groups-table.js +1 -0
  450. package/dist/features/groups/list-params.d.ts +14 -0
  451. package/dist/features/groups/list-params.js +1 -0
  452. package/dist/features/managers/actions.d.ts +43 -0
  453. package/dist/features/managers/actions.js +1 -0
  454. package/dist/features/managers/components/manager-create-button.d.ts +1 -0
  455. package/dist/features/managers/components/manager-create-button.js +1 -0
  456. package/dist/features/managers/components/manager-dialog.d.ts +11 -0
  457. package/dist/features/managers/components/manager-dialog.js +1 -0
  458. package/dist/features/managers/components/manager-permissions-dialog.d.ts +7 -0
  459. package/dist/features/managers/components/manager-permissions-dialog.js +1 -0
  460. package/dist/features/managers/components/manager-profile-fields.d.ts +7 -0
  461. package/dist/features/managers/components/manager-profile-fields.js +1 -0
  462. package/dist/features/managers/components/manager-status-tabs.d.ts +1 -0
  463. package/dist/features/managers/components/manager-status-tabs.js +1 -0
  464. package/dist/features/managers/components/managers-table.d.ts +8 -0
  465. package/dist/features/managers/components/managers-table.js +1 -0
  466. package/dist/features/managers/invite.d.ts +6 -0
  467. package/dist/features/managers/invite.js +1 -0
  468. package/dist/features/managers/list-params.d.ts +14 -0
  469. package/dist/features/managers/list-params.js +1 -0
  470. package/dist/features/payouts/actions.d.ts +12 -0
  471. package/dist/features/payouts/actions.js +1 -0
  472. package/dist/features/payouts/balance.d.ts +2 -0
  473. package/dist/features/payouts/balance.js +1 -0
  474. package/dist/features/payouts/components/my-payouts-table.d.ts +5 -0
  475. package/dist/features/payouts/components/my-payouts-table.js +1 -0
  476. package/dist/features/payouts/components/payout-row-actions.d.ts +5 -0
  477. package/dist/features/payouts/components/payout-row-actions.js +1 -0
  478. package/dist/features/payouts/components/payout-status-badge.d.ts +4 -0
  479. package/dist/features/payouts/components/payout-status-badge.js +1 -0
  480. package/dist/features/payouts/components/payout-status-tabs.d.ts +1 -0
  481. package/dist/features/payouts/components/payout-status-tabs.js +1 -0
  482. package/dist/features/payouts/components/payouts-table.d.ts +6 -0
  483. package/dist/features/payouts/components/payouts-table.js +1 -0
  484. package/dist/features/payouts/components/request-payout-dialog.d.ts +4 -0
  485. package/dist/features/payouts/components/request-payout-dialog.js +1 -0
  486. package/dist/features/payouts/constants.d.ts +2 -0
  487. package/dist/features/payouts/constants.js +1 -0
  488. package/dist/features/payouts/list-params.d.ts +14 -0
  489. package/dist/features/payouts/list-params.js +1 -0
  490. package/dist/features/payouts/my-queries.d.ts +14 -0
  491. package/dist/features/payouts/my-queries.js +1 -0
  492. package/dist/features/payouts/queries.d.ts +14 -0
  493. package/dist/features/payouts/queries.js +1 -0
  494. package/dist/features/postbacks/actions.d.ts +27 -0
  495. package/dist/features/postbacks/actions.js +1 -0
  496. package/dist/features/postbacks/components/integration-dialog.d.ts +6 -0
  497. package/dist/features/postbacks/components/integration-dialog.js +1 -0
  498. package/dist/features/postbacks/components/postback-editor.d.ts +5 -0
  499. package/dist/features/postbacks/components/postback-editor.js +1 -0
  500. package/dist/features/postbacks/components/postbacks-table.d.ts +4 -0
  501. package/dist/features/postbacks/components/postbacks-table.js +1 -0
  502. package/dist/features/settings/actions.d.ts +2 -0
  503. package/dist/features/settings/actions.js +1 -0
  504. package/dist/features/settings/components/affiliate-approval-setting.d.ts +3 -0
  505. package/dist/features/settings/components/affiliate-approval-setting.js +1 -0
  506. package/dist/features/settings/components/manager-totp-setting.d.ts +3 -0
  507. package/dist/features/settings/components/manager-totp-setting.js +1 -0
  508. package/dist/features/support/actions.d.ts +12 -0
  509. package/dist/features/support/actions.js +1 -0
  510. package/dist/features/support/components/support-page.d.ts +4 -0
  511. package/dist/features/support/components/support-page.js +1 -0
  512. package/dist/features/support/email.d.ts +13 -0
  513. package/dist/features/support/email.js +1 -0
  514. package/dist/features/users/actions.d.ts +4 -0
  515. package/dist/features/users/actions.js +1 -0
  516. package/dist/features/users/components/password-section.d.ts +1 -0
  517. package/dist/features/users/components/password-section.js +1 -0
  518. package/dist/features/users/components/preferences-section.d.ts +4 -0
  519. package/dist/features/users/components/preferences-section.js +1 -0
  520. package/dist/features/users/components/settings-tabs.d.ts +1 -0
  521. package/dist/features/users/components/settings-tabs.js +1 -0
  522. package/dist/features/users/components/totp-section.d.ts +4 -0
  523. package/dist/features/users/components/totp-section.js +1 -0
  524. package/dist/features/users/list-params.d.ts +12 -0
  525. package/dist/features/users/list-params.js +1 -0
  526. package/dist/features/users/totp.d.ts +7 -0
  527. package/dist/features/users/totp.js +1 -0
  528. package/dist/i18n/config.d.ts +5 -0
  529. package/dist/i18n/config.js +1 -0
  530. package/dist/i18n/get-locale.d.ts +3 -0
  531. package/dist/i18n/get-locale.js +1 -0
  532. package/dist/i18n/locale.d.ts +2 -0
  533. package/dist/i18n/locale.js +1 -0
  534. package/dist/lib/actions/parse-form.d.ts +3 -0
  535. package/dist/lib/actions/parse-form.js +1 -0
  536. package/dist/lib/actions/state.d.ts +22 -0
  537. package/dist/lib/actions/state.js +0 -0
  538. package/dist/lib/audit/actions.d.ts +9 -0
  539. package/dist/lib/audit/actions.js +1 -0
  540. package/dist/lib/audit/record.d.ts +4 -0
  541. package/dist/lib/audit/record.js +1 -0
  542. package/dist/lib/auth/action.d.ts +45 -0
  543. package/dist/lib/auth/action.js +1 -0
  544. package/dist/lib/auth/config.d.ts +24 -0
  545. package/dist/lib/auth/config.js +1 -0
  546. package/dist/lib/auth/jwt.d.ts +17 -0
  547. package/dist/lib/auth/jwt.js +1 -0
  548. package/dist/lib/auth/password-options.d.ts +6 -0
  549. package/dist/lib/auth/password-options.js +1 -0
  550. package/dist/lib/auth/password.d.ts +3 -0
  551. package/dist/lib/auth/password.js +1 -0
  552. package/dist/lib/auth/session.d.ts +26 -0
  553. package/dist/lib/auth/session.js +1 -0
  554. package/dist/lib/auth/tokens.d.ts +43 -0
  555. package/dist/lib/auth/tokens.js +1 -0
  556. package/dist/lib/auth/totp-challenge.d.ts +4 -0
  557. package/dist/lib/auth/totp-challenge.js +1 -0
  558. package/dist/lib/auth/totp.d.ts +7 -0
  559. package/dist/lib/auth/totp.js +1 -0
  560. package/dist/lib/auth/verification-tokens.d.ts +19 -0
  561. package/dist/lib/auth/verification-tokens.js +1 -0
  562. package/dist/lib/cn.d.ts +2 -0
  563. package/dist/lib/cn.js +1 -0
  564. package/dist/lib/countries.d.ts +18 -0
  565. package/dist/lib/countries.js +1 -0
  566. package/dist/lib/currencies.d.ts +6 -0
  567. package/dist/lib/currencies.js +1 -0
  568. package/dist/lib/data/countries-by-continent.json +257 -0
  569. package/dist/lib/db/errors.d.ts +4 -0
  570. package/dist/lib/db/errors.js +1 -0
  571. package/dist/lib/email/client.d.ts +6 -0
  572. package/dist/lib/email/client.js +1 -0
  573. package/dist/lib/email/env.d.ts +12 -0
  574. package/dist/lib/email/env.js +1 -0
  575. package/dist/lib/email/format.d.ts +5 -0
  576. package/dist/lib/email/format.js +1 -0
  577. package/dist/lib/email/locale.d.ts +3 -0
  578. package/dist/lib/email/locale.js +1 -0
  579. package/dist/lib/email/send.d.ts +12 -0
  580. package/dist/lib/email/send.js +1 -0
  581. package/dist/lib/env.d.ts +20 -0
  582. package/dist/lib/env.js +1 -0
  583. package/dist/lib/errors/codes.d.ts +72 -0
  584. package/dist/lib/errors/codes.js +1 -0
  585. package/dist/lib/errors/server.d.ts +10 -0
  586. package/dist/lib/errors/server.js +1 -0
  587. package/dist/lib/format.d.ts +3 -0
  588. package/dist/lib/format.js +1 -0
  589. package/dist/lib/hooks/use-deferred-dialog.d.ts +11 -0
  590. package/dist/lib/hooks/use-deferred-dialog.js +1 -0
  591. package/dist/lib/hooks/use-form-reset.d.ts +2 -0
  592. package/dist/lib/hooks/use-form-reset.js +1 -0
  593. package/dist/lib/hooks/use-form-toast.d.ts +2 -0
  594. package/dist/lib/hooks/use-form-toast.js +1 -0
  595. package/dist/lib/i18n/format-datetime.d.ts +1 -0
  596. package/dist/lib/i18n/format-datetime.js +1 -0
  597. package/dist/lib/i18n/relative-time.d.ts +1 -0
  598. package/dist/lib/i18n/relative-time.js +1 -0
  599. package/dist/lib/list-params.d.ts +51 -0
  600. package/dist/lib/list-params.js +1 -0
  601. package/dist/lib/money.d.ts +2 -0
  602. package/dist/lib/money.js +1 -0
  603. package/dist/lib/platform-settings.d.ts +5 -0
  604. package/dist/lib/platform-settings.js +1 -0
  605. package/dist/lib/preferences/actions.d.ts +1 -0
  606. package/dist/lib/preferences/actions.js +1 -0
  607. package/dist/lib/preferences/index.d.ts +15 -0
  608. package/dist/lib/preferences/index.js +1 -0
  609. package/dist/lib/preferences/read.d.ts +2 -0
  610. package/dist/lib/preferences/read.js +1 -0
  611. package/dist/lib/slug.d.ts +1 -0
  612. package/dist/lib/slug.js +1 -0
  613. package/dist/lib/toast.d.ts +13 -0
  614. package/dist/lib/toast.js +1 -0
  615. package/dist/lib/tracking-cache.d.ts +2 -0
  616. package/dist/lib/tracking-cache.js +1 -0
  617. package/dist/lib/users.d.ts +12 -0
  618. package/dist/lib/users.js +1 -0
  619. package/dist/lib/validation/zod.d.ts +30 -0
  620. package/dist/lib/validation/zod.js +1 -0
  621. package/dist/messages/de/emails.json +136 -0
  622. package/dist/messages/de/index.json +1104 -0
  623. package/dist/messages/en/emails.json +136 -0
  624. package/dist/messages/en/index.json +1104 -0
  625. package/dist/theme/config.d.ts +8 -0
  626. package/dist/theme/config.js +1 -0
  627. package/dist/theme/get-theme.d.ts +3 -0
  628. package/dist/theme/get-theme.js +1 -0
  629. package/dist/theme/theme.d.ts +2 -0
  630. package/dist/theme/theme.js +1 -0
  631. package/package.json +131 -0
@@ -0,0 +1 @@
1
+ export declare function ManagerStatusTabs(): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as s,jsxs as c}from"react/jsx-runtime";import{useTranslations as i}from"next-intl";import{useQueryStates as T}from"nuqs";import{useTransition as u}from"react";import{Tabs as m,TabsIndicator as p,TabsList as b,TabsTab as f}from"../../../components/ui/tabs.js";import{MANAGER_STATUSES as l,managerStatusParser as S}from"../list-params.js";import{listSearchParsers as g}from"../../../lib/list-params.js";function y(){const t=i("Managers.Tabs"),[r,e]=u(),[{status:n},o]=T({status:S,page:g.page},{shallow:!1,clearOnDefault:!0,startTransition:e});return s(m,{value:n,onValueChange:a=>o({status:a,page:null}),"data-pending":r?"":void 0,children:c(b,{children:[l.map(a=>s(f,{value:a,children:t(a)},a)),s(p,{})]})})}export{y as ManagerStatusTabs};
@@ -0,0 +1,8 @@
1
+ import { type ManagerRow } from "../actions.js";
2
+ import { type ListResult } from "../../../lib/list-params.js";
3
+ export declare function ManagersTable({ result, canManage, currentUserId, now, }: {
4
+ result: ListResult<ManagerRow>;
5
+ canManage: boolean;
6
+ currentUserId: string;
7
+ now: Date;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as i}from"react/jsx-runtime";import{displayName as v,isInvitePending as M,USER_STATUS as g}from"../../../db/schema/index.js";import{IconDots as h,IconLock as P,IconLockOpen as y,IconMailForward as A,IconPencil as z,IconShield as T,IconUserOff as k}from"@tabler/icons-react";import{useLocale as C,useTranslations as w}from"next-intl";import{useMemo as R,useTransition as L}from"react";import{Avatar as B}from"../../../components/ui/avatar.js";import{DataTable as U}from"../../../components/ui/data-table.js";import{DropdownMenu as E,DropdownMenuContent as O,DropdownMenuItem as f,DropdownMenuSeparator as G,DropdownMenuTrigger as _}from"../../../components/ui/dropdown-menu.js";import{Identity as j}from"../../../components/ui/identity.js";import{SortButton as I}from"../../../components/ui/sort-button.js";import{Spinner as F}from"../../../components/ui/spinner.js";import{StatusBadge as b}from"../../../components/ui/status-badge.js";import{TablePagination as Z}from"../../../components/ui/table-pagination.js";import{getManagerEditData as q,getManagerPermissions as H,resendManagerInviteAction as J}from"../actions.js";import{ManagerDialog as K}from"./manager-dialog.js";import{ManagerPermissionsDialog as Q}from"./manager-permissions-dialog.js";import{setUserStatus as V}from"../../users/actions.js";import{useDeferredDialog as x}from"../../../lib/hooks/use-deferred-dialog.js";import{useFormatDateTime as W}from"../../../lib/i18n/format-datetime.js";import{formatRelative as X}from"../../../lib/i18n/relative-time.js";import{PAGE_SIZE_OPTIONS as Y}from"../../../lib/list-params.js";import{toastActionResult as S}from"../../../lib/toast.js";function Ie({result:n,canManage:p,currentUserId:r,now:c}){const o=w("Managers"),l=C(),m=W(),s=R(()=>{const d=[{id:"email",header:()=>e(I,{column:"email",children:o("columnEmail")}),cell:({row:a})=>{const t=a.original,u=v(t),D=u!==t.email;return e(j,{visual:e(B,{seed:t.email,name:u,size:"lg"}),primary:u,secondary:D&&e("span",{className:"font-mono",children:t.email})})}},{id:"group",header:()=>o("columnGroup"),cell:({row:a})=>{const t=a.original.groupName;return t?e("span",{className:"text-sm",children:t}):e("span",{className:"text-sm text-muted-foreground italic",children:o("noGroupAssigned")})}},{id:"directPermissions",header:()=>o("columnDirectPermissions"),cell:({row:a})=>{const t=a.original.directPermissionCount;return e("span",{className:"text-sm tabular-nums",children:t===0?e("span",{className:"text-muted-foreground",children:"-"}):t})}},{id:"status",header:()=>o("columnStatus"),cell:({row:a})=>{const t=a.original;return t.status===g.blocked?e(b,{tone:"danger",children:o("statusDeactivated")}):M(t)?e(b,{tone:"warning",children:o("statusPending")}):e(b,{tone:"success",children:o("statusActive")})}},{id:"createdAt",header:()=>e(I,{column:"createdAt",children:o("columnCreated")}),cell:({row:a})=>{const t=a.original.createdAt;return e("span",{className:"text-sm text-muted-foreground tabular-nums",title:m(t),children:X(l,t,c)})}}];return p?[...d,{id:"actions",header:()=>e("span",{className:"sr-only",children:o("columnActions")}),cell:({row:a})=>e($,{manager:a.original,currentUserId:r}),meta:{pin:"right",className:"text-right"}}]:d},[o,l,m,p,r,c]);return e(U,{data:n.rows,columns:s,getRowId:d=>d.id,empty:i("div",{className:"flex flex-col items-center gap-3 py-4",children:[e("div",{className:"flex size-10 items-center justify-center rounded-full bg-muted text-muted-foreground",children:e(k,{size:18,"aria-hidden":!0})}),e("span",{children:o("empty")})]}),pagination:e(Z,{page:n.page,pageSize:n.pageSize,totalPages:n.totalPages,pageSizeOptions:Y})})}function $({manager:n,currentUserId:p}){const r=w("Managers"),c=x(()=>q(n.id)),o=x(()=>H(n.id)),[l,m]=L();if(n.id===p)return null;const s=n.status===g.blocked,d=M(n),a=v(n),t=c.isLoading||o.isLoading,u=()=>{const N=s?g.active:g.blocked;m(async()=>{S(await V(n.id,N))})},D=()=>{m(async()=>{S(await J(n.id))})};return i("div",{className:"flex justify-end",children:[i(E,{children:[e(_,{"aria-label":r("rowActions"),disabled:t,className:"inline-flex size-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card data-popup-open:bg-accent data-popup-open:text-accent-foreground",children:t?e(F,{}):e(h,{size:16,"aria-hidden":!0})}),i(O,{children:[i(f,{onClick:c.trigger,children:[e(z,{size:14,"aria-hidden":!0,className:"text-muted-foreground"}),r("edit")]}),i(f,{onClick:o.trigger,children:[e(T,{size:14,"aria-hidden":!0,className:"text-muted-foreground"}),r("editPermissions")]}),d&&i(f,{onClick:D,disabled:l,children:[e(A,{size:14,"aria-hidden":!0,className:"text-muted-foreground"}),r("resendInvite")]}),e(G,{}),(!d||s)&&i(f,{variant:s?"default":"destructive",onClick:u,disabled:l,children:[s?e(y,{size:14,"aria-hidden":!0}):e(P,{size:14,"aria-hidden":!0}),r(s?"activate":"deactivate")]})]})]}),e(K,{mode:"edit",managerId:n.id,controller:c}),e(Q,{managerId:n.id,managerLabel:a,controller:o})]})}export{Ie as ManagersTable};
@@ -0,0 +1,6 @@
1
+ import "server-only";
2
+ export declare function sendManagerInvite(args: {
3
+ userId: string;
4
+ email: string;
5
+ firstName: string;
6
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ import"server-only";import{getFormatter as g,getLocale as f,getTranslations as r}from"next-intl/server";import{ManagerInviteEmail as d}from"../../emails/manager/invite.js";import{issueVerificationToken as v}from"../../lib/auth/verification-tokens.js";import{formatTokenExpiry as u}from"../../lib/email/format.js";import{sendEmail as w}from"../../lib/email/send.js";import{env as n}from"../../lib/env.js";async function M(a){const o=await v({userId:a.userId,purpose:"invite"}),t=await f(),[s,e,m]=await Promise.all([r({locale:t,namespace:"Emails.Common"}),r({locale:t,namespace:"Emails.ManagerInvite"}),g({locale:t})]),c=new URL(`/accept-invite/${o.raw}`,n.APP_URL).toString(),p=u(o.expiresAt,m),l=e("greetingNamed",{name:a.firstName}),i=n.BRAND_NAME;await w({to:a.email,subject:e("subject",{brandName:i}),react:d({inviteUrl:c,lang:t,strings:{preview:e("preview",{brandName:i}),heading:e("heading"),greeting:l,body:e("body",{brandName:i}),cta:e("cta"),expiresAtMessage:e("expiresAt",{date:p}),fallback:e("fallback"),brandName:i,footerNote:s("footerNote")}})})}export{M as sendManagerInvite};
@@ -0,0 +1,14 @@
1
+ export declare const MANAGER_SORT_KEYS: readonly ["email", "firstName", "lastName", "createdAt"];
2
+ export type ManagerSortKey = (typeof MANAGER_SORT_KEYS)[number];
3
+ export declare const MANAGER_STATUSES: readonly ["all", "pending", "deactivated"];
4
+ export type ManagerStatusFilter = (typeof MANAGER_STATUSES)[number];
5
+ export declare const managerStatusParser: Omit<import("nuqs/server").SingleParserBuilder<"deactivated" | "pending" | "all">, "parseServerSide"> & {
6
+ readonly defaultValue: NonNullable<"deactivated" | "pending" | "all">;
7
+ parseServerSide(value: string | string[] | undefined): NonNullable<"deactivated" | "pending" | "all">;
8
+ };
9
+ export declare const loadManagerStatus: import("nuqs/server").LoaderFunction<{
10
+ status: Omit<import("nuqs/server").SingleParserBuilder<"deactivated" | "pending" | "all">, "parseServerSide"> & {
11
+ readonly defaultValue: NonNullable<"deactivated" | "pending" | "all">;
12
+ parseServerSide(value: string | string[] | undefined): NonNullable<"deactivated" | "pending" | "all">;
13
+ };
14
+ }>;
@@ -0,0 +1 @@
1
+ import{createLoader as t,parseAsStringLiteral as e}from"nuqs/server";const s=["email","firstName","lastName","createdAt"],a=["all","pending","deactivated"],r=e(a).withDefault("all"),n=t({status:r});export{s as MANAGER_SORT_KEYS,a as MANAGER_STATUSES,n as loadManagerStatus,r as managerStatusParser};
@@ -0,0 +1,12 @@
1
+ import type { FormState } from "../../lib/actions/state.js";
2
+ export type RequestPayoutState = FormState<{
3
+ id: string;
4
+ }>;
5
+ export declare const requestPayoutAction: (args_0: FormState<{
6
+ id: string;
7
+ }>, args_1: FormData) => Promise<FormState<{
8
+ id: string;
9
+ }>>;
10
+ export declare const approvePayoutAction: (args_0: string) => Promise<import("../../lib/actions/state.js").ActionResult<void>>;
11
+ export declare const rejectPayoutAction: (args_0: string, args_1: FormState<void>, args_2: FormData) => Promise<FormState<void>>;
12
+ export declare const markPayoutPaidAction: (args_0: string) => Promise<import("../../lib/actions/state.js").ActionResult<void>>;
@@ -0,0 +1 @@
1
+ "use server";import{db as y}from"../../db/index.js";import{PAYOUT_REQUEST_STATUS as n,payoutRequests as t,USER_ROLE as P}from"../../db/schema/index.js";import{and as f,eq as u,sql as j}from"drizzle-orm";import{z as c}from"zod";import{availableBalanceCents as q}from"./balance.js";import{PAYOUT_CURRENCIES as R}from"./constants.js";import{parseForm as h}from"../../lib/actions/parse-form.js";import{authAction as b,authFormAction as A}from"../../lib/auth/action.js";import{appError as m}from"../../lib/errors/codes.js";import{success as l}from"../../lib/errors/server.js";import{toCents as S}from"../../lib/money.js";const T=c.object({currency:c.string().trim().min(1).max(10),desiredCurrency:c.enum(R),amount:c.coerce.number().positive()}),C=c.object({note:c.string().trim().min(1).max(500)});async function v(e){const[r]=await y.select({id:t.id}).from(t).where(u(t.id,e)).limit(1);if(!r)throw m("payout_not_found",{toast:!0})}const L=A({role:P.affiliate,revalidate:["/earnings","/payouts"]},async({user:e,audit:r},i)=>{const{currency:o,desiredCurrency:a,amount:s}=await h(i,T),d=S(s);if(d<=0)throw m("payout_no_balance",{toast:!0});const p=await y.transaction(async w=>{await w.execute(j`select pg_advisory_xact_lock(hashtext(${`payout:${e.id}:${o}`})::bigint)`);const I=await q(w,e.id,o);if(d>I)throw m("payout_amount_exceeds_balance",{toast:!0});const g=(d/100).toFixed(2),[_]=await w.insert(t).values({userId:e.id,amount:g,currency:o,desiredCurrency:a,status:n.requested}).returning({id:t.id});return await r({action:"payout.request",target:{type:"payout",id:_.id},metadata:{currency:o,desiredCurrency:a,amount:g}},w),{id:_.id}});return l({id:p.id},"Toasts.payoutRequested")}),N=b({permission:"payouts:manage",revalidate:["/payouts"]},async({user:e,audit:r},i)=>{if(!await y.transaction(async a=>{const[s]=await a.update(t).set({status:n.approved,reviewedById:e.id,reviewedAt:new Date}).where(f(u(t.id,i),u(t.status,n.requested))).returning({id:t.id,userId:t.userId});return s?(await r({action:"payout.approve",subjectId:s.userId,target:{type:"payout",id:s.id}},a),s):null}))throw await v(i),m("payout_invalid_status",{toast:!0});return l("Toasts.payoutApproved")}),Q=A({permission:"payouts:manage",revalidate:["/payouts"]},async({user:e,audit:r},i,o)=>{const{note:a}=await h(o,C);if(!await y.transaction(async d=>{const[p]=await d.update(t).set({status:n.rejected,reviewedById:e.id,reviewedAt:new Date,note:a}).where(f(u(t.id,i),u(t.status,n.requested))).returning({id:t.id,userId:t.userId});return p?(await r({action:"payout.reject",subjectId:p.userId,target:{type:"payout",id:p.id},metadata:{note:a}},d),p):null}))throw await v(i),m("payout_invalid_status",{toast:!0});return l("Toasts.payoutRejected")}),G=b({permission:"payouts:manage",revalidate:["/payouts"]},async({audit:e},r)=>{if(!await y.transaction(async o=>{const[a]=await o.update(t).set({status:n.paid,paidAt:new Date}).where(f(u(t.id,r),u(t.status,n.approved))).returning({id:t.id,userId:t.userId});return a?(await e({action:"payout.paid",subjectId:a.userId,target:{type:"payout",id:a.id}},o),a):null}))throw await v(r),m("payout_invalid_status",{toast:!0});return l("Toasts.payoutPaid")});export{N as approvePayoutAction,G as markPayoutPaidAction,Q as rejectPayoutAction,L as requestPayoutAction};
@@ -0,0 +1,2 @@
1
+ import type { Executor } from "../../db/index.js";
2
+ export declare function availableBalanceCents(tx: Executor, userId: string, currency: string): Promise<number>;
@@ -0,0 +1 @@
1
+ import{EARNING_STATUS as l,earningsLedger as t,PAYOUT_REQUEST_STATUS as o,payoutRequests as e}from"../../db/schema/index.js";import{and as i,eq as r,inArray as p,sum as m}from"drizzle-orm";import{toCents as u}from"../../lib/money.js";async function A(a,n,s){const[c]=await a.select({total:m(t.amount)}).from(t).where(i(r(t.userId,n),r(t.currency,s),r(t.status,l.confirmed))),[d]=await a.select({total:m(e.amount)}).from(e).where(i(r(e.userId,n),r(e.currency,s),p(e.status,[o.requested,o.approved,o.paid])));return u(c?.total??0)-u(d?.total??0)}export{A as availableBalanceCents};
@@ -0,0 +1,5 @@
1
+ import type { MyPayoutRow } from "../my-queries.js";
2
+ import { type ListResult } from "../../../lib/list-params.js";
3
+ export declare function MyPayoutsTable({ result, }: {
4
+ result: ListResult<MyPayoutRow>;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as t,jsxs as P}from"react/jsx-runtime";import{IconWallet as i}from"@tabler/icons-react";import{useFormatter as m,useTranslations as u}from"next-intl";import{useMemo as d}from"react";import{DataTable as l}from"../../../components/ui/data-table.js";import{Identity as c}from"../../../components/ui/identity.js";import{SortButton as n}from"../../../components/ui/sort-button.js";import{TablePagination as p}from"../../../components/ui/table-pagination.js";import{PayoutStatusBadge as y}from"./payout-status-badge.js";import{formatMoney as f}from"../../../lib/format.js";import{PAGE_SIZE_OPTIONS as g}from"../../../lib/list-params.js";function T({result:o}){const a=u("Payouts"),r=m(),s=d(()=>[{id:"amount",header:()=>t(n,{column:"amount",children:a("columnAmount")}),cell:({row:e})=>t(c,{visual:t("div",{className:"flex size-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground",children:t(i,{size:18,"aria-hidden":!0})}),primary:t("span",{className:"tabular-nums",children:f(r,e.original.amount,e.original.currency)}),secondary:e.original.desiredCurrency&&e.original.desiredCurrency!==e.original.currency?`\u2192 ${e.original.desiredCurrency}`:void 0})},{id:"requestedAt",header:()=>t(n,{column:"requestedAt",children:a("columnRequestedAt")}),cell:({row:e})=>t("span",{className:"text-sm text-muted-foreground tabular-nums",children:r.dateTime(e.original.requestedAt,{day:"numeric",month:"short",year:"numeric"})})},{id:"reviewedAt",header:()=>a("columnReviewedAt"),cell:({row:e})=>e.original.reviewedAt?t("span",{className:"text-sm text-muted-foreground tabular-nums",children:r.dateTime(e.original.reviewedAt,{day:"numeric",month:"short",year:"numeric"})}):t("span",{className:"text-muted-foreground",children:"\u2014"})},{id:"status",header:()=>a("columnStatus"),cell:({row:e})=>t(y,{status:e.original.status})}],[a,r]);return t(l,{data:o.rows,columns:s,getRowId:e=>e.id,empty:P("div",{className:"flex flex-col items-center gap-3 py-4",children:[t("div",{className:"flex size-10 items-center justify-center rounded-full bg-muted text-muted-foreground",children:t(i,{size:18,"aria-hidden":!0})}),t("span",{children:a("emptyMyPayouts")})]}),pagination:t(p,{page:o.page,pageSize:o.pageSize,totalPages:o.totalPages,pageSizeOptions:g})})}export{T as MyPayoutsTable};
@@ -0,0 +1,5 @@
1
+ import { type PayoutRequestStatus } from "../../../db/schema/index.js";
2
+ export declare function PayoutRowActions({ requestId, status, }: {
3
+ requestId: string;
4
+ status: PayoutRequestStatus;
5
+ }): import("react").JSX.Element | null;
@@ -0,0 +1 @@
1
+ "use client";import{Fragment as Q,jsx as e,jsxs as t}from"react/jsx-runtime";import{PAYOUT_REQUEST_STATUS as f}from"../../../db/schema/index.js";import{IconCheck as A,IconDots as b,IconWallet as v,IconX as y}from"@tabler/icons-react";import{useTranslations as u}from"next-intl";import{useActionState as P,useEffect as j,useState as w,useTransition as R}from"react";import{ActionForm as T}from"../../../components/ui/action-form.js";import{AlertDialog as C,AlertDialogClose as h,AlertDialogContent as I,AlertDialogDescription as M,AlertDialogFooter as x,AlertDialogTitle as S}from"../../../components/ui/alert-dialog.js";import{Button as g}from"../../../components/ui/button.js";import{DropdownMenu as F,DropdownMenuContent as k,DropdownMenuItem as p,DropdownMenuTrigger as q}from"../../../components/ui/dropdown-menu.js";import{FormField as z}from"../../../components/ui/form-field.js";import{Spinner as O}from"../../../components/ui/spinner.js";import{Textarea as B}from"../../../components/ui/textarea.js";import{approvePayoutAction as E,markPayoutPaidAction as L,rejectPayoutAction as N}from"../actions.js";import{toastActionResult as U}from"../../../lib/toast.js";function ne({requestId:a,status:s}){const n=u("Payouts"),[o,c]=R(),[d,r]=w(!1),l=D=>c(async()=>{U(await D(a))}),i=s===f.requested,m=s===f.approved;return!i&&!m?null:t("div",{className:"flex justify-end",children:[t(F,{children:[e(q,{"aria-label":n("rowActions"),disabled:o,className:"inline-flex size-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card data-popup-open:bg-accent data-popup-open:text-accent-foreground",children:o?e(O,{}):e(b,{size:16,"aria-hidden":!0})}),t(k,{align:"end",children:[i&&t(Q,{children:[t(p,{onClick:()=>l(E),disabled:o,children:[e(A,{size:14,"aria-hidden":!0}),n("approve")]}),t(p,{variant:"destructive",onClick:()=>r(!0),disabled:o,children:[e(y,{size:14,"aria-hidden":!0}),n("reject")]})]}),m&&t(p,{onClick:()=>l(L),disabled:o,children:[e(v,{size:14,"aria-hidden":!0}),n("markPaid")]})]})]}),i&&e(_,{requestId:a,open:d,onOpenChange:r})]})}function _({requestId:a,open:s,onOpenChange:n}){const o=u("Payouts"),c=u("Common"),d=N.bind(null,a),[r,l,i]=P(d,void 0);return j(()=>{r?.ok&&n(!1)},[r,n]),e(C,{open:s,onOpenChange:n,children:t(I,{children:[e(S,{children:o("rejectDialogTitle")}),e(M,{children:o("rejectDialogDesc")}),t(T,{action:l,actionState:r,className:"flex flex-col gap-3",children:[e(z,{name:"note",label:o("rejectReasonLabel"),children:e(B,{required:!0,rows:3,maxLength:500,placeholder:o("rejectReasonPlaceholder"),"aria-label":o("rejectReasonLabel")})}),t(x,{children:[e(h,{render:e(g,{type:"button",variant:"secondary",size:"sm",disabled:i,children:c("cancel")})}),e(g,{type:"submit",variant:"destructive",size:"sm",disabled:i,children:o(i?"rejecting":"reject")})]})]})]})})}export{ne as PayoutRowActions};
@@ -0,0 +1,4 @@
1
+ import type { PayoutRequestStatus } from "../../../db/schema/index.js";
2
+ export declare function PayoutStatusBadge({ status }: {
3
+ status: PayoutRequestStatus;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as u}from"react/jsx-runtime";import{useTranslations as a}from"next-intl";import{StatusBadge as s}from"../../../components/ui/status-badge.js";const o={requested:"warning",approved:"success",rejected:"danger",paid:"neutral"};function d({status:t}){const e=a("Payouts.Status");return u(s,{tone:o[t],children:e(t)})}export{d as PayoutStatusBadge};
@@ -0,0 +1 @@
1
+ export declare function PayoutStatusTabs(): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as s,jsxs as c}from"react/jsx-runtime";import{useTranslations as T}from"next-intl";import{useQueryStates as i}from"nuqs";import{useTransition as u}from"react";import{Tabs as m,TabsIndicator as p,TabsList as b,TabsTab as f}from"../../../components/ui/tabs.js";import{PAYOUT_STATUS_FILTERS as l,payoutStatusParser as S}from"../list-params.js";import{listSearchParsers as P}from"../../../lib/list-params.js";function _(){const t=T("Payouts.Tabs"),[r,e]=u(),[{status:o},n]=i({status:S,page:P.page},{shallow:!1,clearOnDefault:!0,startTransition:e});return s(m,{value:o,onValueChange:a=>n({status:a,page:null}),"data-pending":r?"":void 0,children:c(b,{children:[l.map(a=>s(f,{value:a,children:t(a)},a)),s(p,{})]})})}export{_ as PayoutStatusTabs};
@@ -0,0 +1,6 @@
1
+ import type { PayoutRow } from "../queries.js";
2
+ import { type ListResult } from "../../../lib/list-params.js";
3
+ export declare function PayoutsTable({ result, canManage, }: {
4
+ result: ListResult<PayoutRow>;
5
+ canManage: boolean;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as t,jsxs as n}from"react/jsx-runtime";import{IconUser as l,IconWallet as d}from"@tabler/icons-react";import{useFormatter as c,useTranslations as f}from"next-intl";import{useMemo as p}from"react";import{DataTable as g}from"../../../components/ui/data-table.js";import{Identity as y}from"../../../components/ui/identity.js";import{SortButton as m}from"../../../components/ui/sort-button.js";import{TablePagination as x}from"../../../components/ui/table-pagination.js";import{PayoutRowActions as P}from"./payout-row-actions.js";import{PayoutStatusBadge as h}from"./payout-status-badge.js";import{formatMoney as N}from"../../../lib/format.js";import{PAGE_SIZE_OPTIONS as S}from"../../../lib/list-params.js";function E({result:o,canManage:s}){const a=f("Payouts"),r=c(),u=p(()=>{const i=[{id:"affiliate",header:()=>a("columnAffiliate"),cell:({row:e})=>t(y,{visual:t("div",{className:"flex size-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground",children:t(l,{size:18,"aria-hidden":!0})}),primary:e.original.affiliateName,secondary:e.original.affiliateEmail})},{id:"amount",header:()=>t(m,{column:"amount",children:a("columnAmount")}),cell:({row:e})=>n("div",{className:"flex flex-col",children:[t("span",{className:"text-sm font-medium text-foreground tabular-nums",children:N(r,e.original.amount,e.original.currency)}),e.original.desiredCurrency&&e.original.desiredCurrency!==e.original.currency&&n("span",{className:"text-xs text-muted-foreground",children:["\u2192 ",e.original.desiredCurrency]})]})},{id:"requestedAt",header:()=>t(m,{column:"requestedAt",children:a("columnRequestedAt")}),cell:({row:e})=>t("span",{className:"text-sm text-muted-foreground tabular-nums",children:r.dateTime(e.original.requestedAt,{day:"numeric",month:"short",year:"numeric"})})},{id:"status",header:()=>a("columnStatus"),cell:({row:e})=>t(h,{status:e.original.status})}];return s?[...i,{id:"actions",header:()=>t("span",{className:"sr-only",children:a("rowActions")}),cell:({row:e})=>t(P,{requestId:e.original.id,status:e.original.status}),meta:{pin:"right",className:"text-right"}}]:i},[a,r,s]);return t(g,{data:o.rows,columns:u,getRowId:i=>i.id,empty:n("div",{className:"flex flex-col items-center gap-3 py-4",children:[t("div",{className:"flex size-10 items-center justify-center rounded-full bg-muted text-muted-foreground",children:t(d,{size:18,"aria-hidden":!0})}),t("span",{children:a("emptyState")})]}),pagination:t(x,{page:o.page,pageSize:o.pageSize,totalPages:o.totalPages,pageSizeOptions:S})})}export{E as PayoutsTable};
@@ -0,0 +1,4 @@
1
+ import type { EarningsBalance } from "../../earnings/queries.js";
2
+ export declare function RequestPayoutButton({ balances, }: {
3
+ balances: EarningsBalance[];
4
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{Fragment as j,jsx as e,jsxs as a}from"react/jsx-runtime";import{IconWallet as A}from"@tabler/icons-react";import{useFormatter as R,useTranslations as c}from"next-intl";import{useActionState as E,useMemo as H,useState as m}from"react";import{ActionForm as L}from"../../../components/ui/action-form.js";import{Button as f}from"../../../components/ui/button.js";import{Dialog as O,DialogBody as T,DialogClose as z,DialogContent as I,DialogDescription as V,DialogFooter as k,DialogHeader as M,DialogTitle as U}from"../../../components/ui/dialog.js";import{NumberInput as w}from"../../../components/ui/number-input.js";import{SelectField as x}from"../../../components/ui/select-field.js";import{requestPayoutAction as W}from"../actions.js";import{PAYOUT_CURRENCIES as C}from"../constants.js";import{formatMoney as Y}from"../../../lib/format.js";function ae({balances:n}){const s=c("Payouts"),o=c("Common"),[d,i]=m(!1),l=H(()=>n.filter(p=>Number(p.available)>0),[n]),r=l.length>0;return a(j,{children:[e("span",{title:r?void 0:s("noEligibleBalance"),children:a(f,{variant:"primary",size:"sm",disabled:!r,onClick:()=>i(!0),children:[e(A,{size:16,"aria-hidden":!0}),s("requestPayout")]})}),r&&e(O,{open:d,onOpenChange:i,disablePointerDismissal:!0,children:a(I,{closeLabel:o("close"),children:[a(M,{children:[e(U,{children:s("requestDialogTitle")}),e(V,{children:s("requestDialogDesc")})]}),e(_,{eligible:l,onSuccess:()=>i(!1)})]})})]})}function _({eligible:n,onSuccess:s}){const o=c("Payouts"),d=c("Common"),i=R(),l=(t,g)=>Y(i,t,g),[r,p]=m(n[0].currency),[D,h]=m(C.includes(n[0].currency)?n[0].currency:C[0]),[u,b]=m(0),v=n.find(t=>t.currency===r)??n[0],P=Number(v.available),[B,N,y]=E(async(t,g)=>{const q=await W(t,g);return q?.ok&&s(),q},void 0),S=n.map(t=>({value:t.currency,label:l(t.available,t.currency)})),F=C.map(t=>({value:t,label:t}));return a(L,{action:N,actionState:B,className:"contents",errorClassName:"mx-6 mt-4",children:[a(T,{children:[e("input",{type:"hidden",name:"currency",value:r}),e("input",{type:"hidden",name:"desiredCurrency",value:D}),e("input",{type:"hidden",name:"amount",value:String(u)}),a("div",{className:"flex flex-col gap-3",children:[e(x,{label:o("currencyLabel"),help:o("currencyHelp"),value:r,options:S,onValueChange:t=>{p(t),b(0)}}),a("div",{className:"flex flex-col gap-1.5",children:[e("span",{className:"text-sm text-foreground",children:o("amountLabel")}),e(w,{min:0,max:P,step:.01,value:u,onValueChange:b,"aria-label":o("amountLabel")}),e("p",{className:"text-xs text-muted-foreground",children:o("availableHint",{amount:l(v.available,r)})})]}),e(x,{label:o("desiredCurrencyLabel"),help:o("desiredCurrencyHelp"),value:D,options:F,onValueChange:t=>h(t)})]})]}),a(k,{children:[e(z,{render:e(f,{type:"button",variant:"secondary",size:"sm",disabled:y}),children:d("cancel")}),e(f,{type:"submit",size:"sm",disabled:y||u<=0||u>P,children:o(y?"requesting":"requestPayout")})]})]})}export{ae as RequestPayoutButton};
@@ -0,0 +1,2 @@
1
+ export declare const PAYOUT_CURRENCIES: readonly ["EUR", "USD", "GBP", "BTC", "USDT"];
2
+ export type PayoutCurrency = (typeof PAYOUT_CURRENCIES)[number];
@@ -0,0 +1 @@
1
+ const t=["EUR","USD","GBP","BTC","USDT"];export{t as PAYOUT_CURRENCIES};
@@ -0,0 +1,14 @@
1
+ export declare const PAYOUT_SORT_KEYS: readonly ["requestedAt", "amount"];
2
+ export type PayoutSortKey = (typeof PAYOUT_SORT_KEYS)[number];
3
+ export declare const PAYOUT_STATUS_FILTERS: readonly ["all", "requested", "approved", "rejected", "paid"];
4
+ export type PayoutStatusFilter = (typeof PAYOUT_STATUS_FILTERS)[number];
5
+ export declare const payoutStatusParser: Omit<import("nuqs/server").SingleParserBuilder<"rejected" | "paid" | "requested" | "approved" | "all">, "parseServerSide"> & {
6
+ readonly defaultValue: NonNullable<"rejected" | "paid" | "requested" | "approved" | "all">;
7
+ parseServerSide(value: string | string[] | undefined): NonNullable<"rejected" | "paid" | "requested" | "approved" | "all">;
8
+ };
9
+ export declare const loadPayoutStatus: import("nuqs/server").LoaderFunction<{
10
+ status: Omit<import("nuqs/server").SingleParserBuilder<"rejected" | "paid" | "requested" | "approved" | "all">, "parseServerSide"> & {
11
+ readonly defaultValue: NonNullable<"rejected" | "paid" | "requested" | "approved" | "all">;
12
+ parseServerSide(value: string | string[] | undefined): NonNullable<"rejected" | "paid" | "requested" | "approved" | "all">;
13
+ };
14
+ }>;
@@ -0,0 +1 @@
1
+ import{createLoader as t,parseAsStringLiteral as e}from"nuqs/server";const s=["requestedAt","amount"],o=["all","requested","approved","rejected","paid"],r=e(o).withDefault("requested"),p=t({status:r});export{s as PAYOUT_SORT_KEYS,o as PAYOUT_STATUS_FILTERS,p as loadPayoutStatus,r as payoutStatusParser};
@@ -0,0 +1,14 @@
1
+ import "server-only";
2
+ import { type PayoutRequestStatus } from "../../db/schema/index.js";
3
+ import type { PayoutSortKey } from "./list-params.js";
4
+ import { type ListParams, type ListResult } from "../../lib/list-params.js";
5
+ export type MyPayoutRow = {
6
+ id: string;
7
+ amount: string;
8
+ currency: string;
9
+ desiredCurrency: string | null;
10
+ status: PayoutRequestStatus;
11
+ requestedAt: Date;
12
+ reviewedAt: Date | null;
13
+ };
14
+ export declare function listMyPayouts(userId: string, params: ListParams<PayoutSortKey>): Promise<ListResult<MyPayoutRow>>;
@@ -0,0 +1 @@
1
+ import"server-only";import{db as a}from"../../db/index.js";import{payoutRequests as t}from"../../db/schema/index.js";import{asc as i,count as c,desc as d,eq as m}from"drizzle-orm";import{paginate as p}from"../../lib/list-params.js";function l(s,e){const r=s==="amount"?t.amount:t.requestedAt;return[e==="asc"?i(r):d(r),i(t.id)]}async function S(s,e){const r=m(t.userId,s),[u,y]=l(e.sort,e.dir);return p(e,{count:async()=>{const[o]=await a.select({value:c()}).from(t).where(r);return o?.value??0},fetch:({offset:o,limit:n})=>a.select({id:t.id,amount:t.amount,currency:t.currency,desiredCurrency:t.desiredCurrency,status:t.status,requestedAt:t.requestedAt,reviewedAt:t.reviewedAt}).from(t).where(r).orderBy(u,y).offset(o).limit(n)})}export{S as listMyPayouts};
@@ -0,0 +1,14 @@
1
+ import { type PayoutRequestStatus } from "../../db/schema/index.js";
2
+ import { type ListParams, type ListResult } from "../../lib/list-params.js";
3
+ export type PayoutRow = {
4
+ id: string;
5
+ affiliateName: string;
6
+ affiliateEmail: string;
7
+ amount: string;
8
+ currency: string;
9
+ desiredCurrency: string | null;
10
+ status: PayoutRequestStatus;
11
+ requestedAt: Date;
12
+ reviewedAt: Date | null;
13
+ };
14
+ export declare const listPayoutRequests: (params: ListParams<"amount" | "requestedAt">, statusFilter: "rejected" | "paid" | "requested" | "approved" | "all") => Promise<ListResult<PayoutRow>>;
@@ -0,0 +1 @@
1
+ import{db as n}from"../../db/index.js";import{displayName as p,payoutRequests as e,users as s}from"../../db/schema/index.js";import{asc as d,count as f,desc as P,eq as y}from"drizzle-orm";import{authQuery as q}from"../../lib/auth/action.js";import{paginate as S}from"../../lib/list-params.js";const A={requested:"requested",approved:"approved",rejected:"rejected",paid:"paid"};function R(o,r){const a=o==="amount"?e.amount:e.requestedAt;return[r==="asc"?d(a):P(a),d(e.id)]}const C=q("payouts:read",async(o,r,a)=>{const u=a==="all"?void 0:y(e.status,A[a]),[m,c]=R(r.sort,r.dir);return S(r,{count:async()=>{const[i]=await n.select({value:f()}).from(e).where(u);return i?.value??0},fetch:async({offset:i,limit:l})=>(await n.select({id:e.id,amount:e.amount,currency:e.currency,desiredCurrency:e.desiredCurrency,status:e.status,requestedAt:e.requestedAt,reviewedAt:e.reviewedAt,firstName:s.firstName,lastName:s.lastName,email:s.email}).from(e).innerJoin(s,y(s.id,e.userId)).where(u).orderBy(m,c).offset(i).limit(l)).map(t=>({id:t.id,amount:t.amount,currency:t.currency,desiredCurrency:t.desiredCurrency,status:t.status,requestedAt:t.requestedAt,reviewedAt:t.reviewedAt,affiliateName:p({firstName:t.firstName,lastName:t.lastName}),affiliateEmail:t.email}))})});export{C as listPayoutRequests};
@@ -0,0 +1,27 @@
1
+ import type { FormState } from "../../lib/actions/state.js";
2
+ export type PostbackFormState = FormState<{
3
+ id: string;
4
+ }>;
5
+ export type CasinoPostbackListItem = {
6
+ id: string;
7
+ name: string;
8
+ isActive: boolean;
9
+ landingUrl: string;
10
+ };
11
+ export type CasinoPostbackConfig = {
12
+ id: string;
13
+ name: string;
14
+ landingUrl: string;
15
+ trackingParamName: string;
16
+ postbackSecret: string;
17
+ };
18
+ export declare const listCasinosForPostbacks: () => Promise<CasinoPostbackListItem[]>;
19
+ export declare const getCasinoPostbackConfig: (casinoId: string) => Promise<CasinoPostbackConfig | null>;
20
+ export declare const updatePostbackConfigAction: (args_0: string, args_1: FormState<{
21
+ id: string;
22
+ }>, args_2: FormData) => Promise<FormState<{
23
+ id: string;
24
+ }>>;
25
+ export declare const regeneratePostbackSecretAction: (args_0: string) => Promise<import("../../lib/actions/state.js").ActionResult<{
26
+ secret: string;
27
+ }>>;
@@ -0,0 +1 @@
1
+ "use server";import{randomUUID as k}from"node:crypto";import{db as i}from"../../db/index.js";import{casinos as t}from"../../db/schema/index.js";import{eq as n}from"drizzle-orm";import{revalidatePath as p}from"next/cache";import{z as s}from"zod";import{parseForm as u}from"../../lib/actions/parse-form.js";import{authAction as b,authFormAction as f,authQuery as g}from"../../lib/auth/action.js";import{appError as d}from"../../lib/errors/codes.js";import{success as l}from"../../lib/errors/server.js";import{invalidateCasinoCampaignTrackingCache as P}from"../../lib/tracking-cache.js";import{V as w}from"../../lib/validation/zod.js";const C=r=>r===""||r===void 0?null:r,y=s.object({landingUrl:s.preprocess(C,s.url().nullable()),trackingParamName:s.string().trim().min(1,w.fieldRequired).max(64)}),L=g("postbacks:read",async()=>i.select({id:t.id,name:t.name,isActive:t.isActive,landingUrl:t.landingUrl}).from(t).orderBy(t.name)),R=g("postbacks:read",async(r,a)=>{const[e]=await i.select({id:t.id,name:t.name,landingUrl:t.landingUrl,trackingParamName:t.trackingParamName,postbackSecret:t.postbackSecret}).from(t).where(n(t.id,a)).limit(1);return e??null}),$=f({permission:"postbacks:manage",revalidate:["/postbacks"]},async({audit:r},a,e)=>{const c=await u(e,y),[o]=await i.select({id:t.id}).from(t).where(n(t.id,a)).limit(1);if(!o)throw d("casino_not_found",{toast:!0});return await i.update(t).set({landingUrl:c.landingUrl??"",trackingParamName:c.trackingParamName}).where(n(t.id,a)),await r({action:"casino.postback_update",target:{type:"casino",id:a}}),await P(a),p(`/postbacks/${a}`),l({id:a},"Toasts.postbackConfigSaved")}),z=b({permission:"postbacks:manage",revalidate:["/postbacks"]},async({audit:r},a)=>{const e=k();if(!await i.transaction(async o=>{const[m]=await o.update(t).set({postbackSecret:e}).where(n(t.id,a)).returning({id:t.id});return m?(await r({action:"casino.postback_secret_regenerate",target:{type:"casino",id:a}},o),m):null}))throw d("casino_not_found",{toast:!0});return p(`/postbacks/${a}`),l({secret:e},"Toasts.postbackSecretRegenerated")});export{R as getCasinoPostbackConfig,L as listCasinosForPostbacks,z as regeneratePostbackSecretAction,$ as updatePostbackConfigAction};
@@ -0,0 +1,6 @@
1
+ export declare function IntegrationDialog({ casinoId, postbackUrl, secret, canManage, }: {
2
+ casinoId: string;
3
+ postbackUrl: string;
4
+ secret: string;
5
+ canManage: boolean;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{IconKey as v,IconRefresh as C}from"@tabler/icons-react";import{useRouter as L}from"next/navigation";import{useTranslations as c}from"next-intl";import{useState as T,useTransition as F}from"react";import{Button as i}from"../../../components/ui/button.js";import{CopyButton as m}from"../../../components/ui/copy-button.js";import{Dialog as h,DialogBody as k,DialogClose as x,DialogContent as I,DialogDescription as N,DialogFooter as z,DialogHeader as B,DialogTitle as S,DialogTrigger as P}from"../../../components/ui/dialog.js";import{FormField as g}from"../../../components/ui/form-field.js";import{Input as w}from"../../../components/ui/input.js";import{PasswordInput as R}from"../../../components/ui/password-input.js";import{regeneratePostbackSecretAction as A}from"../actions.js";import{toastActionResult as H}from"../../../lib/toast.js";function Y({casinoId:d,postbackUrl:r,secret:p,canManage:f}){const o=c("Postbacks"),n=c("Common"),u=L(),[l,D]=T(p),[s,b]=F(),y=()=>{b(async()=>{const t=await A(d);t.ok&&(D(t.data.secret),u.refresh()),H(t)})};return a(h,{children:[a(P,{render:e(i,{variant:"secondary",size:"sm"}),children:[e(v,{size:14,"aria-hidden":!0}),o("integrationTitle")]}),a(I,{closeLabel:n("close"),children:[a(B,{children:[e(S,{children:o("integrationTitle")}),e(N,{children:o("integrationDesc")})]}),a(k,{className:"flex flex-col gap-4",children:[e(g,{name:"postbackUrl",label:o("postbackUrlLabel"),children:a("div",{className:"flex items-center gap-2",children:[e(w,{value:r,readOnly:!0,className:"flex-1 font-mono"}),e(m,{value:r,copyLabel:o("copy"),copiedLabel:o("copied")})]})}),e(g,{name:"postbackSecret",label:o("secretLabel"),children:a("div",{className:"flex items-center gap-2",children:[e(R,{value:l,readOnly:!0,className:"flex-1",inputClassName:"font-mono",showLabel:o("reveal"),hideLabel:o("hide")}),e(m,{value:l,copyLabel:o("copy"),copiedLabel:o("copied")}),f?e(i,{type:"button",size:"sm",variant:"secondary",disabled:s,"aria-label":o(s?"regenerating":"regenerate"),onClick:y,children:e(C,{size:16,"aria-hidden":!0})}):null]})})]}),e(z,{children:e(x,{render:e(i,{variant:"secondary",size:"sm"}),children:n("close")})})]})]})}export{Y as IntegrationDialog};
@@ -0,0 +1,5 @@
1
+ import { type CasinoPostbackConfig } from "../actions.js";
2
+ export declare function PostbackEditor({ config, canManage, }: {
3
+ config: CasinoPostbackConfig;
4
+ canManage: boolean;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as t,jsxs as l}from"react/jsx-runtime";import{IconSettings as c}from"@tabler/icons-react";import{useTranslations as u}from"next-intl";import{useActionState as p}from"react";import{ActionForm as f}from"../../../components/ui/action-form.js";import{Button as b}from"../../../components/ui/button.js";import{FormField as n}from"../../../components/ui/form-field.js";import{Input as r}from"../../../components/ui/input.js";import{SectionCard as g}from"../../../components/ui/section-card.js";import{updatePostbackConfigAction as k}from"../actions.js";function h({config:e,canManage:o}){const a=u("Postbacks"),m=k.bind(null,e.id),[s,d,i]=p(m,void 0);return l(f,{action:d,actionState:s,className:"flex flex-col gap-6",children:[l(g,{icon:t(c,{size:18,"aria-hidden":!0}),title:a("generalTitle"),description:a("generalDesc"),children:[t(n,{name:"landingUrl",label:a("landingUrlLabel"),children:t(r,{name:"landingUrl",type:"url",inputMode:"url",defaultValue:e.landingUrl,placeholder:"https://casino.com",disabled:!o,autoComplete:"off"},e.landingUrl)}),t(n,{name:"trackingParamName",label:a("trackingParamLabel"),children:t(r,{name:"trackingParamName",type:"text","aria-required":"true",maxLength:64,defaultValue:e.trackingParamName,disabled:!o,autoComplete:"off"},e.trackingParamName)})]}),o?t("div",{className:"flex justify-end",children:t(b,{type:"submit",size:"sm",disabled:i,children:a(i?"saving":"save")})}):null]})}export{h as PostbackEditor};
@@ -0,0 +1,4 @@
1
+ import type { CasinoPostbackListItem } from "../actions.js";
2
+ export declare function PostbacksTable({ data }: {
3
+ data: CasinoPostbackListItem[];
4
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as t,jsxs as u}from"react/jsx-runtime";import{IconBuildingStore as i}from"@tabler/icons-react";import{useTranslations as r}from"next-intl";import{useMemo as m}from"react";import{DataTable as d}from"../../../components/ui/data-table.js";import{Identity as l}from"../../../components/ui/identity.js";import{StatusBadge as s}from"../../../components/ui/status-badge.js";import{TextLink as c}from"../../../components/ui/text-link.js";function y({data:n}){const a=r("Postbacks"),o=m(()=>[{id:"name",header:()=>a("columnName"),cell:({row:e})=>t(l,{visual:t("div",{className:"flex size-9 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground",children:t(i,{size:18,"aria-hidden":!0})}),primary:t(c,{href:`/postbacks/${e.original.id}`,tone:"plain",children:e.original.name})})},{id:"status",header:()=>a("columnStatus"),cell:({row:e})=>e.original.isActive?t(s,{tone:"success",children:a("statusActive")}):t(s,{tone:"danger",children:a("statusDeactivated")})},{id:"landing",header:()=>a("columnLanding"),cell:({row:e})=>e.original.landingUrl?t("span",{className:"text-sm text-muted-foreground",children:e.original.landingUrl}):t("span",{className:"text-sm text-muted-foreground italic",children:a("notConfigured")})}],[a]);return t(d,{data:n,columns:o,getRowId:e=>e.id,empty:u("div",{className:"flex flex-col items-center gap-3 py-4",children:[t("div",{className:"flex size-10 items-center justify-center rounded-full bg-muted text-muted-foreground",children:t(i,{size:18,"aria-hidden":!0})}),t("span",{children:a("listEmpty")})]})})}export{y as PostbacksTable};
@@ -0,0 +1,2 @@
1
+ export declare const setRequireManagerTotpAction: (args_0: boolean) => Promise<import("../../lib/actions/state.js").ActionResult<void>>;
2
+ export declare const setRequireAffiliateApprovalAction: (args_0: boolean) => Promise<import("../../lib/actions/state.js").ActionResult<void>>;
@@ -0,0 +1 @@
1
+ "use server";import{db as r}from"../../db/index.js";import{USER_ROLE as p}from"../../db/schema/index.js";import{redirect as f}from"next/navigation";import{bulkApprovePendingAffiliates as m}from"../affiliates/bulk-approve.js";import{authAction as o}from"../../lib/auth/action.js";import{success as s}from"../../lib/errors/server.js";import{updatePlatformSettings as n}from"../../lib/platform-settings.js";const v=o({permission:"settings:manage",revalidate:["/settings"]},async({user:t,audit:i},a)=>(await r.transaction(async e=>{await n({requireManagerTotp:a},t.id,e),await i({action:"settings.update",target:{type:"settings",id:"requireManagerTotp"},metadata:{changed:["requireManagerTotp"]}},e)}),a&&t.role===p.manager&&!t.totpConfirmedAt&&f("/user/settings"),s("Toasts.platformSettingsUpdated"))),w=o({permission:"settings:manage",revalidate:["/settings","/affiliates"]},async({user:t,audit:i},a)=>(await r.transaction(async e=>{await n({requireAffiliateApproval:a},t.id,e),await i({action:"settings.update",target:{type:"settings",id:"requireAffiliateApproval"},metadata:{changed:["requireAffiliateApproval"]}},e)}),a||await m(t.id),s("Toasts.platformSettingsUpdated")));export{w as setRequireAffiliateApprovalAction,v as setRequireManagerTotpAction};
@@ -0,0 +1,3 @@
1
+ export declare function AffiliateApprovalSetting({ enabled }: {
2
+ enabled: boolean;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{Fragment as z,jsx as t,jsxs as l}from"react/jsx-runtime";import{IconUserCheck as d}from"@tabler/icons-react";import{useTranslations as g}from"next-intl";import{useOptimistic as u,useState as C,useTransition as b}from"react";import{AlertDialog as D,AlertDialogClose as h,AlertDialogContent as T,AlertDialogDescription as v,AlertDialogFooter as y,AlertDialogTitle as O}from"../../../components/ui/alert-dialog.js";import{Button as s}from"../../../components/ui/button.js";import{SwitchField as k}from"../../../components/ui/switch-field.js";import{setRequireAffiliateApprovalAction as B}from"../actions.js";import{toastActionResult as S}from"../../../lib/toast.js";function G({enabled:r}){const e=g("Settings.AffiliateApproval"),[p,c]=u(r),[o,m]=b(),[f,n]=C(!1),a=i=>{m(async()=>{c(i),S(await B(i))})},A=i=>{if(!i&&r){n(!0);return}a(i)};return l(z,{children:[t(k,{icon:t(d,{size:18}),label:e("title"),help:e("description"),checked:p,disabled:o,onCheckedChange:A}),t(D,{open:f,onOpenChange:n,children:l(T,{children:[t(O,{children:e("disableConfirmTitle")}),t(v,{children:e("disableConfirmBody")}),l(y,{children:[t(h,{render:t(s,{type:"button",variant:"secondary",size:"sm",disabled:o,children:e("disableConfirmCancel")})}),t(s,{type:"button",variant:"destructive",size:"sm",disabled:o,onClick:()=>{n(!1),a(!1)},children:e("disableConfirmAccept")})]})]})})]})}export{G as AffiliateApprovalSetting};
@@ -0,0 +1,3 @@
1
+ export declare function ManagerTotpSetting({ enabled }: {
2
+ enabled: boolean;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as i}from"react/jsx-runtime";import{IconShieldLock as p}from"@tabler/icons-react";import{useTranslations as l}from"next-intl";import{useOptimistic as m,useTransition as d}from"react";import{SwitchField as g}from"../../../components/ui/switch-field.js";import{setRequireManagerTotpAction as f}from"../actions.js";import{toastActionResult as u}from"../../../lib/toast.js";function w({enabled:e}){const t=l("Settings.ManagerTotp"),[n,s]=m(e),[r,a]=d(),c=o=>{a(async()=>{s(o),u(await f(o))})};return i(g,{icon:i(p,{size:18}),label:t("title"),help:t("description"),checked:n,disabled:r,onCheckedChange:c})}export{w as ManagerTotpSetting};
@@ -0,0 +1,12 @@
1
+ export type PlatformAdminContact = {
2
+ id: string;
3
+ firstName: string;
4
+ lastName: string;
5
+ email: string;
6
+ };
7
+ export declare const listPlatformAdmins: () => Promise<PlatformAdminContact[]>;
8
+ export declare const sendSupportMessageAction: (args_0: import("../../lib/actions/state.js").FormState<{
9
+ message: string;
10
+ }>, args_1: FormData) => Promise<import("../../lib/actions/state.js").FormState<{
11
+ message: string;
12
+ }>>;
@@ -0,0 +1 @@
1
+ "use server";import{db as m}from"../../db/index.js";import{USER_ROLE as r,USER_STATUS as o,users as e}from"../../db/schema/index.js";import{and as n,asc as p,eq as t}from"drizzle-orm";import{z as a}from"zod";import{parseForm as d}from"../../lib/actions/parse-form.js";import{authFormAction as u,roleQuery as g}from"../../lib/auth/action.js";import{appError as S}from"../../lib/errors/codes.js";import{success as N}from"../../lib/errors/server.js";import{SUPPORT_MESSAGE_MAX as _,SUPPORT_SUBJECT_MAX as A,V as f}from"../../lib/validation/zod.js";import{sendSupportMessageEmail as E}from"./email.js";const q=g(r.manager,async()=>m.select({id:e.id,firstName:e.firstName,lastName:e.lastName,email:e.email}).from(e).where(n(t(e.role,r.platform_admin),t(e.status,o.active))).orderBy(p(e.firstName),p(e.lastName))),P=a.object({recipientId:a.uuid(),subject:a.string().trim().min(1,f.fieldRequired).max(A),message:a.string().trim().min(1,f.fieldRequired).max(_)}),v=u({role:r.manager},async({user:l},c)=>{const s=await d(c,P),[i]=await m.select({id:e.id,firstName:e.firstName,lastName:e.lastName,email:e.email}).from(e).where(n(t(e.id,s.recipientId),t(e.role,r.platform_admin),t(e.status,o.active))).limit(1);if(!i)throw S("user_not_found",{toast:!0});return await E({recipient:i,sender:l,subject:s.subject,message:s.message}),N("Toasts.supportMessageSent")});export{q as listPlatformAdmins,v as sendSupportMessageAction};
@@ -0,0 +1,4 @@
1
+ import { type PlatformAdminContact } from "../actions.js";
2
+ export declare function SupportPage({ admins }: {
3
+ admins: PlatformAdminContact[];
4
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{IconSend as b}from"@tabler/icons-react";import{useTranslations as s}from"next-intl";import{useActionState as F,useState as N}from"react";import{ActionForm as A}from"../../../components/ui/action-form.js";import{Avatar as S}from"../../../components/ui/avatar.js";import{Button as h}from"../../../components/ui/button.js";import{Card as c}from"../../../components/ui/card.js";import{Field as C,FieldLabel as P}from"../../../components/ui/field.js";import{FormField as i}from"../../../components/ui/form-field.js";import{Input as R}from"../../../components/ui/input.js";import{RadioGroup as v,RadioGroupItem as I}from"../../../components/ui/radio-group.js";import{Textarea as y}from"../../../components/ui/textarea.js";import{sendSupportMessageAction as L}from"../actions.js";import{useFormReset as w}from"../../../lib/hooks/use-form-reset.js";import{SUPPORT_MESSAGE_MAX as T,SUPPORT_SUBJECT_MAX as j}from"../../../lib/validation/zod.js";function l(o){return`${o.firstName} ${o.lastName}`.trim()}function K({admins:o}){const t=s("Support");return r("div",{className:"mx-auto flex w-full max-w-3xl flex-col gap-6",children:[r("section",{className:"flex flex-col gap-1",children:[e("h1",{className:"text-2xl font-semibold tracking-tight text-foreground",children:t("title")}),e("p",{className:"text-sm text-muted-foreground",children:t("subtitle")})]}),o.length===0?e(c,{className:"bg-muted/40 p-6 text-sm text-muted-foreground",children:t("emptyAdmins")}):e(G,{admins:o})]})}function G({admins:o}){const t=s("Support"),p=s("Common"),n=o[0]?.id??"",[u,d]=N(n),f=w(()=>d(n)),[x,g,m]=F(L,void 0);return e(c,{className:"flex flex-col gap-5 p-4",children:r(A,{action:g,actionState:x,resetOnSuccess:!0,className:"flex flex-col gap-5",children:[e(i,{name:"recipientId",label:t("recipientLabel"),children:e(v,{ref:f,name:"recipientId",value:u,onValueChange:a=>d(a),disabled:m,className:"flex flex-col gap-2",children:o.map(a=>r(C,{className:"flex-row items-center gap-3 rounded-md border border-border bg-card p-3",children:[e(I,{value:a.id,"aria-label":l(a)}),e(S,{seed:a.id,name:l(a),size:"lg"}),r(P,{className:"flex min-w-0 flex-1 cursor-pointer flex-col font-normal",children:[e("span",{className:"truncate text-sm font-medium text-foreground",children:l(a)}),e("span",{className:"truncate text-xs text-muted-foreground",children:a.email})]})]},a.id))})}),e(i,{name:"subject",label:t("subjectLabel"),children:e(R,{name:"subject",type:"text",maxLength:j,placeholder:t("subjectPlaceholder"),disabled:m,"aria-required":"true"})}),e(i,{name:"message",label:t("messageLabel"),children:e(y,{name:"message",maxLength:T,placeholder:t("messagePlaceholder"),rows:6,disabled:m,"aria-required":"true"})}),e("div",{className:"flex items-center justify-end gap-2",children:r(h,{type:"submit",variant:"primary",size:"sm",disabled:m,children:[e(b,{size:14,"aria-hidden":!0}),m?t("sending"):p("send")]})})]})})}export{K as SupportPage};
@@ -0,0 +1,13 @@
1
+ import "server-only";
2
+ import type { PublicUser } from "../../db/schema/index.js";
3
+ export declare function sendSupportMessageEmail(args: {
4
+ recipient: {
5
+ id: string;
6
+ firstName: string;
7
+ lastName: string;
8
+ email: string;
9
+ };
10
+ sender: PublicUser;
11
+ subject: string;
12
+ message: string;
13
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ import"server-only";import{getTranslations as m}from"next-intl/server";import{AdminSupportMessageEmail as a}from"../../emails/admin/support-message.js";import{resolveUserLocale as n}from"../../lib/email/locale.js";import{sendEmail as l}from"../../lib/email/send.js";import{env as c}from"../../lib/env.js";async function g(e){const s=await n(e.recipient.id),[r,t]=await Promise.all([m({locale:s,namespace:"Emails.Common"}),m({locale:s,namespace:"Emails.AdminSupportMessage"})]),o=`${e.sender.firstName} ${e.sender.lastName}`.trim(),i=c.BRAND_NAME;await l({to:e.recipient.email,replyTo:e.sender.email,subject:t("subject",{subject:e.subject}),react:a({senderName:o,senderEmail:e.sender.email,subject:e.subject,message:e.message,lang:s,strings:{preview:t("preview",{subject:e.subject}),heading:t("heading"),intro:t("intro",{brandName:i}),fromLabel:t("fromLabel"),subjectLabel:t("subjectLabel"),messageLabel:t("messageLabel"),brandName:i,footerNote:r("footerNote")}})})}export{g as sendSupportMessageEmail};
@@ -0,0 +1,4 @@
1
+ import { USER_STATUS } from "../../db/schema/index.js";
2
+ type ToggleableUserStatus = typeof USER_STATUS.active | typeof USER_STATUS.blocked;
3
+ export declare const setUserStatus: (args_0: string, args_1: ToggleableUserStatus) => Promise<import("../../lib/actions/state.js").ActionResult<void>>;
4
+ export {};
@@ -0,0 +1 @@
1
+ "use server";import{db as m}from"../../db/index.js";import{publicUserColumns as S,USER_ROLE as s,USER_STATUS as r,users as i}from"../../db/schema/index.js";import{eq as c}from"drizzle-orm";import{requirePermission as u}from"../auth/authorization.js";import{authAction as _}from"../../lib/auth/action.js";import{revokeAllSessionsForUser as T}from"../../lib/auth/tokens.js";import{appError as o}from"../../lib/errors/codes.js";import{success as A}from"../../lib/errors/server.js";const U=["/","/managers","/affiliates"],D=_({revalidate:U},async({user:p,carrier:n,audit:d},a,e)=>{if(e!==r.active&&e!==r.blocked)throw o("invalid_input",{toast:!0});if(p.id===a)throw o("cannot_target_self",{toast:!0});const[t]=await m.select(S).from(i).where(c(i.id,a)).limit(1);if(!t)throw o("user_not_found",{toast:!0});if(t.role===s.manager)u(n,"managers:manage");else if(t.role===s.affiliate)u(n,"affiliates:manage");else throw o("user_not_found",{toast:!0});if(e===r.blocked&&t.inviteAcceptedAt===null)throw o("user_invite_pending",{toast:!0});if(t.status===e)return;const g=t.status;await m.transaction(async l=>{await l.update(i).set({status:e}).where(c(i.id,a)),await d({action:"user.status.update",subjectId:a,target:{type:"user",id:a,label:t.email},metadata:{from:g,to:e}},l)}),e===r.blocked&&await T(a);const f=t.role===s.affiliate;return A(e===r.blocked?f?"Toasts.affiliateDeactivated":"Toasts.managerDeactivated":f?"Toasts.affiliateActivated":"Toasts.managerActivated")});export{D as setUserStatus};
@@ -0,0 +1 @@
1
+ export declare function PasswordSection(): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{useTranslations as m}from"next-intl";import{useActionState as d}from"react";import{ActionForm as l}from"../../../components/ui/action-form.js";import{Button as c}from"../../../components/ui/button.js";import{Card as u}from"../../../components/ui/card.js";import{FormField as o}from"../../../components/ui/form-field.js";import{PasswordInput as t}from"../../../components/ui/password-input.js";import{changePasswordAction as f}from"../../auth/actions.js";function h(){const r=m("User.Settings.Password"),[i,n,s]=d(f,void 0);return a(u,{className:"flex flex-col gap-4",children:[a("header",{className:"flex flex-col gap-1",children:[e("h2",{className:"text-base font-semibold text-foreground",children:r("title")}),e("p",{className:"text-sm text-muted-foreground",children:r("description")})]}),a(l,{action:n,actionState:i,resetOnSuccess:!0,className:"flex flex-col gap-4",children:[e(o,{name:"currentPassword",label:r("currentLabel"),children:e(t,{name:"currentPassword",autoComplete:"current-password","aria-required":"true"})}),e(o,{name:"password",label:r("newLabel"),children:e(t,{name:"password",autoComplete:"new-password","aria-required":"true"})}),e(o,{name:"confirmPassword",label:r("confirmLabel"),children:e(t,{name:"confirmPassword",autoComplete:"new-password","aria-required":"true"})}),e("div",{className:"flex justify-end",children:e(c,{type:"submit",disabled:s,children:r(s?"submitting":"submit")})})]})]})}export{h as PasswordSection};
@@ -0,0 +1,4 @@
1
+ import { type Theme } from "../../../theme/config.js";
2
+ export declare function PreferencesSection({ theme }: {
3
+ theme: Theme;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{Fragment as P,jsx as t,jsxs as U}from"react/jsx-runtime";import{IconLanguage as u,IconPalette as g}from"@tabler/icons-react";import{useRouter as L}from"next/navigation";import{useLocale as T,useTranslations as a}from"next-intl";import{useTransition as b}from"react";import{SelectField as c}from"../../../components/ui/select-field.js";import{locales as d}from"../../../i18n/config.js";import{setUserLocale as S}from"../../../i18n/locale.js";import{themes as w}from"../../../theme/config.js";import{setUserTheme as y}from"../../../theme/theme.js";function v({theme:r}){const o=a("User.Settings.Preferences"),m=a("LocaleSwitcher"),h=a("ThemeSwitcher"),n=T(),l=L(),[s,i]=b();function p(e){e!==n&&i(async()=>{await S(e),l.refresh()})}function f(e){e!==r&&i(async()=>{await y(e),l.refresh()})}return U(P,{children:[t(c,{icon:t(u,{size:18}),label:o("languageLabel"),help:o("languageHelp"),value:n,options:d.map(e=>({value:e,label:m(e)})),onValueChange:p,disabled:s}),t(c,{icon:t(g,{size:18}),label:o("themeLabel"),help:o("themeHelp"),value:r,options:w.map(e=>({value:e,label:h(e)})),onValueChange:f,disabled:s})]})}export{v as PreferencesSection};
@@ -0,0 +1 @@
1
+ export declare function SettingsTabs(): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{jsx as t,jsxs as l}from"react/jsx-runtime";import{useTranslations as o}from"next-intl";import{useQueryStates as T}from"nuqs";import{useTransition as b}from"react";import{Tabs as m,TabsIndicator as u,TabsList as S,TabsTab as f}from"../../../components/ui/tabs.js";import{USER_SETTINGS_TABS as p,userSettingsTabParser as g}from"../list-params.js";function h(){const a=o("User.Settings.Tabs"),[e,n]=b(),[{tab:r},i]=T({tab:g},{shallow:!1,clearOnDefault:!0,startTransition:n});return t(m,{value:r,onValueChange:s=>i({tab:s}),"data-pending":e?"":void 0,children:l(S,{children:[p.map(s=>t(f,{value:s,children:a(s)},s)),t(u,{})]})})}export{h as SettingsTabs};
@@ -0,0 +1,4 @@
1
+ export declare function TotpSection({ confirmedAt, disableLocked, }: {
2
+ confirmedAt: Date | null;
3
+ disableLocked?: boolean;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1 @@
1
+ "use client";import{Fragment as J,jsx as e,jsxs as n}from"react/jsx-runtime";import{IconShieldCheck as b,IconShieldOff as x}from"@tabler/icons-react";import S from"next/image";import{useFormatter as v,useTranslations as l}from"next-intl";import{useActionState as u,useEffect as w,useState as p,useTransition as F}from"react";import{ActionForm as f}from"../../../components/ui/action-form.js";import{AlertDialog as T,AlertDialogClose as D,AlertDialogContent as h,AlertDialogDescription as y,AlertDialogFooter as C,AlertDialogTitle as A}from"../../../components/ui/alert-dialog.js";import{Button as d}from"../../../components/ui/button.js";import{Card as N}from"../../../components/ui/card.js";import{FormField as g}from"../../../components/ui/form-field.js";import{OTPField as B,OTPFieldGroup as k,OTPFieldInput as c}from"../../../components/ui/otp-field.js";import{PasswordInput as O}from"../../../components/ui/password-input.js";import{StatusBadge as z}from"../../../components/ui/status-badge.js";import{beginTotpSetup as P,confirmTotpSetup as U,disableTotp as I}from"../totp.js";import{chunkString as L}from"../../../lib/format.js";import{errorToast as q}from"../../../lib/toast.js";function ie({confirmedAt:o,disableLocked:a=!1}){const t=l("User.Settings.TwoFactor");return n(N,{className:"flex flex-col gap-4",children:[n("header",{className:"flex items-start justify-between gap-3",children:[n("div",{className:"flex flex-col gap-1",children:[e("h2",{className:"text-base font-semibold text-foreground",children:t("title")}),e("p",{className:"text-sm text-muted-foreground",children:t("description")})]}),e(K,{active:!!o})]}),o?e(G,{confirmedAt:o,disableLocked:a}):e(V,{})]})}function K({active:o}){const a=l("User.Settings.TwoFactor");return n(z,{tone:o?"success":"neutral",showDot:!1,children:[e(o?b:x,{size:14,"aria-hidden":!0}),a(o?"statusOn":"statusOff")]})}function V(){const[o,a]=p(null);return o?e(E,{setup:o,onCancel:()=>a(null)}):e(j,{onStarted:a})}function j({onStarted:o}){const a=l("User.Settings.TwoFactor"),[t,s]=F();function i(){s(async()=>{const r=await P();if(r.ok){o(r.data);return}q(r.error)})}return e("div",{children:e(d,{type:"button",size:"sm",onClick:i,disabled:t,children:a(t?"activatingButton":"activateButton")})})}function E({setup:o,onCancel:a}){const t=l("User.Settings.TwoFactor"),[s,i,r]=u(U,void 0);return n("div",{className:"flex flex-col gap-5",children:[n("ol",{className:"flex flex-col gap-1 text-sm text-muted-foreground",children:[e("li",{children:t("setupStep1")}),e("li",{children:t("setupStep2")}),e("li",{children:t("setupStep3")})]}),n("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-start",children:[e(S,{src:o.qrDataUrl,alt:t("qrAlt"),width:192,height:192,unoptimized:!0,className:"size-48 shrink-0 self-center rounded-md border border-border bg-white p-2 sm:self-start"}),n("div",{className:"flex flex-1 flex-col gap-2",children:[e("p",{className:"text-sm font-medium text-foreground",children:t("manualKeyLabel")}),e("p",{className:"text-xs text-muted-foreground",children:t("manualKeyHelp")}),e("code",{className:"block break-all rounded-md border border-border bg-muted px-3 py-2 font-mono text-xs tracking-wider text-foreground",children:L(o.manualKey)})]})]}),n(f,{action:i,actionState:s,className:"flex flex-col gap-3",children:[e("input",{type:"hidden",name:"secret",value:o.secret}),e(g,{name:"code",label:t("codeLabel"),children:e(B,{name:"code",length:6,autoComplete:"one-time-code","aria-required":"true",disabled:r,children:n(k,{children:[e(c,{autoFocus:!0}),e(c,{}),e(c,{}),e(c,{}),e(c,{}),e(c,{})]})})}),n("div",{className:"flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-end",children:[e(d,{type:"button",variant:"ghost",size:"sm",disabled:r,onClick:a,children:t("cancelSetup")}),e(d,{type:"submit",size:"sm",disabled:r,children:t(r?"confirmingButton":"confirmButton")})]})]})]})}function G({confirmedAt:o,disableLocked:a}){const t=l("User.Settings.TwoFactor"),s=v(),[i,r]=p(!1);return n("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e("p",{className:"text-sm text-muted-foreground",children:t("activeSince",{date:s.dateTime(o,{day:"numeric",month:"short",year:"numeric"})})}),a?e("p",{className:"text-xs text-muted-foreground",children:t("disableLocked")}):n(J,{children:[e(H,{open:i,onOpenChange:r}),e(d,{type:"button",variant:"secondary",size:"sm",onClick:()=>r(!0),children:t("disableButton")})]})]})}function H({open:o,onOpenChange:a}){const t=l("User.Settings.TwoFactor"),s=l("Common"),[i,r,m]=u(I,void 0);return w(()=>{i?.ok&&a(!1)},[i,a]),e(T,{open:o,onOpenChange:a,children:n(h,{children:[e(A,{children:t("disableTitle")}),e(y,{children:t("disableHelp")}),n(f,{action:r,actionState:i,className:"flex flex-col gap-3",children:[e(g,{name:"password",label:s("password"),children:e(O,{name:"password","aria-required":"true",autoComplete:"current-password"})}),n(C,{children:[e(D,{render:e(d,{type:"button",variant:"secondary",size:"sm",disabled:m,children:s("cancel")})}),e(d,{type:"submit",variant:"destructive",size:"sm",disabled:m,children:t(m?"disablingButton":"disableConfirmButton")})]})]})]})})}export{ie as TotpSection};
@@ -0,0 +1,12 @@
1
+ export declare const USER_SETTINGS_TABS: readonly ["preferences", "security"];
2
+ export type UserSettingsTab = (typeof USER_SETTINGS_TABS)[number];
3
+ export declare const userSettingsTabParser: Omit<import("nuqs/server").SingleParserBuilder<"security" | "preferences">, "parseServerSide"> & {
4
+ readonly defaultValue: NonNullable<"security" | "preferences">;
5
+ parseServerSide(value: string | string[] | undefined): NonNullable<"security" | "preferences">;
6
+ };
7
+ export declare const loadUserSettingsTab: import("nuqs/server").LoaderFunction<{
8
+ tab: Omit<import("nuqs/server").SingleParserBuilder<"security" | "preferences">, "parseServerSide"> & {
9
+ readonly defaultValue: NonNullable<"security" | "preferences">;
10
+ parseServerSide(value: string | string[] | undefined): NonNullable<"security" | "preferences">;
11
+ };
12
+ }>;
@@ -0,0 +1 @@
1
+ import{createLoader as e,parseAsStringLiteral as t}from"nuqs/server";const r=["preferences","security"],s=t(r).withDefault("preferences"),a=e({tab:s});export{r as USER_SETTINGS_TABS,a as loadUserSettingsTab,s as userSettingsTabParser};
@@ -0,0 +1,7 @@
1
+ export declare const beginTotpSetup: () => Promise<import("../../lib/actions/state.js").ActionResult<{
2
+ qrDataUrl: string;
3
+ manualKey: string;
4
+ secret: string;
5
+ }>>;
6
+ export declare const confirmTotpSetup: (args_0: import("../../lib/actions/state.js").FormState<void>, args_1: FormData) => Promise<import("../../lib/actions/state.js").FormState<void>>;
7
+ export declare const disableTotp: (args_0: import("../../lib/actions/state.js").FormState<void>, args_1: FormData) => Promise<import("../../lib/actions/state.js").FormState<void>>;
@@ -0,0 +1 @@
1
+ "use server";import{db as s}from"../../db/index.js";import{USER_ROLE as u,users as e}from"../../db/schema/index.js";import{eq as n}from"drizzle-orm";import{z as d}from"zod";import{parseForm as l}from"../../lib/actions/parse-form.js";import{authAction as g,authFormAction as w}from"../../lib/auth/action.js";import{verifyPassword as h}from"../../lib/auth/password.js";import{buildOtpAuthUri as b,encryptSecret as A,generateSecret as y,renderQrDataUrl as S,verifyCode as _}from"../../lib/auth/totp.js";import{appError as o}from"../../lib/errors/codes.js";import{success as f}from"../../lib/errors/server.js";import{getPlatformSettings as v}from"../../lib/platform-settings.js";import{PASSWORD_MAX as C,PASSWORD_MIN as D}from"../../lib/validation/zod.js";const W=g({},async({user:t})=>{const[a]=await s.select({totpConfirmedAt:e.totpConfirmedAt}).from(e).where(n(e.id,t.id)).limit(1);if(a?.totpConfirmedAt)throw o("totp_already_enabled",{toast:!0});const r=y();return{qrDataUrl:await S(b(r,t.email)),manualKey:r,secret:r}}),T=d.object({code:d.string().regex(/^\d{6}$/),secret:d.string().regex(/^[A-Z2-7]{16,64}$/)}),$=w({revalidate:["/user/settings"]},async({user:t,audit:a},r)=>{const i=await l(r,T),[p]=await s.select({totpConfirmedAt:e.totpConfirmedAt}).from(e).where(n(e.id,t.id)).limit(1);if(p?.totpConfirmedAt)throw o("totp_already_enabled",{toast:!0});if(!_(i.secret,i.code,t.email))throw o("totp_invalid_code",{field:"code"});return await s.transaction(async c=>{await c.update(e).set({totpSecret:A(i.secret),totpConfirmedAt:new Date}).where(n(e.id,t.id)),await a({action:"user.totp.enable",subjectId:t.id,target:{type:"user",id:t.id,label:t.email}},c)}),f("Toasts.twoFactorEnabled")}),U=d.object({password:d.string().min(D).max(C)}),k=w({revalidate:["/user/settings"]},async({user:t,audit:a},r)=>{const i=await l(r,U);if(t.role===u.manager&&(await v()).requireManagerTotp)throw o("totp_disable_blocked",{toast:!0});const[p]=await s.select({passwordHash:e.passwordHash}).from(e).where(n(e.id,t.id)).limit(1);if(!p?.passwordHash)throw o("user_not_found",{toast:!0});if(!await h(p.passwordHash,i.password))throw o("invalid_credentials",{field:"password"});return await s.transaction(async m=>{await m.update(e).set({totpSecret:null,totpConfirmedAt:null}).where(n(e.id,t.id)),await a({action:"user.totp.disable",subjectId:t.id,target:{type:"user",id:t.id,label:t.email}},m)}),f("Toasts.twoFactorDisabled")});export{W as beginTotpSetup,$ as confirmTotpSetup,k as disableTotp};
@@ -0,0 +1,5 @@
1
+ export declare const locales: readonly ["de", "en"];
2
+ export type Locale = (typeof locales)[number];
3
+ export declare const defaultLocale: Locale;
4
+ export declare const LOCALE_COOKIE = "LOCALE";
5
+ export declare const TIME_ZONE = "Europe/Berlin";
@@ -0,0 +1 @@
1
+ const e=["de","en"],o="de",t="LOCALE",c="Europe/Berlin";export{t as LOCALE_COOKIE,c as TIME_ZONE,o as defaultLocale,e as locales};
@@ -0,0 +1,3 @@
1
+ import "server-only";
2
+ import { type Locale } from "./config.js";
3
+ export declare function getUserLocale(): Promise<Locale>;
@@ -0,0 +1 @@
1
+ import"server-only";import{cookies as e}from"next/headers";import{defaultLocale as a,LOCALE_COOKIE as t,locales as c}from"./config.js";async function L(){const o=(await e()).get(t)?.value;return c.includes(o)?o:a}export{L as getUserLocale};
@@ -0,0 +1,2 @@
1
+ import { type Locale } from "./config.js";
2
+ export declare function setUserLocale(locale: Locale): Promise<void>;
@@ -0,0 +1 @@
1
+ "use server";import{cookies as o}from"next/headers";import{getCurrentUser as t}from"../lib/auth/session.js";import{PREFERENCE_COOKIE_OPTIONS as s,writePreferencesForUser as i}from"../lib/preferences/index.js";import{LOCALE_COOKIE as a}from"./config.js";async function O(e){(await o()).set(a,e,s);const r=await t();r&&await i(r.id,{locale:e})}export{O as setUserLocale};
@@ -0,0 +1,3 @@
1
+ import "server-only";
2
+ import type { ZodType } from "zod";
3
+ export declare function parseForm<TOutput>(formData: FormData, schema: ZodType<TOutput>): Promise<TOutput>;
@@ -0,0 +1 @@
1
+ import"server-only";import{getTranslations as c}from"next-intl/server";import{appError as u}from"../errors/codes.js";import{formDataToObject as d}from"../validation/zod.js";function m(r,t){try{return r(t)}catch{return}}function f(r,t){return(r.message.includes(".")?m(t,r.message):void 0)??m(t,`Validation.${r.code}`)??r.message}async function h(r,t){const s=t.safeParse(d(r));if(s.success)return s.data;const p=await c(),e={};for(const o of s.error.issues){const a=o.path.join(".")||"_form",n=f(o,p),i=e[a];i?i.push(n):e[a]=[n]}throw u("invalid_input",{fieldErrors:e,toast:!0})}export{h as parseForm};