@tuturuuu/ui 0.8.0 → 0.10.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 (245) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/biome.json +1 -1
  3. package/package.json +74 -71
  4. package/src/components/ui/accordion.tsx +1 -1
  5. package/src/components/ui/breadcrumb.tsx +1 -1
  6. package/src/components/ui/calendar-app/calendar-page-shell.tsx +4 -0
  7. package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +239 -33
  8. package/src/components/ui/calendar-app/components/load-smart-scheduling-tasks.tsx +143 -0
  9. package/src/components/ui/calendar-app/components/priority-view.tsx +10 -3
  10. package/src/components/ui/calendar-app/components/tasks-sidebar.tsx +4 -116
  11. package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +67 -2
  12. package/src/components/ui/calendar.tsx +1 -1
  13. package/src/components/ui/carousel.tsx +1 -1
  14. package/src/components/ui/chat/chat-agent-details-external-thread-panel.test.tsx +1 -1
  15. package/src/components/ui/chat/chat-agent-details-external-thread-panel.tsx +1 -1
  16. package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +1 -1
  17. package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +1 -1
  18. package/src/components/ui/chat/chat-agent-details-setup-panel.tsx +1 -1
  19. package/src/components/ui/chat/chat-agent-details-sidebar.test.tsx +1 -1
  20. package/src/components/ui/chat/chat-agent-details-sidebar.tsx +2 -2
  21. package/src/components/ui/chat/chat-agent-details-utils.test.ts +1 -1
  22. package/src/components/ui/chat/chat-agent-details-utils.tsx +1 -1
  23. package/src/components/ui/chat/chat-agent-details-zalo-personal-panel.tsx +2 -2
  24. package/src/components/ui/checkbox.tsx +1 -1
  25. package/src/components/ui/color-picker.tsx +1 -1
  26. package/src/components/ui/command.tsx +1 -1
  27. package/src/components/ui/context-menu.tsx +5 -1
  28. package/src/components/ui/custom/__tests__/settings-dialog-search.test.ts +78 -0
  29. package/src/components/ui/custom/__tests__/settings-dialog-shell-compile-graph.test.ts +76 -0
  30. package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +3 -0
  31. package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +46 -1
  32. package/src/components/ui/custom/combobox.test.tsx +195 -0
  33. package/src/components/ui/custom/combobox.tsx +273 -156
  34. package/src/components/ui/custom/education/modules/youtube/delete-link-button.tsx +5 -13
  35. package/src/components/ui/custom/facebook-mockup/facebook-mockup.tsx +7 -1
  36. package/src/components/ui/custom/facebook-mockup/form.tsx +1 -1
  37. package/src/components/ui/custom/facebook-mockup/image-upload-field.tsx +1 -1
  38. package/src/components/ui/custom/facebook-mockup/preview.tsx +1 -1
  39. package/src/components/ui/custom/nav-link.test.tsx +165 -0
  40. package/src/components/ui/custom/nav-link.tsx +69 -11
  41. package/src/components/ui/custom/navigation.tsx +1 -0
  42. package/src/components/ui/custom/settings/task-settings.tsx +104 -0
  43. package/src/components/ui/custom/settings-dialog-search-loader.d.ts +5 -0
  44. package/src/components/ui/custom/settings-dialog-search-loader.js +3 -0
  45. package/src/components/ui/custom/settings-dialog-search.ts +75 -0
  46. package/src/components/ui/custom/settings-dialog-shell.tsx +65 -28
  47. package/src/components/ui/custom/theme-toggle.tsx +1 -1
  48. package/src/components/ui/custom/workspace-select-helpers.ts +23 -0
  49. package/src/components/ui/custom/workspace-select.tsx +25 -19
  50. package/src/components/ui/dialog.test.tsx +52 -0
  51. package/src/components/ui/dialog.tsx +6 -2
  52. package/src/components/ui/dropdown-menu.tsx +5 -1
  53. package/src/components/ui/finance/debts/debt-loan-form.tsx +12 -5
  54. package/src/components/ui/finance/debts/debt-loan-summary.tsx +3 -2
  55. package/src/components/ui/finance/debts/debts-page.test.tsx +54 -5
  56. package/src/components/ui/finance/debts/debts-page.tsx +15 -2
  57. package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +3 -5
  58. package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +25 -5
  59. package/src/components/ui/finance/invoices/new-invoice-page.tsx +7 -2
  60. package/src/components/ui/finance/invoices/standard-invoice.tsx +4 -2
  61. package/src/components/ui/finance/invoices/subscription-invoice.tsx +4 -2
  62. package/src/components/ui/finance/invoices/utils.ts +3 -1
  63. package/src/components/ui/finance/transactions/form-content-dialog.tsx +3 -0
  64. package/src/components/ui/finance/transactions/form-types.ts +1 -0
  65. package/src/components/ui/finance/transactions/form.tsx +2 -0
  66. package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +2 -0
  67. package/src/components/ui/finance/transactions/period-charts/category-breakdown-dialog.tsx +1 -1
  68. package/src/components/ui/finance/transactions/transaction-edit-dialog.tsx +1 -4
  69. package/src/components/ui/finance/transactions/transactions-create-summary.tsx +3 -0
  70. package/src/components/ui/finance/transactions/transactions-page.tsx +4 -1
  71. package/src/components/ui/finance/wallets/form.test.tsx +51 -3
  72. package/src/components/ui/finance/wallets/form.tsx +15 -4
  73. package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
  74. package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +4 -2
  75. package/src/components/ui/finance/wallets/wallets-data-table.tsx +1 -0
  76. package/src/components/ui/finance/wallets/wallets-page.tsx +5 -2
  77. package/src/components/ui/input-otp.tsx +1 -1
  78. package/src/components/ui/legacy/calendar/all-day-event-bar.tsx +28 -39
  79. package/src/components/ui/legacy/calendar/calendar-cell.tsx +2 -0
  80. package/src/components/ui/legacy/calendar/calendar-content.tsx +10 -6
  81. package/src/components/ui/legacy/calendar/calendar-header.tsx +23 -3
  82. package/src/components/ui/legacy/calendar/calendar-loading-skeleton.tsx +135 -0
  83. package/src/components/ui/legacy/calendar/calendar-matrix.tsx +175 -237
  84. package/src/components/ui/legacy/calendar/event-card.test.tsx +177 -0
  85. package/src/components/ui/legacy/calendar/event-card.tsx +220 -131
  86. package/src/components/ui/legacy/calendar/event-modal.tsx +17 -17
  87. package/src/components/ui/legacy/calendar/event-provider-display.tsx +69 -0
  88. package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +86 -4
  89. package/src/components/ui/legacy/calendar/smart-calendar.tsx +32 -2
  90. package/src/components/ui/legacy/meet/create-plan-dialog.tsx +19 -10
  91. package/src/components/ui/navigation-menu.tsx +1 -1
  92. package/src/components/ui/pagination.tsx +1 -1
  93. package/src/components/ui/radio-group.tsx +1 -1
  94. package/src/components/ui/select.tsx +5 -1
  95. package/src/components/ui/sheet.tsx +1 -1
  96. package/src/components/ui/sidebar.tsx +1 -1
  97. package/src/components/ui/storefront/cart-popover.tsx +61 -0
  98. package/src/components/ui/storefront/cart-summary-parts.tsx +290 -0
  99. package/src/components/ui/storefront/cart-summary.tsx +93 -154
  100. package/src/components/ui/storefront/checkout-overlay.tsx +4 -5
  101. package/src/components/ui/storefront/listing-card.tsx +1 -1
  102. package/src/components/ui/storefront/merch-sections.tsx +70 -0
  103. package/src/components/ui/storefront/product-detail.tsx +1 -1
  104. package/src/components/ui/storefront/storefront-surface.test.tsx +106 -11
  105. package/src/components/ui/storefront/storefront-surface.tsx +101 -166
  106. package/src/components/ui/storefront/types.ts +4 -0
  107. package/src/components/ui/storefront/utils.ts +6 -0
  108. package/src/components/ui/text-editor/__tests__/extensions.test.ts +123 -0
  109. package/src/components/ui/text-editor/background-color-extension.ts +62 -0
  110. package/src/components/ui/text-editor/color-controls.tsx +284 -0
  111. package/src/components/ui/text-editor/editor.tsx +69 -14
  112. package/src/components/ui/text-editor/extensions.ts +8 -2
  113. package/src/components/ui/text-editor/highlight-extension.ts +22 -0
  114. package/src/components/ui/text-editor/tool-bar.tsx +9 -16
  115. package/src/components/ui/toast.tsx +1 -1
  116. package/src/components/ui/tu-do/boards/__tests__/board-share-dialog.test.tsx +286 -0
  117. package/src/components/ui/tu-do/boards/__tests__/task-board-form.test.tsx +12 -0
  118. package/src/components/ui/tu-do/boards/board-public-link-section.tsx +231 -0
  119. package/src/components/ui/tu-do/boards/board-share-dialog.tsx +15 -226
  120. package/src/components/ui/tu-do/boards/board-share-settings-panel.tsx +351 -0
  121. package/src/components/ui/tu-do/boards/boardId/board-column.tsx +121 -39
  122. package/src/components/ui/tu-do/boards/boardId/enhanced-task-list.tsx +7 -0
  123. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +2 -0
  124. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-move.ts +5 -0
  125. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +3 -0
  126. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-types.ts +3 -3
  127. package/src/components/ui/tu-do/boards/boardId/kanban/data/kanban-deadline-query.ts +50 -2
  128. package/src/components/ui/tu-do/boards/boardId/kanban/data/use-bulk-resources.ts +59 -5
  129. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/__tests__/column-reorder.test.ts +17 -0
  130. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/column-reorder.ts +4 -1
  131. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/drag-preview.tsx +20 -1
  132. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-cache.ts +38 -9
  133. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-order.ts +2 -8
  134. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-sort-key.ts +47 -0
  135. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +81 -30
  136. package/src/components/ui/tu-do/boards/boardId/kanban/planner/__tests__/kanban-planner-island.test.tsx +380 -0
  137. package/src/components/ui/tu-do/boards/boardId/kanban/planner/kanban-planner-dialog.tsx +204 -0
  138. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-digest-panel.tsx +61 -0
  139. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-item-strip.tsx +54 -0
  140. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-plan-toolbar.tsx +251 -0
  141. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-scope-badge.tsx +27 -0
  142. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-section.tsx +58 -0
  143. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-share-dialog.tsx +238 -0
  144. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-target-controls.tsx +143 -0
  145. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-utils.ts +65 -0
  146. package/src/components/ui/tu-do/boards/boardId/kanban/planner/use-kanban-planner-state.ts +234 -0
  147. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +642 -5
  148. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +224 -15
  149. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-deadline-panels.tsx +535 -53
  150. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-skeleton.tsx +101 -33
  151. package/src/components/ui/tu-do/boards/boardId/kanban.tsx +235 -113
  152. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +50 -5
  153. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +12 -2
  154. package/src/components/ui/tu-do/boards/boardId/task-card/measured-task-card.tsx +10 -1
  155. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +3 -0
  156. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +20 -0
  157. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +10 -0
  158. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +271 -36
  159. package/src/components/ui/tu-do/boards/boardId/task-filter.test.tsx +152 -0
  160. package/src/components/ui/tu-do/boards/boardId/task-filter.tsx +555 -545
  161. package/src/components/ui/tu-do/boards/boardId/task-list.tsx +22 -0
  162. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-grid.tsx +9 -0
  163. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-task-row.tsx +9 -0
  164. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-toolbar.tsx +9 -0
  165. package/src/components/ui/tu-do/boards/boardId/timeline-board.tsx +35 -3
  166. package/src/components/ui/tu-do/boards/form.tsx +1 -1
  167. package/src/components/ui/tu-do/boards/share-section.tsx +100 -0
  168. package/src/components/ui/tu-do/drafts/draft-convert-dialog.tsx +10 -12
  169. package/src/components/ui/tu-do/drafts/drafts-page.tsx +33 -16
  170. package/src/components/ui/tu-do/hooks/__tests__/useTaskLabelManagement.test.tsx +48 -0
  171. package/src/components/ui/tu-do/hooks/__tests__/useTaskProjectManagement.test.tsx +144 -0
  172. package/src/components/ui/tu-do/hooks/useTaskDialog.ts +7 -0
  173. package/src/components/ui/tu-do/hooks/useTaskLabelManagement.ts +115 -106
  174. package/src/components/ui/tu-do/hooks/useTaskProjectManagement.ts +115 -122
  175. package/src/components/ui/tu-do/initiatives/task-initiatives-client.tsx +56 -88
  176. package/src/components/ui/tu-do/my-tasks/my-tasks-content.tsx +26 -2
  177. package/src/components/ui/tu-do/my-tasks/use-my-tasks-state.ts +55 -8
  178. package/src/components/ui/tu-do/notes/note-edit-dialog.tsx +1 -4
  179. package/src/components/ui/tu-do/progress/task-progress-import-panel.tsx +60 -0
  180. package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +156 -0
  181. package/src/components/ui/tu-do/progress/task-progress-page.tsx +348 -0
  182. package/src/components/ui/tu-do/progress/task-progress-panels.tsx +301 -0
  183. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +26 -0
  184. package/src/components/ui/tu-do/shared/__tests__/assignee-select.test.tsx +81 -10
  185. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +141 -1
  186. package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +377 -36
  187. package/src/components/ui/tu-do/shared/__tests__/board-switcher.test.tsx +374 -0
  188. package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +419 -5
  189. package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +38 -0
  190. package/src/components/ui/tu-do/shared/__tests__/task-cache-patches.test.ts +147 -0
  191. package/src/components/ui/tu-do/shared/__tests__/task-legacy-route-recovery.test.tsx +16 -0
  192. package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +3 -0
  193. package/src/components/ui/tu-do/shared/assignee-select.tsx +77 -26
  194. package/src/components/ui/tu-do/shared/board-client.tsx +15 -10
  195. package/src/components/ui/tu-do/shared/board-config-storage.ts +7 -1
  196. package/src/components/ui/tu-do/shared/board-header.tsx +471 -975
  197. package/src/components/ui/tu-do/shared/board-layout-settings.tsx +165 -136
  198. package/src/components/ui/tu-do/shared/board-switcher.tsx +244 -220
  199. package/src/components/ui/tu-do/shared/board-user-presence-avatars.tsx +18 -12
  200. package/src/components/ui/tu-do/shared/board-views.tsx +577 -85
  201. package/src/components/ui/tu-do/shared/list-view.tsx +246 -2
  202. package/src/components/ui/tu-do/shared/recycle-bin-panel.tsx +142 -94
  203. package/src/components/ui/tu-do/shared/special-task-list-pins.ts +51 -0
  204. package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +28 -0
  205. package/src/components/ui/tu-do/shared/task-cache-patches.ts +394 -0
  206. package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +21 -1
  207. package/src/components/ui/tu-do/shared/task-edit-dialog/components/quick-settings-popover.tsx +5 -1
  208. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +25 -2
  209. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-list-selector.tsx +7 -1
  210. package/src/components/ui/tu-do/shared/task-edit-dialog/field-diff-viewer.tsx +3 -2
  211. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-data.ts +79 -10
  212. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +76 -77
  213. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.test.tsx +63 -0
  214. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.ts +78 -69
  215. package/src/components/ui/tu-do/shared/task-edit-dialog/personal-overrides-section.tsx +28 -8
  216. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/dependencies-section.tsx +14 -3
  217. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/parent-section.tsx +6 -1
  218. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/related-section.tsx +6 -1
  219. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/subtasks-section.tsx +6 -1
  220. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/types/task-relationships.types.ts +8 -0
  221. package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.test.tsx +91 -0
  222. package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.tsx +123 -78
  223. package/src/components/ui/tu-do/shared/task-edit-dialog/task-activity-section.tsx +7 -1
  224. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +8 -1
  225. package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.test.tsx +150 -0
  226. package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.tsx +61 -35
  227. package/src/components/ui/tu-do/shared/task-edit-dialog/task-relationships-properties.tsx +44 -2
  228. package/src/components/ui/tu-do/shared/task-edit-dialog/task-snapshot-dialog.tsx +8 -3
  229. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +11 -1
  230. package/src/components/ui/tu-do/shared/task-legacy-route-recovery.tsx +2 -9
  231. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +11 -0
  232. package/src/components/ui/tu-do/shared/use-progressive-board-loader.ts +2 -0
  233. package/src/declarations.d.ts +1 -0
  234. package/src/hooks/__tests__/use-calendar-readonly.test.tsx +322 -2
  235. package/src/hooks/__tests__/use-calendar-sync.test.tsx +446 -0
  236. package/src/hooks/__tests__/useBoardPresence.test.tsx +191 -0
  237. package/src/hooks/__tests__/useBoardRealtime.test.tsx +24 -144
  238. package/src/hooks/use-calendar-sync.tsx +247 -243
  239. package/src/hooks/use-calendar.tsx +323 -138
  240. package/src/hooks/use-task-actions.ts +24 -0
  241. package/src/hooks/use-user-workspace-config.ts +75 -0
  242. package/src/hooks/use-workspace-currency.ts +8 -3
  243. package/src/hooks/useBoardPresence.ts +364 -0
  244. package/src/hooks/useBoardRealtimeEventHandler.ts +45 -90
  245. package/src/lib/workspace-actions.ts +2 -6
