@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.
- package/CHANGELOG.md +69 -0
- package/biome.json +1 -1
- package/package.json +74 -71
- package/src/components/ui/accordion.tsx +1 -1
- package/src/components/ui/breadcrumb.tsx +1 -1
- package/src/components/ui/calendar-app/calendar-page-shell.tsx +4 -0
- package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +239 -33
- package/src/components/ui/calendar-app/components/load-smart-scheduling-tasks.tsx +143 -0
- package/src/components/ui/calendar-app/components/priority-view.tsx +10 -3
- package/src/components/ui/calendar-app/components/tasks-sidebar.tsx +4 -116
- package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +67 -2
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/carousel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-external-thread-panel.test.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-external-thread-panel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-setup-panel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-sidebar.test.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-sidebar.tsx +2 -2
- package/src/components/ui/chat/chat-agent-details-utils.test.ts +1 -1
- package/src/components/ui/chat/chat-agent-details-utils.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-zalo-personal-panel.tsx +2 -2
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/color-picker.tsx +1 -1
- package/src/components/ui/command.tsx +1 -1
- package/src/components/ui/context-menu.tsx +5 -1
- package/src/components/ui/custom/__tests__/settings-dialog-search.test.ts +78 -0
- package/src/components/ui/custom/__tests__/settings-dialog-shell-compile-graph.test.ts +76 -0
- package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +3 -0
- package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +46 -1
- package/src/components/ui/custom/combobox.test.tsx +195 -0
- package/src/components/ui/custom/combobox.tsx +273 -156
- package/src/components/ui/custom/education/modules/youtube/delete-link-button.tsx +5 -13
- package/src/components/ui/custom/facebook-mockup/facebook-mockup.tsx +7 -1
- package/src/components/ui/custom/facebook-mockup/form.tsx +1 -1
- package/src/components/ui/custom/facebook-mockup/image-upload-field.tsx +1 -1
- package/src/components/ui/custom/facebook-mockup/preview.tsx +1 -1
- package/src/components/ui/custom/nav-link.test.tsx +165 -0
- package/src/components/ui/custom/nav-link.tsx +69 -11
- package/src/components/ui/custom/navigation.tsx +1 -0
- package/src/components/ui/custom/settings/task-settings.tsx +104 -0
- package/src/components/ui/custom/settings-dialog-search-loader.d.ts +5 -0
- package/src/components/ui/custom/settings-dialog-search-loader.js +3 -0
- package/src/components/ui/custom/settings-dialog-search.ts +75 -0
- package/src/components/ui/custom/settings-dialog-shell.tsx +65 -28
- package/src/components/ui/custom/theme-toggle.tsx +1 -1
- package/src/components/ui/custom/workspace-select-helpers.ts +23 -0
- package/src/components/ui/custom/workspace-select.tsx +25 -19
- package/src/components/ui/dialog.test.tsx +52 -0
- package/src/components/ui/dialog.tsx +6 -2
- package/src/components/ui/dropdown-menu.tsx +5 -1
- package/src/components/ui/finance/debts/debt-loan-form.tsx +12 -5
- package/src/components/ui/finance/debts/debt-loan-summary.tsx +3 -2
- package/src/components/ui/finance/debts/debts-page.test.tsx +54 -5
- package/src/components/ui/finance/debts/debts-page.tsx +15 -2
- package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +3 -5
- package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +25 -5
- package/src/components/ui/finance/invoices/new-invoice-page.tsx +7 -2
- package/src/components/ui/finance/invoices/standard-invoice.tsx +4 -2
- package/src/components/ui/finance/invoices/subscription-invoice.tsx +4 -2
- package/src/components/ui/finance/invoices/utils.ts +3 -1
- package/src/components/ui/finance/transactions/form-content-dialog.tsx +3 -0
- package/src/components/ui/finance/transactions/form-types.ts +1 -0
- package/src/components/ui/finance/transactions/form.tsx +2 -0
- package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +2 -0
- package/src/components/ui/finance/transactions/period-charts/category-breakdown-dialog.tsx +1 -1
- package/src/components/ui/finance/transactions/transaction-edit-dialog.tsx +1 -4
- package/src/components/ui/finance/transactions/transactions-create-summary.tsx +3 -0
- package/src/components/ui/finance/transactions/transactions-page.tsx +4 -1
- package/src/components/ui/finance/wallets/form.test.tsx +51 -3
- package/src/components/ui/finance/wallets/form.tsx +15 -4
- package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
- package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +4 -2
- package/src/components/ui/finance/wallets/wallets-data-table.tsx +1 -0
- package/src/components/ui/finance/wallets/wallets-page.tsx +5 -2
- package/src/components/ui/input-otp.tsx +1 -1
- package/src/components/ui/legacy/calendar/all-day-event-bar.tsx +28 -39
- package/src/components/ui/legacy/calendar/calendar-cell.tsx +2 -0
- package/src/components/ui/legacy/calendar/calendar-content.tsx +10 -6
- package/src/components/ui/legacy/calendar/calendar-header.tsx +23 -3
- package/src/components/ui/legacy/calendar/calendar-loading-skeleton.tsx +135 -0
- package/src/components/ui/legacy/calendar/calendar-matrix.tsx +175 -237
- package/src/components/ui/legacy/calendar/event-card.test.tsx +177 -0
- package/src/components/ui/legacy/calendar/event-card.tsx +220 -131
- package/src/components/ui/legacy/calendar/event-modal.tsx +17 -17
- package/src/components/ui/legacy/calendar/event-provider-display.tsx +69 -0
- package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +86 -4
- package/src/components/ui/legacy/calendar/smart-calendar.tsx +32 -2
- package/src/components/ui/legacy/meet/create-plan-dialog.tsx +19 -10
- package/src/components/ui/navigation-menu.tsx +1 -1
- package/src/components/ui/pagination.tsx +1 -1
- package/src/components/ui/radio-group.tsx +1 -1
- package/src/components/ui/select.tsx +5 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/sidebar.tsx +1 -1
- package/src/components/ui/storefront/cart-popover.tsx +61 -0
- package/src/components/ui/storefront/cart-summary-parts.tsx +290 -0
- package/src/components/ui/storefront/cart-summary.tsx +93 -154
- package/src/components/ui/storefront/checkout-overlay.tsx +4 -5
- package/src/components/ui/storefront/listing-card.tsx +1 -1
- package/src/components/ui/storefront/merch-sections.tsx +70 -0
- package/src/components/ui/storefront/product-detail.tsx +1 -1
- package/src/components/ui/storefront/storefront-surface.test.tsx +106 -11
- package/src/components/ui/storefront/storefront-surface.tsx +101 -166
- package/src/components/ui/storefront/types.ts +4 -0
- package/src/components/ui/storefront/utils.ts +6 -0
- package/src/components/ui/text-editor/__tests__/extensions.test.ts +123 -0
- package/src/components/ui/text-editor/background-color-extension.ts +62 -0
- package/src/components/ui/text-editor/color-controls.tsx +284 -0
- package/src/components/ui/text-editor/editor.tsx +69 -14
- package/src/components/ui/text-editor/extensions.ts +8 -2
- package/src/components/ui/text-editor/highlight-extension.ts +22 -0
- package/src/components/ui/text-editor/tool-bar.tsx +9 -16
- package/src/components/ui/toast.tsx +1 -1
- package/src/components/ui/tu-do/boards/__tests__/board-share-dialog.test.tsx +286 -0
- package/src/components/ui/tu-do/boards/__tests__/task-board-form.test.tsx +12 -0
- package/src/components/ui/tu-do/boards/board-public-link-section.tsx +231 -0
- package/src/components/ui/tu-do/boards/board-share-dialog.tsx +15 -226
- package/src/components/ui/tu-do/boards/board-share-settings-panel.tsx +351 -0
- package/src/components/ui/tu-do/boards/boardId/board-column.tsx +121 -39
- package/src/components/ui/tu-do/boards/boardId/enhanced-task-list.tsx +7 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +2 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-move.ts +5 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +3 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-types.ts +3 -3
- package/src/components/ui/tu-do/boards/boardId/kanban/data/kanban-deadline-query.ts +50 -2
- package/src/components/ui/tu-do/boards/boardId/kanban/data/use-bulk-resources.ts +59 -5
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/__tests__/column-reorder.test.ts +17 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/column-reorder.ts +4 -1
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/drag-preview.tsx +20 -1
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-cache.ts +38 -9
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-order.ts +2 -8
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-sort-key.ts +47 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +81 -30
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/__tests__/kanban-planner-island.test.tsx +380 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/kanban-planner-dialog.tsx +204 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-digest-panel.tsx +61 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-item-strip.tsx +54 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-plan-toolbar.tsx +251 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-scope-badge.tsx +27 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-section.tsx +58 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-share-dialog.tsx +238 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-target-controls.tsx +143 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-utils.ts +65 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/use-kanban-planner-state.ts +234 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +642 -5
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +224 -15
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-deadline-panels.tsx +535 -53
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-skeleton.tsx +101 -33
- package/src/components/ui/tu-do/boards/boardId/kanban.tsx +235 -113
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +50 -5
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +12 -2
- package/src/components/ui/tu-do/boards/boardId/task-card/measured-task-card.tsx +10 -1
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +3 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +20 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +10 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +271 -36
- package/src/components/ui/tu-do/boards/boardId/task-filter.test.tsx +152 -0
- package/src/components/ui/tu-do/boards/boardId/task-filter.tsx +555 -545
- package/src/components/ui/tu-do/boards/boardId/task-list.tsx +22 -0
- package/src/components/ui/tu-do/boards/boardId/timeline/timeline-grid.tsx +9 -0
- package/src/components/ui/tu-do/boards/boardId/timeline/timeline-task-row.tsx +9 -0
- package/src/components/ui/tu-do/boards/boardId/timeline/timeline-toolbar.tsx +9 -0
- package/src/components/ui/tu-do/boards/boardId/timeline-board.tsx +35 -3
- package/src/components/ui/tu-do/boards/form.tsx +1 -1
- package/src/components/ui/tu-do/boards/share-section.tsx +100 -0
- package/src/components/ui/tu-do/drafts/draft-convert-dialog.tsx +10 -12
- package/src/components/ui/tu-do/drafts/drafts-page.tsx +33 -16
- package/src/components/ui/tu-do/hooks/__tests__/useTaskLabelManagement.test.tsx +48 -0
- package/src/components/ui/tu-do/hooks/__tests__/useTaskProjectManagement.test.tsx +144 -0
- package/src/components/ui/tu-do/hooks/useTaskDialog.ts +7 -0
- package/src/components/ui/tu-do/hooks/useTaskLabelManagement.ts +115 -106
- package/src/components/ui/tu-do/hooks/useTaskProjectManagement.ts +115 -122
- package/src/components/ui/tu-do/initiatives/task-initiatives-client.tsx +56 -88
- package/src/components/ui/tu-do/my-tasks/my-tasks-content.tsx +26 -2
- package/src/components/ui/tu-do/my-tasks/use-my-tasks-state.ts +55 -8
- package/src/components/ui/tu-do/notes/note-edit-dialog.tsx +1 -4
- package/src/components/ui/tu-do/progress/task-progress-import-panel.tsx +60 -0
- package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +156 -0
- package/src/components/ui/tu-do/progress/task-progress-page.tsx +348 -0
- package/src/components/ui/tu-do/progress/task-progress-panels.tsx +301 -0
- package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +26 -0
- package/src/components/ui/tu-do/shared/__tests__/assignee-select.test.tsx +81 -10
- package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +141 -1
- package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +377 -36
- package/src/components/ui/tu-do/shared/__tests__/board-switcher.test.tsx +374 -0
- package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +419 -5
- package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +38 -0
- package/src/components/ui/tu-do/shared/__tests__/task-cache-patches.test.ts +147 -0
- package/src/components/ui/tu-do/shared/__tests__/task-legacy-route-recovery.test.tsx +16 -0
- package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +3 -0
- package/src/components/ui/tu-do/shared/assignee-select.tsx +77 -26
- package/src/components/ui/tu-do/shared/board-client.tsx +15 -10
- package/src/components/ui/tu-do/shared/board-config-storage.ts +7 -1
- package/src/components/ui/tu-do/shared/board-header.tsx +471 -975
- package/src/components/ui/tu-do/shared/board-layout-settings.tsx +165 -136
- package/src/components/ui/tu-do/shared/board-switcher.tsx +244 -220
- package/src/components/ui/tu-do/shared/board-user-presence-avatars.tsx +18 -12
- package/src/components/ui/tu-do/shared/board-views.tsx +577 -85
- package/src/components/ui/tu-do/shared/list-view.tsx +246 -2
- package/src/components/ui/tu-do/shared/recycle-bin-panel.tsx +142 -94
- package/src/components/ui/tu-do/shared/special-task-list-pins.ts +51 -0
- package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +28 -0
- package/src/components/ui/tu-do/shared/task-cache-patches.ts +394 -0
- package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +21 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/components/quick-settings-popover.tsx +5 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +25 -2
- package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-list-selector.tsx +7 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/field-diff-viewer.tsx +3 -2
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-data.ts +79 -10
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +76 -77
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.test.tsx +63 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.ts +78 -69
- package/src/components/ui/tu-do/shared/task-edit-dialog/personal-overrides-section.tsx +28 -8
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/dependencies-section.tsx +14 -3
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/parent-section.tsx +6 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/related-section.tsx +6 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/subtasks-section.tsx +6 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/types/task-relationships.types.ts +8 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.test.tsx +91 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.tsx +123 -78
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-activity-section.tsx +7 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +8 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.test.tsx +150 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.tsx +61 -35
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-relationships-properties.tsx +44 -2
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-snapshot-dialog.tsx +8 -3
- package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +11 -1
- package/src/components/ui/tu-do/shared/task-legacy-route-recovery.tsx +2 -9
- package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +11 -0
- package/src/components/ui/tu-do/shared/use-progressive-board-loader.ts +2 -0
- package/src/declarations.d.ts +1 -0
- package/src/hooks/__tests__/use-calendar-readonly.test.tsx +322 -2
- package/src/hooks/__tests__/use-calendar-sync.test.tsx +446 -0
- package/src/hooks/__tests__/useBoardPresence.test.tsx +191 -0
- package/src/hooks/__tests__/useBoardRealtime.test.tsx +24 -144
- package/src/hooks/use-calendar-sync.tsx +247 -243
- package/src/hooks/use-calendar.tsx +323 -138
- package/src/hooks/use-task-actions.ts +24 -0
- package/src/hooks/use-user-workspace-config.ts +75 -0
- package/src/hooks/use-workspace-currency.ts +8 -3
- package/src/hooks/useBoardPresence.ts +364 -0
- package/src/hooks/useBoardRealtimeEventHandler.ts +45 -90
- 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: '
|
|
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: '
|
|
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: '
|
|
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
|
|
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?:
|
|
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?:
|
|
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
|
|
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={
|
|
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: (
|
|
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
|
|
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
|
|
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 ||
|
|
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 ||
|
|
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 ||
|
|
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
|
|
121
|
-
const
|
|
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
|
/>
|
|
@@ -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={
|
|
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={
|
|
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';
|