@@ -1,5 +1,6 @@
1
1
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
2
  import { render, waitFor } from '@testing-library/react';
3
+ import type { ComponentProps } from 'react';
3
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
5
  import NewInvoicePage from './new-invoice-page';
5
6
 
@@ -62,10 +63,12 @@ function createQueryClient() {
62
63
  });
63
64
  }
64
65
 
65
- function renderPage() {
66
+ function renderPage(
67
+ props: Partial<ComponentProps<typeof NewInvoicePage>> = {}
68
+ ) {
66
69
  return render(
67
70
  <QueryClientProvider client={createQueryClient()}>
68
- <NewInvoicePage wsId="ws-1" />
71
+ <NewInvoicePage wsId="ws-1" {...props} />
69
72
  </QueryClientProvider>
70
73
  );
71
74
  }
@@ -80,7 +83,7 @@ describe('NewInvoicePage', () => {
80
83
  fetchMock = vi.fn().mockResolvedValue({
81
84
  ok: true,
82
85
  json: async () => ({
83
- DEFAULT_CURRENCY: 'VND',
86
+ DEFAULT_CURRENCY: 'SGD',
84
87
  DEFAULT_SUBSCRIPTION_CATEGORY_ID: 'category-1',
85
88
  default_wallet_id: 'wallet-1',
86
89
  }),
@@ -107,7 +110,7 @@ describe('NewInvoicePage', () => {
107
110
  await waitFor(() =>
108
111
  expect(invoiceMocks.StandardInvoice).toHaveBeenLastCalledWith(
109
112
  expect.objectContaining({
110
- defaultCurrency: 'VND',
113
+ defaultCurrency: 'SGD',
111
114
  defaultWalletId: 'wallet-1',
112
115
  })
113
116
  )
@@ -128,10 +131,27 @@ describe('NewInvoicePage', () => {
128
131
  expect(invoiceMocks.SubscriptionInvoice).toHaveBeenLastCalledWith(
129
132
  expect.objectContaining({
130
133
  defaultCategoryId: 'category-1',
131
- defaultCurrency: 'VND',
134
+ defaultCurrency: 'SGD',
132
135
  defaultWalletId: 'wallet-1',
133
136
  })
134
137
  )
135
138
  );
136
139
  });
140
+
141
+ it('uses the server-provided currency when batched config read is denied', async () => {
142
+ fetchMock.mockResolvedValueOnce({
143
+ ok: false,
144
+ status: 403,
145
+ });
146
+
147
+ renderPage({ defaultCurrency: 'VND' });
148
+
149
+ await waitFor(() =>
150
+ expect(invoiceMocks.StandardInvoice).toHaveBeenLastCalledWith(
151
+ expect.objectContaining({
152
+ defaultCurrency: 'VND',
153
+ })
154
+ )
155
+ );
156
+ });
137
157
  });
@@ -12,6 +12,7 @@ import { Separator } from '@tuturuuu/ui/separator';
12
12
  import { Skeleton } from '@tuturuuu/ui/skeleton';
13
13
  import { Switch } from '@tuturuuu/ui/switch';
14
14
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '@tuturuuu/ui/tabs';
15
+ import { resolveSupportedCurrency } from '@tuturuuu/utils/currencies';
15
16
  import { useTranslations } from 'next-intl';
16
17
  import { useQueryState } from 'nuqs';
17
18
  import { useState } from 'react';
@@ -38,6 +39,7 @@ interface Props {
38
39
  canReadInvoiceProducts?: boolean;
39
40
  canReadInvoiceProductStock?: boolean;
40
41
  canReadGroupLinkedProducts?: boolean;
42
+ defaultCurrency?: string;
41
43
  permissionRequestUser?: FinancePermissionRequestUser | null;
42
44
  }
43
45
 
@@ -49,6 +51,7 @@ export default function NewInvoicePage({
49
51
  canReadInvoiceProducts = true,
50
52
  canReadInvoiceProductStock = true,
51
53
  canReadGroupLinkedProducts = true,
54
+ defaultCurrency: workspaceDefaultCurrency,
52
55
  permissionRequestUser,
53
56
  }: Props) {
54
57
  const t = useTranslations();
@@ -74,8 +77,10 @@ export default function NewInvoicePage({
74
77
  const defaultWalletId = defaultConfigs.default_wallet_id ?? undefined;
75
78
  const defaultCategoryId =
76
79
  defaultConfigs.DEFAULT_SUBSCRIPTION_CATEGORY_ID ?? undefined;
77
- const defaultCurrency =
78
- defaultConfigs.DEFAULT_CURRENCY === 'VND' ? 'VND' : 'USD';
80
+ const defaultCurrency = resolveSupportedCurrency(
81
+ defaultConfigs.DEFAULT_CURRENCY,
82
+ resolveSupportedCurrency(workspaceDefaultCurrency)
83
+ );
79
84
 
80
85
  const [
81
86
  createMultipleInvoices,
@@ -6,6 +6,7 @@ import { Button } from '@tuturuuu/ui/button';
6
6
  import { Card, CardContent, CardHeader, CardTitle } from '@tuturuuu/ui/card';
7
7
  import { Separator } from '@tuturuuu/ui/separator';
8
8
  import { toast } from '@tuturuuu/ui/sonner';
9
+ import { resolveSupportedCurrency } from '@tuturuuu/utils/currencies';
9
10
  import { shouldLockFinanceWalletSelectionOnCreate } from '@tuturuuu/utils/finance';
10
11
  import { useRouter } from 'next/navigation';
11
12
  import { useTranslations } from 'next-intl';
@@ -56,7 +57,7 @@ interface Props {
56
57
  printAfterCreate?: boolean;
57
58
  downloadImageAfterCreate?: boolean;
58
59
  defaultWalletId?: string;
59
- defaultCurrency?: 'VND' | 'USD';
60
+ defaultCurrency?: string;
60
61
  canChangeFinanceWallets?: boolean;
61
62
  canSetFinanceWalletsOnCreate?: boolean;
62
63
  canReadInvoiceProducts?: boolean;
@@ -70,7 +71,7 @@ export function StandardInvoice({
70
71
  printAfterCreate = false,
71
72
  downloadImageAfterCreate = false,
72
73
  defaultWalletId,
73
- defaultCurrency = 'USD',
74
+ defaultCurrency: rawDefaultCurrency = 'USD',
74
75
  canChangeFinanceWallets = true,
75
76
  canSetFinanceWalletsOnCreate = true,
76
77
  canReadInvoiceProducts = true,
@@ -79,6 +80,7 @@ export function StandardInvoice({
79
80
  }: Props) {
80
81
  const t = useTranslations();
81
82
  const router = useRouter();
83
+ const defaultCurrency = resolveSupportedCurrency(rawDefaultCurrency);
82
84
  const { isConfidential: areNumbersHidden } =
83
85
  useFinanceConfidentialVisibility();
84
86
 
@@ -6,6 +6,7 @@ import { Button } from '@tuturuuu/ui/button';
6
6
  import { Card, CardContent, CardHeader, CardTitle } from '@tuturuuu/ui/card';
7
7
  import { Separator } from '@tuturuuu/ui/separator';
8
8
  import { toast } from '@tuturuuu/ui/sonner';
9
+ import { resolveSupportedCurrency } from '@tuturuuu/utils/currencies';
9
10
  import { shouldLockFinanceWalletSelectionOnCreate } from '@tuturuuu/utils/finance';
10
11
  import { useRouter } from 'next/navigation';
11
12
  import { useLocale, useTranslations } from 'next-intl';
@@ -81,7 +82,7 @@ interface Props {
81
82
  downloadImageAfterCreate?: boolean;
82
83
  defaultWalletId?: string;
83
84
  defaultCategoryId?: string;
84
- defaultCurrency?: 'VND' | 'USD';
85
+ defaultCurrency?: string;
85
86
  canChangeFinanceWallets?: boolean;
86
87
  canSetFinanceWalletsOnCreate?: boolean;
87
88
  canReadInvoiceProducts?: boolean;
@@ -98,7 +99,7 @@ export function SubscriptionInvoice({
98
99
  downloadImageAfterCreate = false,
99
100
  defaultWalletId,
100
101
  defaultCategoryId,
101
- defaultCurrency = 'USD',
102
+ defaultCurrency: rawDefaultCurrency = 'USD',
102
103
  canChangeFinanceWallets = true,
103
104
  canSetFinanceWalletsOnCreate = true,
104
105
  canReadInvoiceProducts = true,
@@ -108,6 +109,7 @@ export function SubscriptionInvoice({
108
109
  }: Props) {
109
110
  const t = useTranslations();
110
111
  const locale = useLocale();
112
+ const defaultCurrency = resolveSupportedCurrency(rawDefaultCurrency);
111
113
  const { isConfidential: areNumbersHidden } =
112
114
  useFinanceConfidentialVisibility();
113
115
  const router = useRouter();
@@ -14,7 +14,9 @@ type AttendanceStats = {
14
14
  };
15
15
 
16
16
  export type WorkspaceUserGroup =
17
- Database['public']['Tables']['workspace_user_groups']['Row'];
17
+ Database['public']['Tables']['workspace_user_groups']['Row'] & {
18
+ sessions?: string[] | null;
19
+ };
18
20
 
19
21
  export type UserGroup = {
20
22
  workspace_user_groups: WorkspaceUserGroup | null;
@@ -31,6 +31,7 @@ interface FormContentDialogProps {
31
31
  setNewContentType: Dispatch<SetStateAction<NewContentType | undefined>>;
32
32
  newContent: NewContent;
33
33
  setNewContent: Dispatch<SetStateAction<NewContent>>;
34
+ defaultCurrency?: string;
34
35
  newTagColor: string;
35
36
  setNewTagColor: Dispatch<SetStateAction<string>>;
36
37
  }
@@ -53,6 +54,7 @@ export function FormContentDialog({
53
54
  setNewContentType,
54
55
  newContent,
55
56
  setNewContent,
57
+ defaultCurrency,
56
58
  newTagColor,
57
59
  setNewTagColor,
58
60
  }: FormContentDialogProps) {
@@ -101,6 +103,7 @@ export function FormContentDialog({
101
103
  <WalletForm
102
104
  wsId={wsId}
103
105
  data={newContent as WalletType}
106
+ defaultCurrency={defaultCurrency}
104
107
  onFinish={() => {
105
108
  setNewContent(undefined);
106
109
  setNewContentType(undefined);
@@ -55,6 +55,7 @@ export interface TransactionFormProps {
55
55
  canUpdateConfidentialTransactions?: boolean;
56
56
  canChangeFinanceWallets?: boolean;
57
57
  canSetFinanceWalletsOnCreate?: boolean;
58
+ defaultCurrency?: string;
58
59
  initialMode?: TransactionFormInitialMode;
59
60
  initialTransaction?: TransactionFormInitialTransaction;
60
61
  initialTransfer?: TransactionFormInitialTransfer;
@@ -138,6 +138,7 @@ export function TransactionForm({
138
138
  canUpdateConfidentialTransactions,
139
139
  canChangeFinanceWallets = true,
140
140
  canSetFinanceWalletsOnCreate = true,
141
+ defaultCurrency,
141
142
  initialMode = 'transaction',
142
143
  initialTransaction,
143
144
  initialTransfer,
@@ -1005,6 +1006,7 @@ export function TransactionForm({
1005
1006
  setNewContentType={setNewContentType}
1006
1007
  newContent={newContent}
1007
1008
  setNewContent={setNewContent}
1009
+ defaultCurrency={defaultCurrency}
1008
1010
  newTagColor={newTagColor}
1009
1011
  setNewTagColor={setNewTagColor}
1010
1012
  />
@@ -1067,6 +1067,7 @@ export function InfiniteTransactionsList({
1067
1067
  canUpdateConfidentialTransactions={
1068
1068
  canUpdateConfidentialTransactions
1069
1069
  }
1070
+ defaultCurrency={currency}
1070
1071
  timezone={resolvedTimezone}
1071
1072
  refreshPageOnFinish={!!walletId}
1072
1073
  permissionRequestUser={permissionRequestUser}
@@ -1102,6 +1103,7 @@ export function InfiniteTransactionsList({
1102
1103
  canCreateConfidentialTransactions={
1103
1104
  canCreateConfidentialTransactions
1104
1105
  }
1106
+ defaultCurrency={currency}
1105
1107
  timezone={resolvedTimezone}
1106
1108
  preferInitialWalletSelection={!!walletId}
1107
1109
  refreshPageOnFinish={!!walletId}
@@ -497,7 +497,7 @@ export function CategoryBreakdownDialog({
497
497
 
498
498
  return (
499
499
  <Dialog open={open} onOpenChange={onOpenChange}>
500
- <DialogContent className="data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-bottom-2 data-[state=open]:slide-in-from-bottom-2 inset-0! top-0! left-0! flex h-screen max-h-screen w-screen max-w-none! translate-x-0! translate-y-0! flex-col gap-0 overflow-hidden rounded-none! border-0 p-0">
500
+ <DialogContent presentation="fullscreen" className="flex-col">
501
501
  {/* Header */}
502
502
  <DialogHeader className="shrink-0 border-b px-6 py-5">
503
503
  <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
@@ -481,10 +481,7 @@ export function TransactionEditDialog({
481
481
  return (
482
482
  <>
483
483
  <Dialog open={isOpen} onOpenChange={handleClose} modal={true}>
484
- <DialogContent
485
- showCloseButton={false}
486
- className="data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 inset-0! top-0! left-0! flex h-screen max-h-screen w-screen max-w-none! translate-x-0! translate-y-0! gap-0 rounded-none! border-0 p-0"
487
- >
484
+ <DialogContent showCloseButton={false} presentation="fullscreen">
488
485
  {/* Main content area */}
489
486
  <div className="flex min-w-0 flex-1 flex-col bg-background">
490
487
  {/* Header with gradient */}
@@ -15,6 +15,7 @@ interface TransactionsCreateSummaryProps {
15
15
  createDescription: string;
16
16
  createTitle: string;
17
17
  defaultOpen?: boolean;
18
+ defaultCurrency?: string;
18
19
  description: string;
19
20
  initialMode?: 'transaction' | 'transfer';
20
21
  permissionRequestUser?: FinancePermissionRequestUser | null;
@@ -32,6 +33,7 @@ export function TransactionsCreateSummary({
32
33
  createDescription,
33
34
  createTitle,
34
35
  defaultOpen = false,
36
+ defaultCurrency,
35
37
  description,
36
38
  initialMode = 'transaction',
37
39
  permissionRequestUser,
@@ -59,6 +61,7 @@ export function TransactionsCreateSummary({
59
61
  canCreateConfidentialTransactions
60
62
  }
61
63
  initialMode={initialMode}
64
+ defaultCurrency={defaultCurrency}
62
65
  timezone={timezone}
63
66
  permissionRequestUser={permissionRequestUser}
64
67
  />
@@ -7,6 +7,7 @@ import ExportDialogContent from '@tuturuuu/ui/finance/transactions/export-dialog
7
7
  import { TransactionsCreateSummary } from '@tuturuuu/ui/finance/transactions/transactions-create-summary';
8
8
  import { TransactionsInfinitePage } from '@tuturuuu/ui/finance/transactions/transactions-infinite-page';
9
9
  import { Separator } from '@tuturuuu/ui/separator';
10
+ import { resolveSupportedCurrency } from '@tuturuuu/utils/currencies';
10
11
  import {
11
12
  getPermissions,
12
13
  getWorkspace,
@@ -51,6 +52,7 @@ export default async function TransactionsPage({
51
52
  ]);
52
53
  if (!resolvedWorkspace || !resolvedPermissions) return notFound();
53
54
  const { containsPermission } = resolvedPermissions;
55
+ const workspaceCurrency = resolveSupportedCurrency(resolvedCurrency);
54
56
 
55
57
  const canViewTransactions = containsPermission('view_transactions');
56
58
  const canExportFinanceData = containsPermission('export_finance_data');
@@ -110,13 +112,14 @@ export default async function TransactionsPage({
110
112
  canChangeFinanceWallets={canChangeFinanceWallets}
111
113
  canSetFinanceWalletsOnCreate={canSetFinanceWalletsOnCreate}
112
114
  canCreateConfidentialTransactions={canCreateConfidentialTransactions}
115
+ defaultCurrency={workspaceCurrency}
113
116
  timezone={resolvedWorkspace.timezone}
114
117
  permissionRequestUser={permissionRequestUser}
115
118
  />
116
119
  <Separator className="my-4" />
117
120
  <TransactionsInfinitePage
118
121
  wsId={wsId}
119
- currency={resolvedCurrency ?? 'USD'}
122
+ currency={workspaceCurrency}
120
123
  timezone={resolvedWorkspace.timezone}
121
124
  canExport={canExportFinanceData}
122
125
  exportContent={
@@ -5,10 +5,27 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
5
  import type { WalletFormValues } from './form';
6
6
  import { WalletForm } from './form';
7
7
 
8
+ const mocks = vi.hoisted(() => ({
9
+ createWallet: vi.fn(),
10
+ updateWallet: vi.fn(),
11
+ }));
12
+
8
13
  vi.mock('@tuturuuu/ui/hooks/use-workspace-currency', () => ({
9
- useWorkspaceCurrency: () => ({ currency: 'USD' }),
14
+ useWorkspaceCurrency: (_wsId: string, fallbackCurrency = 'USD') => ({
15
+ currency: fallbackCurrency,
16
+ }),
10
17
  }));
11
18
 
19
+ vi.mock('@tuturuuu/internal-api/finance', async (importOriginal) => {
20
+ const actual =
21
+ await importOriginal<typeof import('@tuturuuu/internal-api/finance')>();
22
+ return {
23
+ ...actual,
24
+ createWallet: mocks.createWallet,
25
+ updateWallet: mocks.updateWallet,
26
+ };
27
+ });
28
+
12
29
  vi.mock('next/navigation', () => ({
13
30
  useRouter: () => ({ refresh: vi.fn() }),
14
31
  }));
@@ -29,6 +46,7 @@ function renderWalletForm(
29
46
  options: {
30
47
  data?: ComponentProps<typeof WalletForm>['data'];
31
48
  defaultType?: WalletFormValues['type'];
49
+ defaultCurrency?: string;
32
50
  } = {}
33
51
  ) {
34
52
  const data =
@@ -41,13 +59,18 @@ function renderWalletForm(
41
59
  name: 'Primary',
42
60
  type: 'STANDARD',
43
61
  } as never);
44
- const { defaultType } = options;
62
+ const { defaultCurrency, defaultType } = options;
45
63
 
46
64
  const queryClient = new QueryClient();
47
65
 
48
66
  return render(
49
67
  <QueryClientProvider client={queryClient}>
50
- <WalletForm wsId="ws-1" data={data} defaultType={defaultType} />
68
+ <WalletForm
69
+ wsId="ws-1"
70
+ data={data}
71
+ defaultType={defaultType}
72
+ defaultCurrency={defaultCurrency}
73
+ />
51
74
  </QueryClientProvider>
52
75
  );
53
76
  }
@@ -69,6 +92,8 @@ function typeIntoCurrencyInput(input: HTMLInputElement, value: string) {
69
92
  describe('WalletForm', () => {
70
93
  beforeEach(() => {
71
94
  vi.clearAllMocks();
95
+ mocks.createWallet.mockResolvedValue({ message: 'success' });
96
+ mocks.updateWallet.mockResolvedValue({ message: 'success' });
72
97
  // biome-ignore lint/suspicious/noDocumentCookie: test resets the finance visibility cookie.
73
98
  document.cookie =
74
99
  'finance-confidential-mode=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/';
@@ -118,6 +143,29 @@ describe('WalletForm', () => {
118
143
  );
119
144
  });
120
145
 
146
+ it('initializes new wallet currency from the supplied workspace default', async () => {
147
+ renderWalletForm({
148
+ data: undefined,
149
+ defaultCurrency: 'SGD',
150
+ });
151
+
152
+ fireEvent.change(screen.getByLabelText('wallet-data-table.wallet_name'), {
153
+ target: { value: 'Singapore Cash' },
154
+ });
155
+ fireEvent.click(screen.getByRole('button', { name: 'ws-wallets.create' }));
156
+
157
+ await waitFor(() =>
158
+ expect(mocks.createWallet).toHaveBeenCalledWith(
159
+ 'ws-1',
160
+ expect.objectContaining({
161
+ currency: 'SGD',
162
+ name: 'Singapore Cash',
163
+ type: 'STANDARD',
164
+ })
165
+ )
166
+ );
167
+ });
168
+
121
169
  it('keeps accepting large credit limits after locale grouping is inserted', () => {
122
170
  renderWalletForm({
123
171
  data: {
@@ -20,6 +20,7 @@ import { Input } from '@tuturuuu/ui/input';
20
20
  import { zodResolver } from '@tuturuuu/ui/resolvers';
21
21
  import {
22
22
  getCurrencyLocale,
23
+ resolveSupportedCurrency,
23
24
  SUPPORTED_CURRENCIES,
24
25
  } from '@tuturuuu/utils/currencies';
25
26
  import { useRouter } from 'next/navigation';
@@ -97,6 +98,7 @@ interface Props {
97
98
  wsId: string;
98
99
  data?: Wallet;
99
100
  defaultType?: WalletFormValues['type'];
101
+ defaultCurrency?: string;
100
102
  onFinish?: (data: WalletFormValues) => void;
101
103
  isPersonalWorkspace?: boolean;
102
104
  }
@@ -105,11 +107,20 @@ export function WalletForm({
105
107
  wsId,
106
108
  data,
107
109
  defaultType = 'STANDARD',
110
+ defaultCurrency,
108
111
  onFinish,
109
112
  isPersonalWorkspace,
110
113
  }: Props) {
111
114
  const t = useTranslations();
112
- const { currency: workspaceCurrency } = useWorkspaceCurrency(wsId);
115
+ const fallbackCurrency = resolveSupportedCurrency(defaultCurrency);
116
+ const { currency: workspaceCurrency } = useWorkspaceCurrency(
117
+ wsId,
118
+ fallbackCurrency
119
+ );
120
+ const resolvedWorkspaceCurrency = resolveSupportedCurrency(
121
+ workspaceCurrency,
122
+ fallbackCurrency
123
+ );
113
124
  const { isConfidential: areNumbersHidden } =
114
125
  useFinanceConfidentialVisibility();
115
126
  const queryClient = useQueryClient();
@@ -127,7 +138,7 @@ export function WalletForm({
127
138
  description: data?.description || '',
128
139
  balance: data?.balance || 0,
129
140
  type: data?.type || defaultType,
130
- currency: data?.currency || workspaceCurrency || 'USD',
141
+ currency: data?.currency || resolvedWorkspaceCurrency,
131
142
  icon: data?.icon || null,
132
143
  image_src: data?.image_src || null,
133
144
  limit: data?.limit ?? undefined,
@@ -193,7 +204,7 @@ export function WalletForm({
193
204
  ? ''
194
205
  : new Intl.NumberFormat(
195
206
  getCurrencyLocale(
196
- walletCurrency || workspaceCurrency || 'USD'
207
+ walletCurrency || resolvedWorkspaceCurrency
197
208
  ),
198
209
  {
199
210
  maximumFractionDigits: 2,
@@ -296,7 +307,7 @@ export function WalletForm({
296
307
  <WalletCreditFields
297
308
  form={form}
298
309
  loading={loading}
299
- currency={walletCurrency || workspaceCurrency || 'USD'}
310
+ currency={walletCurrency || resolvedWorkspaceCurrency}
300
311
  />
301
312
  )}
302
313
 
@@ -35,6 +35,7 @@ interface WalletDetailsActionsProps {
35
35
  canSetFinanceWalletsOnCreate?: boolean;
36
36
  canDeleteWallets: boolean;
37
37
  isPersonalWorkspace: boolean;
38
+ defaultCurrency?: string;
38
39
  timezone?: string | null;
39
40
  permissionRequestUser?: FinancePermissionRequestUser | null;
40
41
  }
@@ -51,6 +52,7 @@ export function WalletDetailsActions({
51
52
  canSetFinanceWalletsOnCreate,
52
53
  canDeleteWallets,
53
54
  isPersonalWorkspace,
55
+ defaultCurrency,
54
56
  timezone,
55
57
  permissionRequestUser,
56
58
  }: WalletDetailsActionsProps) {
@@ -110,6 +112,7 @@ export function WalletDetailsActions({
110
112
  <WalletForm
111
113
  wsId={wsId}
112
114
  data={wallet}
115
+ defaultCurrency={defaultCurrency}
113
116
  isPersonalWorkspace={isPersonalWorkspace}
114
117
  />
115
118
  }
@@ -210,6 +213,7 @@ export function WalletDetailsActions({
210
213
  canCreateConfidentialTransactions={
211
214
  canCreateConfidentialTransactions
212
215
  }
216
+ defaultCurrency={defaultCurrency}
213
217
  timezone={timezone}
214
218
  preferInitialWalletSelection={transactionAction !== 'payment'}
215
219
  refreshPageOnFinish
@@ -11,6 +11,7 @@ import type { FinancePermissionRequestUser } from '@tuturuuu/ui/finance/shared/f
11
11
  import { InfiniteTransactionsList } from '@tuturuuu/ui/finance/transactions/infinite-transactions-list';
12
12
  import { Separator } from '@tuturuuu/ui/separator';
13
13
  import { Skeleton } from '@tuturuuu/ui/skeleton';
14
+ import { resolveSupportedCurrency } from '@tuturuuu/utils/currencies';
14
15
  import type { ExchangeRate } from '@tuturuuu/utils/exchange-rates';
15
16
  import { getCurrencyLocale } from '@tuturuuu/utils/format';
16
17
  import {
@@ -117,8 +118,8 @@ export default async function WalletDetailsPage({
117
118
  notFound();
118
119
  }
119
120
 
120
- const currency = wallet.currency || resolvedDefaultCurrency || 'USD';
121
- const workspaceCurrency = resolvedDefaultCurrency || 'USD';
121
+ const workspaceCurrency = resolveSupportedCurrency(resolvedDefaultCurrency);
122
+ const currency = wallet.currency || workspaceCurrency;
122
123
  const initialAction = getInitialWalletAction(searchParams.action);
123
124
 
124
125
  // Fetch exchange rates for conversion display
@@ -153,6 +154,7 @@ export default async function WalletDetailsPage({
153
154
  canSetFinanceWalletsOnCreate={canSetFinanceWalletsOnCreate}
154
155
  canDeleteWallets={canDeleteWallets}
155
156
  isPersonalWorkspace={!!resolvedWorkspace.personal}
157
+ defaultCurrency={workspaceCurrency}
156
158
  timezone={resolvedWorkspace.timezone}
157
159
  permissionRequestUser={permissionRequestUser}
158
160
  />
@@ -228,6 +228,7 @@ export function WalletsDataTable({
228
228
  <WalletForm
229
229
  wsId={wsId}
230
230
  data={selectedWallet}
231
+ defaultCurrency={currency}
231
232
  onFinish={handleEditComplete}
232
233
  isPersonalWorkspace={isPersonalWorkspace}
233
234
  />
@@ -6,6 +6,7 @@ import { WalletTotalCheckDialog } from '@tuturuuu/ui/finance/wallets/checkpoints
6
6
  import { WalletForm } from '@tuturuuu/ui/finance/wallets/form';
7
7
  import { WalletsDataTable } from '@tuturuuu/ui/finance/wallets/wallets-data-table';
8
8
  import { Separator } from '@tuturuuu/ui/separator';
9
+ import { resolveSupportedCurrency } from '@tuturuuu/utils/currencies';
9
10
  import {
10
11
  getPermissions,
11
12
  getWorkspace,
@@ -51,6 +52,7 @@ export default async function WalletsPage({
51
52
  ]);
52
53
  if (!resolvedPermissions || !resolvedWorkspace) notFound();
53
54
  const { containsPermission } = resolvedPermissions;
55
+ const workspaceCurrency = resolveSupportedCurrency(resolvedCurrency);
54
56
 
55
57
  const canCreateWallets = containsPermission('create_wallets');
56
58
  const canUpdateWallets = containsPermission('update_wallets');
@@ -76,6 +78,7 @@ export default async function WalletsPage({
76
78
  <WalletForm
77
79
  wsId={wsId}
78
80
  defaultType={isCreditCardCreate ? 'CREDIT' : 'STANDARD'}
81
+ defaultCurrency={workspaceCurrency}
79
82
  />
80
83
  ) : undefined
81
84
  }
@@ -95,7 +98,7 @@ export default async function WalletsPage({
95
98
  />
96
99
  <WalletTotalCheckDialog
97
100
  wsId={wsId}
98
- currency={resolvedCurrency ?? 'USD'}
101
+ currency={workspaceCurrency}
99
102
  canUpdateWallets={canUpdateWallets}
100
103
  defaultOpen={searchParams.tool === 'all-wallet-check'}
101
104
  />
@@ -105,7 +108,7 @@ export default async function WalletsPage({
105
108
  wsId={wsId}
106
109
  canUpdateWallets={canUpdateWallets}
107
110
  canDeleteWallets={canDeleteWallets}
108
- currency={resolvedCurrency ?? 'USD'}
111
+ currency={workspaceCurrency}
109
112
  financePrefix={financePrefix}
110
113
  isPersonalWorkspace={!!resolvedWorkspace?.personal}
111
114
  query={searchParams.q}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { MinusIcon } from '@tuturuuu/icons';
3
+ import { MinusIcon } from '@tuturuuu/icons/lucide-static';
4
4
  import { cn } from '@tuturuuu/utils/format';
5
5
  import { OTPInput, OTPInputContext, type SlotProps } from 'input-otp';
6
6
  import * as React from 'react';